From bf77b9112fa633ac8b4bdcbe213fc69acae28c33 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Fri, 5 Jul 2024 14:12:00 +0200 Subject: [PATCH] Ajoute ECTS acquis sur TableJury et cursus_etud BUT --- app/but/cursus_but.py | 8 ++++++-- app/comp/res_compat.py | 6 +++--- app/models/but_validations.py | 9 +++++---- app/tables/jury_recap.py | 21 ++++++++++++++++++++- app/tables/recap.py | 2 +- app/templates/but/cursus_etud.j2 | 2 +- sco_version.py | 2 +- 7 files changed, 37 insertions(+), 13 deletions(-) diff --git a/app/but/cursus_but.py b/app/but/cursus_but.py index 455355450..83b921fbb 100644 --- a/app/but/cursus_but.py +++ b/app/but/cursus_but.py @@ -207,6 +207,10 @@ class EtudCursusBUT: # slow, utile pour affichage fiche return annee in [n.annee for n in self.competences[competence_id].niveaux] + def get_ects_acquis(self) -> int: + "Nombre d'ECTS validés par etud dans le BUT de ce référentiel" + return but_ects_valides(self.etud, self.formation.referentiel_competence.id) + def load_validation_by_niveau(self) -> dict[int, list[ApcValidationRCUE]]: """Cherche les validations de jury enregistrées pour chaque niveau Résultat: { niveau_id : [ ApcValidationRCUE ] } @@ -378,7 +382,7 @@ class FormSemestreCursusBUT: # "cache { competence_id : competence }" -def but_ects_valides(etud: Identite, referentiel_competence_id: int) -> float: +def but_ects_valides(etud: Identite, referentiel_competence_id: int) -> int: """Nombre d'ECTS validés par etud dans le BUT de référentiel indiqué. Ne prend que les UE associées à des niveaux de compétences, et ne les compte qu'une fois même en cas de redoublement avec re-validation. @@ -398,7 +402,7 @@ def but_ects_valides(etud: Identite, referentiel_competence_id: int) -> float: if v.code in CODES_UE_VALIDES: ects_dict[key] = v.ue.ects - return sum(ects_dict.values()) if ects_dict else 0.0 + return int(sum(ects_dict.values())) if ects_dict else 0 def etud_ues_de_but1_non_validees( diff --git a/app/comp/res_compat.py b/app/comp/res_compat.py index 765be90c1..0b11c06ba 100644 --- a/app/comp/res_compat.py +++ b/app/comp/res_compat.py @@ -322,7 +322,7 @@ class NotesTableCompat(ResultatsSemestre): validations = self.get_formsemestre_validations() return validations.decisions_jury_ues.get(etudid, None) - def get_etud_ects_valides(self, etudid: int, decisions_ues: dict = False) -> 0: + def get_etud_ects_valides(self, etudid: int, decisions_ues: dict = False) -> int: """Le total des ECTS validés (et enregistrés) par l'étudiant dans ce semestre. NB: avant jury, rien d'enregistré, donc zéro ECTS. Optimisation: si decisions_ues est passé, l'utilise, sinon appelle get_etud_decisions_ue() @@ -330,8 +330,8 @@ class NotesTableCompat(ResultatsSemestre): if decisions_ues is False: decisions_ues = self.get_etud_decisions_ue(etudid) if not decisions_ues: - return 0.0 - return sum([d.get("ects", 0.0) for d in decisions_ues.values()]) + return 0 + return int(sum(d.get("ects", 0) for d in decisions_ues.values())) def get_etud_decision_sem(self, etudid: int) -> dict: """Decision du jury semestre prise pour cet etudiant, ou None s'il n'y en pas eu. diff --git a/app/models/but_validations.py b/app/models/but_validations.py index d6eb9d87c..e2e8692ce 100644 --- a/app/models/but_validations.py +++ b/app/models/but_validations.py @@ -247,10 +247,11 @@ def _build_decisions_rcue_list(decisions_rcue: dict) -> list[str]: # où validation est {'code': 'CMP', 'niveau': {'annee': 'BUT3', 'competence': {}, ... } validation_by_competence = defaultdict(list) for validation in decisions_rcue: - competence_id = ( - validation.get("niveau", {}).get("competence", {}).get("id_orebut") - ) - validation_by_competence[competence_id].append(validation) + if validation: + competence_id = ( + validation.get("niveau", {}).get("competence", {}).get("id_orebut") + ) + validation_by_competence[competence_id].append(validation) # Tri des listes de validation par numéro de compétence validations_niveaux = sorted( validation_by_competence.values(), diff --git a/app/tables/jury_recap.py b/app/tables/jury_recap.py index 96933a210..2cb25ede4 100644 --- a/app/tables/jury_recap.py +++ b/app/tables/jury_recap.py @@ -8,9 +8,11 @@ """ import collections +import time import numpy as np from flask import g, url_for +from app import log from app.but import cursus_but from app.but import jury_but from app.but.jury_but import DecisionsProposeesRCUE @@ -33,10 +35,12 @@ class TableJury(TableRecap): - les RCUEs (moyenne et code décision) Pour toutes les formations: - les codes de décisions jury sur les UEs + - les ECTS acquis dans le parcours - le lien de saisie ou modif de la décision de jury """ def __init__(self, *args, row_class: str = None, read_only=True, **kwargs): + t0 = time.time() super().__init__( *args, row_class=row_class or RowJury, finalize=False, **kwargs ) @@ -55,6 +59,7 @@ class TableJury(TableRecap): self.add_groups_header() # Termine la table self.finalize() + log(f"Built TableJury for {self.res.formsemestre} in {time.time() - t0}s") def add_rcues(self): """Ajoute les colonnes indiquant le nb de RCUEs et chaque RCUE @@ -75,7 +80,7 @@ class TableJury(TableRecap): self.freq_codes_annuels["total"] = len(self.rows) def add_jury(self): - """Ajoute la colonne code jury et le lien. + """Ajoute la colonne code jury, ECTS et le lien. - Le code jury est celui du semestre: cette colonne n'est montrée que pour les formations classiques, ce code n'est pas utilisé en BUT. - En BUT, on donne la décision de jury annuelle. @@ -138,6 +143,20 @@ class TableJury(TableRecap): group="jury_code_sem", classes=["recorded_code"], ) + # ECTS acquis en BUT + if res.formsemestre.formation.referentiel_competence_id: + row.add_cell( + "ects_acquis", + "ECTS", + # res.get_etud_ects_valides(etud.id), + # cette recherche augmente de 10% le temps de contsruction de la table + cursus_but.but_ects_valides( + etud, res.formsemestre.formation.referentiel_competence_id + ), + group="jury_code_sem", + classes=["recorded_code"], + target_attrs={"title": "crédits validés en BUT"}, + ) # Lien saisie ou visu jury a_saisir = (not res.validations) or (not res.validations.has_decision(etud)) row.add_cell( diff --git a/app/tables/recap.py b/app/tables/recap.py index e32ceb0b3..f66ddddf6 100644 --- a/app/tables/recap.py +++ b/app/tables/recap.py @@ -661,7 +661,7 @@ class RowRecap(tb.Row): # Ajoute bulle sur titre du pied de table: cell = table.foot_title_row.cells.get("moy_gen") if cell: - table.foot_title_row.cells["moy_gen"].target_attrs["title"] = ( + cell.target_attrs["title"] = ( "Moyenne générale indicative" if res.is_apc else "Moyenne générale du semestre" diff --git a/app/templates/but/cursus_etud.j2 b/app/templates/but/cursus_etud.j2 index 16361ee61..0a0782d6d 100644 --- a/app/templates/but/cursus_etud.j2 +++ b/app/templates/but/cursus_etud.j2 @@ -1,7 +1,7 @@ {# Affichage cursus BUT fiche étudiant #}
-
+
{{cursus.get_ects_acquis()}} ECTS
BUT 1
BUT 2
BUT 3
diff --git a/sco_version.py b/sco_version.py index a811341d6..5a56a8eda 100644 --- a/sco_version.py +++ b/sco_version.py @@ -1,7 +1,7 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "9.6.987" +SCOVERSION = "9.6.988" SCONAME = "ScoDoc"