diff --git a/app/api/jury.py b/app/api/jury.py index 66324ab34..4aa31ce0f 100644 --- a/app/api/jury.py +++ b/app/api/jury.py @@ -86,6 +86,12 @@ def _news_delete_jury_etud(etud: Identite, detail: str = ""): text=f"""Suppression décision jury {detail} pour {etud.nomprenom}""", url=url, ) + Scolog.logdb( + "jury_delete_manual", + etudid=etud.id, + msg=f"Validation {detail} effacée", + commit=True, + ) @bp.route( diff --git a/app/but/jury_but.py b/app/but/jury_but.py index a12877d92..a7a37ab6b 100644 --- a/app/but/jury_but.py +++ b/app/but/jury_but.py @@ -501,7 +501,7 @@ class DecisionsProposeesAnnee(DecisionsProposees): scodoc_dept=g.scodoc_dept, semestre_idx=formsemestre.semestre_id, formation_id=formsemestre.formation.id)}"> - {formsemestre.formation.html()} ({ + {formsemestre.formation.html()|safe} ({ formsemestre.formation.id}) diff --git a/app/models/formations.py b/app/models/formations.py index 65538fda4..1384873f1 100644 --- a/app/models/formations.py +++ b/app/models/formations.py @@ -64,7 +64,7 @@ class Formation(ScoDocModel): def html(self) -> str: "titre complet pour affichage" - return f"""Formation {self.titre} ({self.acronyme}) [version {self.version}] code {self.formation_code}""" + return f"""Formation {self.titre} ({self.acronyme}) version {self.version} code {self.formation_code}""" @classmethod def get_formation(cls, formation_id: int | str, dept_id: int = None) -> "Formation": diff --git a/app/models/validations.py b/app/models/validations.py index a9a3ad2b4..150bb94a2 100644 --- a/app/models/validations.py +++ b/app/models/validations.py @@ -91,7 +91,7 @@ class ScolarFormSemestreValidation(db.Model): d.pop("_sa_instance_state", None) return d - def html(self, detail=False) -> str: + def html(self, detail=True) -> str: "Affichage html" if self.ue_id is not None: moyenne = ( @@ -114,11 +114,12 @@ class ScolarFormSemestreValidation(db.Model): + ", ".join([p.code for p in self.ue.parcours])) + "" if self.ue.parcours else ""} - {("émise par " + link)} : {self.code}{moyenne} {(self.ue.ects or 0):g} ECTS - le {self.event_date.strftime(scu.DATEATIME_FMT)} - """ + {("émise par " + link)} + """ + ( + f"le {self.event_date.strftime(scu.DATEATIME_FMT)}" if detail else "" + ) else: return f"""Validation du semestre S{ self.formsemestre.semestre_id if self.formsemestre else "?"} diff --git a/app/scodoc/sco_edit_ue.py b/app/scodoc/sco_edit_ue.py index 40989539e..89af78ec8 100644 --- a/app/scodoc/sco_edit_ue.py +++ b/app/scodoc/sco_edit_ue.py @@ -765,7 +765,7 @@ def ue_table(formation_id=None, semestre_idx=1, msg=""): # was ue_list "delete_small_dis_img", title="Suppression impossible (module utilisé)" ) H = [ - f"""

{formation.html()} {lockicon} + f"""

{formation.html()|safe} {lockicon}

""", ] diff --git a/app/static/css/jury_delete_manual.css b/app/static/css/jury_delete_manual.css index 478167ebd..59bf1291d 100644 --- a/app/static/css/jury_delete_manual.css +++ b/app/static/css/jury_delete_manual.css @@ -8,7 +8,12 @@ span.parcours { color: blueviolet; } -div.ue_list_etud_validations ul.liste_validations li { +div.liste_validations { + margin-top: 16px; + margin-bottom: 16px; +} + +div.ue_list_etud_validations div.liste_validations details { margin-bottom: 8px; } @@ -28,6 +33,7 @@ details { } div.validation-details { - margin-left: 32px; + margin-top: 12px; margin-bottom: 16px; + margin-left: 32px; } \ No newline at end of file diff --git a/app/templates/but/parcour_formation.j2 b/app/templates/but/parcour_formation.j2 index ce8614e41..1b0f23968 100644 --- a/app/templates/but/parcour_formation.j2 +++ b/app/templates/but/parcour_formation.j2 @@ -44,7 +44,7 @@ {%- endmacro %} {% block app_content %} -

{{formation.html()}}

+

{{formation.html()|safe}}

{# Liens vers les différents parcours #}
@@ -133,7 +133,7 @@ Choisissez un parcours... d'associer à chaque semestre d'un niveau de compétence une UE de la formation {{formation.html()}} + }}">{{formation.html()|safe}} .

Le symbole TC désigne un niveau du tronc commun diff --git a/app/templates/jury/etud_bilan_ects.j2 b/app/templates/jury/etud_bilan_ects.j2 index 0908dc7e2..553864b65 100644 --- a/app/templates/jury/etud_bilan_ects.j2 +++ b/app/templates/jury/etud_bilan_ects.j2 @@ -1,4 +1,4 @@ -{% extends "sco_page.j2" %} +{% extends "sco_page_dept.j2" %} {% block styles %} {{super()}} @@ -10,8 +10,13 @@

Bilan des ECTS de {{etud.html_link_fiche()|safe}}

- Cette page donne toutes les UEs acquises par l'étudiant (codes ADM, ADJ, ADJR, ADSUP, CMP...) - dans chaque formation qu'il a suivi. +

+ Cette page donne toutes les UEs acquises par l'étudiant (codes ADM, ADJ, ADJR, ADSUP, CMP...). +

+

+ La somme des crédits ECTS en bas de page peut compter des UEs + suivies plusieurs fois (redoublements) n'a pas de signification pour l'octroit des diplômes. +

{% for diplome in formsemestre_by_diplome %} @@ -21,4 +26,29 @@ {% include "jury/ue_list_etud_validations.j2" %} {% endfor %} + {% if ue_warnings %} +
+
Attention
+ +
Ces problème peuvent dans certains cas affecter + le comptage des crédits ECTS et la délivrance des diplômes.
+
+ {% endif %} + {% endblock app_content %} + +{% block scripts %} +{{super()}} + +{% endblock %} \ No newline at end of file diff --git a/app/templates/jury/ue_list_etud_validations.j2 b/app/templates/jury/ue_list_etud_validations.j2 index aed5b1007..b8652a15f 100644 --- a/app/templates/jury/ue_list_etud_validations.j2 +++ b/app/templates/jury/ue_list_etud_validations.j2 @@ -5,31 +5,52 @@
Liste de toutes les UEs validées par {{etud.html_link_fiche()|safe}}, sur des semestres ou déclarées comme "antérieures" (externes).
- +
+
ouvrir tous les détails
{% if total_ects %}
- Total ECTS: {{ "%g" % total_ects }} + Total ECTS (toutes UEs, y compris redoublées): {{ "%g" % total_ects }}
{% endif %} \ No newline at end of file diff --git a/app/views/jury_validations.py b/app/views/jury_validations.py index 4ecdb443e..b7527e782 100644 --- a/app/views/jury_validations.py +++ b/app/views/jury_validations.py @@ -944,6 +944,8 @@ def etud_bilan_ects(etudid: int): ects_by_diplome = {} titre_by_diplome = {} # { diplome : titre } validations_by_diplome = {} # { diplome : query validations UEs } + validations_by_ue_code = defaultdict(list) # { ue_code : [validation] } + validations_by_niveau_sem = defaultdict(list) # { niveau_sem : [validation] } for diplome, formsemestres in formsemestre_by_diplome.items(): formsemestre = formsemestres[0] titre_by_diplome[diplome] = formsemestre.formation.get_titre_version() @@ -962,6 +964,62 @@ def etud_bilan_ects(etudid: int): (validation.ue.ects or 0.0) for validation in validations_by_diplome[diplome] ) + for validation in validations: + validations_by_ue_code[validation.ue.ue_code].append(validation) + validations_by_niveau_sem[ + ( + ( + validation.ue.niveau_competence.id + if validation.ue.niveau_competence + else None + ), + validation.ue.semestre_idx, + ) + ].append(validation) + + ref_comp_ids = { + v.ue.formation.referentiel_competence_id + for validations in validations_by_ue_code.values() + for v in validations + if v.ue.formation.referentiel_competence_id is not None + } + + ue_warnings = [] + if len(ref_comp_ids) > 1: + ue_warnings.append( + """plusieurs référentiels de compétences utilisés ! + (ok si plusieurs diplôme différents suivis)""" + ) + for ue_code, validations in validations_by_ue_code.items(): + ectss = {v.ue.ects for v in validations} + if len(ectss) > 1: + ects_str = ", ".join( + f"{v.ue.acronyme}: {v.ue.ects} ects" for v in validations + ) + ue_acros = ", ".join({v.ue.acronyme for v in validations}) + ue_warnings.append( + f"""Les UEs {ue_acros} ont le même code ({ue_code + }) mais des ECTS différents: {ects_str}""" + ) + for (niveau_id, semestre_idx), validations in validations_by_niveau_sem.items(): + if not validations: + continue # safeguard + formation = validations[0].ue.formation + ue_acros = ", ".join({v.ue.acronyme for v in validations}) + if niveau_id is None and formation.is_apc(): + ue_warnings.append( + f"""Les UEs {ue_acros} du S{semestre_idx + } n'ont pas de niveau de compétence associé !""" + ) + ectss = {v.ue.ects for v in validations} + if len(ectss) > 1: + ects_str = ", ".join( + f"{v.ue.acronyme}: {v.ue.ects} ects" for v in validations + ) + ue_warnings.append( + f"""Les UEs {ue_acros} du même code niveau de compétence + ({validations[0].ue.niveau_competence}) ont des ECTS différents: {ects_str}""" + ) return render_template( "jury/etud_bilan_ects.j2", @@ -969,5 +1027,8 @@ def etud_bilan_ects(etudid: int): ects_by_diplome=ects_by_diplome, formsemestre_by_diplome=formsemestre_by_diplome, titre_by_diplome=titre_by_diplome, + title=f"Bilan ECTS {etud.nomprenom}", + ue_warnings=ue_warnings, validations_by_diplome=validations_by_diplome, + sco=ScoData(etud=etud), )