############################################################################## # ScoDoc # Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved. # See LICENSE ############################################################################## """Code expérimental: si deux référentiel sont presques identiques (mêmes compétences, niveaux, parcours) essaie de changer une formation de référentiel. """ from app import clear_scodoc_cache, db from app.models import ( ApcParcours, ApcReferentielCompetences, ApcValidationRCUE, Formation, FormSemestreInscription, Module, UniteEns, ) from app.scodoc.sco_exceptions import ScoValueError def map_referentiels( ref1: ApcReferentielCompetences, ref2: ApcReferentielCompetences ) -> str | tuple[dict[int, int], dict[int, int], dict[int, int]]: """Build mapping between two referentiels""" if ref1.type_structure != ref2.type_structure: return "type_structure mismatch" if ref1.type_departement != ref2.type_departement: return "type_departement mismatch" # mêmes parcours ? parcours_by_code_1 = {p.code: p for p in ref1.parcours} parcours_by_code_2 = {p.code: p for p in ref2.parcours} if parcours_by_code_1.keys() != parcours_by_code_2.keys(): return "parcours mismatch" parcours_map = { parcours_by_code_1[code].id: parcours_by_code_2[code].id for code in parcours_by_code_1 } # mêmes compétences ? competence_by_code_1 = {c.titre: c for c in ref1.competences} competence_by_code_2 = {c.titre: c for c in ref2.competences} if competence_by_code_1.keys() != competence_by_code_2.keys(): return "competences mismatch" competences_map = { competence_by_code_1[titre].id: competence_by_code_2[titre].id for titre in competence_by_code_1 } # mêmes niveaux (dans chaque compétence) ? niveaux_map = {} for titre in competence_by_code_1: c1 = competence_by_code_1[titre] c2 = competence_by_code_2[titre] niveau_by_attr_1 = {(n.annee, n.ordre, n.libelle): n for n in c1.niveaux} niveau_by_attr_2 = {(n.annee, n.ordre, n.libelle): n for n in c2.niveaux} if niveau_by_attr_1.keys() != niveau_by_attr_2.keys(): return f"niveaux mismatch in comp. '{titre}'" niveaux_map.update( {niveau_by_attr_1[a].id: niveau_by_attr_2[a].id for a in niveau_by_attr_1} ) return parcours_map, competences_map, niveaux_map def formation_change_referentiel( formation: Formation, new_ref: ApcReferentielCompetences ): """Try to change ref.""" if not formation.referentiel_competence: raise ScoValueError("formation non associée à un référentiel") if not isinstance(new_ref, ApcReferentielCompetences): raise ScoValueError("nouveau référentiel invalide") r = map_referentiels(formation.referentiel_competence, new_ref) if isinstance(r, str): raise ScoValueError(f"référentiels incompatibles: {r}") parcours_map, competences_map, niveaux_map = r formation.referentiel_competence = new_ref db.session.add(formation) # UEs - Niveaux et UEs - parcours for ue in formation.ues: if ue.niveau_competence: ue.niveau_competence_id = niveaux_map[ue.niveau_competence_id] db.session.add(ue) if ue.parcours: new_list = [ApcParcours.query.get(parcours_map[p.id]) for p in ue.parcours] ue.parcours.clear() ue.parcours.extend(new_list) db.session.add(ue) # Modules / parcours et app_critiques for module in formation.modules: if module.parcours: new_list = [ ApcParcours.query.get(parcours_map[p.id]) for p in module.parcours ] module.parcours.clear() module.parcours.extend(new_list) db.session.add(module) if module.app_critiques: # efface les apprentissages critiques module.app_critiques.clear() db.session.add(module) # ApcValidationRCUE for valid_rcue in ApcValidationRCUE.query.join( UniteEns, UniteEns.id == ApcValidationRCUE.ue1_id ).filter_by(formation_id=formation.id): if valid_rcue.parcour: valid_rcue.parcour_id = parcours_map[valid_rcue.parcour.id] db.session.add(valid_rcue) for valid_rcue in ApcValidationRCUE.query.join( UniteEns, UniteEns.id == ApcValidationRCUE.ue2_id ).filter_by(formation_id=formation.id): if valid_rcue.parcour: valid_rcue.parcour_id = parcours_map[valid_rcue.parcour.id] db.session.add(valid_rcue) # FormSemestre / parcours_formsemestre for formsemestre in formation.formsemestres: new_list = [ ApcParcours.query.get(parcours_map[p.id]) for p in formsemestre.parcours ] formsemestre.parcours.clear() formsemestre.parcours.extend(new_list) db.session.add(formsemestre) # FormSemestreInscription.parcour_id for inscr in FormSemestreInscription.query.filter_by( formsemestre_id=formsemestre.id ).filter(FormSemestreInscription.parcour_id != None): if inscr.parcour_id is not None: inscr.parcour_id = parcours_map[inscr.parcour_id] # db.session.commit() clear_scodoc_cache()