Jurys BUT: améliore message erreur si pas RCUE

This commit is contained in:
Emmanuel Viennet 2022-06-26 09:37:50 +02:00
parent 21460df51a
commit 4f7827f8c2
3 changed files with 72 additions and 15 deletions

View File

@ -63,6 +63,8 @@ from operator import attrgetter
import re import re
from typing import Union from typing import Union
from flask import g, url_for
from app import db from app import db
from app import log from app import log
from app.comp.res_but import ResultatsSemestreBUT from app.comp.res_but import ResultatsSemestreBUT
@ -93,6 +95,32 @@ from app.scodoc import sco_utils as scu
from app.scodoc.sco_exceptions import ScoException, ScoValueError from app.scodoc.sco_exceptions import ScoException, ScoValueError
class NoRCUEError(ScoValueError):
"""Erreur en cas de RCUE manquant"""
def __init__(self, deca: "DecisionsProposeesAnnee", ue: UniteEns):
if all(u.niveau_competence for u in deca.ues_pair):
warning_pair = ""
else:
warning_pair = """<div class="warning">certaines UE du semestre pair ne sont pas associées à un niveau de compétence</div>"""
if all(u.niveau_competence for u in deca.ues_impair):
warning_impair = ""
else:
warning_impair = """<div class="warning">certaines UE du semestre impair ne sont pas associées à un niveau de compétence</div>"""
msg = (
f"""<h3>Pas de RCUE pour l'UE {ue.acronyme}</h3>
{warning_impair}
{warning_pair}
<div><b>UE {ue.acronyme}</b>: niveau {html.escape(str(ue.niveau_competence))}</div>
<div><b>UEs impaires:</b> {html.escape(', '.join(str(u.niveau_competence or "pas de niveau")
for u in deca.ues_impair))}
</div>
"""
+ deca.infos()
)
super().__init__(msg)
class DecisionsProposees: class DecisionsProposees:
"""Une décision de jury proposé, constituée d'une liste de codes et d'une explication. """Une décision de jury proposé, constituée d'une liste de codes et d'une explication.
Super-classe, spécialisée pour les UE, les RCUE, les années et le diplôme. Super-classe, spécialisée pour les UE, les RCUE, les années et le diplôme.
@ -196,6 +224,8 @@ class DecisionsProposeesAnnee(DecisionsProposees):
) )
"le rang de l'année dans le BUT: 1, 2, 3" "le rang de l'année dans le BUT: 1, 2, 3"
assert self.annee_but in (1, 2, 3) assert self.annee_but in (1, 2, 3)
self.rcues_annee = []
"RCUEs de l'année"
if self.formsemestre_impair is not None: if self.formsemestre_impair is not None:
self.validation = ApcValidationAnnee.query.filter_by( self.validation = ApcValidationAnnee.query.filter_by(
etudid=self.etud.id, etudid=self.etud.id,
@ -234,7 +264,6 @@ class DecisionsProposeesAnnee(DecisionsProposees):
} }
) )
self.rcues_annee = self.compute_rcues_annee() self.rcues_annee = self.compute_rcues_annee()
"RCUEs de l'année"
formation = ( formation = (
self.formsemestre_impair.formation self.formsemestre_impair.formation
@ -295,15 +324,41 @@ class DecisionsProposeesAnnee(DecisionsProposees):
def infos(self) -> str: def infos(self) -> str:
"informations, for debugging purpose" "informations, for debugging purpose"
return f"""DecisionsProposeesAnnee return f"""<b>DecisionsProposeesAnnee</b>
etud: {self.etud} <ul>
formsemestre_impair: {self.formsemestre_impair} <li>Etudiant: <a href="{url_for("scolar.ficheEtud",
formsemestre_pair: {self.formsemestre_pair} scodoc_dept=g.scodoc_dept, etudid=self.etud.id)
RCUEs: {self.rcues_annee} }">{self.etud.nomprenom}</a>
nb_competences: {self.nb_competences} </li>
nb_nb_validables: {self.nb_validables} <li>formsemestre_impair: <a href="{url_for("notes.formsemestre_status",
codes: {self.codes} scodoc_dept=g.scodoc_dept, formsemestre_id=self.formsemestre_impair.id)
explanation: {self.explanation} }">{html.escape(str(self.formsemestre_impair))}</a>
<ul>
<li>Formation: <a href="{url_for('notes.ue_table', scodoc_dept=g.scodoc_dept,
semestre_idx=self.formsemestre_impair.semestre_id,
formation_id=self.formsemestre_impair.formation.id)}">
{self.formsemestre_impair.formation.to_html()} ({self.formsemestre_impair.formation.id})</a>
</li>
</ul>
</li>
<li>formsemestre_pair: <a href="{url_for("notes.formsemestre_status",
scodoc_dept=g.scodoc_dept, formsemestre_id=self.formsemestre_pair.id)
}">{html.escape(str(self.formsemestre_pair))}</a>
<ul>
<li>Formation: <a href="{url_for('notes.ue_table', scodoc_dept=g.scodoc_dept,
semestre_idx=self.formsemestre_pair.semestre_id,
formation_id=self.formsemestre_pair.formation.id)}">
{self.formsemestre_pair.formation.to_html()} ({self.formsemestre_pair.formation.id})</a>
</li>
</ul>
</li>
<li>RCUEs: {html.escape(str(self.rcues_annee))}</li>
<li>nb_competences: {getattr(self, "nb_competences", "-")}</li>
<li>nb_nb_validables: {getattr(self, "nb_validables", "-")}</li>
<li>codes: {self.codes}</li>
<li>explanation: {self.explanation}</li>
</ul>
""" """
def annee_scolaire(self) -> int: def annee_scolaire(self) -> int:
@ -416,11 +471,11 @@ class DecisionsProposeesAnnee(DecisionsProposees):
ues_impair_sans_rcue.discard(ue_impair.id) ues_impair_sans_rcue.discard(ue_impair.id)
break break
if rcue is None: if rcue is None:
raise ScoValueError(f"pas de RCUE pour l'UE {ue_pair.acronyme}") raise NoRCUEError(deca=self, ue=ue_pair)
rcues_annee.append(rcue) rcues_annee.append(rcue)
if len(ues_impair_sans_rcue) > 0: if len(ues_impair_sans_rcue) > 0:
ue = UniteEns.query.get(ues_impair_sans_rcue.pop()) ue = UniteEns.query.get(ues_impair_sans_rcue.pop())
raise ScoValueError(f"pas de RCUE pour l'UE {ue.acronyme}") raise NoRCUEError(deca=self, ue=ue)
return rcues_annee return rcues_annee
def compute_decisions_niveaux(self) -> dict[int, "DecisionsProposeesRCUE"]: def compute_decisions_niveaux(self) -> dict[int, "DecisionsProposeesRCUE"]:

View File

@ -57,6 +57,10 @@ class Formation(db.Model):
def __repr__(self): def __repr__(self):
return f"<{self.__class__.__name__}(id={self.id}, dept_id={self.dept_id}, acronyme='{self.acronyme!r}')>" return f"<{self.__class__.__name__}(id={self.id}, dept_id={self.dept_id}, acronyme='{self.acronyme!r}')>"
def to_html(self) -> str:
"titre complet pour affichage"
return f"""Formation {self.titre} ({self.acronyme}) [version {self.version}] code {self.formation_code}"""
def to_dict(self): def to_dict(self):
e = dict(self.__dict__) e = dict(self.__dict__)
e.pop("_sa_instance_state", None) e.pop("_sa_instance_state", None)

View File

@ -676,9 +676,7 @@ def ue_table(formation_id=None, semestre_idx=1, msg=""): # was ue_list
], ],
page_title=f"Programme {formation.acronyme}", page_title=f"Programme {formation.acronyme}",
), ),
f"""<h2>Formation {formation.titre} ({formation.acronyme}) f"""<h2>{formation.to_html()} {lockicon}
[version {formation.version}] code {formation.formation_code}
{lockicon}
</h2> </h2>
""", """,
] ]