Corrige Import/Export formations BUT en XML

This commit is contained in:
Emmanuel Viennet 2022-10-24 23:18:45 +02:00
parent 557a0c3f6d
commit 1598537f24
5 changed files with 140 additions and 52 deletions

View File

@ -376,7 +376,9 @@ class ApcAppCritique(db.Model, XMLModel):
query = query.filter(ApcNiveau.competence == competence) query = query.filter(ApcNiveau.competence == competence)
return query return query
def to_dict(self) -> dict: def to_dict(self, with_code=False) -> dict:
if with_code:
return {"code": self.code, "libelle": self.libelle}
return {"libelle": self.libelle} return {"libelle": self.libelle}
def get_label(self) -> str: def get_label(self) -> str:

View File

@ -135,7 +135,6 @@ def do_ue_create(args):
formation.invalidate_module_coefs() formation.invalidate_module_coefs()
# news # news
ue = UniteEns.query.get(ue_id) ue = UniteEns.query.get(ue_id)
flash(f"UE créée (code {ue.ue_code})")
formation = Formation.query.get(args["formation_id"]) formation = Formation.query.get(args["formation_id"])
ScolarNews.add( ScolarNews.add(
typ=ScolarNews.NEWS_FORM, typ=ScolarNews.NEWS_FORM,
@ -512,7 +511,8 @@ def ue_edit(ue_id=None, create=False, formation_id=None, default_semestre_idx=No
"semestre_id": tf[2]["semestre_idx"], "semestre_id": tf[2]["semestre_idx"],
}, },
) )
flash("UE créée") ue = UniteEns.query.get(ue_id)
flash(f"UE créée (code {ue.ue_code})")
else: else:
do_ue_edit(tf[2]) do_ue_edit(tf[2])
flash("UE modifiée") flash("UE modifiée")

View File

@ -38,9 +38,15 @@ import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
from app import db from app import db
from app import log from app import log
from app.models import Formation, Module from app.models import Formation, Module, UniteEns
from app.models import ScolarNews from app.models import ScolarNews
from app.models.but_refcomp import ApcParcours, ApcReferentielCompetences from app.models.but_refcomp import (
ApcAppCritique,
ApcCompetence,
ApcNiveau,
ApcParcours,
ApcReferentielCompetences,
)
from app.scodoc import sco_cache from app.scodoc import sco_cache
from app.scodoc import sco_codes_parcours from app.scodoc import sco_codes_parcours
from app.scodoc import sco_edit_matiere from app.scodoc import sco_edit_matiere
@ -109,23 +115,32 @@ def formation_export(
in desired format in desired format
""" """
formation: Formation = Formation.query.get_or_404(formation_id) formation: Formation = Formation.query.get_or_404(formation_id)
F = formation.to_dict(with_refcomp_attrs=True) f_dict = formation.to_dict(with_refcomp_attrs=True)
selector = {"formation_id": formation_id} selector = {"formation_id": formation_id}
if not export_external_ues: if not export_external_ues:
selector["is_external"] = False selector["is_external"] = False
ues = sco_edit_ue.ue_list(selector) ues = sco_edit_ue.ue_list(selector)
F["ue"] = ues f_dict["ue"] = ues
for ue in ues: for ue_dict in ues:
ue_id = ue["ue_id"] ue_id = ue_dict["ue_id"]
ue["reference"] = ue_id # pour les coefficients if formation.is_apc():
# BUT: indique niveau de compétence associé à l'UE
ue = UniteEns.query.get(ue_id)
if ue.niveau_competence:
ue_dict["apc_niveau_libelle"] = ue.niveau_competence.libelle
ue_dict["apc_niveau_annee"] = ue.niveau_competence.annee
ue_dict["apc_niveau_ordre"] = ue.niveau_competence.ordre
ue_dict["reference"] = ue_id # pour les coefficients
if not export_ids: if not export_ids:
del ue["id"] del ue_dict["id"]
del ue["ue_id"] del ue_dict["ue_id"]
del ue["formation_id"] del ue_dict["formation_id"]
if ue["ects"] is None: if "niveau_competence_id" in ue_dict:
del ue["ects"] del ue_dict["niveau_competence_id"]
if ue_dict["ects"] is None:
del ue_dict["ects"]
mats = sco_edit_matiere.matiere_list({"ue_id": ue_id}) mats = sco_edit_matiere.matiere_list({"ue_id": ue_id})
ue["matiere"] = mats ue_dict["matiere"] = mats
for mat in mats: for mat in mats:
matiere_id = mat["matiere_id"] matiere_id = mat["matiere_id"]
if not export_ids: if not export_ids:
@ -153,6 +168,12 @@ def formation_export(
p.to_dict(with_annees=False) for p in module.parcours p.to_dict(with_annees=False) for p in module.parcours
] ]
# Et les AC # Et les AC
if format == "xml":
# XML préfère une liste
mod["app_critiques"] = [
x.to_dict(with_code=True) for x in module.app_critiques
]
else:
mod["app_critiques"] = { mod["app_critiques"] = {
x.code: x.to_dict() for x in module.app_critiques x.code: x.to_dict() for x in module.app_critiques
} }
@ -167,7 +188,7 @@ def formation_export(
filename = f"scodoc_formation_{formation.departement.acronym}_{formation.acronyme or ''}_v{formation.version}" filename = f"scodoc_formation_{formation.departement.acronym}_{formation.acronyme or ''}_v{formation.version}"
return scu.sendResult( return scu.sendResult(
F, f_dict,
name="formation", name="formation",
format=format, format=format,
force_outer_xml_tag=False, force_outer_xml_tag=False,
@ -176,6 +197,50 @@ def formation_export(
) )
def _formation_retreive_refcomp(f_dict: dict) -> int:
"""Recherche si on un référentiel de compétence chargé pour
cette formation: utilise comme clé (version_orebut, specialite, type_titre)
Retourne: referentiel_competence_id ou None
"""
refcomp_version_orebut = f_dict.get("refcomp_version_orebut")
refcomp_specialite = f_dict.get("refcomp_specialite")
refcomp_type_titre = f_dict.get("refcomp_type_titre")
if all((refcomp_version_orebut, refcomp_specialite, refcomp_type_titre)):
refcomp = ApcReferentielCompetences.query.filter_by(
dept_id=g.scodoc_dept_id,
type_titre=refcomp_type_titre,
specialite=refcomp_specialite,
version_orebut=refcomp_version_orebut,
).first()
if refcomp:
return refcomp.id
else:
flash(
f"Impossible de trouver le référentiel de compétence pour {refcomp_specialite} : est-il chargé ?"
)
return None
def _formation_retreive_apc_niveau(
referentiel_competence_id: int, ue_dict: dict
) -> int:
"""Recherche dans le ref. de comp. un niveau pour cette UE
utilise comme clé (libelle, annee, ordre)
"""
libelle = ue_dict.get("apc_niveau_libelle")
annee = ue_dict.get("apc_niveau_annee")
ordre = ue_dict.get("apc_niveau_ordre")
if all((libelle, annee, ordre)):
niveau = (
ApcNiveau.query.filter_by(libelle=libelle, annee=annee, ordre=ordre)
.join(ApcCompetence)
.filter_by(referentiel_id=referentiel_competence_id)
).first()
if niveau is not None:
return niveau.id
return None
def formation_import_xml(doc: str, import_tags=True, use_local_refcomp=False): def formation_import_xml(doc: str, import_tags=True, use_local_refcomp=False):
"""Create a formation from XML representation """Create a formation from XML representation
(format dumped by formation_export( format='xml' )) (format dumped by formation_export( format='xml' ))
@ -206,47 +271,32 @@ def formation_import_xml(doc: str, import_tags=True, use_local_refcomp=False):
(élément 'formation' inexistant par exemple).""" (élément 'formation' inexistant par exemple)."""
) from exc ) from exc
assert D[0] == "formation" assert D[0] == "formation"
F = D[1] f_dict = D[1]
F["dept_id"] = g.scodoc_dept_id f_dict["dept_id"] = g.scodoc_dept_id
# Pour les clonages, on prend le refcomp_id donné: # Pour les clonages, on prend le refcomp_id donné:
referentiel_competence_id = ( referentiel_competence_id = (
F.get("referentiel_competence_id") if use_local_refcomp else None f_dict.get("referentiel_competence_id") if use_local_refcomp else None
) )
# Sinon, on cherche a retrouver le ref. comp. # Sinon, on cherche a retrouver le ref. comp.
if referentiel_competence_id is None: if referentiel_competence_id is None:
refcomp_version_orebut = F.get("refcomp_version_orebut") referentiel_competence_id = _formation_retreive_refcomp(f_dict)
refcomp_specialite = F.get("refcomp_specialite") f_dict["referentiel_competence_id"] = referentiel_competence_id
refcomp_type_titre = F.get("refcomp_type_titre")
if all((refcomp_version_orebut, refcomp_specialite, refcomp_type_titre)):
refcomp = ApcReferentielCompetences.query.filter_by(
dept_id=g.scodoc_dept_id,
type_titre=refcomp_type_titre,
specialite=refcomp_specialite,
version_orebut=refcomp_version_orebut,
).first()
if refcomp:
referentiel_competence_id = refcomp.id
else:
flash(
f"Impossible de trouver le référentiel de compétence pour {refcomp_specialite} : est-il chargé ?"
)
F["referentiel_competence_id"] = referentiel_competence_id
# find new version number # find new version number
formations = sco_formations.formation_list( formations = sco_formations.formation_list(
args={ args={
"acronyme": F["acronyme"], "acronyme": f_dict["acronyme"],
"titre": F["titre"], "titre": f_dict["titre"],
"dept_id": F["dept_id"], "dept_id": f_dict["dept_id"],
} }
) )
if formations: if formations:
version = max(f["version"] or 0 for f in formations) version = max(f["version"] or 0 for f in formations)
else: else:
version = 0 version = 0
F["version"] = version + 1 f_dict["version"] = version + 1
# create formation # create formation
formation_id = sco_edit_formation.do_formation_create(F) formation_id = sco_edit_formation.do_formation_create(f_dict)
log(f"formation {formation_id} created") log(f"formation {formation_id} created")
ues_old2new = {} # xml ue_id : new ue_id ues_old2new = {} # xml ue_id : new ue_id
@ -265,6 +315,13 @@ def formation_import_xml(doc: str, import_tags=True, use_local_refcomp=False):
del ue_info[1]["ue_id"] del ue_info[1]["ue_id"]
else: else:
xml_ue_id = None xml_ue_id = None
if referentiel_competence_id is None:
if "niveau_competence_id" in ue_info[1]:
del ue_info[1]["niveau_competence_id"]
else:
ue_info[1]["niveau_competence_id"] = _formation_retreive_apc_niveau(
referentiel_competence_id, ue_info[1]
)
ue_id = sco_edit_ue.do_ue_create(ue_info[1]) ue_id = sco_edit_ue.do_ue_create(ue_info[1])
if xml_ue_id: if xml_ue_id:
ues_old2new[xml_ue_id] = ue_id ues_old2new[xml_ue_id] = ue_id
@ -304,10 +361,26 @@ def formation_import_xml(doc: str, import_tags=True, use_local_refcomp=False):
ue_reference = int(child[1]["ue_reference"]) ue_reference = int(child[1]["ue_reference"])
coef = float(child[1]["coef"]) coef = float(child[1]["coef"])
ue_coef_dict[ue_reference] = coef ue_coef_dict[ue_reference] = coef
elif child[0] == "app_critiques" and (
referentiel_competence_id is not None
):
ac_code = child[1]["code"]
ac = (
ApcAppCritique.query.filter_by(code=ac_code)
.join(ApcNiveau)
.join(ApcCompetence)
.filter_by(referentiel_id=referentiel_competence_id)
).first()
if ac is not None:
module.app_critiques.append(ac)
db.session.add(module)
else:
log(f"Warning: AC {ac_code} inexistant !")
elif child[0] == "parcours": elif child[0] == "parcours":
# Si on a un référentiel de compétences, # Si on a un référentiel de compétences,
# associe les parcours de ce module (BUT) # associe les parcours de ce module (BUT)
if referentiel_competence_id: if referentiel_competence_id is not None:
code_parcours = child[1]["code"] code_parcours = child[1]["code"]
parcours = ApcParcours.query.filter_by( parcours = ApcParcours.query.filter_by(
code=code_parcours, code=code_parcours,

View File

@ -54,13 +54,14 @@ Solution proposée (nov 2014):
""" """
import flask import flask
from flask import request from flask import flash, request
from flask_login import current_user from flask_login import current_user
from app.models.formsemestre import FormSemestre from app.models.formsemestre import FormSemestre
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app import log from app import log
from app.models import UniteEns
from app.scodoc import html_sco_header from app.scodoc import html_sco_header
from app.scodoc import sco_codes_parcours from app.scodoc import sco_codes_parcours
from app.scodoc import sco_edit_matiere from app.scodoc import sco_edit_matiere
@ -83,8 +84,11 @@ def external_ue_create(
acronyme="", acronyme="",
ue_type=sco_codes_parcours.UE_STANDARD, ue_type=sco_codes_parcours.UE_STANDARD,
ects=0.0, ects=0.0,
): ) -> int:
"""Crée UE/matiere/module/evaluation puis saisie les notes""" """Crée UE/matiere/module dans la formation du formsemestre
puis un moduleimpl.
Return: moduleimpl_id
"""
formsemestre = FormSemestre.query.get_or_404(formsemestre_id) formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
log(f"creating external UE in {formsemestre}: {acronyme}") log(f"creating external UE in {formsemestre}: {acronyme}")
@ -112,7 +116,8 @@ def external_ue_create(
"is_external": True, "is_external": True,
}, },
) )
ue = UniteEns.query.get(ue_id)
flash(f"UE créée (code {ue.ue_code})")
matiere_id = sco_edit_matiere.do_matiere_create( matiere_id = sco_edit_matiere.do_matiere_create(
{"ue_id": ue_id, "titre": titre or acronyme, "numero": 1} {"ue_id": ue_id, "titre": titre or acronyme, "numero": 1}
) )

View File

@ -679,9 +679,17 @@ def formation_import_xml_form():
return f""" return f"""
{ html_sco_header.sco_header(page_title="Import d'une formation") } { html_sco_header.sco_header(page_title="Import d'une formation") }
<h2>Import effectué !</h2> <h2>Import effectué !</h2>
<p><a class="stdlink" href="{ <ul>
<li><a class="stdlink" href="{
url_for("notes.ue_list", scodoc_dept=g.scodoc_dept, formation_id=formation_id url_for("notes.ue_list", scodoc_dept=g.scodoc_dept, formation_id=formation_id
)}">Voir la formation</a></p> )}">Voir la formation</a>
</li>
<li><a class="stdlink" href="{
url_for("notes.formation_delete", scodoc_dept=g.scodoc_dept, formation_id=formation_id
)}">Supprimer cette formation</a>
(en cas d'erreur, par exemple pour charger auparavant le référentiel de compétences)
</li>
</ul>
{ html_sco_header.sco_footer() } { html_sco_header.sco_footer() }
""" """