diff --git a/app/comp/moy_sem.py b/app/comp/moy_sem.py index db42616c8e..2b73b9df4a 100644 --- a/app/comp/moy_sem.py +++ b/app/comp/moy_sem.py @@ -30,7 +30,8 @@ import numpy as np import pandas as pd -from flask import flash +from flask import flash, g, Markup, url_for +from app.models.formations import Formation def compute_sem_moys_apc_using_coefs( @@ -51,7 +52,7 @@ def compute_sem_moys_apc_using_coefs( def compute_sem_moys_apc_using_ects( - etud_moy_ue_df: pd.DataFrame, ects: list, formation_id=None + etud_moy_ue_df: pd.DataFrame, ects: list, formation_id=None, skip_empty_ues=False ) -> pd.Series: """Calcule les moyennes générales indicatives de tous les étudiants = moyenne des moyennes d'UE, pondérée par leurs ECTS. @@ -59,13 +60,29 @@ def compute_sem_moys_apc_using_ects( etud_moy_ue_df: DataFrame, colonnes ue_id, lignes etudid ects: liste de floats ou None, 1 par UE + Si skip_empty_ues: ne compte pas les UE non notées. + Sinon (par défaut), une UE non notée compte comme zéro. + Result: panda Series, index etudid, valeur float (moyenne générale) """ try: - moy_gen = (etud_moy_ue_df * ects).sum(axis=1) / sum(ects) + if skip_empty_ues: + # annule les coefs des UE sans notes (NaN) + ects = np.where(etud_moy_ue_df.isna(), 0, np.array(ects)) + # ects est devenu nb_etuds x nb_ues + moy_gen = (etud_moy_ue_df * ects).sum(axis=1) / ects.sum(axis=1) + else: + moy_gen = (etud_moy_ue_df * ects).sum(axis=1) / sum(ects) except TypeError: if None in ects: - flash("""Calcul moyenne générale impossible: ECTS des UE manquants !""") + formation = Formation.query.get(formation_id) + flash( + Markup( + f"""Calcul moyenne générale impossible: ECTS des UE manquants !
+ (formation: {formation.get_titre_version()})""" + ) + ) moy_gen = pd.Series(np.NaN, index=etud_moy_ue_df.index) else: raise diff --git a/app/comp/res_but.py b/app/comp/res_but.py index 228c6506b3..3ffed67004 100644 --- a/app/comp/res_but.py +++ b/app/comp/res_but.py @@ -17,6 +17,7 @@ from app.comp.bonus_spo import BonusSport from app.models import ScoDocSiteConfig from app.models.moduleimpls import ModuleImpl from app.models.ues import UniteEns +from app.scodoc import sco_preferences from app.scodoc.sco_codes_parcours import UE_SPORT @@ -113,6 +114,9 @@ class ResultatsSemestreBUT(NotesTableCompat): self.etud_moy_ue, [ue.ects for ue in self.ues if ue.type != UE_SPORT], formation_id=self.formsemestre.formation_id, + skip_empty_ues=sco_preferences.get_preference( + "but_moy_skip_empty_ues", self.formsemestre.id + ), ) # --- UE capitalisées self.apply_capitalisation() diff --git a/app/models/formations.py b/app/models/formations.py index edd57097d0..c0f375ddc6 100644 --- a/app/models/formations.py +++ b/app/models/formations.py @@ -59,6 +59,10 @@ class Formation(db.Model): """get l'instance de TypeParcours de cette formation""" return sco_codes_parcours.get_parcours_from_code(self.type_parcours) + def get_titre_version(self) -> str: + """Titre avec version""" + return f"{self.acronyme} {self.titre} v{self.version}" + def is_apc(self): "True si formation APC avec SAE (BUT)" return self.get_parcours().APC_SAE diff --git a/app/scodoc/sco_preferences.py b/app/scodoc/sco_preferences.py index b320c164e5..ba2229dbab 100644 --- a/app/scodoc/sco_preferences.py +++ b/app/scodoc/sco_preferences.py @@ -358,8 +358,22 @@ class BasePreferences(object): "use_ue_coefs", { "initvalue": 0, - "title": "Utiliser les coefficients d'UE pour calculer la moyenne générale", - "explanation": """Calcule les moyennes dans chaque UE, puis pondère ces résultats pour obtenir la moyenne générale. Par défaut, le coefficient d'une UE est simplement la somme des coefficients des modules dans lesquels l'étudiant a des notes. Attention: changer ce réglage va modifier toutes les moyennes du semestre !""", + "title": "Utiliser les coefficients d'UE pour calculer la moyenne générale (hors BUT)", + "explanation": """Calcule les moyennes dans chaque UE, puis pondère ces résultats pour obtenir la moyenne générale. Par défaut, le coefficient d'une UE est simplement la somme des coefficients des modules dans lesquels l'étudiant a des notes. Attention: changer ce réglage va modifier toutes les moyennes du semestre !. Aucun effet en BUT.""", + "input_type": "boolcheckbox", + "category": "misc", + "labels": ["non", "oui"], + "only_global": False, + }, + ), + ( + "but_moy_skip_empty_ues", + { + "initvalue": 0, + "title": "BUT: moyenne générale sans les UE sans notes", + "explanation": """La moyenne générale indicative BUT est basée sur les moyennes d'UE pondérées par leurs ECTS. + Si cette option est cochée, ne prend pas en compte les UEs sans notes. Attention: changer ce réglage va modifier toutes + les moyennes du semestre !. Aucun effet dans les formations non BUT.""", "input_type": "boolcheckbox", "category": "misc", "labels": ["non", "oui"],