forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -102,7 +102,7 @@ class EtudCursusBUT:
|
|||||||
"Liste des inscriptions aux sem. de la formation, triées par indice et chronologie"
|
"Liste des inscriptions aux sem. de la formation, triées par indice et chronologie"
|
||||||
self.parcour: ApcParcours = self.inscriptions[-1].parcour
|
self.parcour: ApcParcours = self.inscriptions[-1].parcour
|
||||||
"Le parcours à valider: celui du DERNIER semestre suivi (peut être None)"
|
"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 }"
|
"{ annee:int : liste des niveaux à valider }"
|
||||||
self.niveaux: dict[int, ApcNiveau] = {}
|
self.niveaux: dict[int, ApcNiveau] = {}
|
||||||
"cache les niveaux"
|
"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.
|
# 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:
|
if self.passage_de_droit and self.annee_but == 2:
|
||||||
inscription = formsemestre.etuds_inscriptions.get(etud.id)
|
inscription = formsemestre.etuds_inscriptions.get(etud.id)
|
||||||
if inscription:
|
if not inscription or inscription.etat != scu.INSCRIT:
|
||||||
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:
|
|
||||||
# pas inscrit dans le semestre courant ???
|
# pas inscrit dans le semestre courant ???
|
||||||
self.passage_de_droit = False
|
self.passage_de_droit = False
|
||||||
|
else:
|
||||||
|
self.passage_de_droit, explanation = self.passage_de_droit_en_but3()
|
||||||
|
|
||||||
# Enfin calcule les codes des UEs:
|
# Enfin calcule les codes des UEs:
|
||||||
for dec_ue in self.decisions_ues.values():
|
for dec_ue in self.decisions_ues.values():
|
||||||
@ -423,6 +413,53 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
|||||||
)
|
)
|
||||||
self.codes = [self.codes[0]] + sorted(self.codes[1:])
|
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)
|
# WIP TODO XXX def get_moyenne_annuelle(self)
|
||||||
|
|
||||||
def infos(self) -> str:
|
def infos(self) -> str:
|
||||||
@ -1235,13 +1272,16 @@ class DecisionsProposeesRCUE(DecisionsProposees):
|
|||||||
self, semestre_id: int, ordre_inferieur: int, competence: ApcCompetence
|
self, semestre_id: int, ordre_inferieur: int, competence: ApcCompetence
|
||||||
):
|
):
|
||||||
"""Au besoin, enregistre une validation d'UE ADSUP pour le niveau de compétence
|
"""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] = (
|
validations_ues: list[ScolarFormSemestreValidation] = (
|
||||||
ScolarFormSemestreValidation.query.filter_by(etudid=self.etud.id)
|
ScolarFormSemestreValidation.query.filter_by(etudid=self.etud.id)
|
||||||
.join(UniteEns)
|
.join(UniteEns)
|
||||||
.filter_by(semestre_idx=semestre_id)
|
.filter_by(semestre_idx=semestre_id_inferieur)
|
||||||
.join(ApcNiveau)
|
.join(ApcNiveau)
|
||||||
.filter_by(ordre=ordre_inferieur)
|
.filter_by(ordre=ordre_inferieur)
|
||||||
.join(ApcCompetence)
|
.join(ApcCompetence)
|
||||||
@ -1256,13 +1296,14 @@ class DecisionsProposeesRCUE(DecisionsProposees):
|
|||||||
# Il faut créer une validation d'UE
|
# Il faut créer une validation d'UE
|
||||||
# cherche l'UE de notre formation associée à ce niveau
|
# cherche l'UE de notre formation associée à ce niveau
|
||||||
# et warning si il n'y en a pas
|
# 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:
|
if not ue:
|
||||||
# programme incomplet ou mal paramétré
|
# programme incomplet ou mal paramétré
|
||||||
flash(
|
flash(
|
||||||
f"""Impossible de valider l'UE inférieure du niveau {
|
f"""Impossible de valider l'UE inférieure de la compétence {
|
||||||
ordre_inferieur
|
competence.titre} (niveau {ordre_inferieur})
|
||||||
} de la compétence {competence.titre}
|
|
||||||
car elle n'existe pas dans la formation
|
car elle n'existe pas dans la formation
|
||||||
""",
|
""",
|
||||||
"warning",
|
"warning",
|
||||||
|
@ -364,6 +364,9 @@ class ApcNiveau(db.Model, XMLModel):
|
|||||||
return f"""<{self.__class__.__name__} {self.id} ordre={self.ordre!r} annee={
|
return f"""<{self.__class__.__name__} {self.id} ordre={self.ordre!r} annee={
|
||||||
self.annee!r} {self.competence!r}>"""
|
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):
|
def to_dict(self, with_app_critiques=True):
|
||||||
"as a dict, recursif (ou non) sur les AC"
|
"as a dict, recursif (ou non) sur les AC"
|
||||||
return {
|
return {
|
||||||
|
@ -35,6 +35,8 @@ quelle que soit leur origine.</p>
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div class="sco_box">
|
<div class="sco_box">
|
||||||
<div class="sco_box_title">Autres actions:</div>
|
<div class="sco_box_title">Autres actions:</div>
|
||||||
<ul>
|
<ul>
|
||||||
@ -60,8 +62,6 @@ quelle que soit leur origine.</p>
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -109,6 +109,16 @@ FormSemestres:
|
|||||||
idx: 1
|
idx: 1
|
||||||
date_debut: 2022-09-02
|
date_debut: 2022-09-02
|
||||||
date_fin: 2023-01-12
|
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:
|
Etudiants:
|
||||||
geii8:
|
geii8:
|
||||||
@ -1326,3 +1336,74 @@ Etudiants:
|
|||||||
# moy_rcue: 13.5000 # Pas de moyenne calculée
|
# moy_rcue: 13.5000 # Pas de moyenne calculée
|
||||||
est_compensable: False
|
est_compensable: False
|
||||||
decision_annee: ATJ # Passage tout de même en S3
|
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