diff --git a/app/comp/res_but.py b/app/comp/res_but.py index 502cd980c..9e8719ef9 100644 --- a/app/comp/res_but.py +++ b/app/comp/res_but.py @@ -17,6 +17,7 @@ from app.comp.bonus_spo import BonusSport from app.models import ScoDocSiteConfig from app.models.moduleimpls import ModuleImpl from app.models.ues import DispenseUE, UniteEns +from app.models.but_validations import ApcValidationAnnee, ApcValidationRCUE from app.scodoc import sco_preferences from app.scodoc.codes_cursus import UE_SPORT from app.scodoc.sco_utils import ModuleType @@ -261,3 +262,18 @@ class ResultatsSemestreBUT(NotesTableCompat): """ s = self.ues_inscr_parcours_df.loc[etudid] return s.index[s.notna()] + + def etud_has_decision(self, etudid): + """True s'il y a une décision de jury pour cet étudiant émanant de ce formsemestre. + prend aussi en compte les autorisations de passage. + Sous-classée en BUT pour les RCUEs et années. + """ + return ( + super().etud_has_decision(etudid) + or ApcValidationAnnee.query.filter_by( + formsemestre_id=self.formsemestre.id, etudid=etudid + ).count() + or ApcValidationRCUE.query.filter_by( + formsemestre_id=self.formsemestre.id, etudid=etudid + ).count() + ) diff --git a/app/comp/res_compat.py b/app/comp/res_compat.py index 00b6446e6..bc501b64a 100644 --- a/app/comp/res_compat.py +++ b/app/comp/res_compat.py @@ -15,9 +15,7 @@ from app import log from app.comp import moy_sem from app.comp.aux_stats import StatsMoyenne from app.comp.res_common import ResultatsSemestre -from app.models import FormSemestre -from app.models import Identite -from app.models import ModuleImpl +from app.models import Identite, FormSemestre, ModuleImpl, ScolarAutorisationInscription from app.scodoc.codes_cursus import UE_SPORT, DEF from app.scodoc import sco_utils as scu @@ -280,8 +278,17 @@ class NotesTableCompat(ResultatsSemestre): return True def etud_has_decision(self, etudid): - """True s'il y a une décision de jury pour cet étudiant""" - return self.get_etud_decisions_ue(etudid) or self.get_etud_decision_sem(etudid) + """True s'il y a une décision de jury pour cet étudiant émanant de ce formsemestre. + prend aussi en compte les autorisations de passage. + Sous-classée en BUT pour les RCUEs et années. + """ + return ( + self.get_etud_decisions_ue(etudid) + or self.get_etud_decision_sem(etudid) + or ScolarAutorisationInscription.query.filter_by( + origin_formsemestre_id=self.formsemestre.id, etudid=etudid + ).count() + ) def get_etud_decisions_ue(self, etudid: int) -> dict: """Decisions du jury pour les UE de cet etudiant, ou None s'il n'y en pas eu. diff --git a/app/models/validations.py b/app/models/validations.py index 6f1482381..cc5565187 100644 --- a/app/models/validations.py +++ b/app/models/validations.py @@ -131,7 +131,7 @@ class ScolarAutorisationInscription(db.Model): etudid: int, origin_formsemestre_id: int, ): - """Efface les autorisations de cette étudiant venant du sem. origine""" + """Efface les autorisations de cet étudiant venant du sem. origine""" autorisations = cls.query.filter_by( etudid=etudid, origin_formsemestre_id=origin_formsemestre_id ) diff --git a/app/scodoc/sco_formsemestre_edit.py b/app/scodoc/sco_formsemestre_edit.py index cd231467b..cdb8277a7 100644 --- a/app/scodoc/sco_formsemestre_edit.py +++ b/app/scodoc/sco_formsemestre_edit.py @@ -35,8 +35,18 @@ from flask_login import current_user from app import db from app.auth.models import User from app.models import APO_CODE_STR_LEN, SHORT_STR_LEN -from app.models import Module, ModuleImpl, Evaluation, EvaluationUEPoids, UniteEns -from app.models import ScolarNews +from app.models import ( + Module, + ModuleImpl, + Evaluation, + EvaluationUEPoids, + UniteEns, + ScolarFormSemestreValidation, + ScolarAutorisationInscription, + ApcValidationAnnee, + ApcValidationRCUE, + ScolarNews, +) from app.models.formations import Formation from app.models.formsemestre import FormSemestre from app.models.but_refcomp import ApcParcours @@ -1524,9 +1534,11 @@ Ceci n'est possible que si : cancelbutton="Annuler", ) if tf[0] == 0: - if formsemestre_has_decisions_or_compensations(formsemestre_id): + if formsemestre_has_decisions_or_compensations(formsemestre): H.append( - """
Ce semestre ne peut pas être supprimé ! (il y a des décisions de jury ou des compensations par d'autres semestres)
""" + """Ce semestre ne peut pas être supprimé ! + (il y a des décisions de jury ou des compensations par d'autres semestres) +
""" ) else: H.append(tf[1]) @@ -1560,18 +1572,32 @@ def formsemestre_delete2(formsemestre_id, dialog_confirmed=False): return flask.redirect(scu.ScoURL() + "?head_message=Semestre%20supprimé") -def formsemestre_has_decisions_or_compensations(formsemestre_id): - """True if decision de jury dans ce semestre - ou bien compensation de ce semestre par d'autre ssemestres. +def formsemestre_has_decisions_or_compensations(formsemestre: FormSemestre): + """True if decision de jury (sem. UE, RCUE, année) émanant de ce semestre + ou compensation de ce semestre par d'autres semestres + ou autorisations de passage. """ - r = ndb.SimpleDictFetch( - """SELECT v.id AS formsemestre_validation_id, v.* - FROM scolar_formsemestre_validation v - WHERE v.formsemestre_id = %(formsemestre_id)s - OR v.compense_formsemestre_id = %(formsemestre_id)s""", - {"formsemestre_id": formsemestre_id}, - ) - return r + # Validations de semestre ou d'UEs + if ScolarFormSemestreValidation.query.filter_by( + formsemestre_id=formsemestre.id + ).count(): + return True + if ScolarFormSemestreValidation.query.filter_by( + compense_formsemestre_id=formsemestre.id + ).count(): + return True + # Autorisations d'inscription: + if ScolarAutorisationInscription.query.filter_by( + origin_formsemestre_id=formsemestre.id + ).count(): + return True + # Validations d'années BUT + if ApcValidationAnnee.query.filter_by(formsemestre_id=formsemestre.id).count(): + return True + # Validations de RCUEs + if ApcValidationRCUE.query.filter_by(formsemestre_id=formsemestre.id).count(): + return True + return False def do_formsemestre_delete(formsemestre_id): diff --git a/app/scodoc/sco_pv_dict.py b/app/scodoc/sco_pv_dict.py index 9c059b62a..d597f12b6 100644 --- a/app/scodoc/sco_pv_dict.py +++ b/app/scodoc/sco_pv_dict.py @@ -154,7 +154,7 @@ def dict_pvjury( etudid=etudid, origin_formsemestre_id=formsemestre_id ).all() d["autorisations"] = [a.to_dict() for a in autorisations] - d["autorisations_descr"] = _descr_autorisations(autorisations) + d["autorisations_descr"] = descr_autorisations(autorisations) d["validation_parcours"] = Se.parcours_validated() d["parcours"] = Se.get_cursus_descr(filter_futur=True) @@ -259,7 +259,7 @@ def _comp_ects_by_ue_code(nt, decisions_ue): return ects_by_ue_code -def _descr_autorisations(autorisations: list[ScolarAutorisationInscription]) -> str: +def descr_autorisations(autorisations: list[ScolarAutorisationInscription]) -> str: "résumé textuel des autorisations d'inscription (-> 'S1, S3' )" return ", ".join([f"S{a.semestre_id}" for a in autorisations]) diff --git a/app/views/notes.py b/app/views/notes.py index 13f971639..ae2a69d37 100644 --- a/app/views/notes.py +++ b/app/views/notes.py @@ -50,7 +50,7 @@ from app.but import jury_but_view from app.comp import res_sem from app.comp.res_compat import NotesTableCompat -from app.models import ScolarNews, Scolog +from app.models import ScolarAutorisationInscription, ScolarNews, Scolog from app.models.but_refcomp import ApcNiveau, ApcParcours from app.models.config import ScoDocSiteConfig from app.models.etudiants import Identite @@ -137,8 +137,8 @@ from app.scodoc import sco_tag_module from app.scodoc import sco_ue_external from app.scodoc import sco_undo_notes from app.scodoc import sco_users -from app.scodoc import sco_xml from app.scodoc.gen_tables import GenTable +from app.scodoc.sco_pv_dict import descr_autorisations from app.scodoc.sco_permissions import Permission from app.scodoc.TrivialFormulator import TrivialFormulator from app.views import ScoData @@ -2770,6 +2770,8 @@ def formsemestre_validation_suppress_etud(