diff --git a/app/forms/pe/pe_sem_recap.py b/app/forms/pe/pe_sem_recap.py index de2dbfd50a663af34a195498cf3f8b5a9108b3d6..ae86cab485c19b0064879441fda6adac73b8f4b0 100644 --- a/app/forms/pe/pe_sem_recap.py +++ b/app/forms/pe/pe_sem_recap.py @@ -27,7 +27,7 @@ Formulaire options génération table poursuite études (PE) """ from flask_wtf import FlaskForm -from wtforms import BooleanField, HiddenField, SubmitField +from wtforms import BooleanField, SubmitField class ParametrageClasseurPE(FlaskForm): @@ -61,5 +61,6 @@ class ParametrageClasseurPE(FlaskForm): # default=False, # render_kw={"checked": ""}, ) + assiduite = BooleanField("Inclure les comptes d'absences non justifiées") submit = SubmitField("Générer les classeurs poursuites d'études") cancel = SubmitField("Annuler", render_kw={"formnovalidate": True}) diff --git a/app/pe/pe_etudiant.py b/app/pe/pe_etudiant.py index 693f04d61ff63ef28fa6c202c91d348c55655770..4218d174f48c89721850b79b794ba5e6b1dfc413 100644 --- a/app/pe/pe_etudiant.py +++ b/app/pe/pe_etudiant.py @@ -49,11 +49,13 @@ from app.comp.res_sem import load_formsemestre_results class EtudiantsJuryPE: """Classe centralisant la gestion des étudiants à prendre en compte dans un jury de PE""" - def __init__(self, annee_diplome: int): + def __init__(self, annee_diplome: int, options: dict | None = None): """ Args: annee_diplome: L'année de diplomation """ + self.options = options or {} + "Options de configuration (cf. pe_sem_recap)" self.annee_diplome = annee_diplome """L'année du diplôme""" @@ -388,6 +390,10 @@ class EtudiantsJuryPE: # Ajout des noms de semestres parcourus etapes = etapes_du_cursus(formsemestres, nbre_semestres_max) administratif[etudid] |= etapes + if self.options["assiduite"]: + # Colonnes avec absences non jutifiées + abs_dict = absences_du_cursus(etudiant, formsemestres) + administratif[etudid] |= abs_dict # Construction du dataframe df = pd.DataFrame.from_dict(administratif, orient="index") @@ -586,9 +592,22 @@ def arret_de_formation(etud: Identite, cosemestres: dict[int, FormSemestre]) -> return est_demissionnaire +def absences_du_cursus( + etud: Identite, semestres: dict[int, FormSemestre] +) -> dict[str, int]: + """Ajoute les absences non just. de chaque formsemestre du cursus + de cet étudiant. + """ + abs_dict = {} + for i, formsemestre in enumerate(reversed(semestres.values()), start=1): + nbabsnj, nbabsjust, nbabs = formsemestre.get_abs_count(etud.id) + abs_dict[f"Etape {i+1}_ABS"] = nbabsnj + return abs_dict + + def etapes_du_cursus( semestres: dict[int, FormSemestre], nbre_etapes_max: int -) -> list[str]: +) -> dict[str, str]: """Partant d'un dictionnaire de semestres (qui retrace la scolarité d'un étudiant), liste les noms des semestres (en version abbrégée) @@ -598,15 +617,15 @@ def etapes_du_cursus( avec i variant jusqu'à nbre_semestres_max. (S'il n'y a pas de semestre à l'étape i, le nom affiché est vide. - La fonction suppose la liste des semestres triées par ordre + La fonction suppose la items du dict des semestres sont triés par ordre décroissant de date. Args: - semestres: une liste de ``FormSemestre`` + semestres: un dict formsemestre_id : ``FormSemestre`` nbre_etapes_max: le nombre d'étapes max prise en compte Returns: - Une liste de nom de semestre (dans le même ordre que les ``semestres``) + Une liste de noms de semestre (dans le même ordre que les ``semestres``) See also: app.pe.pe_affichage.nom_semestre_etape @@ -626,11 +645,12 @@ def nom_semestre_etape(semestre: FormSemestre, avec_fid=False) -> str: """Nom d'un semestre à afficher dans le descriptif des étapes de la scolarité d'un étudiant. - Par ex: Pour un S2, affiche ``"Semestre 2 FI S014-2015 (129)"`` avec : + Par ex: Pour un S2, affiche ``"Semestre 2 FI S014-2015"`` avec : * 2 le numéro du semestre, * FI la modalité, * 2014-2015 les dates + Si avec_fid, ajoute le fid du semestre (debug). Args: semestre: Un ``FormSemestre`` diff --git a/app/pe/pe_jury.py b/app/pe/pe_jury.py index 103c8919a1e624c0c673550cfb8eaecc09bb0f72..f060fdb4c18d961b747bbd8b33fbd070e694146c 100644 --- a/app/pe/pe_jury.py +++ b/app/pe/pe_jury.py @@ -90,18 +90,20 @@ class JuryPE(object): diplome : l'année d'obtention du diplome BUT et du jury de PE (généralement février XXXX) """ - def __init__( - self, - diplome: int, - formsemestre_id_base, - options={ - "moyennes_tags": True, - "moyennes_ue_res_sae": True, - "moyennes_ues_rcues": True, - "min_max_moy": False, - "publipostage": False, - }, - ): + _default_options = { + "moyennes_tags": True, + "moyennes_ue_res_sae": True, + "moyennes_ues_rcues": True, + "min_max_moy": False, + "publipostage": False, + "assiduite": False, + } + + def __init__(self, diplome: int, formsemestre_id_base, options: dict | None = None): + options = options or {} + for k, y in self._default_options.items(): + if k not in options: + options[k] = v pe_affichage.pe_start_log() self.diplome = diplome "L'année du diplome" @@ -123,21 +125,22 @@ class JuryPE(object): pe_affichage.pe_print("Options", info=True) for cle, val in self.options.items(): - pe_affichage.pe_print(f" > {cle} -> {val}", info=True) + if cle != "csrf_token": + pe_affichage.pe_print(f" > {cle} -> {val}", info=True) # Chargement des étudiants à prendre en compte dans le jury pe_affichage.pe_print( - f"""***********************************************************""" + """***********************************************************""" ) pe_affichage.pe_print( f"""*** Recherche des étudiants diplômés 🎓 en {self.diplome}""", info=True ) pe_affichage.pe_print( - f"""***********************************************************""" + """***********************************************************""" ) # Les infos sur les étudiants - self.etudiants = pe_etudiant.EtudiantsJuryPE(self.diplome) + self.etudiants = pe_etudiant.EtudiantsJuryPE(self.diplome, self.options) """Les informations sur les étudiants du jury PE""" self.etudiants.find_etudiants() self.diplomes_ids = self.etudiants.diplomes_ids diff --git a/app/pe/pe_view.py b/app/pe/pe_view.py index 2add21ba89d5b474bcc8f6f7856b0d46e2d05026..6aebfa28852e2e205873b2e4ac9b94d3361ff4e4 100644 --- a/app/pe/pe_view.py +++ b/app/pe/pe_view.py @@ -90,6 +90,7 @@ def pe_view_sem_recap(formsemestre_id: int): sco=ScoData(formsemestre=formsemestre), cosemestres=affichage_cosemestres_tries, rangs_tries=sorted(affichage_cosemestres_tries.keys()), + title="Avis de poursuite d'étude", ) # request.method == "POST"