Merge branch 'refactor_nt' of https://scodoc.org/git/ScoDoc/ScoDoc into entreprises
This commit is contained in:
commit
e85149f4a6
@ -71,7 +71,7 @@ class BulletinBUT(ResultatsSemestreBUT):
|
||||
"bonus": fmt_note(self.bonus_ues[ue.id][etud.id])
|
||||
if self.bonus_ues is not None and ue.id in self.bonus_ues
|
||||
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
|
||||
"ressources": self.etud_ue_mod_results(etud, ue, self.ressources),
|
||||
"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)
|
||||
# ou (nb_etuds, nb_mod_sport, nb_ues_non_bonus)
|
||||
nb_etuds, nb_mod_sport = sem_modimpl_moys_spo.shape[:2]
|
||||
nb_ues = len(ues)
|
||||
# Enlève les NaN du numérateur:
|
||||
sem_modimpl_moys_no_nan = np.nan_to_num(sem_modimpl_moys_spo, nan=0.0)
|
||||
|
||||
@ -124,7 +123,7 @@ class BonusSport:
|
||||
# Annule les coefs des modules où l'étudiant n'est pas inscrit:
|
||||
modimpl_coefs_etuds = np.where(
|
||||
modimpl_inscr_spo_stacked,
|
||||
np.stack([modimpl_coefs_spo.T] * nb_etuds),
|
||||
np.stack([modimpl_coefs_spo] * nb_etuds),
|
||||
0.0,
|
||||
)
|
||||
else:
|
||||
@ -162,7 +161,7 @@ class BonusSport:
|
||||
"""
|
||||
raise NotImplementedError("méthode virtuelle")
|
||||
|
||||
def get_bonus_ues(self) -> pd.Series:
|
||||
def get_bonus_ues(self) -> pd.DataFrame:
|
||||
"""Les bonus à appliquer aux UE
|
||||
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_exceptions import ScoValueError
|
||||
|
||||
from app.scodoc.sco_utils import ModuleType
|
||||
|
||||
|
||||
@dataclass
|
||||
class EvaluationEtat:
|
||||
@ -233,6 +235,8 @@ class ModuleImplResultsAPC(ModuleImplResults):
|
||||
assert evals_poids_df.shape[0] == nb_evals # compat notes/poids
|
||||
if nb_etuds == 0:
|
||||
return pd.DataFrame(index=[], columns=evals_poids_df.columns)
|
||||
if nb_ues == 0:
|
||||
return pd.DataFrame(index=self.evals_notes.index, columns=[])
|
||||
evals_coefs = self.get_evaluations_coefs(moduleimpl)
|
||||
evals_poids = evals_poids_df.values * evals_coefs
|
||||
# -> evals_poids shape : (nb_evals, nb_ues)
|
||||
@ -289,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...
|
||||
|
||||
# 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():
|
||||
ue_coefs = modimpl.module.get_ue_coef_dict()
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
"""Fonctions de calcul des moyennes d'UE (classiques ou BUT)
|
||||
"""
|
||||
from re import X
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
@ -263,6 +264,7 @@ def compute_ue_moys_apc(
|
||||
#
|
||||
# Version vectorisée
|
||||
#
|
||||
with np.errstate(invalid="ignore"): # ignore les 0/0 (-> NaN)
|
||||
etud_moy_ue = np.sum(
|
||||
modimpl_coefs_etuds_no_nan * sem_cube_inscrits, axis=1
|
||||
) / np.sum(modimpl_coefs_etuds_no_nan, axis=1)
|
||||
@ -379,3 +381,42 @@ def compute_ue_moys_classic(
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
# --- 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
|
||||
if len(modimpls_sport) > 0:
|
||||
bonus_class = ScoDocSiteConfig.get_bonus_sport_class()
|
||||
|
@ -71,6 +71,16 @@ class ResultatsSemestreClassic(NotesTableCompat):
|
||||
self.modimpl_coefs,
|
||||
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_class = ScoDocSiteConfig.get_bonus_sport_class()
|
||||
if bonus_class is not None:
|
||||
|
@ -70,7 +70,7 @@ class CodesDecisionsForm(FlaskForm):
|
||||
ATT = _build_code_field("ATT")
|
||||
CMP = _build_code_field("CMP")
|
||||
DEF = _build_code_field("DEF")
|
||||
DEM = _build_code_field("DEF")
|
||||
DEM = _build_code_field("DEM")
|
||||
NAR = _build_code_field("NAR")
|
||||
RAT = _build_code_field("RAT")
|
||||
submit = SubmitField("Valider")
|
||||
|
@ -178,7 +178,7 @@ class ScoDocSiteConfig(db.Model):
|
||||
return getattr(bonus_sport, func_name)
|
||||
except AttributeError:
|
||||
raise ScoValueError(
|
||||
f"""Fonction de calcul maison inexistante: {func_name}.
|
||||
f"""Fonction de calcul de l'UE bonus inexistante: "{func_name}".
|
||||
(contacter votre administrateur local)."""
|
||||
)
|
||||
|
||||
|
@ -276,14 +276,24 @@ class TF(object):
|
||||
)
|
||||
ok = 0
|
||||
if typ[:3] == "int" or typ == "float" or typ == "real":
|
||||
if "min_value" in descr and val < descr["min_value"]:
|
||||
if (
|
||||
val != ""
|
||||
and val != None
|
||||
and "min_value" in descr
|
||||
and val < descr["min_value"]
|
||||
):
|
||||
msg.append(
|
||||
"La valeur (%d) du champ '%s' est trop petite (min=%s)"
|
||||
% (val, field, descr["min_value"])
|
||||
)
|
||||
ok = 0
|
||||
|
||||
if "max_value" in descr and val > descr["max_value"]:
|
||||
if (
|
||||
val != ""
|
||||
and val != None
|
||||
and "max_value" in descr
|
||||
and val > descr["max_value"]
|
||||
):
|
||||
msg.append(
|
||||
"La valeur (%s) du champ '%s' est trop grande (max=%s)"
|
||||
% (val, field, descr["max_value"])
|
||||
|
@ -456,6 +456,11 @@ def bonus_iutbeziers(notes_sport, coefs, infos=None):
|
||||
return bonus
|
||||
|
||||
|
||||
def bonus_iutlemans(notes_sport, coefs, infos=None):
|
||||
"fake: formule inutilisée en ScoDoc 9.2 mais doiut être présente"
|
||||
return 0.0
|
||||
|
||||
|
||||
def bonus_iutlr(notes_sport, coefs, infos=None):
|
||||
"""Calcul bonus modules optionels (sport, culture), règle IUT La Rochelle
|
||||
Si la note de sport est comprise entre 0 et 10 : pas d'ajout de point
|
||||
|
@ -125,8 +125,8 @@ APO_NEWLINE = "\r\n"
|
||||
|
||||
def _apo_fmt_note(note):
|
||||
"Formatte une note pour Apogée (séparateur décimal: ',')"
|
||||
if not note and isinstance(note, float):
|
||||
return ""
|
||||
# if not note and isinstance(note, float): changé le 31/1/2022, étrange ?
|
||||
# return ""
|
||||
try:
|
||||
val = float(note)
|
||||
except ValueError:
|
||||
|
@ -141,7 +141,7 @@ BUG = "BUG"
|
||||
|
||||
ALL = "ALL"
|
||||
|
||||
# Explication des codes (de demestre ou d'UE)
|
||||
# Explication des codes (de semestre ou d'UE)
|
||||
CODES_EXPL = {
|
||||
ADC: "Validé par compensation",
|
||||
ADJ: "Validé par le Jury",
|
||||
@ -154,6 +154,7 @@ CODES_EXPL = {
|
||||
DEF: "Défaillant",
|
||||
NAR: "Échec, non autorisé à redoubler",
|
||||
RAT: "En attente d'un rattrapage",
|
||||
DEM: "Démission",
|
||||
}
|
||||
# Nota: ces explications sont personnalisables via le fichier
|
||||
# de config locale /opt/scodoc/var/scodoc/config/scodoc_local.py
|
||||
|
@ -115,22 +115,30 @@ def do_module_create(args) -> int:
|
||||
return r
|
||||
|
||||
|
||||
def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
||||
"""Création d'un module"""
|
||||
def module_create(
|
||||
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_edit_ue
|
||||
|
||||
if matiere_id:
|
||||
matiere = Matiere.query.get_or_404(matiere_id)
|
||||
if matiere is None:
|
||||
raise ScoValueError("invalid matiere !")
|
||||
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
|
||||
ues = ue.formation.ues.order_by(
|
||||
ues = formation.ues.order_by(
|
||||
UniteEns.semestre_idx, UniteEns.numero, UniteEns.acronyme
|
||||
).all()
|
||||
# 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:
|
||||
default_num = max([m.numero or 0 for m in modules]) + 10
|
||||
else:
|
||||
@ -143,9 +151,11 @@ def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
||||
H = [
|
||||
html_sco_header.sco_header(page_title=f"Création {object_name}"),
|
||||
]
|
||||
if is_apc:
|
||||
if not matiere_id:
|
||||
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:
|
||||
H += [
|
||||
@ -158,7 +168,6 @@ def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
||||
render_template(
|
||||
"scodoc/help/modules.html",
|
||||
is_apc=is_apc,
|
||||
ue=ue,
|
||||
semestre_id=semestre_id,
|
||||
)
|
||||
]
|
||||
@ -170,7 +179,7 @@ def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
||||
"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.",
|
||||
"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
|
||||
),
|
||||
},
|
||||
@ -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))
|
||||
|
||||
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 += [
|
||||
(
|
||||
"module_type",
|
||||
@ -199,8 +217,8 @@ def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
||||
"input_type": "menu",
|
||||
"title": "Type",
|
||||
"explanation": "",
|
||||
"labels": [x.name.capitalize() for x in scu.ModuleType],
|
||||
"allowed_values": [str(int(x)) for x in scu.ModuleType],
|
||||
"labels": [x.name.capitalize() for x in module_types],
|
||||
"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 += [
|
||||
# ('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"}),
|
||||
("ue_id", {"default": ue.id, "input_type": "hidden"}),
|
||||
("matiere_id", {"default": matiere.id, "input_type": "hidden"}),
|
||||
("formation_id", {"default": formation.id, "input_type": "hidden"}),
|
||||
(
|
||||
"code_apogee",
|
||||
{
|
||||
@ -290,6 +327,20 @@ def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
||||
if tf[0] == 0:
|
||||
return "\n".join(H) + tf[1] + html_sco_header.sco_footer()
|
||||
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
|
||||
|
||||
_ = do_module_create(tf[2])
|
||||
@ -298,7 +349,7 @@ def module_create(matiere_id=None, module_type=None, semestre_id=None):
|
||||
url_for(
|
||||
"notes.ue_table",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formation_id=ue.formation_id,
|
||||
formation_id=formation.id,
|
||||
semestre_idx=tf[2]["semestre_id"],
|
||||
)
|
||||
)
|
||||
@ -493,6 +544,13 @@ def module_edit(module_id=None):
|
||||
soyez prudents !
|
||||
</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 = [
|
||||
(
|
||||
@ -514,8 +572,8 @@ def module_edit(module_id=None):
|
||||
"input_type": "menu",
|
||||
"title": "Type",
|
||||
"explanation": "",
|
||||
"labels": [x.name.capitalize() for x in scu.ModuleType],
|
||||
"allowed_values": [str(int(x)) for x in scu.ModuleType],
|
||||
"labels": [x.name.capitalize() for x in module_types],
|
||||
"allowed_values": [str(int(x)) for x in module_types],
|
||||
"enabled": unlocked,
|
||||
},
|
||||
),
|
||||
|
@ -998,6 +998,7 @@ def _ue_table_matieres(
|
||||
H.append(
|
||||
_ue_table_modules(
|
||||
parcours,
|
||||
ue,
|
||||
mat,
|
||||
modules,
|
||||
editable,
|
||||
@ -1031,6 +1032,7 @@ def _ue_table_matieres(
|
||||
|
||||
def _ue_table_modules(
|
||||
parcours,
|
||||
ue,
|
||||
mat,
|
||||
modules,
|
||||
editable,
|
||||
@ -1121,8 +1123,12 @@ def _ue_table_modules(
|
||||
tag_cls,
|
||||
",".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(
|
||||
" %s %s" % (parcours.SESSION_NAME, mod["semestre_id"])
|
||||
" %s %s%s" % (parcours.SESSION_NAME, mod["semestre_id"], warning_semestre)
|
||||
+ " (%s)" % heurescoef
|
||||
+ tag_edit
|
||||
)
|
||||
|
@ -546,7 +546,7 @@ def do_formsemestre_createwithmodules(edit=False):
|
||||
for mod in mods:
|
||||
if mod["semestre_id"] == semestre_id and (
|
||||
(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 (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']}"
|
||||
),
|
||||
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_{
|
||||
scu.ModuleType(Mod['module_type']).name.lower()}">
|
||||
<table>
|
||||
|
@ -71,13 +71,21 @@
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
||||
{% if editable and matiere_parent %}
|
||||
<li><a class="stdlink" href="{{
|
||||
{% if editable %}
|
||||
<li><a class="stdlink" href=
|
||||
{% if matiere_parent %}"{{
|
||||
url_for("notes.module_create",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
module_type=module_type|int,
|
||||
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>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
@ -191,7 +191,7 @@ def get_etud_dept():
|
||||
# le choix a peu d'importance...
|
||||
last_etud = etuds[-1]
|
||||
|
||||
return Departement.query.get(last_etud.dept_id).acronym
|
||||
return Departement.query.get_or_404(last_etud.dept_id).acronym
|
||||
|
||||
|
||||
# Bricolage pour le portail IUTV avec ScoDoc 7: (DEPRECATED: NE PAS UTILISER !)
|
||||
|
@ -149,7 +149,7 @@ def user_info(user_name, format="json"):
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoUsersAdmin)
|
||||
@scodoc7func
|
||||
def create_user_form(user_name=None, edit=0, all_roles=1):
|
||||
def create_user_form(user_name=None, edit=0, all_roles=False):
|
||||
"form. création ou édition utilisateur"
|
||||
if user_name is not None: # scodoc7func converti en int !
|
||||
user_name = str(user_name)
|
||||
@ -218,9 +218,11 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
|
||||
}
|
||||
if current_user.is_administrator():
|
||||
editable_roles_set |= {
|
||||
(Role.get_named_role(r), "")
|
||||
(Role.get_named_role(r), None)
|
||||
for r in sco_roles_default.ROLES_ATTRIBUABLES_SCODOC
|
||||
}
|
||||
# Un super-admin peut nommer d'autres super-admin:
|
||||
editable_roles_set |= {(Role.get_named_role("SuperAdmin"), None)}
|
||||
#
|
||||
if not edit:
|
||||
submitlabel = "Créer utilisateur"
|
||||
@ -251,16 +253,23 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
|
||||
orig_roles_strings = {r.name + "_" + (dept or "") for (r, dept) in orig_roles}
|
||||
# add existing user roles
|
||||
displayed_roles = list(editable_roles_set.union(orig_roles))
|
||||
displayed_roles.sort(key=lambda x: (x[1] or "", x[0].name or ""))
|
||||
displayed_roles.sort(
|
||||
key=lambda x: (
|
||||
x[1] or "",
|
||||
(x[0].name or "") if x[0].name != "SuperAdmin" else "A",
|
||||
)
|
||||
)
|
||||
displayed_roles_strings = [
|
||||
r.name + "_" + (dept or "") for (r, dept) in displayed_roles
|
||||
]
|
||||
displayed_roles_labels = [f"{dept}: {r.name}" for (r, dept) in displayed_roles]
|
||||
displayed_roles_labels = [
|
||||
f"{dept or '<em>tout dépt.</em>'}: {r.name}" for (r, dept) in displayed_roles
|
||||
]
|
||||
disabled_roles = {} # pour désactiver les roles que l'on ne peut pas éditer
|
||||
for i in range(len(displayed_roles_strings)):
|
||||
if displayed_roles_strings[i] not in editable_roles_strings:
|
||||
disabled_roles[i] = True
|
||||
|
||||
breakpoint()
|
||||
descr = [
|
||||
("edit", {"input_type": "hidden", "default": edit}),
|
||||
("nom", {"title": "Nom", "size": 20, "allow_null": False}),
|
||||
|
Loading…
Reference in New Issue
Block a user