forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -14,6 +14,7 @@ Classe raccordant avec ScoDoc 7:
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
import collections
|
import collections
|
||||||
|
from operator import attrgetter
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from flask import g, url_for
|
from flask import g, url_for
|
||||||
@ -23,8 +24,6 @@ from app import log
|
|||||||
from app.comp.res_but import ResultatsSemestreBUT
|
from app.comp.res_but import ResultatsSemestreBUT
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
|
|
||||||
from app.comp import res_sem
|
|
||||||
|
|
||||||
from app.models.but_refcomp import (
|
from app.models.but_refcomp import (
|
||||||
ApcAnneeParcours,
|
ApcAnneeParcours,
|
||||||
ApcCompetence,
|
ApcCompetence,
|
||||||
@ -45,7 +44,7 @@ from app.models.formsemestre import FormSemestre, FormSemestreInscription
|
|||||||
from app.models.ues import UniteEns
|
from app.models.ues import UniteEns
|
||||||
from app.models.validations import ScolarFormSemestreValidation
|
from app.models.validations import ScolarFormSemestreValidation
|
||||||
from app.scodoc import codes_cursus as sco_codes
|
from app.scodoc import codes_cursus as sco_codes
|
||||||
from app.scodoc.codes_cursus import RED, UE_STANDARD
|
from app.scodoc.codes_cursus import code_ue_validant, RED, UE_STANDARD
|
||||||
from app.scodoc import sco_utils as scu
|
from app.scodoc import sco_utils as scu
|
||||||
from app.scodoc.sco_exceptions import ScoNoReferentielCompetences, ScoValueError
|
from app.scodoc.sco_exceptions import ScoNoReferentielCompetences, ScoValueError
|
||||||
|
|
||||||
@ -360,6 +359,40 @@ class FormSemestreCursusBUT:
|
|||||||
"cache { competence_id : competence }"
|
"cache { competence_id : competence }"
|
||||||
|
|
||||||
|
|
||||||
|
def etud_ues_de_but1_non_validees(
|
||||||
|
etud: Identite, formation: Formation, parcour: ApcParcours
|
||||||
|
) -> list[UniteEns]:
|
||||||
|
"""Vrai si cet étudiant a validé toutes ses UEs de S1 et S2, dans son parcours"""
|
||||||
|
# Les UEs avec décisions, dans les S1 ou S2 d'une formation de même code:
|
||||||
|
validations = (
|
||||||
|
ScolarFormSemestreValidation.query.filter_by(etudid=etud.id)
|
||||||
|
.filter(ScolarFormSemestreValidation.ue_id != None)
|
||||||
|
.join(UniteEns)
|
||||||
|
.filter(db.or_(UniteEns.semestre_idx == 1, UniteEns.semestre_idx == 2))
|
||||||
|
.join(Formation)
|
||||||
|
.filter_by(formation_code=formation.formation_code)
|
||||||
|
)
|
||||||
|
codes_validations_by_ue = collections.defaultdict(list)
|
||||||
|
for v in validations:
|
||||||
|
codes_validations_by_ue[v.ue_id].append(v.code)
|
||||||
|
|
||||||
|
# Les UEs du parcours en S1 et S2:
|
||||||
|
ues = formation.query_ues_parcour(parcour).filter(
|
||||||
|
db.or_(UniteEns.semestre_idx == 1, UniteEns.semestre_idx == 2)
|
||||||
|
)
|
||||||
|
# Liste triée des ues non validées
|
||||||
|
return sorted(
|
||||||
|
[
|
||||||
|
ue
|
||||||
|
for ue in ues
|
||||||
|
if any(
|
||||||
|
(not code_ue_validant(code) for code in codes_validations_by_ue[ue.id])
|
||||||
|
)
|
||||||
|
],
|
||||||
|
key=attrgetter("numero", "acronyme"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def formsemestre_warning_apc_setup(
|
def formsemestre_warning_apc_setup(
|
||||||
formsemestre: FormSemestre, res: ResultatsSemestreBUT
|
formsemestre: FormSemestre, res: ResultatsSemestreBUT
|
||||||
) -> str:
|
) -> str:
|
||||||
|
@ -69,6 +69,7 @@ from flask import flash, g, url_for
|
|||||||
|
|
||||||
from app import db
|
from app import db
|
||||||
from app import log
|
from app import log
|
||||||
|
from app.but import cursus_but
|
||||||
from app.but.cursus_but import EtudCursusBUT
|
from app.but.cursus_but import EtudCursusBUT
|
||||||
from app.comp.res_but import ResultatsSemestreBUT
|
from app.comp.res_but import ResultatsSemestreBUT
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
@ -363,15 +364,33 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
|||||||
"Vrai si plus de la moitié des RCUE validables"
|
"Vrai si plus de la moitié des RCUE validables"
|
||||||
self.passage_de_droit = self.valide_moitie_rcue and (self.nb_rcues_under_8 == 0)
|
self.passage_de_droit = self.valide_moitie_rcue and (self.nb_rcues_under_8 == 0)
|
||||||
"Vrai si peut passer dans l'année BUT suivante: plus de la moitié validables et tous > 8"
|
"Vrai si peut passer dans l'année BUT suivante: plus de la moitié validables et tous > 8"
|
||||||
# XXX TODO ajouter condition pour passage en S5
|
explanation = ""
|
||||||
|
# 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, formation, inscription.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 ???
|
||||||
|
self.passage_de_droit = False
|
||||||
|
|
||||||
# Enfin calcule les codes des UE:
|
# Enfin calcule les codes des UEs:
|
||||||
for dec_ue in self.decisions_ues.values():
|
for dec_ue in self.decisions_ues.values():
|
||||||
dec_ue.compute_codes()
|
dec_ue.compute_codes()
|
||||||
|
|
||||||
# Reste à attribuer ADM, ADJ, PASD, PAS1NCI, RED, NAR
|
# Reste à attribuer ADM, ADJ, PASD, PAS1NCI, RED, NAR
|
||||||
plural = self.nb_validables > 1
|
plural = self.nb_validables > 1
|
||||||
expl_rcues = f"""{self.nb_validables} niveau{"x" if plural else ""} validable{
|
explanation += f"""{self.nb_validables} niveau{"x" if plural else ""} validable{
|
||||||
"s" if plural else ""} sur {self.nb_competences}"""
|
"s" if plural else ""} sur {self.nb_competences}"""
|
||||||
if self.admis:
|
if self.admis:
|
||||||
self.codes = [sco_codes.ADM] + self.codes
|
self.codes = [sco_codes.ADM] + self.codes
|
||||||
@ -390,7 +409,7 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
|||||||
sco_codes.ABL,
|
sco_codes.ABL,
|
||||||
sco_codes.EXCLU,
|
sco_codes.EXCLU,
|
||||||
]
|
]
|
||||||
expl_rcues = ""
|
explanation = ""
|
||||||
elif self.passage_de_droit:
|
elif self.passage_de_droit:
|
||||||
self.codes = [sco_codes.PASD, sco_codes.ADJ] + self.codes
|
self.codes = [sco_codes.PASD, sco_codes.ADJ] + self.codes
|
||||||
elif self.valide_moitie_rcue: # mais au moins 1 rcue insuffisante
|
elif self.valide_moitie_rcue: # mais au moins 1 rcue insuffisante
|
||||||
@ -400,7 +419,7 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
|||||||
sco_codes.PAS1NCI,
|
sco_codes.PAS1NCI,
|
||||||
sco_codes.ADJ,
|
sco_codes.ADJ,
|
||||||
] + self.codes
|
] + self.codes
|
||||||
expl_rcues += f" et {self.nb_rcues_under_8} < 8"
|
explanation += f" et {self.nb_rcues_under_8} < 8"
|
||||||
else:
|
else:
|
||||||
self.codes = [
|
self.codes = [
|
||||||
sco_codes.RED,
|
sco_codes.RED,
|
||||||
@ -409,7 +428,7 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
|||||||
sco_codes.ADJ,
|
sco_codes.ADJ,
|
||||||
sco_codes.PASD, # voir #488 (discutable, conventions locales)
|
sco_codes.PASD, # voir #488 (discutable, conventions locales)
|
||||||
] + self.codes
|
] + self.codes
|
||||||
expl_rcues += f""" et {self.nb_rcues_under_8} niveau{'x' if self.nb_rcues_under_8 > 1 else ''} < 8"""
|
explanation += f""" et {self.nb_rcues_under_8} niveau{'x' if self.nb_rcues_under_8 > 1 else ''} < 8"""
|
||||||
|
|
||||||
# Si l'un des semestres est extérieur, propose ADM
|
# Si l'un des semestres est extérieur, propose ADM
|
||||||
if (
|
if (
|
||||||
@ -419,7 +438,7 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
|||||||
# Si validée par niveau supérieur:
|
# Si validée par niveau supérieur:
|
||||||
if self.code_valide == sco_codes.ADSUP:
|
if self.code_valide == sco_codes.ADSUP:
|
||||||
self.codes.insert(0, sco_codes.ADSUP)
|
self.codes.insert(0, sco_codes.ADSUP)
|
||||||
self.explanation = f"<div>{expl_rcues}</div>"
|
self.explanation = f"<div>{explanation}</div>"
|
||||||
messages = self.descr_pb_coherence()
|
messages = self.descr_pb_coherence()
|
||||||
if messages:
|
if messages:
|
||||||
self.explanation += (
|
self.explanation += (
|
||||||
@ -1261,6 +1280,8 @@ class DecisionsProposeesRCUE(DecisionsProposees):
|
|||||||
validation_rcue = validations_rcue[0]
|
validation_rcue = validations_rcue[0]
|
||||||
validation_rcue.code = sco_codes.ADSUP
|
validation_rcue.code = sco_codes.ADSUP
|
||||||
validation_rcue.date = datetime.now()
|
validation_rcue.date = datetime.now()
|
||||||
|
db.session.add(validation_rcue)
|
||||||
|
db.session.commit()
|
||||||
log(f"updating {validation_rcue}")
|
log(f"updating {validation_rcue}")
|
||||||
if validation_rcue.formsemestre_id is not None:
|
if validation_rcue.formsemestre_id is not None:
|
||||||
sco_cache.invalidate_formsemestre(
|
sco_cache.invalidate_formsemestre(
|
||||||
@ -1271,9 +1292,9 @@ class DecisionsProposeesRCUE(DecisionsProposees):
|
|||||||
validation_rcue = ApcValidationRCUE(
|
validation_rcue = ApcValidationRCUE(
|
||||||
etudid=self.etud.id, ue1_id=ue1.id, ue2_id=ue2.id, code=sco_codes.ADSUP
|
etudid=self.etud.id, ue1_id=ue1.id, ue2_id=ue2.id, code=sco_codes.ADSUP
|
||||||
)
|
)
|
||||||
|
db.session.add(validation_rcue)
|
||||||
|
db.session.commit()
|
||||||
log(f"recording {validation_rcue}")
|
log(f"recording {validation_rcue}")
|
||||||
db.session.add(validation_rcue)
|
|
||||||
db.session.commit()
|
|
||||||
self.valide_annee_inferieure()
|
self.valide_annee_inferieure()
|
||||||
|
|
||||||
def valide_annee_inferieure(self) -> None:
|
def valide_annee_inferieure(self) -> None:
|
||||||
|
@ -11,7 +11,7 @@ from app.models.events import Scolog
|
|||||||
|
|
||||||
|
|
||||||
class ScolarFormSemestreValidation(db.Model):
|
class ScolarFormSemestreValidation(db.Model):
|
||||||
"""Décisions de jury"""
|
"""Décisions de jury (sur semestre ou UEs)"""
|
||||||
|
|
||||||
__tablename__ = "scolar_formsemestre_validation"
|
__tablename__ = "scolar_formsemestre_validation"
|
||||||
# Assure unicité de la décision:
|
# Assure unicité de la décision:
|
||||||
|
@ -255,3 +255,26 @@ Etudiants:
|
|||||||
parcours: TP
|
parcours: TP
|
||||||
notes_modules:
|
notes_modules:
|
||||||
"R4.01": 14 # toutes UE
|
"R4.01": 14 # toutes UE
|
||||||
|
|
||||||
|
D: # Etudiant arrive en S4 avec une UE manquante en S1
|
||||||
|
prenom: Étudiant_TP_malaise
|
||||||
|
civilite: M
|
||||||
|
formsemestres:
|
||||||
|
S1:
|
||||||
|
parcours: TP
|
||||||
|
notes_modules:
|
||||||
|
"R1.01": 11 # toutes UEs
|
||||||
|
"SAÉ 1-2": 8 # plombe l'UE 2
|
||||||
|
S2:
|
||||||
|
parcours: TP
|
||||||
|
notes_modules:
|
||||||
|
"R2.01": 11 # toutes UEs
|
||||||
|
S3:
|
||||||
|
parcours: TP
|
||||||
|
notes_modules:
|
||||||
|
"R3.01": 12 # toutes UEs
|
||||||
|
S4:
|
||||||
|
parcours: TP
|
||||||
|
notes_modules:
|
||||||
|
"R4.01": 14 # toutes UE
|
||||||
|
"R4.04": 6 # plombe l'UE1
|
||||||
|
@ -146,7 +146,7 @@ def create_formsemestre(
|
|||||||
return formsemestre
|
return formsemestre
|
||||||
|
|
||||||
|
|
||||||
def create_evaluations(formsemestre: FormSemestre):
|
def create_evaluations(formsemestre: FormSemestre, publish_incomplete=True):
|
||||||
"""Crée une évaluation dans chaque module du semestre"""
|
"""Crée une évaluation dans chaque module du semestre"""
|
||||||
for modimpl in formsemestre.modimpls:
|
for modimpl in formsemestre.modimpls:
|
||||||
evaluation = Evaluation(
|
evaluation = Evaluation(
|
||||||
@ -156,6 +156,7 @@ def create_evaluations(formsemestre: FormSemestre):
|
|||||||
coefficient=1.0,
|
coefficient=1.0,
|
||||||
note_max=20.0,
|
note_max=20.0,
|
||||||
numero=1,
|
numero=1,
|
||||||
|
publish_incomplete=publish_incomplete,
|
||||||
)
|
)
|
||||||
db.session.add(evaluation)
|
db.session.add(evaluation)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user