329 lines
13 KiB
Python
329 lines
13 KiB
Python
# -*- mode: python -*-
|
|
# -*- coding: utf-8 -*-
|
|
|
|
##############################################################################
|
|
#
|
|
# Gestion scolarite IUT
|
|
#
|
|
# Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
#
|
|
# Emmanuel Viennet emmanuel.viennet@viennet.net
|
|
#
|
|
##############################################################################
|
|
|
|
"""Génération du bulletin en format XML / compatibilité ScoDoc 7
|
|
|
|
=> exporte quelques résultats BUT dans le format des anciens bulletins XML ScoDoc 7
|
|
afin d'avoir un affichage acceptable sur les ENT anciens.
|
|
|
|
Les plate-formes modernes utilisent uniquement la version JSON (but/bulletin_but.py)
|
|
"""
|
|
|
|
|
|
import datetime
|
|
from xml.etree import ElementTree
|
|
from xml.etree.ElementTree import Element
|
|
|
|
from app import db, log
|
|
from app.but import bulletin_but
|
|
from app.models import BulAppreciations, FormSemestre, Identite, UniteEns
|
|
import app.scodoc.sco_utils as scu
|
|
from app.scodoc import codes_cursus
|
|
from app.scodoc import sco_photos
|
|
from app.scodoc import sco_preferences
|
|
from app.scodoc import sco_xml
|
|
from app.scodoc.sco_xml import quote_xml_attr
|
|
|
|
|
|
def bulletin_but_xml_compat(
|
|
formsemestre_id,
|
|
etudid,
|
|
doc=None, # XML document
|
|
force_publishing=False,
|
|
xml_nodate=False,
|
|
xml_with_decisions=False, # inclue les decisions même si non publiées
|
|
version="long",
|
|
) -> str:
|
|
"""Bulletin XML au format ScoDoc 7, avec informations "BUT" """
|
|
from app.scodoc import sco_bulletins
|
|
|
|
log(
|
|
f"bulletin_but_xml_compat( formsemestre_id={formsemestre_id}, etudid={etudid} )"
|
|
)
|
|
etud = Identite.get_etud(etudid)
|
|
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
|
results = bulletin_but.ResultatsSemestreBUT(formsemestre)
|
|
nb_inscrits = results.get_inscriptions_counts()[scu.INSCRIT]
|
|
# etat_inscription = etud.inscription_etat(formsemestre.id)
|
|
etat_inscription = results.formsemestre.etuds_inscriptions[etudid].etat
|
|
if (not formsemestre.bul_hide_xml) or force_publishing:
|
|
published = 1
|
|
else:
|
|
published = 0
|
|
if xml_nodate:
|
|
docdate = ""
|
|
else:
|
|
docdate = datetime.datetime.now().isoformat()
|
|
el = {
|
|
"etudid": str(etudid),
|
|
"formsemestre_id": str(formsemestre_id),
|
|
"date": docdate,
|
|
"publie": str(published),
|
|
}
|
|
if formsemestre.etapes:
|
|
el["etape_apo"] = formsemestre.etapes[0].etape_apo or ""
|
|
n = 2
|
|
for et in formsemestre.etapes[1:]:
|
|
el["etape_apo" + str(n)] = et.etape_apo or ""
|
|
n += 1
|
|
x = Element("bulletinetud", **el)
|
|
if doc:
|
|
is_appending = True
|
|
doc.append(x)
|
|
else:
|
|
is_appending = False
|
|
doc = x
|
|
# Infos sur l'etudiant
|
|
doc.append(
|
|
Element(
|
|
"etudiant",
|
|
etudid=str(etudid),
|
|
code_nip=etud.code_nip or "",
|
|
code_ine=etud.code_ine or "",
|
|
nom=quote_xml_attr(etud.nom),
|
|
prenom=quote_xml_attr(etud.prenom),
|
|
civilite=quote_xml_attr(etud.civilite_str),
|
|
sexe=quote_xml_attr(etud.civilite_str), # compat
|
|
photo_url=quote_xml_attr(sco_photos.get_etud_photo_url(etud.id)),
|
|
email=quote_xml_attr(etud.get_first_email() or ""),
|
|
emailperso=quote_xml_attr(etud.get_first_email("emailperso") or ""),
|
|
)
|
|
)
|
|
# Disponible pour publication ?
|
|
if not published:
|
|
return sco_xml.XML_HEADER + ElementTree.tostring(doc).decode(
|
|
scu.SCO_ENCODING
|
|
) # stop !
|
|
|
|
if etat_inscription == scu.INSCRIT:
|
|
# Moyenne générale:
|
|
doc.append(
|
|
Element(
|
|
"note",
|
|
value=scu.fmt_note(results.etud_moy_gen[etud.id]),
|
|
min=scu.fmt_note(results.etud_moy_gen.min()),
|
|
max=scu.fmt_note(results.etud_moy_gen.max()),
|
|
moy=scu.fmt_note(results.etud_moy_gen.mean()), # moyenne des moy. gen.
|
|
)
|
|
)
|
|
rang = 0 # XXX TODO rang de l'étudiant selon la moy gen indicative
|
|
# valeur du bonus sport
|
|
if results.bonus is not None:
|
|
bonus = results.bonus[etud.id]
|
|
else:
|
|
bonus = 0
|
|
doc.append(Element("rang", value=str(rang), ninscrits=str(nb_inscrits)))
|
|
# XXX TODO: ajouter "rang_group" : rangs dans les partitions
|
|
doc.append(Element("note_max", value="20")) # notes toujours sur 20
|
|
doc.append(Element("bonus_sport_culture", value=str(bonus)))
|
|
# Liste les UE / modules /evals
|
|
for ue in results.ues: # avec bonus
|
|
rang_ue = 0 # XXX TODO rang de l'étudiant dans cette UE
|
|
nb_inscrits_ue = (
|
|
nb_inscrits # approx: compliqué de définir le "nb d'inscrit à une UE"
|
|
)
|
|
x_ue = Element(
|
|
"ue",
|
|
id=str(ue.id),
|
|
numero=quote_xml_attr(ue.numero),
|
|
acronyme=quote_xml_attr(ue.acronyme or ""),
|
|
titre=quote_xml_attr(ue.titre or ""),
|
|
code_apogee=quote_xml_attr(ue.code_apogee or ""),
|
|
)
|
|
doc.append(x_ue)
|
|
if ue.type != codes_cursus.UE_SPORT:
|
|
v = results.etud_moy_ue[ue.id][etud.id]
|
|
vmin = results.etud_moy_ue[ue.id].min()
|
|
vmax = results.etud_moy_ue[ue.id].max()
|
|
else:
|
|
v = results.bonus or 0.0
|
|
vmin = vmax = 0.0
|
|
x_ue.append(
|
|
Element(
|
|
"note",
|
|
value=scu.fmt_note(v),
|
|
min=scu.fmt_note(vmin),
|
|
max=scu.fmt_note(vmax),
|
|
)
|
|
)
|
|
x_ue.append(Element("ects", value=str(ue.ects if ue.ects else 0)))
|
|
x_ue.append(Element("rang", value=str(rang_ue)))
|
|
x_ue.append(Element("effectif", value=str(nb_inscrits_ue)))
|
|
# Liste les modules rattachés à cette UE
|
|
for modimpl in results.formsemestre.modimpls:
|
|
# Liste ici uniquement les modules rattachés à cette UE
|
|
if modimpl.module.ue.id == ue.id:
|
|
# mod_moy = scu.fmt_note(results.etud_moy_ue[ue.id][etud.id])
|
|
try:
|
|
coef = results.modimpl_coefs_df[modimpl.id][ue.id]
|
|
except KeyError:
|
|
coef = 0.0
|
|
x_mod = Element(
|
|
"module",
|
|
id=str(modimpl.id),
|
|
code=str(modimpl.module.code or ""),
|
|
coefficient=str(coef),
|
|
numero=str(modimpl.module.numero or 0),
|
|
titre=quote_xml_attr(modimpl.module.titre or ""),
|
|
abbrev=quote_xml_attr(modimpl.module.abbrev or ""),
|
|
code_apogee=quote_xml_attr(modimpl.module.code_apogee or ""),
|
|
)
|
|
# XXX TODO rangs et effectifs
|
|
# --- notes de chaque eval:
|
|
if version != "short":
|
|
for e in modimpl.evaluations:
|
|
if e.visibulletin or version == "long":
|
|
x_eval = Element(
|
|
"evaluation",
|
|
date_debut=(
|
|
e.date_debut.isoformat() if e.date_debut else ""
|
|
),
|
|
date_fin=(
|
|
e.date_fin.isoformat() if e.date_debut else ""
|
|
),
|
|
coefficient=str(e.coefficient),
|
|
# pas les poids en XML compat
|
|
evaluation_type=str(e.evaluation_type),
|
|
description=quote_xml_attr(e.description),
|
|
# notes envoyées sur 20, ceci juste pour garder trace:
|
|
note_max_origin=str(e.note_max),
|
|
# --- deprecated
|
|
jour=(
|
|
e.date_debut.isoformat() if e.date_debut else ""
|
|
),
|
|
heure_debut=e.heure_debut(),
|
|
heure_fin=e.heure_fin(),
|
|
)
|
|
x_mod.append(x_eval)
|
|
try:
|
|
x_eval.append(
|
|
Element(
|
|
"note",
|
|
value=scu.fmt_note(
|
|
results.modimpls_results[
|
|
e.moduleimpl_id
|
|
].evals_notes[e.id][etud.id],
|
|
note_max=e.note_max,
|
|
),
|
|
)
|
|
)
|
|
except KeyError:
|
|
x_eval.append(
|
|
Element("note", value="", note_max="")
|
|
)
|
|
|
|
# XXX TODO: Evaluations incomplètes ou futures: XXX
|
|
# XXX TODO UE capitalisee (listee seulement si meilleure que l'UE courante)
|
|
|
|
# --- Absences
|
|
if sco_preferences.get_preference("bul_show_abs", formsemestre_id):
|
|
nbabs, nbabsjust = formsemestre.get_abs_count(etud.id)
|
|
doc.append(Element("absences", nbabs=str(nbabs), nbabsjust=str(nbabsjust)))
|
|
|
|
# -------- LA SUITE EST COPIEE SANS MODIF DE sco_bulletins_xml.py ---------
|
|
# TODO : refactoring
|
|
|
|
# --- Decision Jury
|
|
if (
|
|
sco_preferences.get_preference("bul_show_decision", formsemestre_id)
|
|
or xml_with_decisions
|
|
):
|
|
infos, dpv = sco_bulletins.etud_descr_situation_semestre(
|
|
etudid,
|
|
formsemestre,
|
|
fmt="xml",
|
|
show_uevalid=sco_preferences.get_preference(
|
|
"bul_show_uevalid", formsemestre_id
|
|
),
|
|
)
|
|
x_situation = Element("situation")
|
|
x_situation.text = quote_xml_attr(infos["situation"])
|
|
doc.append(x_situation)
|
|
if dpv:
|
|
decision = dpv["decisions"][0]
|
|
etat = decision["etat"]
|
|
if decision["decision_sem"]:
|
|
code = decision["decision_sem"]["code"] or ""
|
|
else:
|
|
code = ""
|
|
if (
|
|
decision["decision_sem"]
|
|
and "compense_formsemestre_id" in decision["decision_sem"]
|
|
):
|
|
doc.append(
|
|
Element(
|
|
"decision",
|
|
code=code,
|
|
etat=str(etat),
|
|
compense_formsemestre_id=str(
|
|
decision["decision_sem"]["compense_formsemestre_id"] or ""
|
|
),
|
|
)
|
|
)
|
|
else:
|
|
doc.append(Element("decision", code=code, etat=str(etat)))
|
|
|
|
if decision[
|
|
"decisions_ue"
|
|
]: # and sco_preferences.get_preference( 'bul_show_uevalid', formsemestre_id): always publish (car utile pour export Apogee)
|
|
for ue_id in decision["decisions_ue"].keys():
|
|
ue = db.session.get(UniteEns, ue_id)
|
|
if ue:
|
|
doc.append(
|
|
Element(
|
|
"decision_ue",
|
|
ue_id=str(ue.id),
|
|
numero=quote_xml_attr(ue.numero),
|
|
acronyme=quote_xml_attr(ue.acronyme),
|
|
titre=quote_xml_attr(ue.titre or ""),
|
|
code=decision["decisions_ue"][ue_id]["code"],
|
|
)
|
|
)
|
|
|
|
for aut in decision["autorisations"]:
|
|
doc.append(
|
|
Element(
|
|
"autorisation_inscription", semestre_id=str(aut["semestre_id"])
|
|
)
|
|
)
|
|
else:
|
|
doc.append(Element("decision", code="", etat="DEM"))
|
|
# --- Appreciations
|
|
appreciations = BulAppreciations.get_appreciations_list(formsemestre.id, etudid)
|
|
for appreciation in appreciations:
|
|
x_appr = Element(
|
|
"appreciation",
|
|
date=appreciation.date.isoformat() if appreciation.date else "",
|
|
)
|
|
x_appr.text = quote_xml_attr(appreciation.comment_safe())
|
|
doc.append(x_appr)
|
|
|
|
if is_appending:
|
|
return None
|
|
else:
|
|
return sco_xml.XML_HEADER + ElementTree.tostring(doc).decode(scu.SCO_ENCODING)
|