bulletins XML sans jaxml

This commit is contained in:
Emmanuel Viennet 2021-07-10 16:01:37 +02:00
parent 0afab38f6e
commit cdc1969520
2 changed files with 168 additions and 162 deletions

View File

@ -895,17 +895,16 @@ def do_formsemestre_bulletinetud(
et filigranne est un message à placer en "filigranne" (eg "Provisoire"). et filigranne est un message à placer en "filigranne" (eg "Provisoire").
""" """
if format == "xml": if format == "xml":
bul = repr( bul = sco_bulletins_xml.make_xml_formsemestre_bulletinetud(
sco_bulletins_xml.make_xml_formsemestre_bulletinetud( context,
context, formsemestre_id,
formsemestre_id, etudid,
etudid, REQUEST=REQUEST,
REQUEST=REQUEST, xml_with_decisions=xml_with_decisions,
xml_with_decisions=xml_with_decisions, force_publishing=force_publishing,
force_publishing=force_publishing, version=version,
version=version,
)
) )
return bul, "" return bul, ""
elif format == "json": elif format == "json":

View File

@ -29,16 +29,20 @@
Note: la structure de ce XML est issue de (mauvais) choix historiques Note: la structure de ce XML est issue de (mauvais) choix historiques
et ne peut pas être modifiée car d'autres logiciels l'utilisent (portail publication bulletins etudiants). et ne peut pas être modifiée car d'autres logiciels l'utilisent (portail publication
bulletins etudiants).
Je recommande d'utiliser la version JSON. Je recommande d'utiliser la version JSON.
Malheureusement, le code de génération JSON et XML sont séparés, ce qui est absurde et complique la maintenance (si on ajoute des informations aux bulletins). Malheureusement, le code de génération JSON et XML sont séparés, ce qui est absurde et
complique la maintenance (si on ajoute des informations aux bulletins).
Je propose de considérer le XMl comme "deprecated" et de ne plus le modifier, sauf nécessité.
""" """
# revu en juillet 21 pour utiliser ElementTree au lieu de jaxml
import datetime import datetime
import jaxml from xml.etree import ElementTree
from xml.etree.ElementTree import Element
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
@ -53,6 +57,7 @@ from app.scodoc import sco_groups
from app.scodoc import sco_photos from app.scodoc import sco_photos
from app.scodoc import sco_preferences from app.scodoc import sco_preferences
from app.scodoc import sco_etud from app.scodoc import sco_etud
from app.scodoc import sco_xml
# -------- Bulletin en XML # -------- Bulletin en XML
# (fonction séparée: n'utilise pas formsemestre_bulletinetud_dict() # (fonction séparée: n'utilise pas formsemestre_bulletinetud_dict()
@ -75,14 +80,12 @@ def make_xml_formsemestre_bulletinetud(
log("xml_bulletin( formsemestre_id=%s, etudid=%s )" % (formsemestre_id, etudid)) log("xml_bulletin( formsemestre_id=%s, etudid=%s )" % (formsemestre_id, etudid))
if REQUEST: if REQUEST:
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE) REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
if not doc:
doc = jaxml.XML_document(encoding=scu.SCO_ENCODING)
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
if sem["bul_hide_xml"] == "0" or force_publishing: if sem["bul_hide_xml"] == "0" or force_publishing:
published = 1 published = "1"
else: else:
published = 0 published = "0"
if xml_nodate: if xml_nodate:
docdate = "" docdate = ""
else: else:
@ -95,30 +98,34 @@ def make_xml_formsemestre_bulletinetud(
"publie": published, "publie": published,
} }
if sem["etapes"]: if sem["etapes"]:
el["etape_apo"] = sem["etapes"][0] or "" el["etape_apo"] = str(sem["etapes"][0]) or ""
n = 2 n = 2
for et in sem["etapes"][1:]: for et in sem["etapes"][1:]:
el["etape_apo" + str(n)] = et or "" el["etape_apo" + str(n)] = str(et) or ""
n += 1 n += 1
doc.bulletinetud(**el) x = Element("bulletinetud", **el)
if doc:
doc.append(x)
else:
doc = x
# Infos sur l'etudiant # Infos sur l'etudiant
etudinfo = sco_etud.get_etud_info(etudid=etudid, filled=1)[0] etudinfo = sco_etud.get_etud_info(etudid=etudid, filled=1)[0]
doc._push() doc.append(
doc.etudiant( Element(
etudid=etudid, "etudiant",
code_nip=etudinfo["code_nip"], etudid=etudid,
code_ine=etudinfo["code_ine"], code_nip=etudinfo["code_nip"],
nom=scu.quote_xml_attr(etudinfo["nom"]), code_ine=etudinfo["code_ine"],
prenom=scu.quote_xml_attr(etudinfo["prenom"]), nom=scu.quote_xml_attr(etudinfo["nom"]),
civilite=scu.quote_xml_attr(etudinfo["civilite_str"]), prenom=scu.quote_xml_attr(etudinfo["prenom"]),
sexe=scu.quote_xml_attr(etudinfo["civilite_str"]), # compat civilite=scu.quote_xml_attr(etudinfo["civilite_str"]),
photo_url=scu.quote_xml_attr(sco_photos.etud_photo_url(context, etudinfo)), sexe=scu.quote_xml_attr(etudinfo["civilite_str"]), # compat
email=scu.quote_xml_attr(etudinfo["email"]), photo_url=scu.quote_xml_attr(sco_photos.etud_photo_url(context, etudinfo)),
emailperso=scu.quote_xml_attr(etudinfo["emailperso"]), email=scu.quote_xml_attr(etudinfo["email"]),
emailperso=scu.quote_xml_attr(etudinfo["emailperso"]),
)
) )
doc._pop()
# Disponible pour publication ? # Disponible pour publication ?
if not published: if not published:
@ -158,68 +165,61 @@ def make_xml_formsemestre_bulletinetud(
context, etudid, formsemestre_id, partitions, partitions_etud_groups, nt context, etudid, formsemestre_id, partitions, partitions_etud_groups, nt
) )
doc._push() doc.append(
doc.note( Element(
value=mg, "note",
min=scu.fmt_note(nt.moy_min), value=mg,
max=scu.fmt_note(nt.moy_max), min=scu.fmt_note(nt.moy_min),
moy=scu.fmt_note(nt.moy_moy), max=scu.fmt_note(nt.moy_max),
moy=scu.fmt_note(nt.moy_moy),
)
) )
doc._pop() doc.append(Element("rang", value=str(rang), ninscrits=str(nbetuds)))
doc._push()
doc.rang(value=rang, ninscrits=nbetuds)
doc._pop()
if rang_gr: if rang_gr:
for partition in partitions: for partition in partitions:
doc._push() doc.append(
doc.rang_group( Element(
group_type=partition["partition_name"], "rang_group",
group_name=gr_name[partition["partition_id"]], group_type=partition["partition_name"],
value=rang_gr[partition["partition_id"]], group_name=gr_name[partition["partition_id"]],
ninscrits=ninscrits_gr[partition["partition_id"]], value=str(rang_gr[partition["partition_id"]]),
ninscrits=str(ninscrits_gr[partition["partition_id"]]),
)
) )
doc._pop() doc.append(Element("note_max", value="20")) # notes toujours sur 20
doc._push() doc.append(Element("bonus_sport_culture", value=str(nt.bonus[etudid])))
doc.note_max(value=20) # notes toujours sur 20
doc._pop()
doc._push()
doc.bonus_sport_culture(value=nt.bonus[etudid])
doc._pop()
# Liste les UE / modules /evals # Liste les UE / modules /evals
for ue in ues: for ue in ues:
ue_status = nt.get_etud_ue_status(etudid, ue["ue_id"]) ue_status = nt.get_etud_ue_status(etudid, ue["ue_id"])
doc._push() x_ue = Element(
doc.ue( "ue",
id=ue["ue_id"], id=ue["ue_id"],
numero=scu.quote_xml_attr(ue["numero"]), numero=scu.quote_xml_attr(ue["numero"]),
acronyme=scu.quote_xml_attr(ue["acronyme"]), acronyme=scu.quote_xml_attr(ue["acronyme"]),
titre=scu.quote_xml_attr(ue["titre"]), titre=scu.quote_xml_attr(ue["titre"]),
code_apogee=scu.quote_xml_attr(ue["code_apogee"]), code_apogee=scu.quote_xml_attr(ue["code_apogee"]),
) )
doc._push() doc.append(x_ue)
if ue["type"] != sco_codes_parcours.UE_SPORT: if ue["type"] != sco_codes_parcours.UE_SPORT:
v = ue_status["cur_moy_ue"] v = ue_status["cur_moy_ue"]
else: else:
v = nt.bonus[etudid] v = nt.bonus[etudid]
doc.note( x_ue.append(
value=scu.fmt_note(v), Element(
min=scu.fmt_note(ue["min"]), "note",
max=scu.fmt_note(ue["max"]), value=scu.fmt_note(v),
min=scu.fmt_note(ue["min"]),
max=scu.fmt_note(ue["max"]),
)
) )
doc._pop()
try: try:
ects_txt = str(int(ue["ects"])) ects_txt = str(int(ue["ects"]))
except: except (ValueError, TypeError):
ects_txt = "" ects_txt = ""
doc._push() x_ue.append(Element("ects", value=ects_txt))
doc.ects(value=ects_txt) x_ue.append(Element("rang", value=str(nt.ue_rangs[ue["ue_id"]][0][etudid])))
doc._pop() x_ue.append(Element("effectif", value=str(nt.ue_rangs[ue["ue_id"]][1])))
doc._push()
doc.rang(value=str(nt.ue_rangs[ue["ue_id"]][0][etudid]))
doc._pop()
doc._push()
doc.effectif(value=str(nt.ue_rangs[ue["ue_id"]][1]))
doc._pop()
# Liste les modules de l'UE # Liste les modules de l'UE
ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue["ue_id"]] ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue["ue_id"]]
for modimpl in ue_modimpls: for modimpl in ue_modimpls:
@ -229,46 +229,53 @@ def make_xml_formsemestre_bulletinetud(
if mod_moy == "NI": # ne mentionne pas les modules ou n'est pas inscrit if mod_moy == "NI": # ne mentionne pas les modules ou n'est pas inscrit
continue continue
mod = modimpl["module"] mod = modimpl["module"]
doc._push()
# if mod['ects'] is None: # if mod['ects'] is None:
# ects = '' # ects = ''
# else: # else:
# ects = str(mod['ects']) # ects = str(mod['ects'])
doc.module( x_mod = Element(
"module",
id=modimpl["moduleimpl_id"], id=modimpl["moduleimpl_id"],
code=mod["code"], code=mod["code"],
coefficient=mod["coefficient"], coefficient=str(mod["coefficient"]),
numero=mod["numero"], numero=str(mod["numero"]),
titre=scu.quote_xml_attr(mod["titre"]), titre=scu.quote_xml_attr(mod["titre"]),
abbrev=scu.quote_xml_attr(mod["abbrev"]), abbrev=scu.quote_xml_attr(mod["abbrev"]),
code_apogee=scu.quote_xml_attr(mod["code_apogee"]) code_apogee=scu.quote_xml_attr(mod["code_apogee"])
# ects=ects ects des modules maintenant inutilisés # ects=ects ects des modules maintenant inutilisés
) )
doc._push() x_ue.append(x_mod)
modstat = nt.get_mod_stats(modimpl["moduleimpl_id"]) modstat = nt.get_mod_stats(modimpl["moduleimpl_id"])
doc.note( x_mod.append(
value=mod_moy, Element(
min=scu.fmt_note(modstat["min"]), "note",
max=scu.fmt_note(modstat["max"]), value=mod_moy,
moy=scu.fmt_note(modstat["moy"]), min=scu.fmt_note(modstat["min"]),
max=scu.fmt_note(modstat["max"]),
moy=scu.fmt_note(modstat["moy"]),
)
) )
doc._pop()
if sco_preferences.get_preference( if sco_preferences.get_preference(
context, "bul_show_mod_rangs", formsemestre_id context, "bul_show_mod_rangs", formsemestre_id
): ):
doc._push() x_mod.append(
doc.rang(value=nt.mod_rangs[modimpl["moduleimpl_id"]][0][etudid]) Element(
doc._pop() "rang",
doc._push() value=str(nt.mod_rangs[modimpl["moduleimpl_id"]][0][etudid]),
doc.effectif(value=nt.mod_rangs[modimpl["moduleimpl_id"]][1]) )
doc._pop() )
x_mod.append(
Element(
"effectif", value=str(nt.mod_rangs[modimpl["moduleimpl_id"]][1])
)
)
# --- notes de chaque eval: # --- notes de chaque eval:
evals = nt.get_evals_in_mod(modimpl["moduleimpl_id"]) evals = nt.get_evals_in_mod(modimpl["moduleimpl_id"])
if version != "short": if version != "short":
for e in evals: for e in evals:
if int(e["visibulletin"]) == 1 or version == "long": if int(e["visibulletin"]) == 1 or version == "long":
doc._push() x_eval = Element(
doc.evaluation( "evaluation",
jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True), jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True),
heure_debut=ndb.TimetoISO8601( heure_debut=ndb.TimetoISO8601(
e["heure_debut"], null_is_empty=True e["heure_debut"], null_is_empty=True
@ -276,19 +283,18 @@ def make_xml_formsemestre_bulletinetud(
heure_fin=ndb.TimetoISO8601( heure_fin=ndb.TimetoISO8601(
e["heure_fin"], null_is_empty=True e["heure_fin"], null_is_empty=True
), ),
coefficient=e["coefficient"], coefficient=str(e["coefficient"]),
evaluation_type=e["evaluation_type"], evaluation_type=str(e["evaluation_type"]),
description=scu.quote_xml_attr(e["description"]), description=scu.quote_xml_attr(e["description"]),
note_max_origin=e[ # notes envoyées sur 20, ceci juste pour garder trace:
"note_max" note_max_origin=str(e["note_max"]),
], # notes envoyées sur 20, ceci juste pour garder trace
) )
x_mod.append(x_eval)
val = e["notes"].get(etudid, {"value": "NP"})[ val = e["notes"].get(etudid, {"value": "NP"})[
"value" "value"
] # NA si etud demissionnaire ] # NA si etud demissionnaire
val = scu.fmt_note(val, note_max=e["note_max"]) val = scu.fmt_note(val, note_max=e["note_max"])
doc.note(value=val) x_eval.append(Element("note", value=val))
doc._pop()
# Evaluations incomplètes ou futures: # Evaluations incomplètes ou futures:
complete_eval_ids = set([e["evaluation_id"] for e in evals]) complete_eval_ids = set([e["evaluation_id"] for e in evals])
if sco_preferences.get_preference( if sco_preferences.get_preference(
@ -300,8 +306,8 @@ def make_xml_formsemestre_bulletinetud(
all_evals.reverse() # plus ancienne d'abord all_evals.reverse() # plus ancienne d'abord
for e in all_evals: for e in all_evals:
if e["evaluation_id"] not in complete_eval_ids: if e["evaluation_id"] not in complete_eval_ids:
doc._push() x_eval = Element(
doc.evaluation( "evaluation",
jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True), jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True),
heure_debut=ndb.TimetoISO8601( heure_debut=ndb.TimetoISO8601(
e["heure_debut"], null_is_empty=True e["heure_debut"], null_is_empty=True
@ -309,50 +315,45 @@ def make_xml_formsemestre_bulletinetud(
heure_fin=ndb.TimetoISO8601( heure_fin=ndb.TimetoISO8601(
e["heure_fin"], null_is_empty=True e["heure_fin"], null_is_empty=True
), ),
coefficient=e["coefficient"], coefficient=str(e["coefficient"]),
description=scu.quote_xml_attr(e["description"]), description=scu.quote_xml_attr(e["description"]),
incomplete="1", incomplete="1",
note_max_origin=e[ # notes envoyées sur 20, ceci juste pour garder trace:
"note_max" note_max_origin=e["note_max"],
], # notes envoyées sur 20, ceci juste pour garder trace
) )
doc._pop() x_mod.append(x_eval)
doc._pop()
doc._pop()
# UE capitalisee (listee seulement si meilleure que l'UE courante) # UE capitalisee (listee seulement si meilleure que l'UE courante)
if ue_status["is_capitalized"]: if ue_status["is_capitalized"]:
try: try:
ects_txt = str(int(ue_status["ue"].get("ects", ""))) ects_txt = str(int(ue_status["ue"].get("ects", "")))
except: except (ValueError, TypeError):
ects_txt = "" ects_txt = ""
doc._push() x_ue = Element(
doc.ue_capitalisee( "ue_capitalisee",
id=ue["ue_id"], id=ue["ue_id"],
numero=scu.quote_xml_attr(ue["numero"]), numero=scu.quote_xml_attr(ue["numero"]),
acronyme=scu.quote_xml_attr(ue["acronyme"]), acronyme=scu.quote_xml_attr(ue["acronyme"]),
titre=scu.quote_xml_attr(ue["titre"]), titre=scu.quote_xml_attr(ue["titre"]),
) )
doc._push() doc.append(x_ue)
doc.note(value=scu.fmt_note(ue_status["moy"])) x_ue.append(Element("note", value=scu.fmt_note(ue_status["moy"])))
doc._pop() x_ue.append(Element("ects", value=ects_txt))
doc._push() x_ue.append(
doc.ects(value=ects_txt) Element("coefficient_ue", value=scu.fmt_note(ue_status["coef_ue"]))
doc._pop() )
doc._push() x_ue.append(
doc.coefficient_ue(value=scu.fmt_note(ue_status["coef_ue"])) Element(
doc._pop() "date_capitalisation",
doc._push() value=ndb.DateDMYtoISO(ue_status["event_date"]),
doc.date_capitalisation(value=ndb.DateDMYtoISO(ue_status["event_date"])) )
doc._pop() )
doc._pop()
# --- Absences # --- Absences
if sco_preferences.get_preference(context, "bul_show_abs", formsemestre_id): if sco_preferences.get_preference(context, "bul_show_abs", formsemestre_id):
AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid) abs_sem_etud = sco_abs.getAbsSemEtud(context, sem, etudid)
nbabs = AbsEtudSem.CountAbs() nbabs = abs_sem_etud.CountAbs()
nbabsjust = AbsEtudSem.CountAbsJust() nbabsjust = abs_sem_etud.CountAbsJust()
doc._push() doc.append(Element("absences", nbabs=nbabs, nbabsjust=nbabsjust))
doc.absences(nbabs=nbabs, nbabsjust=nbabsjust)
doc._pop()
# --- Decision Jury # --- Decision Jury
if ( if (
sco_preferences.get_preference(context, "bul_show_decision", formsemestre_id) sco_preferences.get_preference(context, "bul_show_decision", formsemestre_id)
@ -367,7 +368,9 @@ def make_xml_formsemestre_bulletinetud(
context, "bul_show_uevalid", formsemestre_id context, "bul_show_uevalid", formsemestre_id
), ),
) )
doc.situation(scu.quote_xml_attr(infos["situation"])) x_situation = Element("situation")
x_situation.text = scu.quote_xml_attr(infos["situation"])
doc.append(x_situation)
if dpv: if dpv:
decision = dpv["decisions"][0] decision = dpv["decisions"][0]
etat = decision["etat"] etat = decision["etat"]
@ -375,54 +378,58 @@ def make_xml_formsemestre_bulletinetud(
code = decision["decision_sem"]["code"] code = decision["decision_sem"]["code"]
else: else:
code = "" code = ""
doc._push()
if ( if (
decision["decision_sem"] decision["decision_sem"]
and "compense_formsemestre_id" in decision["decision_sem"] and "compense_formsemestre_id" in decision["decision_sem"]
): ):
doc.decision( doc.append(
code=code, Element(
etat=etat, "decision",
compense_formsemestre_id=decision["decision_sem"][ code=code,
"compense_formsemestre_id" etat=str(etat),
], compense_formsemestre_id=decision["decision_sem"][
"compense_formsemestre_id"
],
)
) )
else: else:
doc.decision(code=code, etat=etat) doc.append(Element("decision", code=code, etat=str(etat)))
doc._pop()
if decision[ if decision[
"decisions_ue" "decisions_ue"
]: # and sco_preferences.get_preference(context, 'bul_show_uevalid', formsemestre_id): always publish (car utile pour export Apogee) ]: # and sco_preferences.get_preference(context, 'bul_show_uevalid', formsemestre_id): always publish (car utile pour export Apogee)
for ue_id in decision["decisions_ue"].keys(): for ue_id in decision["decisions_ue"].keys():
ue = sco_edit_ue.do_ue_list(context, {"ue_id": ue_id})[0] ue = sco_edit_ue.do_ue_list(context, {"ue_id": ue_id})[0]
doc._push() doc.append(
doc.decision_ue( Element(
ue_id=ue["ue_id"], "decision_ue",
numero=scu.quote_xml_attr(ue["numero"]), ue_id=ue["ue_id"],
acronyme=scu.quote_xml_attr(ue["acronyme"]), numero=scu.quote_xml_attr(ue["numero"]),
titre=scu.quote_xml_attr(ue["titre"]), acronyme=scu.quote_xml_attr(ue["acronyme"]),
code=decision["decisions_ue"][ue_id]["code"], titre=scu.quote_xml_attr(ue["titre"]),
code=decision["decisions_ue"][ue_id]["code"],
)
) )
doc._pop()
for aut in decision["autorisations"]: for aut in decision["autorisations"]:
doc._push() doc.append(
doc.autorisation_inscription(semestre_id=aut["semestre_id"]) Element(
doc._pop() "autorisation_inscription", semestre_id=str(aut["semestre_id"])
)
)
else: else:
doc._push() doc.append(Element("decision", code="", etat="DEM"))
doc.decision(code="", etat="DEM")
doc._pop()
# --- Appreciations # --- Appreciations
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()
apprecs = sco_etud.appreciations_list( apprecs = sco_etud.appreciations_list(
cnx, args={"etudid": etudid, "formsemestre_id": formsemestre_id} cnx, args={"etudid": etudid, "formsemestre_id": formsemestre_id}
) )
for app in apprecs: for app in apprecs:
doc.appreciation( doc.append(
scu.quote_xml_attr(app["comment"]), date=ndb.DateDMYtoISO(app["date"]) Element(
"appreciation",
scu.quote_xml_attr(app["comment"]),
date=ndb.DateDMYtoISO(app["date"]),
)
) )
return doc return sco_xml.XML_HEADER + ElementTree.tostring(doc)