From 512b38665f372f0b721e0b217d3767b0dbb16ada Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Mon, 4 Jul 2022 23:50:55 +0200 Subject: [PATCH] Jury BUT: traitement des DEF et DEM. Close #426 --- app/but/jury_but.py | 78 ++++++++++++++++++++++++++++------- app/but/jury_but_recap.py | 4 +- app/models/but_validations.py | 14 ++++++- sco_version.py | 2 +- 4 files changed, 78 insertions(+), 20 deletions(-) diff --git a/app/but/jury_but.py b/app/but/jury_but.py index 0a7660345f..397bd05f59 100644 --- a/app/but/jury_but.py +++ b/app/but/jury_but.py @@ -68,7 +68,7 @@ from flask import g, url_for from app import db from app import log from app.comp.res_but import ResultatsSemestreBUT -from app.comp import res_sem +from app.comp import inscr_mod, res_sem from app.models import formsemestre from app.models.but_refcomp import ( @@ -219,15 +219,16 @@ class DecisionsProposeesAnnee(DecisionsProposees): "le 1er semestre de l'année scolaire considérée (S1, S3, S5)" self.formsemestre_pair = formsemestre_pair "le second formsemestre de la même année scolaire (S2, S4, S6)" - self.annee_but = ( - (formsemestre_impair.semestre_id + 1) // 2 - if formsemestre_impair - else (formsemestre_pair.semestre_id + 1) // 2 - ) + formsemestre_last = formsemestre_pair or formsemestre_impair + "le formsemestre le plus avancé dans cette année" + + self.annee_but = (formsemestre_last.semestre_id + 1) // 2 "le rang de l'année dans le BUT: 1, 2, 3" assert self.annee_but in (1, 2, 3) self.rcues_annee = [] "RCUEs de l'année" + self.inscription_etat = etud.inscription_etat(formsemestre_last.id) + if self.formsemestre_impair is not None: self.validation = ApcValidationAnnee.query.filter_by( etudid=self.etud.id, @@ -255,13 +256,17 @@ class DecisionsProposeesAnnee(DecisionsProposees): self.ues_impair, self.ues_pair = self.compute_ues_annee() # pylint: disable=all self.decisions_ues = { - ue.id: DecisionsProposeesUE(etud, formsemestre_impair, ue) + ue.id: DecisionsProposeesUE( + etud, formsemestre_impair, ue, self.inscription_etat + ) for ue in self.ues_impair } "{ue_id : DecisionsProposeesUE} pour toutes les UE de l'année" self.decisions_ues.update( { - ue.id: DecisionsProposeesUE(etud, formsemestre_pair, ue) + ue.id: DecisionsProposeesUE( + etud, formsemestre_pair, ue, self.inscription_etat + ) for ue in self.ues_pair } ) @@ -291,8 +296,10 @@ class DecisionsProposeesAnnee(DecisionsProposees): [rcue for rcue in rcues_avec_niveau if not rcue.est_suffisant()] ) "le nb de comp. sous la barre de 8/20" - # année ADM si toutes RCUE validées (sinon PASD) - self.admis = self.nb_validables == self.nb_competences + # année ADM si toutes RCUE validées (sinon PASD) et non DEM ou DEF + self.admis = (self.nb_validables == self.nb_competences) and ( + self.inscription_etat == scu.INSCRIT + ) "vrai si l'année est réussie, tous niveaux validables" self.valide_moitie_rcue = self.nb_validables > (self.nb_competences // 2) # Peut passer si plus de la moitié validables et tous > 8 @@ -310,6 +317,19 @@ class DecisionsProposeesAnnee(DecisionsProposees): if self.admis: self.codes = [sco_codes.ADM] + self.codes self.explanation = expl_rcues + elif self.inscription_etat != scu.INSCRIT: + self.codes = [ + sco_codes.DEM + if self.inscription_etat == scu.DEMISSION + else sco_codes.DEF, + # propose aussi d'autres codes, au cas où... + sco_codes.DEM + if self.inscription_etat != scu.DEMISSION + else sco_codes.DEF, + sco_codes.ABAN, + sco_codes.ABL, + sco_codes.EXCLU, + ] elif self.passage_de_droit: self.codes = [sco_codes.PASD, sco_codes.ADJ] + self.codes self.explanation = expl_rcues @@ -482,6 +502,7 @@ class DecisionsProposeesAnnee(DecisionsProposees): ue_impair, self.formsemestre_pair, ue_pair, + self.inscription_etat, ) ues_impair_sans_rcue.discard(ue_impair.id) break @@ -509,7 +530,7 @@ class DecisionsProposeesAnnee(DecisionsProposees): rcue = rc break if rcue is not None: - dec_rcue = DecisionsProposeesRCUE(self, rcue) + dec_rcue = DecisionsProposeesRCUE(self, rcue, self.inscription_etat) rc_niveaux.append((dec_rcue, niveau.id)) # prévient les UE concernées :-) self.decisions_ues[dec_rcue.rcue.ue_1.id].set_rcue(dec_rcue.rcue) @@ -724,14 +745,26 @@ class DecisionsProposeesRCUE(DecisionsProposees): ] def __init__( - self, dec_prop_annee: DecisionsProposeesAnnee, rcue: RegroupementCoherentUE + self, + dec_prop_annee: DecisionsProposeesAnnee, + rcue: RegroupementCoherentUE, + inscription_etat: str = scu.INSCRIT, ): super().__init__(etud=dec_prop_annee.etud) self.rcue = rcue if rcue is None: # RCUE non dispo, eg un seul semestre self.codes = [] return + self.inscription_etat = inscription_etat + "inscription: I, DEM, DEF" self.parcour = dec_prop_annee.parcour + if inscription_etat != scu.INSCRIT: + self.validation = None # cache toute validation + self.explanation = "non incrit (dem. ou déf.)" + self.codes = [ + sco_codes.DEM if inscription_etat == scu.DEMISSION else sco_codes.DEF + ] + return self.validation = rcue.query_validations().first() if self.validation is not None: self.code_valide = self.validation.code @@ -828,12 +861,27 @@ class DecisionsProposeesUE(DecisionsProposees): etud: Identite, formsemestre: FormSemestre, ue: UniteEns, + inscription_etat: str = scu.INSCRIT, ): super().__init__(etud=etud) self.formsemestre = formsemestre self.ue: UniteEns = ue self.rcue: RegroupementCoherentUE = None "Le rcu auquel est rattaché cette UE, ou None" + self.inscription_etat = inscription_etat + "inscription: I, DEM, DEF" + if ue.type == sco_codes.UE_SPORT: + self.explanation = "UE bonus, pas de décision de jury" + self.codes = [] # aucun code proposé + return + if inscription_etat != scu.INSCRIT: + self.validation = None # cache toute validation + self.explanation = "non incrit (dem. ou déf.)" + self.codes = [ + sco_codes.DEM if inscription_etat == scu.DEMISSION else sco_codes.DEF + ] + self.moy_ue = "-" + return # Une UE peut être validée plusieurs fois en cas de redoublement (qu'elle soit capitalisée ou non) # mais ici on a restreint au formsemestre donc une seule (prend la première) self.validation = ScolarFormSemestreValidation.query.filter_by( @@ -841,10 +889,6 @@ class DecisionsProposeesUE(DecisionsProposees): ).first() if self.validation is not None: self.code_valide = self.validation.code - if ue.type == sco_codes.UE_SPORT: - self.explanation = "UE bonus, pas de décision de jury" - self.codes = [] # aucun code proposé - return # Moyenne de l'UE ? res: ResultatsSemestreBUT = res_sem.load_formsemestre_results(formsemestre) @@ -863,6 +907,8 @@ class DecisionsProposeesUE(DecisionsProposees): def compute_codes(self): """Calcul des .codes attribuables et de l'explanation associée""" + if self.inscription_etat != scu.INSCRIT: + return if self.moy_ue > (sco_codes.ParcoursBUT.BARRE_MOY - sco_codes.NOTES_TOLERANCE): self.codes.insert(0, sco_codes.ADM) self.explanation = (f"Moyenne >= {sco_codes.ParcoursBUT.BARRE_MOY}/20",) diff --git a/app/but/jury_but_recap.py b/app/but/jury_but_recap.py index c2944d98ce..7d47cbe5e4 100644 --- a/app/but/jury_but_recap.py +++ b/app/but/jury_but_recap.py @@ -409,7 +409,9 @@ def get_table_jury_but( )}" class="stdlink"> {"voir" if read_only else ("modif." if deca.code_valide else "saisie")} décision - """, + """ + if deca.inscription_etat == scu.INSCRIT + else deca.inscription_etat, "col_lien_saisie_but", ) rows.append(row) diff --git a/app/models/but_validations.py b/app/models/but_validations.py index 6c2814424c..ebedadd715 100644 --- a/app/models/but_validations.py +++ b/app/models/but_validations.py @@ -16,6 +16,7 @@ from app.models.ues import UniteEns from app.models.formations import Formation from app.models.formsemestre import FormSemestre from app.scodoc import sco_codes_parcours as sco_codes +from app.scodoc import sco_utils as scu class ApcValidationRCUE(db.Model): @@ -84,6 +85,7 @@ class RegroupementCoherentUE: ue_1: UniteEns, formsemestre_2: FormSemestre, ue_2: UniteEns, + inscription_etat: str, ): from app.comp import res_sem from app.comp.res_but import ResultatsSemestreBUT @@ -109,6 +111,11 @@ class RegroupementCoherentUE: "semestre pair" self.ue_2 = ue_2 # Stocke les moyennes d'UE + if inscription_etat != scu.INSCRIT: + self.moy_rcue = None + self.moy_ue_1 = self.moy_ue_2 = "-" + self.moy_ue_1_val = self.moy_ue_2_val = 0.0 + return res: ResultatsSemestreBUT = res_sem.load_formsemestre_results(formsemestre_1) if ue_1.id in res.etud_moy_ue and etud.id in res.etud_moy_ue[ue_1.id]: self.moy_ue_1 = res.etud_moy_ue[ue_1.id][etud.id] @@ -201,8 +208,9 @@ class RegroupementCoherentUE: return None +# unused def find_rcues( - formsemestre: FormSemestre, ue: UniteEns, etud: Identite + formsemestre: FormSemestre, ue: UniteEns, etud: Identite, inscription_etat: str ) -> list[RegroupementCoherentUE]: """Les RCUE (niveau de compétence) à considérer pour cet étudiant dans ce semestre pour cette UE. @@ -250,7 +258,9 @@ def find_rcues( other_ue = UniteEns.query.get(ue_id) other_formsemestre = FormSemestre.query.get(formsemestre_id) rcues.append( - RegroupementCoherentUE(etud, formsemestre, ue, other_formsemestre, other_ue) + RegroupementCoherentUE( + etud, formsemestre, ue, other_formsemestre, other_ue, inscription_etat + ) ) # safety check: 1 seul niveau de comp. concerné: assert len({rcue.ue_1.niveau_competence_id for rcue in rcues}) == 1 diff --git a/sco_version.py b/sco_version.py index 4d1ccafcb2..d7a1305ec9 100644 --- a/sco_version.py +++ b/sco_version.py @@ -1,7 +1,7 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "9.3.13" +SCOVERSION = "9.3.14" SCONAME = "ScoDoc"