From 73c263b89519960af15935b528ebc44db377626c Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sun, 25 Aug 2024 22:00:29 +0200 Subject: [PATCH] =?UTF-8?q?D=C3=A9livrance=20dipl=C3=B4me=20BUT:=20v=C3=A9?= =?UTF-8?q?rifie=20ECTS=20du=20parcours?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/but/cursus_but.py | 89 ++++++++++++++++++++++++---- app/tables/jury_recap.py | 2 +- app/templates/but/validate_dut120.j2 | 2 +- sco_version.py | 2 +- 4 files changed, 79 insertions(+), 16 deletions(-) diff --git a/app/but/cursus_but.py b/app/but/cursus_but.py index fc1ee3cfd..0abaf31aa 100644 --- a/app/but/cursus_but.py +++ b/app/but/cursus_but.py @@ -18,7 +18,6 @@ from collections.abc import Iterable from operator import attrgetter from flask import g, url_for -from flask_sqlalchemy.query import Query from app import db, log from app.comp.res_but import ResultatsSemestreBUT @@ -38,7 +37,12 @@ from app.models.formsemestre import FormSemestre from app.models.ues import UniteEns from app.models.validations import ScolarFormSemestreValidation from app.scodoc import codes_cursus as sco_codes -from app.scodoc.codes_cursus import code_ue_validant, CODES_UE_VALIDES, UE_STANDARD +from app.scodoc.codes_cursus import ( + code_ue_validant, + CODES_UE_VALIDES, + CursusBUT, + UE_STANDARD, +) from app.scodoc.sco_exceptions import ScoNoReferentielCompetences, ScoValueError from app.scodoc import sco_cursus_dut @@ -56,24 +60,39 @@ class SituationEtudCursusBUT(sco_cursus_dut.SituationEtudCursusClassic): return False def parcours_validated(self): - "True si le parcours (ici diplôme BUT) est validé" - return but_parcours_validated( - self.etud.id, self.cur_sem.formation.referentiel_competence_id - ) + """True si le parcours (ici diplôme BUT) est validé. + Considère le parcours du semestre en cours (res). + """ + parcour_id = self.nt.etuds_parcour_id.get(self.etud.id) + return but_parcours_validated(self.etud.id, parcour_id) -def but_parcours_validated(etudid: int, referentiel_competence_id: int) -> bool: - """Détermine si le parcours BUT est validé: - ne regarde que si une validation BUT3 est enregistrée - """ +def but_annee_validated( + etudid: int, referentiel_competence_id: int, annee: int = 3 +) -> bool: + """Vrai si une validation de l'année BUT est enregistrée""" return any( sco_codes.code_annee_validant(v.code) for v in ApcValidationAnnee.query.filter_by( - etudid=etudid, ordre=3, referentiel_competence_id=referentiel_competence_id + etudid=etudid, + ordre=annee, + referentiel_competence_id=referentiel_competence_id, ) ) +def but_parcours_validated(etudid: int, parcour_id: int | None) -> bool: + """Détermine si le parcours BUT est validé. + = 180 ECTS acquis dans les UEs du parcours. + """ + if parcour_id is None: + return False # étudiant non inscrit à un parcours + # Les ECTS + validations = but_validations_ues_parcours(etudid, parcour_id) + ects_acquis = validations_count_ects(validations) + return ects_acquis >= CursusBUT.ECTS_DIPLOME + + class EtudCursusBUT: """L'état de l'étudiant dans son cursus BUT Liste des niveaux validés/à valider @@ -395,9 +414,18 @@ def but_ects_valides( Si annees_but est spécifié, un iterable "BUT1, "BUT2" par exemple, ne prend que ces années. """ validations = but_validations_ues(etud, referentiel_competence_id, annees_but) + return validations_count_ects(validations) + + +def validations_count_ects(validations: list[ScolarFormSemestreValidation]) -> int: + """Somme les ECTS validés par ces UEs, en éliminant les éventuels + doublons (niveaux de compétences validés plusieurs fois)""" ects_dict = {} for v in validations: - key = (v.ue.semestre_idx, v.ue.niveau_competence.id) + key = ( + v.ue.semestre_idx, + v.ue.niveau_competence.id if v.ue.niveau_competence else None, + ) if v.code in CODES_UE_VALIDES: ects_dict[key] = v.ue.ects or 0.0 @@ -427,8 +455,12 @@ def but_validations_ues( validations = validations.join(ApcCompetence).filter_by( referentiel_id=referentiel_competence_id ) + return sorted_validations(validations) - # Tri (nb: fait en python pour gérer les validations externes qui n'ont pas de formsemestre) + +def sorted_validations(validations) -> list[ScolarFormSemestreValidation]: + """Tri (nb: fait en python pour gérer les validations externes qui + n'ont pas de formsemestre)""" return sorted( validations, key=lambda v: ( @@ -439,6 +471,37 @@ def but_validations_ues( ) +def but_validations_ues_parcours( + etudid: int, parcour_id: int +) -> list[ScolarFormSemestreValidation]: + """Query les validations d'UEs pour cet étudiant + dans des UEs appartenant à ce parcours ou à son tronc commun. + """ + # Rappel: + # Les UEs associées à un parcours: + # UniteEns.query.join(UEParcours).filter(UEParcours.parcours_id == parcour.id) ) + # Les UEs associées au tronc commun (à aucun parcours) + # UniteEns.query.filter(~UniteEns.id.in_(UEParcours.query.with_entities(UEParcours.ue_id))) + + # Les validations d'UE de ce parcours ou du tronc commun pour cet étudiant: + validations = ( + ScolarFormSemestreValidation.query.filter_by(etudid=etudid) + .filter(ScolarFormSemestreValidation.ue_id != None) + .join(UniteEns) + .filter( + db.or_( + UniteEns.id.in_( + UEParcours.query.with_entities(UEParcours.ue_id).filter( + UEParcours.parcours_id == parcour_id + ) + ), + ~UniteEns.id.in_(UEParcours.query.with_entities(UEParcours.ue_id)), + ) + ) + ) + return sorted_validations(validations) + + def etud_ues_de_but1_non_validees( etud: Identite, formation: Formation, parcour: ApcParcours ) -> list[UniteEns]: diff --git a/app/tables/jury_recap.py b/app/tables/jury_recap.py index 8c538ad66..56d27e4e3 100644 --- a/app/tables/jury_recap.py +++ b/app/tables/jury_recap.py @@ -113,7 +113,7 @@ class TableJury(TableRecap): if res.is_apc and res.formsemestre.semestre_id == 6: # on ne vérifie le diplôme que dans ce cas pour ne pas ralentir if cursus_but.but_parcours_validated( - etud.id, res.formsemestre.formation.referentiel_competence_id + etud.id, res.etuds_parcour_id.get(etud.id) ): row.add_cell( "autorisations_inscription", diff --git a/app/templates/but/validate_dut120.j2 b/app/templates/but/validate_dut120.j2 index fd13de8ad..e06f04faa 100644 --- a/app/templates/but/validate_dut120.j2 +++ b/app/templates/but/validate_dut120.j2 @@ -44,7 +44,7 @@ une formation utilisant une autre version de référentiel, pensez à revalider {% else %} -
+
{% if validation %} DUT déjà validé dans cette spécialité {{formsemestre.formation.referentiel_competence.get_title()}} diff --git a/sco_version.py b/sco_version.py index e0aa0a8f5..1671505e2 100644 --- a/sco_version.py +++ b/sco_version.py @@ -1,7 +1,7 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "9.7.11" +SCOVERSION = "9.7.12" SCONAME = "ScoDoc"