# -*- mode: python -*- # -*- coding: utf-8 -*- ############################################################################## # # Gestion scolarite IUT # # Copyright (c) 1999 - 2021 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 log from app.but import bulletin_but from app.models import FormSemestre, Identite import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb from app.scodoc import sco_abs from app.scodoc import sco_codes_parcours from app.scodoc import sco_edit_ue from app.scodoc import sco_etud from app.scodoc import sco_photos from app.scodoc import sco_preferences from app.scodoc import sco_xml 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( "bulletin_but_xml_compat( formsemestre_id=%s, etudid=%s )" % (formsemestre_id, etudid) ) sem = FormSemestre.query.get_or_404(formsemestre_id) etud = Identite.query.get_or_404(etudid) results = bulletin_but.ResultatsSemestreBUT(sem) nb_inscrits = len(results.etuds) if sem.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": published, } if sem.etapes: el["etape_apo"] = sem.etapes[0].etape_apo or "" n = 2 for et in sem.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=scu.quote_xml_attr(etud.nom), prenom=scu.quote_xml_attr(etud.prenom), civilite=scu.quote_xml_attr(etud.civilite_str), sexe=scu.quote_xml_attr(etud.civilite_str), # compat photo_url=scu.quote_xml_attr(sco_photos.get_etud_photo_url(etud.id)), email=scu.quote_xml_attr(etud.get_first_email() or ""), emailperso=scu.quote_xml_attr(etud.get_first_email("emailperso") or ""), ) ) # Disponible pour publication ? if not published: return doc # stop ! # 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'étduiant selon la moy gen indicative bonus = 0 # XXX TODO valeur du bonus sport 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: 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=scu.quote_xml_attr(ue.numero), acronyme=scu.quote_xml_attr(ue.acronyme or ""), titre=scu.quote_xml_attr(ue.titre or ""), code_apogee=scu.quote_xml_attr(ue.code_apogee or ""), ) doc.append(x_ue) if ue.type != sco_codes_parcours.UE_SPORT: v = results.etud_moy_ue[ue.id][etud.id] else: v = 0 # XXX TODO valeur bonus sport pour cet étudiant x_ue.append( Element( "note", value=scu.fmt_note(v), min=scu.fmt_note(results.etud_moy_ue[ue.id].min()), max=scu.fmt_note(results.etud_moy_ue[ue.id].max()), ) ) 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.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]) coef = results.modimpl_coefs_df[modimpl.id][ue.id] 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=scu.quote_xml_attr(modimpl.module.titre or ""), abbrev=scu.quote_xml_attr(modimpl.module.abbrev or ""), code_apogee=scu.quote_xml_attr(modimpl.module.code_apogee or ""), ) x_ue.append(x_mod) x_mod.append( Element( "note", value=mod_moy, min=scu.fmt_note(results.etud_moy_ue[ue.id].min()), max=scu.fmt_note(results.etud_moy_ue[ue.id].max()), moy=scu.fmt_note(results.etud_moy_ue[ue.id].mean()), ) ) # 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", jour=e.jour.isoformat() if e.jour else "", heure_debut=e.heure_debut.isoformat() if e.heure_debut else "", heure_fin=e.heure_fin.isoformat() if e.heure_debut else "", coefficient=str(e.coefficient), # pas les poids en XML compat evaluation_type=str(e.evaluation_type), description=scu.quote_xml_attr(e.description), # notes envoyées sur 20, ceci juste pour garder trace: note_max_origin=str(e.note_max), ) x_mod.append(x_eval) x_eval.append( Element( "note", value=scu.fmt_note( results.modimpls_results[ e.moduleimpl_id ].evals_notes[e.id][etud.id] ), ) ) # 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 = sem.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_id, format="xml", show_uevalid=sco_preferences.get_preference( "bul_show_uevalid", formsemestre_id ), ) x_situation = Element("situation") x_situation.text = scu.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 = sco_edit_ue.ue_list({"ue_id": ue_id})[0] doc.append( Element( "decision_ue", ue_id=str(ue["ue_id"]), numero=scu.quote_xml_attr(ue["numero"]), acronyme=scu.quote_xml_attr(ue["acronyme"]), titre=scu.quote_xml_attr(ue["titre"]), 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 cnx = ndb.GetDBConnexion() apprecs = sco_etud.appreciations_list( cnx, args={"etudid": etudid, "formsemestre_id": formsemestre_id} ) for appr in apprecs: x_appr = Element( "appreciation", date=ndb.DateDMYtoISO(appr["date"]), ) x_appr.text = scu.quote_xml_attr(appr["comment"]) doc.append(x_appr) if is_appending: return None else: return sco_xml.XML_HEADER + ElementTree.tostring(doc).decode(scu.SCO_ENCODING)