forked from ScoDoc/ScoDoc
Corrige Import/Export formations BUT en XML
This commit is contained in:
parent
557a0c3f6d
commit
1598537f24
@ -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:
|
||||||
|
@ -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")
|
||||||
|
@ -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,
|
||||||
|
@ -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}
|
||||||
)
|
)
|
||||||
|
@ -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() }
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user