From 17d9b8daa99a4108f135adc80c1240576ee2890a Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Thu, 22 Aug 2024 18:07:38 +0200 Subject: [PATCH] =?UTF-8?q?BUT:=20Ajout=20warning=20si=20niveau=20comp.=20?= =?UTF-8?q?associ=C3=A9=20=C3=A0=20plusieurs=20UEs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/but/cursus_but.py | 23 +++++++++++++++-------- app/static/css/parcour_formation.css | 12 +++++++++++- app/templates/but/parcour_formation.j2 | 3 +++ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/app/but/cursus_but.py b/app/but/cursus_but.py index f3c19925e..7d8243ff5 100644 --- a/app/but/cursus_but.py +++ b/app/but/cursus_but.py @@ -632,17 +632,22 @@ def formation_semestre_niveaux_warning(formation: Formation, semestre_idx: int) def ue_associee_au_niveau_du_parcours( ues_possibles: list[UniteEns], niveau: ApcNiveau, sem_name: str = "S" -) -> UniteEns: - "L'UE associée à ce niveau, ou None" +) -> tuple[UniteEns, str]: + """L'UE associée à ce niveau, ou None. + Renvoie aussi un message d'avertissement en cas d'associations multiples + (en principe un niveau ne doit être associé qu'à une seule UE) + """ ues = [ue for ue in ues_possibles if ue.niveau_competence_id == niveau.id] + msg = "" if len(ues) > 1: + msg = f"""{' et '.join(ue.acronyme for ue in ues)} associées au niveau {niveau} / {sem_name}. Utilisez le cas échéant l'item "Déassocier".""" # plusieurs UEs associées à ce niveau: élimine celles sans parcours - ues_pair_avec_parcours = [ue for ue in ues if ue.parcours] - if ues_pair_avec_parcours: - ues = ues_pair_avec_parcours + ues_avec_parcours = [ue for ue in ues if ue.parcours] + if ues_avec_parcours: + ues = ues_avec_parcours if len(ues) > 1: log(f"_niveau_ues: {len(ues)} associées au niveau {niveau} / {sem_name}") - return ues[0] if ues else None + return ues[0] if ues else None, msg def parcour_formation_competences( @@ -700,6 +705,7 @@ def parcour_formation_competences( "ue_impair": None, "ues_pair": [], "ues_impair": [], + "warning": "", } # Toutes les UEs de la formation dans ce parcours ou tronc commun ues = [ @@ -715,10 +721,10 @@ def parcour_formation_competences( ues_impair_possibles = [ue for ue in ues if ue.semestre_idx == (2 * annee - 1)] # UE associée au niveau dans ce parcours - ue_pair = ue_associee_au_niveau_du_parcours( + ue_pair, warning_pair = ue_associee_au_niveau_du_parcours( ues_pair_possibles, niveau, f"S{2*annee}" ) - ue_impair = ue_associee_au_niveau_du_parcours( + ue_impair, warning_impair = ue_associee_au_niveau_du_parcours( ues_impair_possibles, niveau, f"S{2*annee-1}" ) @@ -736,6 +742,7 @@ def parcour_formation_competences( for ue in ues_impair_possibles if (not ue.niveau_competence) or ue.niveau_competence.id == niveau.id ], + "warning": ", ".join(filter(None, [warning_pair, warning_impair])), } competences = [ diff --git a/app/static/css/parcour_formation.css b/app/static/css/parcour_formation.css index 845a5a9e4..83bbfba0e 100644 --- a/app/static/css/parcour_formation.css +++ b/app/static/css/parcour_formation.css @@ -162,25 +162,35 @@ option.non_associe { div.ue_validation_code { display: inline-block; } + div.ue_validation_code div.code { margin-left: 12px; } + select.validation_rcue { color: black; display: inline-block; margin-left: 32px; } -div.recap_ects, div.link_edit { + +div.recap_ects, +div.link_edit { margin-top: 8px; margin-left: 16px; margin-right: 16px; margin-bottom: 16px; font-weight: bold; } + div.recap_ects { background-color: var(--col-c3-2); padding: 4px; } + .link_edit a { padding-right: 48px; } + +.niveau-warning { + font-weight: bold; +} \ No newline at end of file diff --git a/app/templates/but/parcour_formation.j2 b/app/templates/but/parcour_formation.j2 index b2a74da61..91f57b4e0 100644 --- a/app/templates/but/parcour_formation.j2 +++ b/app/templates/but/parcour_formation.j2 @@ -99,6 +99,9 @@ {% endif %} {{niv['niveau'].libelle if niv['niveau'] else ''}} + {% if niv["warning"] %} +
{{scu.EMO_WARNING|safe}} {{niv["warning"]}}
+ {% endif %}
{{ menu_ue(niv, "impair", 2*annee-1) }}