############################################################################## # ScoDoc # Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved. # See LICENSE ############################################################################## """Jury édition manuelle des décisions RCUE antérieures """ from flask import render_template from app import db, log from app.but import cursus_but from app.models import ( ApcCompetence, ApcNiveau, ApcReferentielCompetences, # ApcValidationAnnee, # TODO ApcValidationRCUE, Formation, FormSemestre, Identite, # ScolarAutorisationInscription, ScolarFormSemestreValidation, UniteEns, ) from app.models.ues import UEParcours from app.scodoc import codes_cursus from app.scodoc.sco_exceptions import ScoNoReferentielCompetences, ScoValueError from app.views import ScoData def validation_rcues(etud: Identite, formsemestre: FormSemestre, edit: bool = False): """Page de saisie des décisions de RCUEs "antérieures" On peut l'utiliser pour saisir la validation de n'importe quel RCUE d'une année antérieure et de la formation du formsemestre indiqué. """ formation: Formation = formsemestre.formation refcomp = formation.referentiel_competence if refcomp is None: raise ScoNoReferentielCompetences(formation=formation) if etud.id not in formsemestre.etuds_inscriptions: raise ScoValueError( f"Etudiant {etud.nom_prenom()} non inscrit à {formsemestre.titre_mois()}" ) parcour = formsemestre.etuds_inscriptions[etud.id].parcour # Si non inscrit à un parcours, prend toutes les compétences competences_parcour, ects_parcours = cursus_but.parcour_formation_competences( parcour, formation ) ue_validation_by_niveau = get_ue_validation_by_niveau(refcomp, etud) rcue_validation_by_niveau = get_rcue_validation_by_niveau( refcomp, etud, None if parcour is None else parcour.id ) ects_acquis = sum((v.ects() for v in ue_validation_by_niveau.values())) return render_template( "but/validation_rcues.j2", competences_parcour=competences_parcour, edit=edit, ects_acquis=ects_acquis, ects_parcours=ects_parcours, formation=formation, parcour=parcour, rcue_validation_by_niveau=rcue_validation_by_niveau, rcue_codes=sorted(codes_cursus.CODES_JURY_RCUE), sco=ScoData(formsemestre=formsemestre, etud=etud), title=f"{formation.acronyme} - Niveaux et UEs", ue_validation_by_niveau=ue_validation_by_niveau, ) def get_ue_validation_by_niveau( refcomp: ApcReferentielCompetences, etud: Identite ) -> dict[tuple[int, str], ScolarFormSemestreValidation]: """Les validations d'UEs de cet étudiant liées à ce référentiel de compétences dans le parcours suivi par l'étudiant (celui de son semestre le plus récent dans un semestre de ce référentiel). Pour chaque niveau / pair ou impair, choisi la "meilleure" validation. """ parcour = cursus_but.get_etud_parcours(etud, refcomp.id) validations = ( cursus_but.but_validations_ues_parcours(etud, parcour.id) if parcour is not None else cursus_but.but_validations_ues(etud, refcomp.id) ) # La meilleure validation pour chaque UE ue_validation_by_niveau = {} # { (niveau_id, pair|impair) : validation } for validation in validations: if validation.ue.niveau_competence is None: log( f"""validation_rcues: ignore validation d'UE { validation.ue.id} pas de niveau de competence""" ) key = ( validation.ue.niveau_competence.id, "impair" if validation.ue.semestre_idx % 2 else "pair", ) existing = ue_validation_by_niveau.get(key, None) if (not existing) or ( codes_cursus.BUT_CODES_ORDER[existing.code] < codes_cursus.BUT_CODES_ORDER[validation.code] ): ue_validation_by_niveau[key] = validation return ue_validation_by_niveau def get_rcue_validation_by_niveau( refcomp: ApcReferentielCompetences, etud: Identite, parcour_id: int | None ) -> dict[int, ApcValidationRCUE]: """Les validations d'UEs de cet étudiant liées à ce référentiel de compétences. Si parcour_id n'est pas None, restreint aux niveaux de ce parcours et du tronc commun. Pour chaque niveau / pair ou impair, choisi la "meilleure" validation. """ validations: list[ApcValidationRCUE] = ( ApcValidationRCUE.query.filter_by(etudid=etud.id) .join(UniteEns, UniteEns.id == ApcValidationRCUE.ue2_id) .join(ApcNiveau, UniteEns.niveau_competence_id == ApcNiveau.id) .join(ApcCompetence) .filter_by(referentiel_id=refcomp.id) .filter( db.or_( UniteEns.id.in_( UEParcours.query.with_entities(UEParcours.ue_id).filter( UEParcours.parcours_id == parcour_id ) ), ~UniteEns.id.in_(UEParcours.query.with_entities(UEParcours.ue_id)), ) ) .all() ) return { validation.ue2.niveau_competence.id: validation for validation in validations }