Jury BUT: cas du passage en BUT3 avec BUT1 non validé. Corrige validation ADSUP UEs. Test unitaire: geii90.
This commit is contained in:
parent
10de8c4cc2
commit
937a96d086
@ -102,7 +102,7 @@ class EtudCursusBUT:
|
||||
"Liste des inscriptions aux sem. de la formation, triées par indice et chronologie"
|
||||
self.parcour: ApcParcours = self.inscriptions[-1].parcour
|
||||
"Le parcours à valider: celui du DERNIER semestre suivi (peut être None)"
|
||||
self.niveaux_by_annee = {}
|
||||
self.niveaux_by_annee: dict[int, list[ApcNiveau]] = {}
|
||||
"{ annee:int : liste des niveaux à valider }"
|
||||
self.niveaux: dict[int, ApcNiveau] = {}
|
||||
"cache les niveaux"
|
||||
|
@ -342,21 +342,11 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
||||
# Cas particulier du passage en BUT 3: nécessité d'avoir validé toutes les UEs du BUT 1.
|
||||
if self.passage_de_droit and self.annee_but == 2:
|
||||
inscription = formsemestre.etuds_inscriptions.get(etud.id)
|
||||
if inscription:
|
||||
ues_but1_non_validees = cursus_but.etud_ues_de_but1_non_validees(
|
||||
etud, self.formsemestre.formation, self.parcour
|
||||
)
|
||||
self.passage_de_droit = not ues_but1_non_validees
|
||||
explanation += (
|
||||
f"""UEs de BUT1 non validées: <b>{
|
||||
', '.join(ue.acronyme for ue in ues_but1_non_validees)
|
||||
}</b>. """
|
||||
if ues_but1_non_validees
|
||||
else ""
|
||||
)
|
||||
else:
|
||||
if not inscription or inscription.etat != scu.INSCRIT:
|
||||
# pas inscrit dans le semestre courant ???
|
||||
self.passage_de_droit = False
|
||||
else:
|
||||
self.passage_de_droit, explanation = self.passage_de_droit_en_but3()
|
||||
|
||||
# Enfin calcule les codes des UEs:
|
||||
for dec_ue in self.decisions_ues.values():
|
||||
@ -423,6 +413,53 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
||||
)
|
||||
self.codes = [self.codes[0]] + sorted(self.codes[1:])
|
||||
|
||||
def passage_de_droit_en_but3(self) -> tuple[bool, str]:
|
||||
"""Vérifie si les conditions supplémentaires de passage BUT2 vers BUT3 sont satisfaites"""
|
||||
cursus: EtudCursusBUT = EtudCursusBUT(self.etud, self.formsemestre.formation)
|
||||
niveaux_but1 = cursus.niveaux_by_annee[1]
|
||||
|
||||
niveaux_but1_non_valides = []
|
||||
for niveau in niveaux_but1:
|
||||
ok = False
|
||||
validation_par_annee = cursus.validation_par_competence_et_annee[
|
||||
niveau.competence_id
|
||||
]
|
||||
if validation_par_annee:
|
||||
validation_niveau = validation_par_annee.get("BUT1")
|
||||
if validation_niveau and validation_niveau.code in CODES_RCUE_VALIDES:
|
||||
ok = True
|
||||
if not ok:
|
||||
niveaux_but1_non_valides.append(niveau)
|
||||
|
||||
# Les niveaux de BUT1 manquants passent-ils en ADSUP ?
|
||||
# en vertu de l'article 4.3,
|
||||
# "La validation des deux UE du niveau d’une compétence emporte la validation de
|
||||
# l’ensemble des UE du niveau inférieur de cette même compétence."
|
||||
explanation = ""
|
||||
ok = True
|
||||
for niveau_but1 in niveaux_but1_non_valides:
|
||||
niveau_but2 = niveau_but1.competence.niveaux.filter_by(annee="BUT2").first()
|
||||
if niveau_but2:
|
||||
rcue = self.rcue_by_niveau.get(niveau_but2.id)
|
||||
if (rcue is None) or (
|
||||
not rcue.est_validable() and not rcue.code_valide()
|
||||
):
|
||||
# le RCUE de BUT2 n'est ni validable (avec les notes en cours) ni déjà validé
|
||||
ok = False
|
||||
explanation += (
|
||||
f"Compétence {niveau_but1} de BUT 1 non validée.<br> "
|
||||
)
|
||||
else:
|
||||
explanation += (
|
||||
f"Compétence {niveau_but1} de BUT 1 validée par ce BUT2.<br> "
|
||||
)
|
||||
else:
|
||||
ok = False
|
||||
explanation += f"""Compétence {
|
||||
niveau_but1} de BUT 1 non validée et non existante en BUT2.<br> """
|
||||
|
||||
return ok, explanation
|
||||
|
||||
# WIP TODO XXX def get_moyenne_annuelle(self)
|
||||
|
||||
def infos(self) -> str:
|
||||
@ -1235,13 +1272,16 @@ class DecisionsProposeesRCUE(DecisionsProposees):
|
||||
self, semestre_id: int, ordre_inferieur: int, competence: ApcCompetence
|
||||
):
|
||||
"""Au besoin, enregistre une validation d'UE ADSUP pour le niveau de compétence
|
||||
semestre_id : l'indice du semestre concerné (le pair ou l'impair)
|
||||
semestre_id : l'indice du semestre concerné (le pair ou l'impair du niveau courant)
|
||||
"""
|
||||
# Les validations d'UE impaires existantes pour ce niveau inférieur ?
|
||||
semestre_id_inferieur = semestre_id - 2
|
||||
if semestre_id_inferieur < 1:
|
||||
return
|
||||
# Les validations d'UE existantes pour ce niveau inférieur ?
|
||||
validations_ues: list[ScolarFormSemestreValidation] = (
|
||||
ScolarFormSemestreValidation.query.filter_by(etudid=self.etud.id)
|
||||
.join(UniteEns)
|
||||
.filter_by(semestre_idx=semestre_id)
|
||||
.filter_by(semestre_idx=semestre_id_inferieur)
|
||||
.join(ApcNiveau)
|
||||
.filter_by(ordre=ordre_inferieur)
|
||||
.join(ApcCompetence)
|
||||
@ -1256,13 +1296,14 @@ class DecisionsProposeesRCUE(DecisionsProposees):
|
||||
# Il faut créer une validation d'UE
|
||||
# cherche l'UE de notre formation associée à ce niveau
|
||||
# et warning si il n'y en a pas
|
||||
ue = self._get_ue_inferieure(semestre_id, ordre_inferieur, competence)
|
||||
ue = self._get_ue_inferieure(
|
||||
semestre_id_inferieur, ordre_inferieur, competence
|
||||
)
|
||||
if not ue:
|
||||
# programme incomplet ou mal paramétré
|
||||
flash(
|
||||
f"""Impossible de valider l'UE inférieure du niveau {
|
||||
ordre_inferieur
|
||||
} de la compétence {competence.titre}
|
||||
f"""Impossible de valider l'UE inférieure de la compétence {
|
||||
competence.titre} (niveau {ordre_inferieur})
|
||||
car elle n'existe pas dans la formation
|
||||
""",
|
||||
"warning",
|
||||
|
@ -364,6 +364,9 @@ class ApcNiveau(db.Model, XMLModel):
|
||||
return f"""<{self.__class__.__name__} {self.id} ordre={self.ordre!r} annee={
|
||||
self.annee!r} {self.competence!r}>"""
|
||||
|
||||
def __str__(self):
|
||||
return f"""{self.competence.titre} niveau {self.ordre}"""
|
||||
|
||||
def to_dict(self, with_app_critiques=True):
|
||||
"as a dict, recursif (ou non) sur les AC"
|
||||
return {
|
||||
|
@ -35,6 +35,8 @@ quelle que soit leur origine.</p>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
<div class="sco_box">
|
||||
<div class="sco_box_title">Autres actions:</div>
|
||||
<ul>
|
||||
@ -60,8 +62,6 @@ quelle que soit leur origine.</p>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
@ -109,6 +109,16 @@ FormSemestres:
|
||||
idx: 1
|
||||
date_debut: 2022-09-02
|
||||
date_fin: 2023-01-12
|
||||
S3:
|
||||
idx: 3
|
||||
codes_parcours: ['AII']
|
||||
date_debut: 2022-09-01
|
||||
date_fin: 2023-01-15
|
||||
S4:
|
||||
idx: 4
|
||||
codes_parcours: ['AII']
|
||||
date_debut: 2023-01-16
|
||||
date_fin: 2023-07-10
|
||||
|
||||
Etudiants:
|
||||
geii8:
|
||||
@ -1326,3 +1336,74 @@ Etudiants:
|
||||
# moy_rcue: 13.5000 # Pas de moyenne calculée
|
||||
est_compensable: False
|
||||
decision_annee: ATJ # Passage tout de même en S3
|
||||
#
|
||||
# ----------------------- geii90 : ADSUP envoyés par BUT2 vers BUT1
|
||||
#
|
||||
geii90:
|
||||
prenom: etugeii90
|
||||
civilite: M
|
||||
code_nip: geii90
|
||||
formsemestres:
|
||||
S1: # 2 UEs, les deux en AJ
|
||||
notes_modules: # on joue avec les SAE seulement car elles sont "diagonales"
|
||||
"S1.1": 9.5000
|
||||
"S1.2": 8.5000
|
||||
attendu: # les codes jury que l'on doit vérifier
|
||||
deca:
|
||||
passage_de_droit: False
|
||||
nb_competences: 2
|
||||
nb_rcue_annee: 0
|
||||
decisions_ues:
|
||||
"UE11":
|
||||
codes: [ "AJ", "..." ]
|
||||
"UE12":
|
||||
codes: [ "AJ", "..." ]
|
||||
S2: # pareil, mais le jury le fait passer en S3
|
||||
notes_modules: # on joue avec les SAE seulement car elles sont "diagonales"
|
||||
"S2.1": 9.8000
|
||||
"S2.2": 9.9000
|
||||
attendu: # les codes jury que l'on doit vérifier
|
||||
deca:
|
||||
passage_de_droit: False # d'apres les notes, on ne peut pas passer
|
||||
autorisations_inscription: [2] # et le jury manuel nous fait passer
|
||||
nb_competences: 2
|
||||
nb_rcue_annee: 2
|
||||
valide_moitie_rcue: False
|
||||
codes: [ "ADJ", "ATJ", "RED", "..." ]
|
||||
code_valide: RED # le code proposé en auto
|
||||
decisions_ues:
|
||||
"UE21":
|
||||
codes: [ "AJ", "..." ]
|
||||
code_valide: AJ
|
||||
moy_ue: 9.8
|
||||
"UE22":
|
||||
code_valide: AJ
|
||||
moy_ue: 9.9
|
||||
decisions_rcues: # on repère ici les RCUE par l'acronyme de leur 1ere UE (donc du S1)
|
||||
"UE11":
|
||||
code_valide: AJ # le code proposé en auto
|
||||
rcue:
|
||||
# moy_rcue: 14.0000 # Pas de moyenne calculée
|
||||
est_compensable: False
|
||||
"UE12":
|
||||
code_valide: AJ # le code proposé en auto
|
||||
rcue:
|
||||
# moy_rcue: 13.5000 # Pas de moyenne calculée
|
||||
est_compensable: False
|
||||
decision_annee: ADJ # Passage tout de même en S3 !
|
||||
S3: # le S3 avec 4 niveaux
|
||||
parcours: AII
|
||||
notes_modules: # combinaison pour avoir ADM AJ AJ AJ
|
||||
"AII3": 9
|
||||
"ER3": 10.75
|
||||
"AU3": 8
|
||||
attendu: # les codes jury que l'on doit vérifier
|
||||
deca:
|
||||
passage_de_droit: False # d'apres les notes, on ne peut pas passer
|
||||
autorisations_inscription: [4] # passe en S4
|
||||
nb_competences: 4
|
||||
S4: # le S4 avec 4 niveaux
|
||||
parcours: AII
|
||||
notes_modules: # combinaison pour avoir ADM ADM ADM AJ
|
||||
"PF4": 12
|
||||
"SAE4AII": 8
|
||||
|
Loading…
Reference in New Issue
Block a user