forked from ScoDoc/DocScoDoc
WIP: jurys BUT: force jury annuel (en attendant page dédiée pour semestres isolés)
This commit is contained in:
parent
c17e2bae47
commit
0939feb9fc
@ -87,6 +87,7 @@ from app.models.formsemestre import FormSemestre, FormSemestreInscription
|
||||
from app.models.ues import UniteEns
|
||||
from app.models.validations import ScolarFormSemestreValidation
|
||||
from app.scodoc import sco_codes_parcours as sco_codes
|
||||
from app.scodoc.sco_codes_parcours import UE_STANDARD
|
||||
from app.scodoc import sco_utils as scu
|
||||
from app.scodoc.sco_exceptions import ScoException, ScoValueError
|
||||
|
||||
@ -211,13 +212,17 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
||||
for ue in self.ues_pair
|
||||
}
|
||||
)
|
||||
assert self.parcour is not None
|
||||
self.rcues_annee = self.compute_rcues_annee()
|
||||
"RCUEs de l'année"
|
||||
|
||||
formation = (
|
||||
self.formsemestre_impair.formation
|
||||
if self.formsemestre_impair
|
||||
else self.formsemestre_pair.formation
|
||||
)
|
||||
self.niveaux_competences = ApcNiveau.niveaux_annee_de_parcours(
|
||||
self.parcour, self.annee_but
|
||||
).all() # XXX à trier, selon l'ordre des UE associées ?
|
||||
self.parcour, self.annee_but, formation.referentiel_competence
|
||||
).all() # non triés
|
||||
"liste des niveaux de compétences associés à cette année"
|
||||
self.decisions_rcue_by_niveau = self.compute_decisions_niveaux()
|
||||
"les décisions rcue associées aux niveau_id"
|
||||
@ -327,7 +332,7 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
||||
# Parcour dans lequel l'étudiant est inscrit, et liste des UEs
|
||||
if res.etuds_parcour_id[etudid] is None:
|
||||
# pas de parcour: prend toutes les UEs (non bonus)
|
||||
ues = list(res.etud_ues(etudid))
|
||||
ues = [ue for ue in res.etud_ues(etudid) if ue.type == UE_STANDARD]
|
||||
else:
|
||||
parcour = ApcParcours.query.get(res.etuds_parcour_id[etudid])
|
||||
if parcour is not None:
|
||||
@ -402,11 +407,12 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
||||
if rc.ue_1.niveau_competence_id == niveau.id:
|
||||
rcue = rc
|
||||
break
|
||||
dec_rcue = DecisionsProposeesRCUE(self, rcue)
|
||||
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)
|
||||
self.decisions_ues[dec_rcue.rcue.ue_2.id].set_rcue(dec_rcue.rcue)
|
||||
if rcue is not None:
|
||||
dec_rcue = DecisionsProposeesRCUE(self, rcue)
|
||||
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)
|
||||
self.decisions_ues[dec_rcue.rcue.ue_2.id].set_rcue(dec_rcue.rcue)
|
||||
# Ordonne par numéro d'UE
|
||||
rc_niveaux.sort(key=lambda x: x[0].rcue.ue_1.numero)
|
||||
decisions_rcue_by_niveau = {x[1]: x[0] for x in rc_niveaux}
|
||||
@ -458,7 +464,7 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
||||
|
||||
def record(self, code: str):
|
||||
"""Enregistre le code"""
|
||||
if not code in self.codes:
|
||||
if code and not code in self.codes:
|
||||
raise ScoValueError(
|
||||
f"code annee <tt>{html.escape(code)}</tt> invalide pour formsemestre {html.escape(self.formsemestre)}"
|
||||
)
|
||||
@ -467,20 +473,22 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
||||
if self.validation:
|
||||
db.session.delete(self.validation)
|
||||
db.session.flush()
|
||||
|
||||
self.validation = ApcValidationAnnee(
|
||||
etudid=self.etud.id,
|
||||
formsemestre=self.formsemestre_impair,
|
||||
ordre=self.annee_but,
|
||||
annee_scolaire=self.annee_scolaire(),
|
||||
code=code,
|
||||
)
|
||||
Scolog.logdb(
|
||||
method="jury_but",
|
||||
etudid=self.etud.id,
|
||||
msg=f"Validation année BUT{self.annee_but}: {code}",
|
||||
)
|
||||
db.session.add(self.validation)
|
||||
if code is None:
|
||||
self.validation = None
|
||||
else:
|
||||
self.validation = ApcValidationAnnee(
|
||||
etudid=self.etud.id,
|
||||
formsemestre=self.formsemestre_impair,
|
||||
ordre=self.annee_but,
|
||||
annee_scolaire=self.annee_scolaire(),
|
||||
code=code,
|
||||
)
|
||||
Scolog.logdb(
|
||||
method="jury_but",
|
||||
etudid=self.etud.id,
|
||||
msg=f"Validation année BUT{self.annee_but}: {code}",
|
||||
)
|
||||
db.session.add(self.validation)
|
||||
self.recorded = True
|
||||
|
||||
def record_all(self):
|
||||
@ -494,7 +502,10 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
||||
)
|
||||
for dec in decisions:
|
||||
if not dec.recorded:
|
||||
dec.record(dec.codes[0]) # rappel: le code par défaut est en tête
|
||||
# rappel: le code par défaut est en tête
|
||||
code = dec.codes[0] if dec.codes else None
|
||||
# s'il n'y a pas de codee, efface
|
||||
dec.record(dec.codes[0])
|
||||
|
||||
|
||||
class DecisionsProposeesRCUE(DecisionsProposees):
|
||||
@ -516,6 +527,9 @@ class DecisionsProposeesRCUE(DecisionsProposees):
|
||||
):
|
||||
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.parcour = dec_prop_annee.parcour
|
||||
self.validation = rcue.query_validations().first()
|
||||
if self.validation is not None:
|
||||
@ -529,7 +543,7 @@ class DecisionsProposeesRCUE(DecisionsProposees):
|
||||
|
||||
def record(self, code: str):
|
||||
"""Enregistre le code"""
|
||||
if not code in self.codes:
|
||||
if code and not code in self.codes:
|
||||
raise ScoValueError(
|
||||
f"code UE invalide pour ue_id={self.ue.id}: {html.escape(code)}"
|
||||
)
|
||||
@ -539,20 +553,23 @@ class DecisionsProposeesRCUE(DecisionsProposees):
|
||||
if self.validation:
|
||||
db.session.delete(self.validation)
|
||||
db.session.flush()
|
||||
self.validation = ApcValidationRCUE(
|
||||
etudid=self.etud.id,
|
||||
formsemestre_id=self.rcue.formsemestre_2.id,
|
||||
ue1_id=self.rcue.ue_1.id,
|
||||
ue2_id=self.rcue.ue_2.id,
|
||||
parcours_id=parcours_id,
|
||||
code=code,
|
||||
)
|
||||
Scolog.logdb(
|
||||
method="jury_but",
|
||||
etudid=self.etud.id,
|
||||
msg=f"Validation RCUE {repr(self.rcue)}",
|
||||
)
|
||||
db.session.add(self.validation)
|
||||
if code is None:
|
||||
self.validation = None
|
||||
else:
|
||||
self.validation = ApcValidationRCUE(
|
||||
etudid=self.etud.id,
|
||||
formsemestre_id=self.rcue.formsemestre_2.id,
|
||||
ue1_id=self.rcue.ue_1.id,
|
||||
ue2_id=self.rcue.ue_2.id,
|
||||
parcours_id=parcours_id,
|
||||
code=code,
|
||||
)
|
||||
Scolog.logdb(
|
||||
method="jury_but",
|
||||
etudid=self.etud.id,
|
||||
msg=f"Validation RCUE {repr(self.rcue)}",
|
||||
)
|
||||
db.session.add(self.validation)
|
||||
self.recorded = True
|
||||
|
||||
|
||||
@ -633,7 +650,7 @@ class DecisionsProposeesUE(DecisionsProposees):
|
||||
|
||||
def record(self, code: str):
|
||||
"""Enregistre le code"""
|
||||
if not code in self.codes:
|
||||
if code and not code in self.codes:
|
||||
raise ScoValueError(
|
||||
f"code UE invalide pour ue_id={self.ue.id}: {html.escape(code)}"
|
||||
)
|
||||
@ -642,18 +659,21 @@ class DecisionsProposeesUE(DecisionsProposees):
|
||||
if self.validation:
|
||||
db.session.delete(self.validation)
|
||||
db.session.flush()
|
||||
self.validation = ScolarFormSemestreValidation(
|
||||
etudid=self.etud.id,
|
||||
formsemestre_id=self.formsemestre.id,
|
||||
ue_id=self.ue.id,
|
||||
code=code,
|
||||
)
|
||||
Scolog.logdb(
|
||||
method="jury_but",
|
||||
etudid=self.etud.id,
|
||||
msg=f"Validation UE {self.ue.id}",
|
||||
)
|
||||
db.session.add(self.validation)
|
||||
if code is None:
|
||||
self.validation = None
|
||||
else:
|
||||
self.validation = ScolarFormSemestreValidation(
|
||||
etudid=self.etud.id,
|
||||
formsemestre_id=self.formsemestre.id,
|
||||
ue_id=self.ue.id,
|
||||
code=code,
|
||||
)
|
||||
Scolog.logdb(
|
||||
method="jury_but",
|
||||
etudid=self.etud.id,
|
||||
msg=f"Validation UE {self.ue.id}",
|
||||
)
|
||||
db.session.add(self.validation)
|
||||
self.recorded = True
|
||||
|
||||
|
||||
|
@ -228,5 +228,5 @@ class ResultatsSemestreBUT(NotesTableCompat):
|
||||
return s.index[s.notna()]
|
||||
|
||||
def etud_ues(self, etudid: int) -> Generator[UniteEns]:
|
||||
"""Liste des UE auxquelles l'étudiant est inscrit (sans bonus)."""
|
||||
"""Liste des UE auxquelles l'étudiant est inscrit."""
|
||||
return (UniteEns.query.get(ue_id) for ue_id in self.etud_ues_ids(etudid))
|
||||
|
@ -270,21 +270,33 @@ class ApcNiveau(db.Model, XMLModel):
|
||||
|
||||
@classmethod
|
||||
def niveaux_annee_de_parcours(
|
||||
cls, parcour: "ApcParcours", annee: int
|
||||
cls,
|
||||
parcour: "ApcParcours",
|
||||
annee: int,
|
||||
referentiel_competence: ApcReferentielCompetences = None,
|
||||
) -> flask_sqlalchemy.BaseQuery:
|
||||
"""Les niveaux de l'année du parcours"""
|
||||
"""Les niveaux de l'année du parcours
|
||||
Si le parcour est None, tous les niveaux de l'année
|
||||
"""
|
||||
if annee not in {1, 2, 3}:
|
||||
raise ValueError("annee invalide pour un parcours BUT")
|
||||
annee_formation = f"BUT{annee}"
|
||||
return ApcNiveau.query.filter(
|
||||
ApcParcoursNiveauCompetence.annee_parcours_id == ApcAnneeParcours.id,
|
||||
ApcParcours.id == ApcAnneeParcours.parcours_id,
|
||||
ApcParcours.referentiel == parcour.referentiel,
|
||||
ApcParcoursNiveauCompetence.competence_id == ApcCompetence.id,
|
||||
ApcCompetence.id == ApcNiveau.competence_id,
|
||||
ApcAnneeParcours.parcours == parcour,
|
||||
ApcNiveau.annee == annee_formation,
|
||||
)
|
||||
if parcour is None:
|
||||
return ApcNiveau.query.filter(
|
||||
ApcNiveau.annee == annee_formation,
|
||||
ApcCompetence.id == ApcNiveau.competence_id,
|
||||
ApcCompetence.referentiel_id == referentiel_competence.id,
|
||||
)
|
||||
else:
|
||||
return ApcNiveau.query.filter(
|
||||
ApcParcoursNiveauCompetence.annee_parcours_id == ApcAnneeParcours.id,
|
||||
ApcParcours.id == ApcAnneeParcours.parcours_id,
|
||||
ApcParcours.referentiel == parcour.referentiel,
|
||||
ApcParcoursNiveauCompetence.competence_id == ApcCompetence.id,
|
||||
ApcCompetence.id == ApcNiveau.competence_id,
|
||||
ApcAnneeParcours.parcours == parcour,
|
||||
ApcNiveau.annee == annee_formation,
|
||||
)
|
||||
|
||||
|
||||
app_critiques_modules = db.Table(
|
||||
|
@ -18,6 +18,7 @@ from app.models.ues import UniteEns
|
||||
from app.scodoc import sco_cache
|
||||
from app.scodoc import sco_codes_parcours
|
||||
from app.scodoc import sco_utils as scu
|
||||
from app.scodoc.sco_codes_parcours import UE_STANDARD
|
||||
|
||||
|
||||
class Formation(db.Model):
|
||||
@ -166,6 +167,7 @@ class Formation(db.Model):
|
||||
"""
|
||||
return UniteEns.query.filter_by(formation=self).filter(
|
||||
UniteEns.niveau_competence_id == ApcNiveau.id,
|
||||
UniteEns.type == UE_STANDARD,
|
||||
ApcParcoursNiveauCompetence.competence_id == ApcNiveau.competence_id,
|
||||
ApcParcoursNiveauCompetence.annee_parcours_id == ApcAnneeParcours.id,
|
||||
ApcAnneeParcours.parcours_id == parcour.id,
|
||||
|
@ -2248,6 +2248,8 @@ def formsemestre_validation_but(formsemestre_id: int, etudid: int):
|
||||
etud = Identite.query.get_or_404(etudid)
|
||||
res: ResultatsSemestreBUT = res_sem.load_formsemestre_results(formsemestre)
|
||||
deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre)
|
||||
if len(deca.rcues_annee) == 0:
|
||||
raise ScoValueError("année incomplète: pas de jury BUT annuel possible")
|
||||
if request.method == "POST":
|
||||
deca.record_form(request.form)
|
||||
flash("codes enregistrés")
|
||||
@ -2264,7 +2266,7 @@ def formsemestre_validation_but(formsemestre_id: int, etudid: int):
|
||||
<form method="POST">
|
||||
<div class="titre_parcours">
|
||||
<h2>Jury BUT{deca.annee_but}
|
||||
- Parcours {deca.parcour.libelle or "non spécifié"}
|
||||
- Parcours {(deca.parcour.libelle if deca.parcour else False) or "non spécifié"}
|
||||
- {deca.annee_scolaire_str()}</h2>
|
||||
</div>
|
||||
<div class="but_section_annee">
|
||||
@ -2339,13 +2341,6 @@ def formsemestre_validation_but(formsemestre_id: int, etudid: int):
|
||||
)
|
||||
H.append("</form>") # but_annee
|
||||
|
||||
# ---- Toutes les UEs, pour infos
|
||||
H.append(f"<ul>")
|
||||
for ue in formsemestre.query_ues(): # volontairement toutes les UE
|
||||
dec_proposee = jury_but.DecisionsProposeesUE(etud, formsemestre, ue)
|
||||
H.append("<li>" + html.escape(f"""{ue} : {dec_proposee}""") + "</li>")
|
||||
H.append(f"</ul>")
|
||||
H.append(f"</div>")
|
||||
return "\n".join(H) + html_sco_header.sco_footer()
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user