diff --git a/app/comp/jury.py b/app/comp/jury.py index ef6bda11a..4869d1306 100644 --- a/app/comp/jury.py +++ b/app/comp/jury.py @@ -32,7 +32,7 @@ class ValidationsSemestre(ResultatsCache): { etudid : { 'code' : None|ATT|..., 'assidu' : 0|1 }}""" self.decisions_jury_ues = {} """Décisions sur des UEs dans ce semestre: - { etudid : { ue_id : { 'code' : Note|ADM|CMP, 'event_date' }}} + { etudid : { ue_id : { 'code' : Note|ADM|CMP, 'event_date': "d/m/y", "ects" : x}}} """ self.ue_capitalisees: pd.DataFrame = None """DataFrame, index etudid diff --git a/app/comp/res_common.py b/app/comp/res_common.py index f548be668..2eb32ac6e 100644 --- a/app/comp/res_common.py +++ b/app/comp/res_common.py @@ -177,7 +177,7 @@ class ResultatsSemestre(ResultatsCache): Rappel: l'étudiant est inscrit à des modimpls et non à des UEs. - En BUT: on considère que l'étudiant va (ou non) valider toutes les UEs des modules - du parcours. XXX notion à implémenter, pour l'instant toutes les UE du semestre. + du parcours. - En classique: toutes les UEs des modimpls auxquels l'étudiant est inscrit sont susceptibles d'être validées. @@ -185,24 +185,23 @@ class ResultatsSemestre(ResultatsCache): Les UE "bonus" (sport) ne sont jamais "validables". """ if self.is_apc: - # TODO: introduire la notion de parcours (#sco93) - return self.formsemestre.query_ues().filter(UniteEns.type != UE_SPORT).all() - else: - # restreint aux UE auxquelles l'étudiant est inscrit (dans l'un des modimpls) - ues = { - modimpl.module.ue - for modimpl in self.formsemestre.modimpls_sorted - if self.modimpl_inscr_df[modimpl.id][etudid] - } - ues = sorted(list(ues), key=lambda x: x.numero or 0) - return ues + return list(self.etud_ues(etudid)) + # Formations classiques: + # restreint aux UE auxquelles l'étudiant est inscrit (dans l'un des modimpls) + ues = { + modimpl.module.ue + for modimpl in self.formsemestre.modimpls_sorted + if self.modimpl_inscr_df[modimpl.id][etudid] + } + ues = sorted(list(ues), key=lambda x: x.numero or 0) + return ues def modimpls_in_ue(self, ue: UniteEns, etudid, with_bonus=True) -> list[ModuleImpl]: """Liste des modimpl de cette UE auxquels l'étudiant est inscrit. Utile en formations classiques, surchargée pour le BUT. Inclus modules bonus le cas échéant. """ - # sert pour l'affichage ou non de l'UE sur le bulletin + # Utilisée pour l'affichage ou non de l'UE sur le bulletin # Méthode surchargée en BUT modimpls = [ modimpl @@ -325,6 +324,8 @@ class ResultatsSemestre(ResultatsCache): "formsemestre_id": None, "capitalized_ue_id": None, "ects_pot": 0.0, + "ects": 0.0, + "ects_ue": ue.ects, } if not ue_id in self.etud_moy_ue: return None @@ -379,6 +380,12 @@ class ResultatsSemestre(ResultatsCache): "is_external": ue_cap["is_external"] if is_capitalized else ue.is_external, "coef_ue": coef_ue, "ects_pot": ue.ects or 0.0, + "ects": self.validations.decisions_jury_ues.get(etudid, {}) + .get(ue.id, {}) + .get("ects", 0.0) + if self.validations.decisions_jury_ues + else 0.0, + "ects_ue": ue.ects, "cur_moy_ue": cur_moy_ue, "moy": moy_ue, "event_date": ue_cap["event_date"] if is_capitalized else None, diff --git a/app/comp/res_compat.py b/app/comp/res_compat.py index 94493928b..99bda62f6 100644 --- a/app/comp/res_compat.py +++ b/app/comp/res_compat.py @@ -333,7 +333,7 @@ class NotesTableCompat(ResultatsSemestre): def get_etud_mod_moy(self, moduleimpl_id: int, etudid: int) -> float: """La moyenne de l'étudiant dans le moduleimpl En APC, il s'agira d'une moyenne indicative sans valeur. - Result: valeur float (peut être naN) ou chaîne "NI" (non inscrit ou DEM) + Result: valeur float (peut être NaN) ou chaîne "NI" (non inscrit ou DEM) """ raise NotImplementedError() # virtual method @@ -351,24 +351,25 @@ class NotesTableCompat(ResultatsSemestre): ects_pot : (float) nb de crédits ECTS qui seraient validés (sous réserve de validation par le jury) ects_pot_fond: (float) nb d'ECTS issus d'UE fondamentales (non électives) + ects_total: (float) total des ECTS validables - Ce sont les ECTS des UE au dessus de la barre (10/20 en principe), avant le jury (donc non - encore enregistrées). + Les ects_pot sont les ECTS des UE au dessus de la barre (10/20 en principe), + avant le jury (donc non encore enregistrés). """ # was nt.get_etud_moy_infos # XXX pour compat nt, à remplacer ultérieurement ues = self.get_etud_ue_validables(etudid) ects_pot = 0.0 + ects_total = 0.0 for ue in ues: - if ( - ue.id in self.etud_moy_ue - and ue.ects is not None - and self.etud_moy_ue[ue.id][etudid] > self.parcours.NOTES_BARRE_VALID_UE - ): - ects_pot += ue.ects + if ue.id in self.etud_moy_ue and ue.ects is not None: + ects_total += ue.ects + if self.etud_moy_ue[ue.id][etudid] > self.parcours.NOTES_BARRE_VALID_UE: + ects_pot += ue.ects return { "ects_pot": ects_pot, "ects_pot_fond": 0.0, # not implemented (anciennemment pour école ingé) + "ects_total": ects_total, } def get_evals_in_mod(self, moduleimpl_id: int) -> list[dict]: diff --git a/app/scodoc/sco_formsemestre_validation.py b/app/scodoc/sco_formsemestre_validation.py index cd1fc3591..cd21bd995 100644 --- a/app/scodoc/sco_formsemestre_validation.py +++ b/app/scodoc/sco_formsemestre_validation.py @@ -679,18 +679,12 @@ def formsemestre_recap_parcours_table( class_ue = "ue" if ue_status and ue_status["is_external"]: # validation externe explanation_ue.append("UE externe.") - # log('x'*12+' EXTERNAL %s' % notes_table.fmt_note(moy_ue)) XXXXXXX - # log('UE=%s' % pprint.pformat(ue)) - # log('explanation_ue=%s\n'%explanation_ue) + if ue_status and ue_status["is_capitalized"]: class_ue += " ue_capitalized" explanation_ue.append( "Capitalisée le %s." % (ue_status["event_date"] or "?") ) - # log('x'*12+' CAPITALIZED %s' % notes_table.fmt_note(moy_ue)) - # log('UE=%s' % pprint.pformat(ue)) - # log('UE_STATUS=%s' % pprint.pformat(ue_status)) XXXXXX - # log('') H.append( '%s' @@ -712,27 +706,30 @@ def formsemestre_recap_parcours_table( sco_preferences.get_preference("bul_show_ects", sem["formsemestre_id"]) or nt.parcours.ECTS_ONLY ): - etud_ects_infos = nt.get_etud_ects_pot(etudid) + etud_ects_infos = nt.get_etud_ects_pot(etudid) # ECTS potentiels H.append( - '' % (class_sem, sem["formsemestre_id"]) + f""" +   + """ ) + # Total ECTS (affiché sous la moyenne générale) H.append( - ' ' - % (bgcolor) + f"""ECTS: + {pv.get("sum_ects",0):2.2g} / {etud_ects_infos["ects_total"]:2.2g} + + """ ) - # total ECTS (affiché sous la moyenne générale) - H.append( - 'ECTS:%g' - % (etud_ects_infos["ects_pot"]) - ) - H.append('') # ECTS validables dans chaque UE for ue in ues: ue_status = nt.get_etud_ue_status(etudid, ue["ue_id"]) - H.append( - '%g' - % (ue_status["ects_pot"] if ue_status else "") - ) + if ue_status: + ects = ue_status["ects"] + ects_pot = ue_status["ects_pot"] + H.append( + f"""{ects:2.2g}""" + ) + else: + H.append(f"""""") H.append("") H.append("")