diff --git a/app/but/jury_but.py b/app/but/jury_but.py index dedb522b..d9f8031a 100644 --- a/app/but/jury_but.py +++ b/app/but/jury_but.py @@ -278,11 +278,15 @@ class DecisionsProposeesAnnee(DecisionsProposees): ) if self.formsemestre_impair is not None: - self.validation = ApcValidationAnnee.query.filter_by( - etudid=self.etud.id, - formation_id=self.formsemestre.formation_id, - ordre=self.annee_but, - ).first() + self.validation = ( + ApcValidationAnnee.query.filter_by( + etudid=self.etud.id, + ordre=self.annee_but, + ) + .join(Formation) + .filter_by(formation_code=self.formsemestre.formation.formation_code) + .first() + ) else: self.validation = None if self.validation is not None: @@ -721,7 +725,7 @@ class DecisionsProposeesAnnee(DecisionsProposees): et qu'il n'y en a pas déjà, enregistre ceux par défaut. """ log("jury_but.DecisionsProposeesAnnee.record_form") - code_annee = None + code_annee = self.codes[0] # si pas dans le form, valeur par defaut codes_rcues = [] # [ (dec_rcue, code), ... ] codes_ues = [] # [ (dec_ue, code), ... ] for key in form: @@ -753,16 +757,15 @@ class DecisionsProposeesAnnee(DecisionsProposees): dec_ue.record(code) for dec_rcue, code in codes_rcues: dec_rcue.record(code) - self.record(code_annee) # XXX , mark_recorded=False) + self.record(code_annee) self.record_autorisation_inscription(code_annee) self.record_all() self.recorded = True db.session.commit() - def record(self, code: str, no_overwrite=False, mark_recorded: bool = True) -> bool: + def record(self, code: str, mark_recorded: bool = True) -> bool: """Enregistre le code de l'année, et au besoin l'autorisation d'inscription. - Si no_overwrite, ne fait rien si un code est déjà enregistré. Si l'étudiant est DEM ou DEF, ne fait rien. Si mark_recorded est vrai, positionne self.recorded """ @@ -773,23 +776,34 @@ class DecisionsProposeesAnnee(DecisionsProposees): f"code annee {html.escape(code)} invalide pour formsemestre {html.escape(self.formsemestre)}" ) - if code != self.code_valide and (self.code_valide is None or not no_overwrite): + if code != self.code_valide: # Enregistrement du code annuel BUT - if self.validation: - db.session.delete(self.validation) - db.session.commit() if code is None: - self.validation = None + if self.validation: + db.session.delete(self.validation) + self.validation = None + db.session.commit() else: - self.validation = ApcValidationAnnee( - etudid=self.etud.id, - formsemestre=self.formsemestre_impair, - formation_id=self.formsemestre.formation_id, - ordre=self.annee_but, - annee_scolaire=self.annee_scolaire(), - code=code, - ) + if self.validation is None: + self.validation = ApcValidationAnnee( + etudid=self.etud.id, + formsemestre=self.formsemestre_impair, + formation_id=self.formsemestre.formation_id, + ordre=self.annee_but, + annee_scolaire=self.annee_scolaire(), + code=code, + ) + else: # Update validation année BUT + self.validation.etud = self.etud + self.validation.formsemestre = self.formsemestre_impair + self.validation.formation_id = self.formsemestre.formation_id + self.validation.ordre = self.annee_but + self.validation.annee_scolaire = self.annee_scolaire() + self.validation.code = code + self.validation.date = datetime.now() + db.session.add(self.validation) + db.session.commit() log(f"Recording {self}: {code}") Scolog.logdb( method="jury_but", @@ -840,9 +854,7 @@ class DecisionsProposeesAnnee(DecisionsProposees): ) return res and self.etud.id in res.get_etudids_attente() - def record_all( - self, no_overwrite: bool = True, only_validantes: bool = False - ) -> bool: + def record_all(self, only_validantes: bool = False) -> bool: """Enregistre les codes qui n'ont pas été spécifiés par le formulaire, et sont donc en mode "automatique". - Si "à cheval", ne modifie pas les codes UE de l'année scolaire précédente. @@ -868,9 +880,8 @@ class DecisionsProposeesAnnee(DecisionsProposees): # rappel: le code par défaut est en tête code = dec_ue.codes[0] if dec_ue.codes else None if (not only_validantes) or code in sco_codes.CODES_UE_VALIDES_DE_DROIT: - # enregistre le code jury seulement s'il n'y a pas déjà de code - # (no_overwrite=True) sauf en mode test yaml - modif |= dec_ue.record(code, no_overwrite=no_overwrite) + # enregistre le code jury + modif |= dec_ue.record(code) # RCUE : for dec_rcue in self.decisions_rcue_by_niveau.values(): code = dec_rcue.codes[0] if dec_rcue.codes else None @@ -888,17 +899,15 @@ class DecisionsProposeesAnnee(DecisionsProposees): ) ) ): - modif |= dec_rcue.record(code, no_overwrite=no_overwrite) + modif |= dec_rcue.record(code) # Année: if not self.recorded: # rappel: le code par défaut est en tête code = self.codes[0] if self.codes else None - # enregistre le code jury seulement s'il n'y a pas déjà de code - # (no_overwrite=True) sauf en mode test yaml if ( not only_validantes ) or code in sco_codes.CODES_ANNEE_BUT_VALIDES_DE_DROIT: - modif |= self.record(code, no_overwrite=no_overwrite) + modif |= self.record(code) self.record_autorisation_inscription(code) return modif @@ -1133,7 +1142,7 @@ class DecisionsProposeesRCUE(DecisionsProposees): return f"""<{self.__class__.__name__} rcue={self.rcue} valid={self.code_valide } codes={self.codes} explanation={self.explanation}""" - def record(self, code: str, no_overwrite=False) -> bool: + def record(self, code: str) -> bool: """Enregistre le code RCUE. Note: - si le RCUE est ADJ, les UE non validées sont passées à ADJ @@ -1147,7 +1156,7 @@ class DecisionsProposeesRCUE(DecisionsProposees): raise ScoValueError( f"code UE invalide pour ue_id={self.ue.id}: {html.escape(code)}" ) - if code == self.code_valide or (self.code_valide is not None and no_overwrite): + if code == self.code_valide: self.recorded = True return False # no change parcours_id = self.parcour.id if self.parcour is not None else None @@ -1322,11 +1331,15 @@ class DecisionsProposeesRCUE(DecisionsProposees): if annee_inferieure < 1: return # Garde-fou: Année déjà validée ? - validations_annee: ApcValidationAnnee = ApcValidationAnnee.query.filter_by( - etudid=self.etud.id, - ordre=annee_inferieure, - formation_id=self.rcue.formsemestre_1.formation_id, - ).all() + validations_annee: ApcValidationAnnee = ( + ApcValidationAnnee.query.filter_by( + etudid=self.etud.id, + ordre=annee_inferieure, + ) + .join(Formation) + .filter_by(formation_code=self.rcue.formsemestre_1.formation.code) + .all() + ) if len(validations_annee) > 1: log( f"warning: {len(validations_annee)} validations d'année\n{validations_annee}" @@ -1519,16 +1532,15 @@ class DecisionsProposeesUE(DecisionsProposees): self.codes = [sco_codes.AJ, sco_codes.ADJ] + self.codes self.explanation = "notes insuffisantes" - def record(self, code: str, no_overwrite=False) -> bool: + def record(self, code: str) -> bool: """Enregistre le code jury pour cette UE. - Si no_overwrite, n'enregistre pas s'il y a déjà un code. Return: True si code enregistré (modifié) """ if code and not code in self.codes: raise ScoValueError( f"code UE invalide pour ue_id={self.ue.id}: {html.escape(code)}" ) - if code == self.code_valide or (self.code_valide is not None and no_overwrite): + if code == self.code_valide: self.recorded = True return False # no change self.erase() @@ -1627,7 +1639,6 @@ class BUTCursusEtud: # WIP TODO ApcValidationAnnee.query.filter_by( etudid=self.etud.id, ordre=ordre, - formation_id=self.formsemestre.formation_id, ) .join(Formation) .filter( diff --git a/app/but/jury_but_validation_auto.py b/app/but/jury_but_validation_auto.py index deae9b59..e698b5dd 100644 --- a/app/but/jury_but_validation_auto.py +++ b/app/but/jury_but_validation_auto.py @@ -16,14 +16,12 @@ from app.scodoc.sco_exceptions import ScoValueError def formsemestre_validation_auto_but( - formsemestre: FormSemestre, only_adm: bool = True, no_overwrite: bool = True + formsemestre: FormSemestre, only_adm: bool = True ) -> int: """Calcul automatique des décisions de jury sur une "année" BUT. - N'enregistre jamais de décisions de l'année scolaire précédente, même si on a des RCUE "à cheval". - - Ne modifie jamais de décisions déjà enregistrées (sauf si no_overwrite est faux, - ce qui est utilisé pour certains tests unitaires). - Normalement, only_adm est True et on n'enregistre que les décisions validantes de droit: ADM ou CMP. En revanche, si only_adm est faux, on enregistre la première décision proposée par ScoDoc @@ -38,9 +36,7 @@ def formsemestre_validation_auto_but( for etudid in formsemestre.etuds_inscriptions: etud = Identite.get_etud(etudid) deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre) - nb_etud_modif += deca.record_all( - no_overwrite=no_overwrite, only_validantes=only_adm - ) + nb_etud_modif += deca.record_all(only_validantes=only_adm) db.session.commit() return nb_etud_modif diff --git a/app/but/jury_but_view.py b/app/but/jury_but_view.py index bbe992cb..87321684 100644 --- a/app/but/jury_but_view.py +++ b/app/but/jury_but_view.py @@ -155,6 +155,7 @@ def _gen_but_select( disabled: bool = False, klass: str = "", data: dict = {}, + code_valide_label: str = "", ) -> str: "Le menu html select avec les codes" # if disabled: # mauvaise idée car le disabled est traité en JS @@ -164,7 +165,10 @@ def _gen_but_select( f"""""" + >{code + if ((code != code_valide) or not code_valide_label) + else code_valide_label + }""" for code in codes ] ) @@ -246,6 +250,7 @@ def _gen_but_rcue(dec_rcue: DecisionsProposeesRCUE, niveau: ApcNiveau) -> str: """ code_propose_menu = dec_rcue.code_valide # le code enregistré + code_valide_label = code_propose_menu if dec_rcue.validation: if dec_rcue.code_valide == dec_rcue.codes[0]: descr_validation = dec_rcue.validation.html() @@ -257,6 +262,9 @@ def _gen_but_rcue(dec_rcue: DecisionsProposeesRCUE, niveau: ApcNiveau) -> str: > sco_codes.BUT_CODES_ORDER[dec_rcue.code_valide] ): code_propose_menu = dec_rcue.codes[0] + code_valide_label = ( + f"{dec_rcue.codes[0]} (actuel {dec_rcue.code_valide})" + ) scoplement = f"""