Implémentation des bonus malus
This commit is contained in:
parent
e3450ebc82
commit
bb40532ca6
@ -71,7 +71,7 @@ class BulletinBUT(ResultatsSemestreBUT):
|
|||||||
"bonus": fmt_note(self.bonus_ues[ue.id][etud.id])
|
"bonus": fmt_note(self.bonus_ues[ue.id][etud.id])
|
||||||
if self.bonus_ues is not None and ue.id in self.bonus_ues
|
if self.bonus_ues is not None and ue.id in self.bonus_ues
|
||||||
else fmt_note(0.0),
|
else fmt_note(0.0),
|
||||||
"malus": None, # XXX TODO voir ce qui est ici
|
"malus": self.malus[ue.id][etud.id],
|
||||||
"capitalise": None, # "AAAA-MM-JJ" TODO
|
"capitalise": None, # "AAAA-MM-JJ" TODO
|
||||||
"ressources": self.etud_ue_mod_results(etud, ue, self.ressources),
|
"ressources": self.etud_ue_mod_results(etud, ue, self.ressources),
|
||||||
"saes": self.etud_ue_mod_results(etud, ue, self.saes),
|
"saes": self.etud_ue_mod_results(etud, ue, self.saes),
|
||||||
|
@ -104,7 +104,6 @@ class BonusSport:
|
|||||||
# sem_modimpl_moys_spo est (nb_etuds, nb_mod_sport)
|
# sem_modimpl_moys_spo est (nb_etuds, nb_mod_sport)
|
||||||
# ou (nb_etuds, nb_mod_sport, nb_ues_non_bonus)
|
# ou (nb_etuds, nb_mod_sport, nb_ues_non_bonus)
|
||||||
nb_etuds, nb_mod_sport = sem_modimpl_moys_spo.shape[:2]
|
nb_etuds, nb_mod_sport = sem_modimpl_moys_spo.shape[:2]
|
||||||
nb_ues = len(ues)
|
|
||||||
# Enlève les NaN du numérateur:
|
# Enlève les NaN du numérateur:
|
||||||
sem_modimpl_moys_no_nan = np.nan_to_num(sem_modimpl_moys_spo, nan=0.0)
|
sem_modimpl_moys_no_nan = np.nan_to_num(sem_modimpl_moys_spo, nan=0.0)
|
||||||
|
|
||||||
@ -162,7 +161,7 @@ class BonusSport:
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError("méthode virtuelle")
|
raise NotImplementedError("méthode virtuelle")
|
||||||
|
|
||||||
def get_bonus_ues(self) -> pd.Series:
|
def get_bonus_ues(self) -> pd.DataFrame:
|
||||||
"""Les bonus à appliquer aux UE
|
"""Les bonus à appliquer aux UE
|
||||||
Résultat: DataFrame de float, index etudid, columns: ue.id
|
Résultat: DataFrame de float, index etudid, columns: ue.id
|
||||||
"""
|
"""
|
||||||
|
@ -43,6 +43,8 @@ from app.scodoc import sco_utils as scu
|
|||||||
from app.scodoc.sco_codes_parcours import UE_SPORT
|
from app.scodoc.sco_codes_parcours import UE_SPORT
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
|
|
||||||
|
from app.scodoc.sco_utils import ModuleType
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class EvaluationEtat:
|
class EvaluationEtat:
|
||||||
@ -291,7 +293,12 @@ def load_evaluations_poids(moduleimpl_id: int) -> tuple[pd.DataFrame, list]:
|
|||||||
pass # poids vers des UE qui n'existent plus ou sont dans un autre semestre...
|
pass # poids vers des UE qui n'existent plus ou sont dans un autre semestre...
|
||||||
|
|
||||||
# Initialise poids non enregistrés:
|
# Initialise poids non enregistrés:
|
||||||
default_poids = 1.0 if modimpl.module.ue.type == UE_SPORT else 0.0
|
default_poids = (
|
||||||
|
1.0
|
||||||
|
if modimpl.module.ue.type == UE_SPORT
|
||||||
|
or modimpl.module.module_type == ModuleType.MALUS
|
||||||
|
else 0.0
|
||||||
|
)
|
||||||
|
|
||||||
if np.isnan(evals_poids.values.flat).any():
|
if np.isnan(evals_poids.values.flat).any():
|
||||||
ue_coefs = modimpl.module.get_ue_coef_dict()
|
ue_coefs = modimpl.module.get_ue_coef_dict()
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
"""Fonctions de calcul des moyennes d'UE (classiques ou BUT)
|
"""Fonctions de calcul des moyennes d'UE (classiques ou BUT)
|
||||||
"""
|
"""
|
||||||
|
from re import X
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
@ -380,3 +381,42 @@ def compute_ue_moys_classic(
|
|||||||
etud_moy_gen_s = pd.Series(etud_moy_gen, index=modimpl_inscr_df.index)
|
etud_moy_gen_s = pd.Series(etud_moy_gen, index=modimpl_inscr_df.index)
|
||||||
|
|
||||||
return etud_moy_gen_s, etud_moy_ue_df, etud_coef_ue_df
|
return etud_moy_gen_s, etud_moy_ue_df, etud_coef_ue_df
|
||||||
|
|
||||||
|
|
||||||
|
def compute_malus(
|
||||||
|
formsemestre: FormSemestre,
|
||||||
|
sem_modimpl_moys: np.array,
|
||||||
|
ues: list[UniteEns],
|
||||||
|
modimpl_inscr_df: pd.DataFrame,
|
||||||
|
) -> pd.DataFrame:
|
||||||
|
"""Calcul le malus sur les UE
|
||||||
|
Dans chaque UE, on peut avoir un ou plusieurs modules de MALUS.
|
||||||
|
Leurs notes sont positives ou négatives. leur somme sera _soustraite_ à la moyenne
|
||||||
|
de chaque UE.
|
||||||
|
Arguments:
|
||||||
|
- sem_modimpl_moys :
|
||||||
|
notes moyennes aux modules (tous les étuds x tous les modimpls)
|
||||||
|
floats avec des NaN.
|
||||||
|
En classique: sem_matrix, ndarray (etuds x modimpls)
|
||||||
|
En APC: sem_cube, ndarray (etuds x modimpls x UEs non bonus)
|
||||||
|
- ues: les ues du semestre (incluant le bonus sport)
|
||||||
|
- modimpl_inscr_df: matrice d'inscription aux modules du semestre (etud x modimpl)
|
||||||
|
|
||||||
|
Résultat: DataFrame de float, index etudid, columns: ue.id (sans NaN)
|
||||||
|
"""
|
||||||
|
ues_idx = [ue.id for ue in ues]
|
||||||
|
malus = pd.DataFrame(index=modimpl_inscr_df.index, columns=ues_idx, dtype=float)
|
||||||
|
for ue in ues:
|
||||||
|
if ue.type != UE_SPORT:
|
||||||
|
modimpl_mask = np.array(
|
||||||
|
[
|
||||||
|
(m.module.module_type == ModuleType.MALUS)
|
||||||
|
and (m.module.ue.id == ue.id)
|
||||||
|
for m in formsemestre.modimpls_sorted
|
||||||
|
]
|
||||||
|
)
|
||||||
|
malus_moys = sem_modimpl_moys[:, modimpl_mask].sum(axis=1)
|
||||||
|
malus[ue.id] = malus_moys
|
||||||
|
|
||||||
|
malus.fillna(0.0, inplace=True)
|
||||||
|
return malus
|
||||||
|
@ -68,6 +68,12 @@ class ResultatsSemestreBUT(NotesTableCompat):
|
|||||||
1.0, index=self.etud_moy_ue.index, columns=self.etud_moy_ue.columns
|
1.0, index=self.etud_moy_ue.index, columns=self.etud_moy_ue.columns
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# --- Modules de MALUS sur les UEs
|
||||||
|
self.malus = moy_ue.compute_malus(
|
||||||
|
self.formsemestre, self.sem_cube, self.ues, self.modimpl_inscr_df
|
||||||
|
)
|
||||||
|
self.etud_moy_ue -= self.malus
|
||||||
|
|
||||||
# --- Bonus Sport & Culture
|
# --- Bonus Sport & Culture
|
||||||
if len(modimpls_sport) > 0:
|
if len(modimpls_sport) > 0:
|
||||||
bonus_class = ScoDocSiteConfig.get_bonus_sport_class()
|
bonus_class = ScoDocSiteConfig.get_bonus_sport_class()
|
||||||
|
@ -71,6 +71,16 @@ class ResultatsSemestreClassic(NotesTableCompat):
|
|||||||
self.modimpl_coefs,
|
self.modimpl_coefs,
|
||||||
modimpl_standards_mask,
|
modimpl_standards_mask,
|
||||||
)
|
)
|
||||||
|
# --- Modules de MALUS sur les UEs et la moyenne générale
|
||||||
|
self.malus = moy_ue.compute_malus(
|
||||||
|
self.formsemestre, self.sem_matrix, self.ues, self.modimpl_inscr_df
|
||||||
|
)
|
||||||
|
self.etud_moy_ue -= self.malus
|
||||||
|
# ajuste la moyenne générale (à l'aide des coefs d'UE)
|
||||||
|
self.etud_moy_gen -= (self.etud_coef_ue_df * self.malus).sum(
|
||||||
|
axis=1
|
||||||
|
) / self.etud_coef_ue_df.sum(axis=1)
|
||||||
|
|
||||||
# --- Bonus Sport & Culture
|
# --- Bonus Sport & Culture
|
||||||
bonus_class = ScoDocSiteConfig.get_bonus_sport_class()
|
bonus_class = ScoDocSiteConfig.get_bonus_sport_class()
|
||||||
if bonus_class is not None:
|
if bonus_class is not None:
|
||||||
|
@ -115,22 +115,30 @@ def do_module_create(args) -> int:
|
|||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
def module_create(
|
||||||
"""Création d'un module"""
|
matiere_id=None, module_type=None, semestre_id=None, formation_id=None
|
||||||
|
):
|
||||||
|
"""Formulaire de création d'un module
|
||||||
|
Si matiere_id est spécifié, le module sera créé dans cette matière (cas normal).
|
||||||
|
Sinon, donne le choix de l'UE de rattachement et utilise la première
|
||||||
|
matière de cette UE (si elle n'existe pas, la crée).
|
||||||
|
"""
|
||||||
from app.scodoc import sco_formations
|
from app.scodoc import sco_formations
|
||||||
from app.scodoc import sco_edit_ue
|
from app.scodoc import sco_edit_ue
|
||||||
|
|
||||||
|
if matiere_id:
|
||||||
matiere = Matiere.query.get_or_404(matiere_id)
|
matiere = Matiere.query.get_or_404(matiere_id)
|
||||||
if matiere is None:
|
|
||||||
raise ScoValueError("invalid matiere !")
|
|
||||||
ue = matiere.ue
|
ue = matiere.ue
|
||||||
parcours = ue.formation.get_parcours()
|
formation = ue.formation
|
||||||
|
else:
|
||||||
|
formation = Formation.query.get_or_404(formation_id)
|
||||||
|
parcours = formation.get_parcours()
|
||||||
is_apc = parcours.APC_SAE
|
is_apc = parcours.APC_SAE
|
||||||
ues = ue.formation.ues.order_by(
|
ues = formation.ues.order_by(
|
||||||
UniteEns.semestre_idx, UniteEns.numero, UniteEns.acronyme
|
UniteEns.semestre_idx, UniteEns.numero, UniteEns.acronyme
|
||||||
).all()
|
).all()
|
||||||
# cherche le numero adéquat (pour placer le module en fin de liste)
|
# cherche le numero adéquat (pour placer le module en fin de liste)
|
||||||
modules = matiere.ue.formation.modules.all()
|
modules = formation.modules.all()
|
||||||
if modules:
|
if modules:
|
||||||
default_num = max([m.numero or 0 for m in modules]) + 10
|
default_num = max([m.numero or 0 for m in modules]) + 10
|
||||||
else:
|
else:
|
||||||
@ -143,9 +151,11 @@ def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
|||||||
H = [
|
H = [
|
||||||
html_sco_header.sco_header(page_title=f"Création {object_name}"),
|
html_sco_header.sco_header(page_title=f"Création {object_name}"),
|
||||||
]
|
]
|
||||||
if is_apc:
|
if not matiere_id:
|
||||||
H += [
|
H += [
|
||||||
f"""<h2>Création {object_name} dans la formation {ue.formation.acronyme}, Semestre {ue.semestre_idx}, {ue.acronyme}</h2>"""
|
f"""<h2>Création {object_name} dans la formation {formation.acronyme}
|
||||||
|
</h2>
|
||||||
|
"""
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
H += [
|
H += [
|
||||||
@ -158,7 +168,6 @@ def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
|||||||
render_template(
|
render_template(
|
||||||
"scodoc/help/modules.html",
|
"scodoc/help/modules.html",
|
||||||
is_apc=is_apc,
|
is_apc=is_apc,
|
||||||
ue=ue,
|
|
||||||
semestre_id=semestre_id,
|
semestre_id=semestre_id,
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
@ -170,7 +179,7 @@ def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
|||||||
"size": 10,
|
"size": 10,
|
||||||
"explanation": "code du module, ressource ou SAÉ. Exemple M1203, R2.01, ou SAÉ 3.4. Ce code doit être unique dans la formation.",
|
"explanation": "code du module, ressource ou SAÉ. Exemple M1203, R2.01, ou SAÉ 3.4. Ce code doit être unique dans la formation.",
|
||||||
"allow_null": False,
|
"allow_null": False,
|
||||||
"validator": lambda val, field, formation_id=ue.formation_id: check_module_code_unicity(
|
"validator": lambda val, field, formation_id=formation_id: check_module_code_unicity(
|
||||||
val, field, formation_id
|
val, field, formation_id
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -192,6 +201,15 @@ def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
|||||||
]
|
]
|
||||||
semestres_indices = list(range(1, parcours.NB_SEM + 1))
|
semestres_indices = list(range(1, parcours.NB_SEM + 1))
|
||||||
|
|
||||||
|
if is_apc:
|
||||||
|
module_types = scu.ModuleType # tous les types
|
||||||
|
else:
|
||||||
|
# ne propose pas SAE et Ressources:
|
||||||
|
module_types = set(scu.ModuleType) - {
|
||||||
|
scu.ModuleType.RESSOURCE,
|
||||||
|
scu.ModuleType.SAE,
|
||||||
|
}
|
||||||
|
|
||||||
descr += [
|
descr += [
|
||||||
(
|
(
|
||||||
"module_type",
|
"module_type",
|
||||||
@ -199,8 +217,8 @@ def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
|||||||
"input_type": "menu",
|
"input_type": "menu",
|
||||||
"title": "Type",
|
"title": "Type",
|
||||||
"explanation": "",
|
"explanation": "",
|
||||||
"labels": [x.name.capitalize() for x in scu.ModuleType],
|
"labels": [x.name.capitalize() for x in module_types],
|
||||||
"allowed_values": [str(int(x)) for x in scu.ModuleType],
|
"allowed_values": [str(int(x)) for x in module_types],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
@ -256,11 +274,30 @@ def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
|||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if matiere_id:
|
||||||
|
descr += [
|
||||||
|
("ue_id", {"default": ue.id, "input_type": "hidden"}),
|
||||||
|
("matiere_id", {"default": matiere_id, "input_type": "hidden"}),
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
# choix de l'UE de rattachement
|
||||||
|
descr += [
|
||||||
|
(
|
||||||
|
"ue_id",
|
||||||
|
{
|
||||||
|
"input_type": "menu",
|
||||||
|
"type": "int",
|
||||||
|
"title": "UE de rattachement",
|
||||||
|
"explanation": "utilisée notamment pour les malus",
|
||||||
|
"labels": [f"{u.acronyme} {u.titre}" for u in ues],
|
||||||
|
"allowed_values": [u.id for u in ues],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
descr += [
|
descr += [
|
||||||
# ('ects', { 'size' : 4, 'type' : 'float', 'title' : 'ECTS', 'explanation' : 'nombre de crédits ECTS (inutilisés: les crédits sont associés aux UE)' }),
|
# ('ects', { 'size' : 4, 'type' : 'float', 'title' : 'ECTS', 'explanation' : 'nombre de crédits ECTS (inutilisés: les crédits sont associés aux UE)' }),
|
||||||
("formation_id", {"default": ue.formation_id, "input_type": "hidden"}),
|
("formation_id", {"default": formation.id, "input_type": "hidden"}),
|
||||||
("ue_id", {"default": ue.id, "input_type": "hidden"}),
|
|
||||||
("matiere_id", {"default": matiere.id, "input_type": "hidden"}),
|
|
||||||
(
|
(
|
||||||
"code_apogee",
|
"code_apogee",
|
||||||
{
|
{
|
||||||
@ -290,6 +327,20 @@ def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + html_sco_header.sco_footer()
|
return "\n".join(H) + tf[1] + html_sco_header.sco_footer()
|
||||||
else:
|
else:
|
||||||
|
if not matiere_id:
|
||||||
|
# formulaire avec choix UE de rattachement
|
||||||
|
ue = UniteEns.query.get(tf[2]["ue_id"])
|
||||||
|
if ue is None:
|
||||||
|
raise ValueError("UE invalide")
|
||||||
|
matiere = ue.matieres.first()
|
||||||
|
if matiere:
|
||||||
|
tf[2]["matiere_id"] = matiere.id
|
||||||
|
else:
|
||||||
|
matiere_id = sco_edit_matiere.do_matiere_create(
|
||||||
|
{"ue_id": ue.id, "titre": ue.titre, "numero": 1},
|
||||||
|
)
|
||||||
|
tf[2]["matiere_id"] = matiere_id
|
||||||
|
|
||||||
tf[2]["semestre_id"] = ue.semestre_idx
|
tf[2]["semestre_id"] = ue.semestre_idx
|
||||||
|
|
||||||
_ = do_module_create(tf[2])
|
_ = do_module_create(tf[2])
|
||||||
@ -298,7 +349,7 @@ def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
|||||||
url_for(
|
url_for(
|
||||||
"notes.ue_table",
|
"notes.ue_table",
|
||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
formation_id=ue.formation_id,
|
formation_id=formation.id,
|
||||||
semestre_idx=tf[2]["semestre_id"],
|
semestre_idx=tf[2]["semestre_id"],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -493,6 +544,13 @@ def module_edit(module_id=None):
|
|||||||
soyez prudents !
|
soyez prudents !
|
||||||
</span></div>"""
|
</span></div>"""
|
||||||
)
|
)
|
||||||
|
if is_apc:
|
||||||
|
module_types = scu.ModuleType # tous les types
|
||||||
|
else:
|
||||||
|
# ne propose pas SAE et Ressources, sauf si déjà de ce type...
|
||||||
|
module_types = (
|
||||||
|
set(scu.ModuleType) - {scu.ModuleType.RESSOURCE, scu.ModuleType.SAE}
|
||||||
|
) | {a_module.module_type}
|
||||||
|
|
||||||
descr = [
|
descr = [
|
||||||
(
|
(
|
||||||
@ -514,8 +572,8 @@ def module_edit(module_id=None):
|
|||||||
"input_type": "menu",
|
"input_type": "menu",
|
||||||
"title": "Type",
|
"title": "Type",
|
||||||
"explanation": "",
|
"explanation": "",
|
||||||
"labels": [x.name.capitalize() for x in scu.ModuleType],
|
"labels": [x.name.capitalize() for x in module_types],
|
||||||
"allowed_values": [str(int(x)) for x in scu.ModuleType],
|
"allowed_values": [str(int(x)) for x in module_types],
|
||||||
"enabled": unlocked,
|
"enabled": unlocked,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -998,6 +998,7 @@ def _ue_table_matieres(
|
|||||||
H.append(
|
H.append(
|
||||||
_ue_table_modules(
|
_ue_table_modules(
|
||||||
parcours,
|
parcours,
|
||||||
|
ue,
|
||||||
mat,
|
mat,
|
||||||
modules,
|
modules,
|
||||||
editable,
|
editable,
|
||||||
@ -1031,6 +1032,7 @@ def _ue_table_matieres(
|
|||||||
|
|
||||||
def _ue_table_modules(
|
def _ue_table_modules(
|
||||||
parcours,
|
parcours,
|
||||||
|
ue,
|
||||||
mat,
|
mat,
|
||||||
modules,
|
modules,
|
||||||
editable,
|
editable,
|
||||||
@ -1121,8 +1123,12 @@ def _ue_table_modules(
|
|||||||
tag_cls,
|
tag_cls,
|
||||||
",".join(sco_tag_module.module_tag_list(mod["module_id"])),
|
",".join(sco_tag_module.module_tag_list(mod["module_id"])),
|
||||||
)
|
)
|
||||||
|
if ue["semestre_idx"] is not None and mod["semestre_id"] != ue["semestre_idx"]:
|
||||||
|
warning_semestre = ' <span class="red">incohérent ?</span>'
|
||||||
|
else:
|
||||||
|
warning_semestre = ""
|
||||||
H.append(
|
H.append(
|
||||||
" %s %s" % (parcours.SESSION_NAME, mod["semestre_id"])
|
" %s %s%s" % (parcours.SESSION_NAME, mod["semestre_id"], warning_semestre)
|
||||||
+ " (%s)" % heurescoef
|
+ " (%s)" % heurescoef
|
||||||
+ tag_edit
|
+ tag_edit
|
||||||
)
|
)
|
||||||
|
@ -546,7 +546,7 @@ def do_formsemestre_createwithmodules(edit=False):
|
|||||||
for mod in mods:
|
for mod in mods:
|
||||||
if mod["semestre_id"] == semestre_id and (
|
if mod["semestre_id"] == semestre_id and (
|
||||||
(not edit) # creation => tous modules
|
(not edit) # creation => tous modules
|
||||||
or (not formation.is_apc()) # pas BUT, on peux mixer les semestres
|
or (not formation.is_apc()) # pas BUT, on peut mixer les semestres
|
||||||
or (semestre_id == formsemestre.semestre_id) # module du semestre
|
or (semestre_id == formsemestre.semestre_id) # module du semestre
|
||||||
or (mod["module_id"] in module_ids_set) # module déjà présent
|
or (mod["module_id"] in module_ids_set) # module déjà présent
|
||||||
):
|
):
|
||||||
|
@ -219,7 +219,9 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
|
|||||||
page_title=f"{mod_type_name} {Mod['code']} {Mod['titre']}"
|
page_title=f"{mod_type_name} {Mod['code']} {Mod['titre']}"
|
||||||
),
|
),
|
||||||
f"""<h2 class="formsemestre">{mod_type_name}
|
f"""<h2 class="formsemestre">{mod_type_name}
|
||||||
<tt>{Mod['code']}</tt> {Mod['titre']}</h2>
|
<tt>{Mod['code']}</tt> {Mod['titre']}
|
||||||
|
{"dans l'UE " + modimpl.module.ue.acronyme if modimpl.module.module_type == scu.ModuleType.MALUS else ""}
|
||||||
|
</h2>
|
||||||
<div class="moduleimpl_tableaubord moduleimpl_type_{
|
<div class="moduleimpl_tableaubord moduleimpl_type_{
|
||||||
scu.ModuleType(Mod['module_type']).name.lower()}">
|
scu.ModuleType(Mod['module_type']).name.lower()}">
|
||||||
<table>
|
<table>
|
||||||
|
@ -71,13 +71,21 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% if editable and matiere_parent %}
|
{% if editable %}
|
||||||
<li><a class="stdlink" href="{{
|
<li><a class="stdlink" href=
|
||||||
|
{% if matiere_parent %}"{{
|
||||||
url_for("notes.module_create",
|
url_for("notes.module_create",
|
||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
module_type=module_type|int,
|
module_type=module_type|int,
|
||||||
matiere_id=matiere_parent.id
|
matiere_id=matiere_parent.id
|
||||||
)}}"
|
)}}"
|
||||||
|
{% else %}"{{
|
||||||
|
url_for("notes.module_create",
|
||||||
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
module_type=module_type|int,
|
||||||
|
formation_id=formation.id
|
||||||
|
)}}"
|
||||||
|
{% endif %}
|
||||||
>{{create_element_msg}}</a>
|
>{{create_element_msg}}</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
Loading…
Reference in New Issue
Block a user