forked from ScoDoc/ScoDoc
135 lines
5.3 KiB
Python
135 lines
5.3 KiB
Python
##############################################################################
|
|
# 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()
|