""" Test jury BUT avec parcours """ import datetime import os from pathlib import Path from flask import current_app, g import pytest import yaml import app from app import db from app.auth.models import User from app.but.import_refcomp import orebut_import_refcomp from app.models import ( ApcParcours, ApcReferentielCompetences, Evaluation, Formation, FormSemestre, Identite, Module, ModuleImpl, ModuleUECoef, ) from app.scodoc import sco_formations from app.scodoc import sco_formsemestre_inscriptions from app.scodoc import sco_groups from app.scodoc import sco_saisie_notes from app.scodoc import sco_utils as scu from config import TestConfig from tests.conftest import RESOURCES_DIR DEPT = TestConfig.DEPT_TEST def setup_but_formation(doc: dict) -> Formation: """Importe la formation BUT, l'associe au référentiel de compétences. Après cette fonction, on a une formation chargée, et associée à son ref. comp. """ refcomp_filename = doc["ReferentielCompetencesFilename"] refcomp_specialite = doc["ReferentielCompetencesSpecialite"] app.set_sco_dept(DEPT) # Lecture fichier XML local: with open( os.path.join(RESOURCES_DIR, "formations", doc["FormationFilename"]), encoding="utf-8", ) as f: doc = f.read() # --- Création de la formation formation_id, _, _ = sco_formations.formation_import_xml(doc) formation: Formation = Formation.query.get(formation_id) assert formation # --- Chargement Référentiel if ( ApcReferentielCompetences.query.filter_by( scodoc_orig_filename=refcomp_filename, dept_id=g.scodoc_dept_id ).first() is None ): # pas déjà chargé filename = ( Path(current_app.config["SCODOC_DIR"]) / "ressources/referentiels/but2022/competences" / refcomp_filename ) with open(filename, encoding="utf-8") as f: xml_data = f.read() referentiel_competence = orebut_import_refcomp( xml_data, dept_id=g.scodoc_dept_id, orig_filename=Path(filename).name ) assert referentiel_competence # --- Association au référentiel de compétences referentiel_competence = ApcReferentielCompetences.query.filter_by( specialite=refcomp_specialite ).first() # le recherche à nouveau (test) assert referentiel_competence formation.referentiel_competence_id = referentiel_competence.id db.session.add(formation) db.session.commit() return formation def _un_semestre( formation: Formation, parcours: list[ApcParcours], semestre_id: int, titre: str, date_debut: str, date_fin: str, ) -> FormSemestre: "Création d'un formsemetre" formsemestre = FormSemestre( formation=formation, parcours=parcours, dept_id=g.scodoc_dept_id, titre=titre, semestre_id=semestre_id, date_debut=date_debut, date_fin=date_fin, ) # set responsable (list) a_user = User.query.first() formsemestre.responsables = [a_user] db.session.add(formsemestre) # Ajoute pour chaque UE une ressource avec un coef vers cette UE added_ressources = set() for parcour in parcours + [None]: for ue in formation.query_ues_parcour(parcour): ressource = ( Module.query.filter_by( formation=formation, semestre_id=1, module_type=scu.ModuleType.RESSOURCE, ) .join(ModuleUECoef) .filter_by(ue=ue) .first() ) if ressource is not None: if ressource.id not in added_ressources: modimpl = ModuleImpl(module=ressource, responsable_id=a_user.id) db.session.add(modimpl) formsemestre.modimpls.append(modimpl) added_ressources.add(ressource.id) # Ajoute la première SAE sae = formation.modules.filter_by( semestre_id=1, module_type=scu.ModuleType.SAE ).first() modimpl = ModuleImpl(module=sae, responsable_id=a_user.id) formsemestre.modimpls.append(modimpl) # Crée une évaluation dans chaque module create_evaluations(formsemestre) # Partition par défaut: db.session.commit() partition_id = sco_groups.partition_create( formsemestre.id, default=True, redirect=False ) _ = sco_groups.create_group(partition_id, default=True) # Partition de parcours: formsemestre.setup_parcours_groups() return formsemestre def create_evaluations(formsemestre: FormSemestre): """Crée une évaluation dans chaque module du semestre""" for modimpl in formsemestre.modimpls: evaluation = Evaluation( moduleimpl=modimpl, jour=formsemestre.date_debut, description=f"Exam {modimpl.module.titre}", coefficient=1.0, note_max=20.0, numero=1, ) db.session.add(evaluation) # Affecte les mêmes poids que les coefs APC: ue_coef_dict = modimpl.module.get_ue_coef_dict() # { ue_id : coef } evaluation.set_ue_poids_dict(ue_coef_dict) def note_les_modules(doc: dict): """Saisie les notes des étudiants""" a_user = User.query.first() for nom, infos in doc["Etudiants"].items(): etud: Identite = Identite.query.filter_by(nom=nom).first() assert etud is not None for titre, sem_infos in infos["formsemestres"].items(): formsemestre: FormSemestre = FormSemestre.query.filter_by( titre=titre ).first() assert formsemestre is not None for code_module, note in sem_infos.get("notes_modules", {}).items(): modimpl = ( formsemestre.modimpls.join(Module) .filter_by(code=code_module) .first() ) # le sem. doit avoir un module du code indiqué: assert modimpl is not None for evaluation in modimpl.evaluations: # s'il y a plusieurs evals, affecte la même note à chacune sco_saisie_notes.notes_add( a_user, evaluation.id, [(etud.id, float(note))], comment="note_les_modules", ) def setup_but_formsemestres(formation: Formation, doc: str): """Création des formsemestres pour tester les parcours BUT""" for titre, infos in doc["FormSemestres"].items(): parcours = [] for code_parcour in infos["codes_parcours"]: parcour = formation.referentiel_competence.parcours.filter_by( code=code_parcour ).first() assert parcour is not None parcours.append(parcour) _ = _un_semestre( formation, parcours, infos["idx"], titre, infos["date_debut"], infos["date_fin"], ) db.session.flush() assert FormSemestre.query.count() == len(doc["FormSemestres"]) def inscrit_les_etudiants(formation: Formation, doc: dict): """Inscrit les étudiants dans chacun de leurs formsemestres""" for nom, infos in doc["Etudiants"].items(): etud = Identite.create_etud( dept_id=g.scodoc_dept_id, nom=nom, prenom=infos["prenom"], civilite=infos["civilite"], ) db.session.add(etud) db.session.commit() # L'inscrire à ses formsemestres for titre, sem_infos in infos["formsemestres"].items(): formsemestre: FormSemestre = FormSemestre.query.filter_by( titre=titre ).first() assert formsemestre is not None partition_parcours = formsemestre.partitions.filter_by( partition_name=scu.PARTITION_PARCOURS ).first() if partition_parcours is None: group_ids = [] else: group = partition_parcours.groups.filter_by( group_name=sem_infos["parcours"] ).first() assert group is not None # le groupe de parcours doit exister group_ids = [group.id] sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules( formsemestre.id, etud.id, group_ids=group_ids, etat=scu.INSCRIT, method="tests/unit/inscrit_les_etudiants", ) # Met à jour les inscriptions: for formsemestre in formation.formsemestres: formsemestre.update_inscriptions_parcours_from_groups() def test_but_jury(test_client): "Test jurys BUT1, BUT2 avec parcours" with open("tests/unit/cursus_but_gb.yaml", encoding="utf-8") as f: doc = yaml.safe_load(f.read()) formation = setup_but_formation(doc) setup_but_formsemestres(formation, doc) inscrit_les_etudiants(formation, doc) note_les_modules(doc)