Fix bulletins legacy + refactoring

This commit is contained in:
Emmanuel Viennet 2021-02-01 16:23:11 +01:00
parent 0d0c391547
commit a4173e1877
10 changed files with 274 additions and 230 deletions

View File

@ -1,7 +1,7 @@
# -*- mode: python -*- # -*- mode: python -*-
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
SCOVERSION = "7.20a" SCOVERSION = "7.21"
SCONAME = "ScoDoc" SCONAME = "ScoDoc"

View File

@ -392,7 +392,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
"version info" "version info"
H = [ H = [
"""<h2>Système de gestion scolarité</h2> """<h2>Système de gestion scolarité</h2>
<p>&copy; Emmanuel Viennet 1997-2020</p> <p>&copy; Emmanuel Viennet 1997-2021</p>
<p>Version %s (subversion %s)</p> <p>Version %s (subversion %s)</p>
""" """
% (SCOVERSION, get_svn_version(file_path)) % (SCOVERSION, get_svn_version(file_path))

View File

@ -28,6 +28,9 @@
"""Génération des bulletins de notes """Génération des bulletins de notes
""" """
from types import StringType
import pprint
import urllib
from email.MIMEMultipart import ( # pylint: disable=no-name-in-module,import-error from email.MIMEMultipart import ( # pylint: disable=no-name-in-module,import-error
MIMEMultipart, MIMEMultipart,
) )
@ -40,8 +43,13 @@ import time
import htmlutils import htmlutils
from reportlab.lib.colors import Color from reportlab.lib.colors import Color
from sco_utils import * import sco_utils as scu
from notes_table import * import notesdb as ndb
from notes_log import log
import scolars
from sco_permissions import ScoImplement, ScoEtudInscrit
from sco_exceptions import AccessDenied
import sco_codes_parcours
import sco_formsemestre import sco_formsemestre
import sco_groups import sco_groups
import sco_pvjury import sco_pvjury
@ -114,7 +122,7 @@ def formsemestre_bulletinetud_dict(
context, formsemestre_id context, formsemestre_id
) # > toutes notes ) # > toutes notes
I = DictDefault(defaultvalue="") I = scu.DictDefault(defaultvalue="")
I["etudid"] = etudid I["etudid"] = etudid
I["formsemestre_id"] = formsemestre_id I["formsemestre_id"] = formsemestre_id
I["sem"] = nt.sem I["sem"] = nt.sem
@ -182,7 +190,7 @@ def formsemestre_bulletinetud_dict(
if I["etud_etat"] == "D": if I["etud_etat"] == "D":
I["demission"] = "(Démission)" I["demission"] = "(Démission)"
I["filigranne"] = "Démission" I["filigranne"] = "Démission"
elif I["etud_etat"] == DEF: elif I["etud_etat"] == sco_codes_parcours.DEF:
I["demission"] = "(Défaillant)" I["demission"] = "(Défaillant)"
I["filigranne"] = "Défaillant" I["filigranne"] = "Défaillant"
elif (prefs["bul_show_temporary"] and not I["decision_sem"]) or prefs[ elif (prefs["bul_show_temporary"] and not I["decision_sem"]) or prefs[
@ -206,16 +214,16 @@ def formsemestre_bulletinetud_dict(
modimpls = nt.get_modimpls() modimpls = nt.get_modimpls()
moy_gen = nt.get_etud_moy_gen(etudid) moy_gen = nt.get_etud_moy_gen(etudid)
I["nb_inscrits"] = len(nt.rangs) I["nb_inscrits"] = len(nt.rangs)
I["moy_gen"] = fmt_note(moy_gen) I["moy_gen"] = scu.fmt_note(moy_gen)
I["moy_min"] = fmt_note(nt.moy_min) I["moy_min"] = scu.fmt_note(nt.moy_min)
I["moy_max"] = fmt_note(nt.moy_max) I["moy_max"] = scu.fmt_note(nt.moy_max)
I["mention"] = "" I["mention"] = ""
if dpv: if dpv:
decision_sem = dpv["decisions"][0]["decision_sem"] decision_sem = dpv["decisions"][0]["decision_sem"]
if decision_sem and sco_codes_parcours.code_semestre_validant( if decision_sem and sco_codes_parcours.code_semestre_validant(
decision_sem["code"] decision_sem["code"]
): ):
I["mention"] = get_mention(moy_gen) I["mention"] = scu.get_mention(moy_gen)
if dpv and dpv["decisions"][0]: if dpv and dpv["decisions"][0]:
I["sum_ects"] = dpv["decisions"][0]["sum_ects"] I["sum_ects"] = dpv["decisions"][0]["sum_ects"]
@ -223,7 +231,7 @@ def formsemestre_bulletinetud_dict(
else: else:
I["sum_ects"] = 0 I["sum_ects"] = 0
I["sum_ects_capitalises"] = 0 I["sum_ects_capitalises"] = 0
I["moy_moy"] = fmt_note(nt.moy_moy) # moyenne des moyennes generales I["moy_moy"] = scu.fmt_note(nt.moy_moy) # moyenne des moyennes generales
if type(moy_gen) != StringType and type(nt.moy_moy) != StringType: if type(moy_gen) != StringType and type(nt.moy_moy) != StringType:
I["moy_gen_bargraph_html"] = "&nbsp;" + htmlutils.horizontal_bargraph( I["moy_gen_bargraph_html"] = "&nbsp;" + htmlutils.horizontal_bargraph(
moy_gen * 5, nt.moy_moy * 5 moy_gen * 5, nt.moy_moy * 5
@ -243,8 +251,8 @@ def formsemestre_bulletinetud_dict(
if nt.get_moduleimpls_attente(): if nt.get_moduleimpls_attente():
# n'affiche pas le rang sur le bulletin s'il y a des # n'affiche pas le rang sur le bulletin s'il y a des
# notes en attente dans ce semestre # notes en attente dans ce semestre
rang = RANG_ATTENTE_STR rang = scu.RANG_ATTENTE_STR
rang_gr = DictDefault(defaultvalue=RANG_ATTENTE_STR) rang_gr = scu.DictDefault(defaultvalue=scu.RANG_ATTENTE_STR)
I["rang"] = rang I["rang"] = rang
I["rang_gr"] = rang_gr I["rang_gr"] = rang_gr
I["gr_name"] = gr_name I["gr_name"] = gr_name
@ -270,17 +278,17 @@ def formsemestre_bulletinetud_dict(
u = ue.copy() u = ue.copy()
ue_status = nt.get_etud_ue_status(etudid, ue["ue_id"]) ue_status = nt.get_etud_ue_status(etudid, ue["ue_id"])
u["ue_status"] = ue_status # { 'moy', 'coef_ue', ...} u["ue_status"] = ue_status # { 'moy', 'coef_ue', ...}
if ue["type"] != UE_SPORT: if ue["type"] != sco_codes_parcours.UE_SPORT:
u["cur_moy_ue_txt"] = fmt_note(ue_status["cur_moy_ue"]) u["cur_moy_ue_txt"] = scu.fmt_note(ue_status["cur_moy_ue"])
else: else:
x = fmt_note(nt.bonus[etudid], keep_numeric=True) x = scu.fmt_note(nt.bonus[etudid], keep_numeric=True)
if type(x) == StringType: if type(x) == StringType:
u["cur_moy_ue_txt"] = "pas de bonus" u["cur_moy_ue_txt"] = "pas de bonus"
else: else:
u["cur_moy_ue_txt"] = "bonus de %.3g points" % x u["cur_moy_ue_txt"] = "bonus de %.3g points" % x
u["moy_ue_txt"] = fmt_note(ue_status["moy"]) u["moy_ue_txt"] = scu.fmt_note(ue_status["moy"])
if ue_status["coef_ue"] != None: if ue_status["coef_ue"] != None:
u["coef_ue_txt"] = fmt_coef(ue_status["coef_ue"]) u["coef_ue_txt"] = scu.fmt_coef(ue_status["coef_ue"])
else: else:
# C'est un bug: # C'est un bug:
log("u=" + pprint.pformat(u)) log("u=" + pprint.pformat(u))
@ -292,7 +300,7 @@ def formsemestre_bulletinetud_dict(
and ue["ue_id"] in dpv["decisions"][0]["decisions_ue"] and ue["ue_id"] in dpv["decisions"][0]["decisions_ue"]
): ):
u["ects"] = dpv["decisions"][0]["decisions_ue"][ue["ue_id"]]["ects"] u["ects"] = dpv["decisions"][0]["decisions_ue"][ue["ue_id"]]["ects"]
if ue["type"] == UE_ELECTIVE: if ue["type"] == sco_codes_parcours.UE_ELECTIVE:
u["ects"] = ( u["ects"] = (
"%g+" % u["ects"] "%g+" % u["ects"]
) # ajoute un "+" pour indiquer ECTS d'une UE élective ) # ajoute un "+" pour indiquer ECTS d'une UE élective
@ -316,7 +324,7 @@ def formsemestre_bulletinetud_dict(
sem_origin = sco_formsemestre.get_formsemestre( sem_origin = sco_formsemestre.get_formsemestre(
context, ue_status["formsemestre_id"] context, ue_status["formsemestre_id"]
) )
u["ue_descr_txt"] = "Capitalisée le %s" % DateISOtoDMY( u["ue_descr_txt"] = "Capitalisée le %s" % ndb.DateISOtoDMY(
ue_status["event_date"] ue_status["event_date"]
) )
u[ u[
@ -334,7 +342,7 @@ def formsemestre_bulletinetud_dict(
context, ue_status["formsemestre_id"] context, ue_status["formsemestre_id"]
) # > toutes notes ) # > toutes notes
u["modules_capitalized"], junk = _ue_mod_bulletin( u["modules_capitalized"], _ = _ue_mod_bulletin(
context, context,
etudid, etudid,
formsemestre_id, formsemestre_id,
@ -347,10 +355,10 @@ def formsemestre_bulletinetud_dict(
_sort_mod_by_matiere(u["modules_capitalized"], nt_cap, etudid) _sort_mod_by_matiere(u["modules_capitalized"], nt_cap, etudid)
) )
else: else:
if prefs["bul_show_ue_rangs"] and ue["type"] != UE_SPORT: if prefs["bul_show_ue_rangs"] and ue["type"] != sco_codes_parcours.UE_SPORT:
if ue_attente: # nt.get_moduleimpls_attente(): if ue_attente: # nt.get_moduleimpls_attente():
u["ue_descr_txt"] = "%s/%s" % ( u["ue_descr_txt"] = "%s/%s" % (
RANG_ATTENTE_STR, scu.RANG_ATTENTE_STR,
nt.ue_rangs[ue["ue_id"]][1], nt.ue_rangs[ue["ue_id"]][1],
) )
else: else:
@ -386,7 +394,7 @@ def _sort_mod_by_matiere(modlist, nt, etudid):
"titre": mod["mat"]["titre"], "titre": mod["mat"]["titre"],
"modules": mod, "modules": mod,
"moy": moy, "moy": moy,
"moy_txt": fmt_note(moy), "moy_txt": scu.fmt_note(moy),
} }
return matmod return matmod
@ -402,8 +410,8 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
) )
if bul_show_abs_modules: if bul_show_abs_modules:
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
debut_sem = DateDMYtoISO(sem["date_debut"]) debut_sem = ndb.DateDMYtoISO(sem["date_debut"])
fin_sem = DateDMYtoISO(sem["date_fin"]) fin_sem = ndb.DateDMYtoISO(sem["date_fin"])
ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue_id] ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue_id]
mods = [] # result mods = [] # result
@ -414,7 +422,7 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
mod_moy = nt.get_etud_mod_moy( mod_moy = nt.get_etud_mod_moy(
modimpl["moduleimpl_id"], etudid modimpl["moduleimpl_id"], etudid
) # peut etre 'NI' ) # peut etre 'NI'
is_malus = mod["module"]["module_type"] == MODULE_MALUS is_malus = mod["module"]["module_type"] == scu.MODULE_MALUS
if bul_show_abs_modules: if bul_show_abs_modules:
mod_abs = [ mod_abs = [
context.Absences.CountAbs( context.Absences.CountAbs(
@ -430,25 +438,25 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
moduleimpl_id=modimpl["moduleimpl_id"], moduleimpl_id=modimpl["moduleimpl_id"],
), ),
] ]
mod["mod_abs_txt"] = fmt_abs(mod_abs) mod["mod_abs_txt"] = scu.fmt_abs(mod_abs)
else: else:
mod["mod_abs_txt"] = "" mod["mod_abs_txt"] = ""
mod["mod_moy_txt"] = fmt_note(mod_moy) mod["mod_moy_txt"] = scu.fmt_note(mod_moy)
if mod["mod_moy_txt"][:2] == "NA": if mod["mod_moy_txt"][:2] == "NA":
mod["mod_moy_txt"] = "-" mod["mod_moy_txt"] = "-"
if is_malus: if is_malus:
if mod_moy > 0: if mod_moy > 0:
mod["mod_moy_txt"] = fmt_note(mod_moy) mod["mod_moy_txt"] = scu.fmt_note(mod_moy)
mod["mod_coef_txt"] = "Malus" mod["mod_coef_txt"] = "Malus"
elif mod_moy < 0: elif mod_moy < 0:
mod["mod_moy_txt"] = fmt_note(-mod_moy) mod["mod_moy_txt"] = scu.fmt_note(-mod_moy)
mod["mod_coef_txt"] = "Bonus" mod["mod_coef_txt"] = "Bonus"
else: else:
mod["mod_moy_txt"] = "-" mod["mod_moy_txt"] = "-"
mod["mod_coef_txt"] = "-" mod["mod_coef_txt"] = "-"
else: else:
mod["mod_coef_txt"] = fmt_coef(modimpl["module"]["coefficient"]) mod["mod_coef_txt"] = scu.fmt_coef(modimpl["module"]["coefficient"])
if mod["mod_moy_txt"] != "NI": # ne montre pas les modules 'non inscrit' if mod["mod_moy_txt"] != "NI": # ne montre pas les modules 'non inscrit'
mods.append(mod) mods.append(mod)
if is_malus: # n'affiche pas les statistiques sur les modules malus if is_malus: # n'affiche pas les statistiques sur les modules malus
@ -464,7 +472,7 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
mod["stats"] = nt.get_mod_stats(modimpl["moduleimpl_id"]) mod["stats"] = nt.get_mod_stats(modimpl["moduleimpl_id"])
mod["mod_descr_txt"] = "Module %s, coef. %s (%s)" % ( mod["mod_descr_txt"] = "Module %s, coef. %s (%s)" % (
modimpl["module"]["titre"], modimpl["module"]["titre"],
fmt_coef(modimpl["module"]["coefficient"]), scu.fmt_coef(modimpl["module"]["coefficient"]),
context.Users.user_info(modimpl["responsable_id"])["nomcomplet"], context.Users.user_info(modimpl["responsable_id"])["nomcomplet"],
) )
link_mod = ( link_mod = (
@ -483,7 +491,7 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
mod_descr = "Module %s, coef. %s (%s)" % ( mod_descr = "Module %s, coef. %s (%s)" % (
modimpl["module"]["titre"], modimpl["module"]["titre"],
fmt_coef(modimpl["module"]["coefficient"]), scu.fmt_coef(modimpl["module"]["coefficient"]),
context.Users.user_info(modimpl["responsable_id"])["nomcomplet"], context.Users.user_info(modimpl["responsable_id"])["nomcomplet"],
) )
link_mod = ( link_mod = (
@ -527,18 +535,18 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
if val == "NP": if val == "NP":
e["note_txt"] = "nd" e["note_txt"] = "nd"
e["note_html"] = '<span class="note_nd">nd</span>' e["note_html"] = '<span class="note_nd">nd</span>'
e["coef_txt"] = fmt_coef(e["coefficient"]) e["coef_txt"] = scu.fmt_coef(e["coefficient"])
else: else:
# (-0.15) s'affiche "bonus de 0.15" # (-0.15) s'affiche "bonus de 0.15"
if is_malus: if is_malus:
val = abs(val) val = abs(val)
e["note_txt"] = fmt_note(val, note_max=e["note_max"]) e["note_txt"] = scu.fmt_note(val, note_max=e["note_max"])
e["note_html"] = e["note_txt"] e["note_html"] = e["note_txt"]
if is_malus: if is_malus:
e["coef_txt"] = "" e["coef_txt"] = ""
else: else:
e["coef_txt"] = fmt_coef(e["coefficient"]) e["coef_txt"] = scu.fmt_coef(e["coefficient"])
if e["evaluation_type"] == EVALUATION_RATTRAPAGE: if e["evaluation_type"] == scu.EVALUATION_RATTRAPAGE:
e["coef_txt"] = "rat." e["coef_txt"] = "rat."
if e["etat"]["evalattente"]: if e["etat"]["evalattente"]:
mod_attente = True # une eval en attente dans ce module mod_attente = True # une eval en attente dans ce module
@ -569,12 +577,12 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
e["name"], e["name"],
) )
e["note_txt"] = e["note_html"] = "" e["note_txt"] = e["note_html"] = ""
e["coef_txt"] = fmt_coef(e["coefficient"]) e["coef_txt"] = scu.fmt_coef(e["coefficient"])
# Classement # Classement
if bul_show_mod_rangs and mod["mod_moy_txt"] != "-" and not is_malus: if bul_show_mod_rangs and mod["mod_moy_txt"] != "-" and not is_malus:
rg = nt.mod_rangs[modimpl["moduleimpl_id"]] rg = nt.mod_rangs[modimpl["moduleimpl_id"]]
if mod_attente: # nt.get_moduleimpls_attente(): if mod_attente: # nt.get_moduleimpls_attente():
mod["mod_rang"] = RANG_ATTENTE_STR mod["mod_rang"] = scu.RANG_ATTENTE_STR
else: else:
mod["mod_rang"] = rg[0][etudid] mod["mod_rang"] = rg[0][etudid]
mod["mod_eff"] = rg[1] # effectif dans ce module mod["mod_eff"] = rg[1] # effectif dans ce module
@ -639,7 +647,7 @@ def etud_descr_situation_semestre(
descr_mention : 'Mention Bien', ou vide si pas de mention ou si pas show_mention descr_mention : 'Mention Bien', ou vide si pas de mention ou si pas show_mention
""" """
cnx = context.GetDBConnexion() cnx = context.GetDBConnexion()
infos = DictDefault(defaultvalue="") infos = scu.DictDefault(defaultvalue="")
# --- Situation et décisions jury # --- Situation et décisions jury
@ -650,7 +658,6 @@ def etud_descr_situation_semestre(
date_inscr = None date_inscr = None
date_dem = None date_dem = None
date_def = None date_def = None
date_echec = None
for event in events: for event in events:
event_type = event["event_type"] event_type = event["event_type"]
if event_type == "INSCRIPTION": if event_type == "INSCRIPTION":
@ -767,7 +774,7 @@ def formsemestre_bulletinetud(
etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0] etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0]
etudid = etud["etudid"] etudid = etud["etudid"]
except: except:
return log_unknown_etud(context, REQUEST, format=format) return scu.log_unknown_etud(context, REQUEST, format=format)
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
@ -889,7 +896,7 @@ def do_formsemestre_bulletinetud(
etud = I["etud"] etud = I["etud"]
if format == "html": if format == "html":
htm, junk = sco_bulletins_generator.make_formsemestre_bulletinetud( htm, _ = sco_bulletins_generator.make_formsemestre_bulletinetud(
context, I, version=version, format="html", REQUEST=REQUEST context, I, version=version, format="html", REQUEST=REQUEST
) )
return htm, I["filigranne"] return htm, I["filigranne"]
@ -905,7 +912,7 @@ def do_formsemestre_bulletinetud(
) )
if format == "pdf": if format == "pdf":
return ( return (
sendPDFFile(REQUEST, bul, filename), scu.sendPDFFile(REQUEST, bul, filename),
I["filigranne"], I["filigranne"],
) # unused ret. value ) # unused ret. value
else: else:
@ -920,7 +927,7 @@ def do_formsemestre_bulletinetud(
if nohtml: if nohtml:
htm = "" # speed up if html version not needed htm = "" # speed up if html version not needed
else: else:
htm, junk = sco_bulletins_generator.make_formsemestre_bulletinetud( htm, _ = sco_bulletins_generator.make_formsemestre_bulletinetud(
context, I, version=version, format="html", REQUEST=REQUEST context, I, version=version, format="html", REQUEST=REQUEST
) )
@ -964,7 +971,7 @@ def mail_bulletin(context, formsemestre_id, I, pdfdata, filename, recipient_addr
""" """
etud = I["etud"] etud = I["etud"]
webmaster = context.get_preference("bul_mail_contact_addr", formsemestre_id) webmaster = context.get_preference("bul_mail_contact_addr", formsemestre_id)
dept = unescape_html(context.get_preference("DeptName", formsemestre_id)) dept = scu.unescape_html(context.get_preference("DeptName", formsemestre_id))
copy_addr = context.get_preference("email_copy_bulletins", formsemestre_id) copy_addr = context.get_preference("email_copy_bulletins", formsemestre_id)
intro_mail = context.get_preference("bul_intro_mail", formsemestre_id) intro_mail = context.get_preference("bul_intro_mail", formsemestre_id)
@ -983,7 +990,7 @@ def mail_bulletin(context, formsemestre_id, I, pdfdata, filename, recipient_addr
) )
msg = MIMEMultipart() msg = MIMEMultipart()
subj = Header("Relevé de notes de %s" % etud["nomprenom"], SCO_ENCODING) subj = Header("Relevé de notes de %s" % etud["nomprenom"], scu.SCO_ENCODING)
recipients = [recipient_addr] recipients = [recipient_addr]
msg["Subject"] = subj msg["Subject"] = subj
msg["From"] = context.get_preference("email_from_addr", formsemestre_id) msg["From"] = context.get_preference("email_from_addr", formsemestre_id)
@ -993,7 +1000,7 @@ def mail_bulletin(context, formsemestre_id, I, pdfdata, filename, recipient_addr
# Guarantees the message ends in a newline # Guarantees the message ends in a newline
msg.epilogue = "" msg.epilogue = ""
# Text # Text
txt = MIMEText(hea, "plain", SCO_ENCODING) txt = MIMEText(hea, "plain", scu.SCO_ENCODING)
# log('hea:\n' + hea) # log('hea:\n' + hea)
msg.attach(txt) msg.attach(txt)
# Attach pdf # Attach pdf
@ -1157,7 +1164,7 @@ def _formsemestre_bulletinetud_header_html(
url url
+ "?formsemestre_id=%s&amp;etudid=%s&amp;format=pdf&amp;version=%s" + "?formsemestre_id=%s&amp;etudid=%s&amp;format=pdf&amp;version=%s"
% (formsemestre_id, etudid, version), % (formsemestre_id, etudid, version),
ICON_PDF, scu.ICON_PDF,
) )
) )
H.append("""</tr></table>""") H.append("""</tr></table>""")

View File

@ -28,12 +28,14 @@
"""Generation bulletins de notes: exemple minimal pour les programmeurs """Generation bulletins de notes: exemple minimal pour les programmeurs
""" """
# Quelques modules ScoDoc utiles: import VERSION
from sco_pdf import * import sco_utils as scu
import sco_pdf
import sco_preferences import sco_preferences
from notes_log import log from notes_log import log
import sco_bulletins_generator import sco_bulletins_generator
import sco_bulletins_standard import sco_bulletins_standard
from reportlab.platypus import Paragraph
class BulletinGeneratorExample(sco_bulletins_standard.BulletinGeneratorStandard): class BulletinGeneratorExample(sco_bulletins_standard.BulletinGeneratorStandard):
@ -59,7 +61,7 @@ class BulletinGeneratorExample(sco_bulletins_standard.BulletinGeneratorStandard)
assert format == "pdf" # garde fou assert format == "pdf" # garde fou
return [ return [
Paragraph( Paragraph(
SU( sco_pdf.SU(
"L'étudiant %(nomprenom)s a une moyenne générale de %(moy_gen)s" "L'étudiant %(nomprenom)s a une moyenne générale de %(moy_gen)s"
% self.infos % self.infos
), ),

View File

@ -28,9 +28,12 @@
"""Génération du bulletin en format JSON (beta, non completement testé) """Génération du bulletin en format JSON (beta, non completement testé)
""" """
import datetime
import json import json
from notes_table import * import sco_utils as scu
import notesdb as ndb
import scolars
import sco_formsemestre import sco_formsemestre
import sco_groups import sco_groups
import sco_photos import sco_photos
@ -62,9 +65,9 @@ def make_json_formsemestre_bulletinetud(
) )
if REQUEST: if REQUEST:
REQUEST.RESPONSE.setHeader("content-type", JSON_MIMETYPE) REQUEST.RESPONSE.setHeader("content-type", scu.JSON_MIMETYPE)
return json.dumps(d, cls=ScoDocJSONEncoder, encoding=SCO_ENCODING) return json.dumps(d, cls=scu.ScoDocJSONEncoder, encoding=scu.SCO_ENCODING)
# (fonction séparée: n'utilise pas formsemestre_bulletinetud_dict() # (fonction séparée: n'utilise pas formsemestre_bulletinetud_dict()
@ -119,14 +122,14 @@ def formsemestre_bulletinetud_published_dict(
etudid=etudid, etudid=etudid,
code_nip=etudinfo["code_nip"], code_nip=etudinfo["code_nip"],
code_ine=etudinfo["code_ine"], code_ine=etudinfo["code_ine"],
nom=quote_xml_attr(etudinfo["nom"]), nom=scu.quote_xml_attr(etudinfo["nom"]),
prenom=quote_xml_attr(etudinfo["prenom"]), prenom=scu.quote_xml_attr(etudinfo["prenom"]),
sexe=quote_xml_attr(etudinfo["sexe"]), sexe=scu.quote_xml_attr(etudinfo["sexe"]),
photo_url=quote_xml_attr( photo_url=scu.quote_xml_attr(
sco_photos.etud_photo_url(context, etudinfo, fast=True) sco_photos.etud_photo_url(context, etudinfo, fast=True)
), ),
email=quote_xml_attr(etudinfo["email"]), email=scu.quote_xml_attr(etudinfo["email"]),
emailperso=quote_xml_attr(etudinfo["emailperso"]), emailperso=scu.quote_xml_attr(etudinfo["emailperso"]),
) )
# Disponible pour publication ? # Disponible pour publication ?
@ -150,7 +153,7 @@ def formsemestre_bulletinetud_published_dict(
ues = nt.get_ues() ues = nt.get_ues()
modimpls = nt.get_modimpls() modimpls = nt.get_modimpls()
nbetuds = len(nt.rangs) nbetuds = len(nt.rangs)
mg = fmt_note(nt.get_etud_moy_gen(etudid)) mg = scu.fmt_note(nt.get_etud_moy_gen(etudid))
if ( if (
nt.get_moduleimpls_attente() nt.get_moduleimpls_attente()
or context.get_preference("bul_show_rangs", formsemestre_id) == 0 or context.get_preference("bul_show_rangs", formsemestre_id) == 0
@ -168,9 +171,9 @@ def formsemestre_bulletinetud_published_dict(
d["note"] = dict( d["note"] = dict(
value=mg, value=mg,
min=fmt_note(nt.moy_min), min=scu.fmt_note(nt.moy_min),
max=fmt_note(nt.moy_max), max=scu.fmt_note(nt.moy_max),
moy=fmt_note(nt.moy_moy), moy=scu.fmt_note(nt.moy_moy),
) )
d["rang"] = dict(value=rang, ninscrits=nbetuds) d["rang"] = dict(value=rang, ninscrits=nbetuds)
d["rang_group"] = [] d["rang_group"] = []
@ -199,25 +202,27 @@ def formsemestre_bulletinetud_published_dict(
ects_txt = "" ects_txt = ""
u = dict( u = dict(
id=ue["ue_id"], id=ue["ue_id"],
numero=quote_xml_attr(ue["numero"]), numero=scu.quote_xml_attr(ue["numero"]),
acronyme=quote_xml_attr(ue["acronyme"]), acronyme=scu.quote_xml_attr(ue["acronyme"]),
titre=quote_xml_attr(ue["titre"]), titre=scu.quote_xml_attr(ue["titre"]),
note=dict( note=dict(
value=fmt_note(ue_status["cur_moy_ue"]), value=scu.fmt_note(ue_status["cur_moy_ue"]),
min=fmt_note(ue["min"]), min=scu.fmt_note(ue["min"]),
max=fmt_note(ue["max"]), max=scu.fmt_note(ue["max"]),
), ),
rang=str(nt.ue_rangs[ue["ue_id"]][0][etudid]), rang=str(nt.ue_rangs[ue["ue_id"]][0][etudid]),
effectif=str(nt.ue_rangs[ue["ue_id"]][1]), effectif=str(nt.ue_rangs[ue["ue_id"]][1]),
ects=ects_txt, ects=ects_txt,
code_apogee=quote_xml_attr(ue["code_apogee"]), code_apogee=scu.quote_xml_attr(ue["code_apogee"]),
) )
d["ue"].append(u) d["ue"].append(u)
u["module"] = [] u["module"] = []
# 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:
mod_moy = fmt_note(nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid)) mod_moy = scu.fmt_note(
nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid)
)
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"]
@ -232,15 +237,15 @@ def formsemestre_bulletinetud_published_dict(
code=mod["code"], code=mod["code"],
coefficient=mod["coefficient"], coefficient=mod["coefficient"],
numero=mod["numero"], numero=mod["numero"],
titre=quote_xml_attr(mod["titre"]), titre=scu.quote_xml_attr(mod["titre"]),
abbrev=quote_xml_attr(mod["abbrev"]), abbrev=scu.quote_xml_attr(mod["abbrev"]),
# ects=ects, ects des modules maintenant inutilisés # ects=ects, ects des modules maintenant inutilisés
note=dict(value=mod_moy), note=dict(value=mod_moy),
code_apogee=quote_xml_attr(mod["code_apogee"]), code_apogee=scu.quote_xml_attr(mod["code_apogee"]),
) )
m["note"].update(modstat) m["note"].update(modstat)
for k in ("min", "max", "moy"): # formatte toutes les notes for k in ("min", "max", "moy"): # formatte toutes les notes
m["note"][k] = fmt_note(m["note"][k]) m["note"][k] = scu.fmt_note(m["note"][k])
u["module"].append(m) u["module"].append(m)
if context.get_preference("bul_show_mod_rangs", formsemestre_id): if context.get_preference("bul_show_mod_rangs", formsemestre_id):
@ -258,19 +263,19 @@ def formsemestre_bulletinetud_published_dict(
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 = fmt_note(val, note_max=e["note_max"]) val = scu.fmt_note(val, note_max=e["note_max"])
m["evaluation"].append( m["evaluation"].append(
dict( dict(
jour=DateDMYtoISO(e["jour"], null_is_empty=True), jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True),
heure_debut=TimetoISO8601( heure_debut=ndb.TimetoISO8601(
e["heure_debut"], null_is_empty=True e["heure_debut"], null_is_empty=True
), ),
heure_fin=TimetoISO8601( heure_fin=ndb.TimetoISO8601(
e["heure_fin"], null_is_empty=True e["heure_fin"], null_is_empty=True
), ),
coefficient=e["coefficient"], coefficient=e["coefficient"],
evaluation_type=e["evaluation_type"], evaluation_type=e["evaluation_type"],
description=quote_xml_attr(e["description"]), description=scu.quote_xml_attr(e["description"]),
note=val, note=val,
) )
) )
@ -285,15 +290,17 @@ def formsemestre_bulletinetud_published_dict(
if e["evaluation_id"] not in complete_eval_ids: if e["evaluation_id"] not in complete_eval_ids:
m["evaluation"].append( m["evaluation"].append(
dict( dict(
jour=DateDMYtoISO(e["jour"], null_is_empty=True), jour=ndb.DateDMYtoISO(
heure_debut=TimetoISO8601( e["jour"], null_is_empty=True
),
heure_debut=ndb.TimetoISO8601(
e["heure_debut"], null_is_empty=True e["heure_debut"], null_is_empty=True
), ),
heure_fin=TimetoISO8601( heure_fin=ndb.TimetoISO8601(
e["heure_fin"], null_is_empty=True e["heure_fin"], null_is_empty=True
), ),
coefficient=e["coefficient"], coefficient=e["coefficient"],
description=quote_xml_attr(e["description"]), description=scu.quote_xml_attr(e["description"]),
incomplete="1", incomplete="1",
) )
) )
@ -307,20 +314,18 @@ def formsemestre_bulletinetud_published_dict(
d["ue_capitalisee"].append( d["ue_capitalisee"].append(
dict( dict(
id=ue["ue_id"], id=ue["ue_id"],
numero=quote_xml_attr(ue["numero"]), numero=scu.quote_xml_attr(ue["numero"]),
acronyme=quote_xml_attr(ue["acronyme"]), acronyme=scu.quote_xml_attr(ue["acronyme"]),
titre=quote_xml_attr(ue["titre"]), titre=scu.quote_xml_attr(ue["titre"]),
note=fmt_note(ue_status["moy"]), note=scu.fmt_note(ue_status["moy"]),
coefficient_ue=fmt_note(ue_status["coef_ue"]), coefficient_ue=scu.fmt_note(ue_status["coef_ue"]),
date_capitalisation=DateDMYtoISO(ue_status["event_date"]), date_capitalisation=ndb.DateDMYtoISO(ue_status["event_date"]),
ects=ects_txt, ects=ects_txt,
) )
) )
# --- Absences # --- Absences
if context.get_preference("bul_show_abs", formsemestre_id): if context.get_preference("bul_show_abs", formsemestre_id):
debut_sem = DateDMYtoISO(sem["date_debut"])
fin_sem = DateDMYtoISO(sem["date_fin"])
AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid) AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid)
nbabs = AbsEtudSem.CountAbs() nbabs = AbsEtudSem.CountAbs()
nbabsjust = AbsEtudSem.CountAbsJust() nbabsjust = AbsEtudSem.CountAbsJust()
@ -339,7 +344,7 @@ def formsemestre_bulletinetud_published_dict(
format="xml", format="xml",
show_uevalid=context.get_preference("bul_show_uevalid", formsemestre_id), show_uevalid=context.get_preference("bul_show_uevalid", formsemestre_id),
) )
d["situation"] = quote_xml_attr(infos["situation"]) d["situation"] = scu.quote_xml_attr(infos["situation"])
if dpv: if dpv:
decision = dpv["decisions"][0] decision = dpv["decisions"][0]
etat = decision["etat"] etat = decision["etat"]
@ -366,11 +371,11 @@ def formsemestre_bulletinetud_published_dict(
d["decision_ue"].append( d["decision_ue"].append(
dict( dict(
ue_id=ue["ue_id"], ue_id=ue["ue_id"],
numero=quote_xml_attr(ue["numero"]), numero=scu.quote_xml_attr(ue["numero"]),
acronyme=quote_xml_attr(ue["acronyme"]), acronyme=scu.quote_xml_attr(ue["acronyme"]),
titre=quote_xml_attr(ue["titre"]), titre=scu.quote_xml_attr(ue["titre"]),
code=decision["decisions_ue"][ue_id]["code"], code=decision["decisions_ue"][ue_id]["code"],
ects=quote_xml_attr(ue["ects"] or ""), ects=scu.quote_xml_attr(ue["ects"] or ""),
) )
) )
d["autorisation_inscription"] = [] d["autorisation_inscription"] = []
@ -389,7 +394,10 @@ def formsemestre_bulletinetud_published_dict(
d["appreciation"] = [] d["appreciation"] = []
for app in apprecs: for app in apprecs:
d["appreciation"].append( d["appreciation"].append(
dict(comment=quote_xml_attr(app["comment"]), date=DateDMYtoISO(app["date"])) dict(
comment=scu.quote_xml_attr(app["comment"]),
date=ndb.DateDMYtoISO(app["date"]),
)
) )
# #

View File

@ -37,8 +37,13 @@
import traceback, re import traceback, re
import sco_utils as scu
from sco_permissions import ScoEtudInscrit
import sco_formsemestre import sco_formsemestre
from sco_pdf import * import sco_pdf
from sco_pdf import Color, Paragraph, Spacer, Table
from sco_pdf import blue, cm, mm
from sco_pdf import SU
import sco_preferences import sco_preferences
from notes_log import log from notes_log import log
import sco_bulletins_generator import sco_bulletins_generator
@ -81,9 +86,7 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
def bul_table_html(self): def bul_table_html(self):
"""Génère la table centrale du bulletin de notes: chaine HTML""" """Génère la table centrale du bulletin de notes: chaine HTML"""
format = "html"
I = self.infos I = self.infos
authuser = self.authuser
formsemestre_id = self.infos["formsemestre_id"] formsemestre_id = self.infos["formsemestre_id"]
context = self.context context = self.context
@ -98,8 +101,8 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
bgcolor = "background-color: rgb(255,255,240)" bgcolor = "background-color: rgb(255,255,240)"
linktmpl = '<span onclick="toggle_vis_ue(this);" class="toggle_ue">%s</span>' linktmpl = '<span onclick="toggle_vis_ue(this);" class="toggle_ue">%s</span>'
minuslink = linktmpl % icontag("minus_img", border="0", alt="-") minuslink = linktmpl % scu.icontag("minus_img", border="0", alt="-")
pluslink = linktmpl % icontag("plus_img", border="0", alt="+") pluslink = linktmpl % scu.icontag("plus_img", border="0", alt="+")
H = ['<table class="notes_bulletin" style="background-color: %s;">' % bgcolor] H = ['<table class="notes_bulletin" style="background-color: %s;">' % bgcolor]
@ -131,8 +134,8 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
if context.get_preference("bul_show_minmax_mod", formsemestre_id): if context.get_preference("bul_show_minmax_mod", formsemestre_id):
rang_minmax = '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' % ( rang_minmax = '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' % (
mod["mod_rang_txt"], mod["mod_rang_txt"],
fmt_note(mod["stats"]["min"]), scu.fmt_note(mod["stats"]["min"]),
fmt_note(mod["stats"]["max"]), scu.fmt_note(mod["stats"]["max"]),
) )
else: else:
rang_minmax = mod["mod_rang_txt"] # vide si pas option rang rang_minmax = mod["mod_rang_txt"] # vide si pas option rang
@ -209,9 +212,9 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
moy_txt = ( moy_txt = (
'%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>'
% ( % (
fmt_note(ue["cur_moy_ue_txt"]), scu.fmt_note(ue["cur_moy_ue_txt"]),
fmt_note(ue["min"]), scu.fmt_note(ue["min"]),
fmt_note(ue["max"]), scu.fmt_note(ue["max"]),
) )
) )
else: else:
@ -441,7 +444,6 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
S = BulTableStyle() S = BulTableStyle()
P = [] # elems pour gen. pdf P = [] # elems pour gen. pdf
formsemestre_id = I["formsemestre_id"] formsemestre_id = I["formsemestre_id"]
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
bul_show_abs_modules = context.get_preference( bul_show_abs_modules = context.get_preference(
"bul_show_abs_modules", formsemestre_id "bul_show_abs_modules", formsemestre_id
) )
@ -460,7 +462,7 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
] ]
if bul_show_abs_modules: if bul_show_abs_modules:
t.append("Abs (J. / N.J.)") t.append("Abs (J. / N.J.)")
P.append(bold_paras(t)) P.append(sco_pdf.bold_paras(t))
def list_modules(ue_modules, ue_type=None): def list_modules(ue_modules, ue_type=None):
"ajoute les lignes decrivant les modules d'une UE, avec eventuellement les évaluations de chacun" "ajoute les lignes decrivant les modules d'une UE, avec eventuellement les évaluations de chacun"
@ -471,8 +473,8 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
if context.get_preference("bul_show_minmax_mod", formsemestre_id): if context.get_preference("bul_show_minmax_mod", formsemestre_id):
rang_minmax = '%s <font size="8">[%s, %s]</font>' % ( rang_minmax = '%s <font size="8">[%s, %s]</font>' % (
mod["mod_rang_txt"], mod["mod_rang_txt"],
fmt_note(mod["stats"]["min"]), scu.fmt_note(mod["stats"]["min"]),
fmt_note(mod["stats"]["max"]), scu.fmt_note(mod["stats"]["max"]),
) )
else: else:
rang_minmax = mod["mod_rang_txt"] # vide si pas option rang rang_minmax = mod["mod_rang_txt"] # vide si pas option rang
@ -504,7 +506,7 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
t = [ue["acronyme"], ue["moy_ue_txt"], ue_descr, "", coef_ue] t = [ue["acronyme"], ue["moy_ue_txt"], ue_descr, "", coef_ue]
if bul_show_abs_modules: if bul_show_abs_modules:
t.append("") t.append("")
P.append(bold_paras(t)) P.append(sco_pdf.bold_paras(t))
coef_ue = "" coef_ue = ""
ue_descr = "(en cours, non prise en compte)" ue_descr = "(en cours, non prise en compte)"
S.ueline() S.ueline()
@ -523,7 +525,7 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
t = [ue["acronyme"], moy_txt, ue_descr, "", coef_ue] t = [ue["acronyme"], moy_txt, ue_descr, "", coef_ue]
if bul_show_abs_modules: if bul_show_abs_modules:
t.append("") t.append("")
P.append(bold_paras(t)) P.append(sco_pdf.bold_paras(t))
S.ueline() S.ueline()
list_modules(ue["modules"], ue_type=ue_type) list_modules(ue["modules"], ue_type=ue_type)

View File

@ -50,13 +50,21 @@ Pour définir un nouveau type de bulletin:
Chaque semestre peut si nécessaire utiliser un type de bulletin différent. Chaque semestre peut si nécessaire utiliser un type de bulletin différent.
""" """
import htmlutils, time import htmlutils
import pprint, traceback import time
import pprint
import traceback
import re
import cStringIO
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
from notes_table import * import VERSION
import sco_utils as scu
from notes_log import log
import sco_formsemestre
import sco_bulletins import sco_bulletins
from sco_pdf import * import sco_pdf
import os import os
@ -84,10 +92,10 @@ def pdfassemblebulletins(
report = cStringIO.StringIO() # in-memory document, no disk file report = cStringIO.StringIO() # in-memory document, no disk file
document = BaseDocTemplate(report) document = BaseDocTemplate(report)
document.addPageTemplates( document.addPageTemplates(
ScolarsPageTemplate( sco_pdf.ScolarsPageTemplate(
document, document,
context=context, context=context,
author="%s %s (E. Viennet)" % (SCONAME, SCOVERSION), author="%s %s (E. Viennet)" % (VERSION.SCONAME, VERSION.SCOVERSION),
title="Bulletin %s" % bul_title, title="Bulletin %s" % bul_title,
subject="Bulletin de note", subject="Bulletin de note",
server_name=server_name, server_name=server_name,
@ -117,7 +125,7 @@ def process_field(
If format = 'html', replaces <para> by <p>. HTML does not allow logos. If format = 'html', replaces <para> by <p>. HTML does not allow logos.
""" """
try: try:
text = (field or "") % WrapDict( text = (field or "") % scu.WrapDict(
cdict cdict
) # note that None values are mapped to empty strings ) # note that None values are mapped to empty strings
except: except:
@ -135,9 +143,9 @@ def process_field(
return text return text
# --- PDF format: # --- PDF format:
# handle logos: # handle logos:
image_dir = SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/" image_dir = scu.SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/"
if not os.path.exists(image_dir): if not os.path.exists(image_dir):
image_dir = SCODOC_LOGOS_DIR + "/" # use global logos image_dir = scu.SCODOC_LOGOS_DIR + "/" # use global logos
text = re.sub( text = re.sub(
r"<(\s*)logo(.*?)src\s*=\s*(.*?)>", r"<\1logo\2\3>", text r"<(\s*)logo(.*?)src\s*=\s*(.*?)>", r"<\1logo\2\3>", text
) # remove forbidden src attribute ) # remove forbidden src attribute
@ -150,7 +158,7 @@ def process_field(
# tentatives d'acceder à d'autres fichiers ! # tentatives d'acceder à d'autres fichiers !
# log('field: %s' % (text)) # log('field: %s' % (text))
return makeParas(text, style, suppress_empty=suppress_empty_pars) return sco_pdf.makeParas(text, style, suppress_empty=suppress_empty_pars)
def get_formsemestre_bulletins_pdf( def get_formsemestre_bulletins_pdf(
@ -180,7 +188,7 @@ def get_formsemestre_bulletins_pdf(
) )
fragments += frag fragments += frag
filigrannes[i] = filigranne filigrannes[i] = filigranne
bookmarks[i] = suppress_accents(nt.get_sexnom(etudid)) bookmarks[i] = scu.suppress_accents(nt.get_sexnom(etudid))
i = i + 1 i = i + 1
# #
infos = {"DeptName": context.get_preference("DeptName", formsemestre_id)} infos = {"DeptName": context.get_preference("DeptName", formsemestre_id)}
@ -189,7 +197,7 @@ def get_formsemestre_bulletins_pdf(
else: else:
server_name = "" server_name = ""
try: try:
PDFLOCK.acquire() sco_pdf.PDFLOCK.acquire()
pdfdoc = pdfassemblebulletins( pdfdoc = pdfassemblebulletins(
formsemestre_id, formsemestre_id,
fragments, fragments,
@ -201,11 +209,11 @@ def get_formsemestre_bulletins_pdf(
context=context, context=context,
) )
finally: finally:
PDFLOCK.release() sco_pdf.PDFLOCK.release()
# #
dt = time.strftime("%Y-%m-%d") dt = time.strftime("%Y-%m-%d")
filename = "bul-%s-%s.pdf" % (sem["titre_num"], dt) filename = "bul-%s-%s.pdf" % (sem["titre_num"], dt)
filename = unescape_html(filename).replace(" ", "_").replace("&", "") filename = scu.unescape_html(filename).replace(" ", "_").replace("&", "")
# fill cache # fill cache
context._getNotesCache().store_bulletins_pdf( context._getNotesCache().store_bulletins_pdf(
formsemestre_id, version, filename, pdfdoc formsemestre_id, version, filename, pdfdoc
@ -239,7 +247,7 @@ def get_etud_bulletins_pdf(context, etudid, REQUEST, version="selectedevals"):
else: else:
server_name = "" server_name = ""
try: try:
PDFLOCK.acquire() sco_pdf.PDFLOCK.acquire()
pdfdoc = pdfassemblebulletins( pdfdoc = pdfassemblebulletins(
None, None,
fragments, fragments,
@ -251,11 +259,11 @@ def get_etud_bulletins_pdf(context, etudid, REQUEST, version="selectedevals"):
context=context, context=context,
) )
finally: finally:
PDFLOCK.release() sco_pdf.PDFLOCK.release()
# #
filename = "bul-%s" % (etud["nomprenom"]) filename = "bul-%s" % (etud["nomprenom"])
filename = ( filename = (
unescape_html(filename).replace(" ", "_").replace("&", "").replace(".", "") scu.unescape_html(filename).replace(" ", "_").replace("&", "").replace(".", "")
+ ".pdf" + ".pdf"
) )

View File

@ -53,53 +53,53 @@ Lien sur Scolarite/edit_preferences (sans formsemestre_id)
et sur page "réglages bulletin" (avec formsemestre_id) et sur page "réglages bulletin" (avec formsemestre_id)
""" """
import os # import os
def form_change_bul_sig(context, side, formsemestre_id=None, REQUEST=None): # def form_change_bul_sig(context, side, formsemestre_id=None, REQUEST=None):
"""Change pdf signature""" # """Change pdf signature"""
filename = _get_sig_existing_filename( # filename = _get_sig_existing_filename(
context, side, formsemestre_id=formsemestre_id # context, side, formsemestre_id=formsemestre_id
) # )
if side == "left": # if side == "left":
sidetxt = "gauche" # sidetxt = "gauche"
elif side == "right": # elif side == "right":
sidetxt = "droite" # sidetxt = "droite"
else: # else:
raise ValueError("invalid value for 'side' parameter") # raise ValueError("invalid value for 'side' parameter")
signatureloc = get_bul_sig_img() # signatureloc = get_bul_sig_img()
H = [ # H = [
self.sco_header(REQUEST, page_title="Changement de signature"), # self.sco_header(REQUEST, page_title="Changement de signature"),
"""<h2>Changement de la signature bulletin de %(sidetxt)s</h2> # """<h2>Changement de la signature bulletin de %(sidetxt)s</h2>
""" # """
% (sidetxt,), # % (sidetxt,),
] # ]
"<p>Photo actuelle (%(signatureloc)s): " # "<p>Photo actuelle (%(signatureloc)s): "
def get_bul_sig_img(context, side, formsemestre_id=None): # def get_bul_sig_img(context, side, formsemestre_id=None):
"send back signature image data" # "send back signature image data"
# slow, not cached, used for unfrequent access (do not bypass python) # # slow, not cached, used for unfrequent access (do not bypass python)
def _sig_filename(context, side, formsemestre_id=None): # def _sig_filename(context, side, formsemestre_id=None):
if not side in ("left", "right"): # if not side in ("left", "right"):
raise ValueError("side must be left or right") # raise ValueError("side must be left or right")
dirs = [SCODOC_LOGOS_DIR, context.DeptId()] # dirs = [SCODOC_LOGOS_DIR, context.DeptId()]
if formsemestre_id: # if formsemestre_id:
dirs.append(formsemestre_id) # dirs.append(formsemestre_id)
dirs.append("bul_sig_{}".format(side)) # dirs.append("bul_sig_{}".format(side))
return os.path.join(*dirs) # return os.path.join(*dirs)
def _get_sig_existing_filename(context, side, formsemestre_id=None): # def _get_sig_existing_filename(context, side, formsemestre_id=None):
"full path to signature to use, or None if no signature available" # "full path to signature to use, or None if no signature available"
if formsemestre_id: # if formsemestre_id:
filename = _sig_filename(context, side, formsemestre_id=formsemestre_id) # filename = _sig_filename(context, side, formsemestre_id=formsemestre_id)
if os.path.exists(filename): # if os.path.exists(filename):
return filename # return filename
filename = _sig_filename(context, side) # filename = _sig_filename(context, side)
if os.path.exists(filename): # if os.path.exists(filename):
return filename # return filename
else: # else:
return None # return None

View File

@ -34,8 +34,12 @@ E. Viennet, juillet 2011
""" """
import traceback import traceback
import sco_utils as scu
import sco_formsemestre import sco_formsemestre
from sco_pdf import * import sco_pdf
from sco_pdf import blue, cm, mm
from sco_pdf import Color, Paragraph, Spacer, Table
import sco_preferences import sco_preferences
from notes_log import log from notes_log import log
@ -72,7 +76,6 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard):
I = self.infos I = self.infos
context = self.context context = self.context
formsemestre_id = I["formsemestre_id"] formsemestre_id = I["formsemestre_id"]
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
prefs = context.get_preferences(formsemestre_id) prefs = context.get_preferences(formsemestre_id)
P = [] # elems pour générer table avec gen_table (liste de dicts) P = [] # elems pour générer table avec gen_table (liste de dicts)
@ -134,7 +137,7 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard):
total_pt_ue_v = ( total_pt_ue_v = (
ue["ue_status"]["cur_moy_ue"] * ue["ue_status"]["coef_ue"] ue["ue_status"]["cur_moy_ue"] * ue["ue_status"]["coef_ue"]
) )
total_pt_ue = fmt_note(total_pt_ue_v) total_pt_ue = scu.fmt_note(total_pt_ue_v)
# log('total_pt_ue = %s' % total_pt_ue) # log('total_pt_ue = %s' % total_pt_ue)
except: except:
# log("ue['ue_status']['cur_moy_ue'] = %s" % ue['ue_status']['cur_moy_ue'] ) # log("ue['ue_status']['cur_moy_ue'] = %s" % ue['ue_status']['cur_moy_ue'] )
@ -212,7 +215,6 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard):
ue_descr = "(en cours, non prise en compte)" ue_descr = "(en cours, non prise en compte)"
ue_type = "cur" ue_type = "cur"
rowstyle = " bul_ucac_row_ue_cur"
# --- UE ordinaire # --- UE ordinaire
pt = list_ue(ue, ue_descr) pt = list_ue(ue, ue_descr)
@ -228,8 +230,8 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard):
{ {
"code_ue": "Total", "code_ue": "Total",
"moyenne_ue": I["moy_gen"], "moyenne_ue": I["moy_gen"],
"coef": fmt_note(sum_coef_ues), "coef": scu.fmt_note(sum_coef_ues),
"total": fmt_note(sum_pt_sem), "total": scu.fmt_note(sum_pt_sem),
"_code_ue_colspan": 4, "_code_ue_colspan": 4,
"_css_row_class": "bul_ucac_row_total", "_css_row_class": "bul_ucac_row_total",
"_pdf_row_markup": ["b"], "_pdf_row_markup": ["b"],

View File

@ -37,7 +37,14 @@ Malheureusement, le code de génération JSON et XML sont séparés, ce qui est
Je propose de considérer le XMl comme "deprecated" et de ne plus le modifier, sauf nécessité. Je propose de considérer le XMl comme "deprecated" et de ne plus le modifier, sauf nécessité.
""" """
from notes_table import * import datetime
import jaxml
import sco_utils as scu
import notesdb as ndb
from notes_log import log
import scolars
import sco_codes_parcours
import sco_formsemestre import sco_formsemestre
import sco_groups import sco_groups
import sco_photos import sco_photos
@ -62,9 +69,9 @@ def make_xml_formsemestre_bulletinetud(
"bulletin au format XML" "bulletin au format XML"
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", XML_MIMETYPE) REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
if not doc: if not doc:
doc = jaxml.XML_document(encoding=SCO_ENCODING) 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:
@ -98,12 +105,12 @@ def make_xml_formsemestre_bulletinetud(
etudid=etudid, etudid=etudid,
code_nip=etudinfo["code_nip"], code_nip=etudinfo["code_nip"],
code_ine=etudinfo["code_ine"], code_ine=etudinfo["code_ine"],
nom=quote_xml_attr(etudinfo["nom"]), nom=scu.quote_xml_attr(etudinfo["nom"]),
prenom=quote_xml_attr(etudinfo["prenom"]), prenom=scu.quote_xml_attr(etudinfo["prenom"]),
sexe=quote_xml_attr(etudinfo["sexe"]), sexe=scu.quote_xml_attr(etudinfo["sexe"]),
photo_url=quote_xml_attr(sco_photos.etud_photo_url(context, etudinfo)), photo_url=scu.quote_xml_attr(sco_photos.etud_photo_url(context, etudinfo)),
email=quote_xml_attr(etudinfo["email"]), email=scu.quote_xml_attr(etudinfo["email"]),
emailperso=quote_xml_attr(etudinfo["emailperso"]), emailperso=scu.quote_xml_attr(etudinfo["emailperso"]),
) )
doc._pop() doc._pop()
@ -128,7 +135,7 @@ def make_xml_formsemestre_bulletinetud(
ues = nt.get_ues() ues = nt.get_ues()
modimpls = nt.get_modimpls() modimpls = nt.get_modimpls()
nbetuds = len(nt.rangs) nbetuds = len(nt.rangs)
mg = fmt_note(nt.get_etud_moy_gen(etudid)) mg = scu.fmt_note(nt.get_etud_moy_gen(etudid))
if ( if (
nt.get_moduleimpls_attente() nt.get_moduleimpls_attente()
or context.get_preference("bul_show_rangs", formsemestre_id) == 0 or context.get_preference("bul_show_rangs", formsemestre_id) == 0
@ -147,9 +154,9 @@ def make_xml_formsemestre_bulletinetud(
doc._push() doc._push()
doc.note( doc.note(
value=mg, value=mg,
min=fmt_note(nt.moy_min), min=scu.fmt_note(nt.moy_min),
max=fmt_note(nt.moy_max), max=scu.fmt_note(nt.moy_max),
moy=fmt_note(nt.moy_moy), moy=scu.fmt_note(nt.moy_moy),
) )
doc._pop() doc._pop()
doc._push() doc._push()
@ -177,17 +184,21 @@ def make_xml_formsemestre_bulletinetud(
doc._push() doc._push()
doc.ue( doc.ue(
id=ue["ue_id"], id=ue["ue_id"],
numero=quote_xml_attr(ue["numero"]), numero=scu.quote_xml_attr(ue["numero"]),
acronyme=quote_xml_attr(ue["acronyme"]), acronyme=scu.quote_xml_attr(ue["acronyme"]),
titre=quote_xml_attr(ue["titre"]), titre=scu.quote_xml_attr(ue["titre"]),
code_apogee=quote_xml_attr(ue["code_apogee"]), code_apogee=scu.quote_xml_attr(ue["code_apogee"]),
) )
doc._push() doc._push()
if ue["type"] != 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(value=fmt_note(v), min=fmt_note(ue["min"]), max=fmt_note(ue["max"])) doc.note(
value=scu.fmt_note(v),
min=scu.fmt_note(ue["min"]),
max=scu.fmt_note(ue["max"]),
)
doc._pop() doc._pop()
try: try:
ects_txt = str(int(ue["ects"])) ects_txt = str(int(ue["ects"]))
@ -205,7 +216,9 @@ def make_xml_formsemestre_bulletinetud(
# 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:
mod_moy = fmt_note(nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid)) mod_moy = scu.fmt_note(
nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid)
)
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"]
@ -219,18 +232,18 @@ def make_xml_formsemestre_bulletinetud(
code=mod["code"], code=mod["code"],
coefficient=mod["coefficient"], coefficient=mod["coefficient"],
numero=mod["numero"], numero=mod["numero"],
titre=quote_xml_attr(mod["titre"]), titre=scu.quote_xml_attr(mod["titre"]),
abbrev=quote_xml_attr(mod["abbrev"]), abbrev=scu.quote_xml_attr(mod["abbrev"]),
code_apogee=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() doc._push()
modstat = nt.get_mod_stats(modimpl["moduleimpl_id"]) modstat = nt.get_mod_stats(modimpl["moduleimpl_id"])
doc.note( doc.note(
value=mod_moy, value=mod_moy,
min=fmt_note(modstat["min"]), min=scu.fmt_note(modstat["min"]),
max=fmt_note(modstat["max"]), max=scu.fmt_note(modstat["max"]),
moy=fmt_note(modstat["moy"]), moy=scu.fmt_note(modstat["moy"]),
) )
doc._pop() doc._pop()
if context.get_preference("bul_show_mod_rangs", formsemestre_id): if context.get_preference("bul_show_mod_rangs", formsemestre_id):
@ -247,14 +260,16 @@ def make_xml_formsemestre_bulletinetud(
if int(e["visibulletin"]) == 1 or version == "long": if int(e["visibulletin"]) == 1 or version == "long":
doc._push() doc._push()
doc.evaluation( doc.evaluation(
jour=DateDMYtoISO(e["jour"], null_is_empty=True), jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True),
heure_debut=TimetoISO8601( heure_debut=ndb.TimetoISO8601(
e["heure_debut"], null_is_empty=True e["heure_debut"], null_is_empty=True
), ),
heure_fin=TimetoISO8601(e["heure_fin"], null_is_empty=True), heure_fin=ndb.TimetoISO8601(
e["heure_fin"], null_is_empty=True
),
coefficient=e["coefficient"], coefficient=e["coefficient"],
evaluation_type=e["evaluation_type"], evaluation_type=e["evaluation_type"],
description=quote_xml_attr(e["description"]), description=scu.quote_xml_attr(e["description"]),
note_max_origin=e[ note_max_origin=e[
"note_max" "note_max"
], # notes envoyées sur 20, ceci juste pour garder trace ], # notes envoyées sur 20, ceci juste pour garder trace
@ -262,7 +277,7 @@ def make_xml_formsemestre_bulletinetud(
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 = fmt_note(val, note_max=e["note_max"]) val = scu.fmt_note(val, note_max=e["note_max"])
doc.note(value=val) doc.note(value=val)
doc._pop() doc._pop()
# Evaluations incomplètes ou futures: # Evaluations incomplètes ou futures:
@ -276,15 +291,15 @@ def make_xml_formsemestre_bulletinetud(
if e["evaluation_id"] not in complete_eval_ids: if e["evaluation_id"] not in complete_eval_ids:
doc._push() doc._push()
doc.evaluation( doc.evaluation(
jour=DateDMYtoISO(e["jour"], null_is_empty=True), jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True),
heure_debut=TimetoISO8601( heure_debut=ndb.TimetoISO8601(
e["heure_debut"], null_is_empty=True e["heure_debut"], null_is_empty=True
), ),
heure_fin=TimetoISO8601( heure_fin=ndb.TimetoISO8601(
e["heure_fin"], null_is_empty=True e["heure_fin"], null_is_empty=True
), ),
coefficient=e["coefficient"], coefficient=e["coefficient"],
description=quote_xml_attr(e["description"]), description=scu.quote_xml_attr(e["description"]),
incomplete="1", incomplete="1",
note_max_origin=e[ note_max_origin=e[
"note_max" "note_max"
@ -302,27 +317,25 @@ def make_xml_formsemestre_bulletinetud(
doc._push() doc._push()
doc.ue_capitalisee( doc.ue_capitalisee(
id=ue["ue_id"], id=ue["ue_id"],
numero=quote_xml_attr(ue["numero"]), numero=scu.quote_xml_attr(ue["numero"]),
acronyme=quote_xml_attr(ue["acronyme"]), acronyme=scu.quote_xml_attr(ue["acronyme"]),
titre=quote_xml_attr(ue["titre"]), titre=scu.quote_xml_attr(ue["titre"]),
) )
doc._push() doc._push()
doc.note(value=fmt_note(ue_status["moy"])) doc.note(value=scu.fmt_note(ue_status["moy"]))
doc._pop() doc._pop()
doc._push() doc._push()
doc.ects(value=ects_txt) doc.ects(value=ects_txt)
doc._pop() doc._pop()
doc._push() doc._push()
doc.coefficient_ue(value=fmt_note(ue_status["coef_ue"])) doc.coefficient_ue(value=scu.fmt_note(ue_status["coef_ue"]))
doc._pop() doc._pop()
doc._push() doc._push()
doc.date_capitalisation(value=DateDMYtoISO(ue_status["event_date"])) doc.date_capitalisation(value=ndb.DateDMYtoISO(ue_status["event_date"]))
doc._pop() doc._pop()
doc._pop() doc._pop()
# --- Absences # --- Absences
if context.get_preference("bul_show_abs", formsemestre_id): if context.get_preference("bul_show_abs", formsemestre_id):
debut_sem = DateDMYtoISO(sem["date_debut"])
fin_sem = DateDMYtoISO(sem["date_fin"])
AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid) AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid)
nbabs = AbsEtudSem.CountAbs() nbabs = AbsEtudSem.CountAbs()
nbabsjust = AbsEtudSem.CountAbsJust() nbabsjust = AbsEtudSem.CountAbsJust()
@ -341,7 +354,7 @@ def make_xml_formsemestre_bulletinetud(
format="xml", format="xml",
show_uevalid=context.get_preference("bul_show_uevalid", formsemestre_id), show_uevalid=context.get_preference("bul_show_uevalid", formsemestre_id),
) )
doc.situation(quote_xml_attr(infos["situation"])) doc.situation(scu.quote_xml_attr(infos["situation"]))
if dpv: if dpv:
decision = dpv["decisions"][0] decision = dpv["decisions"][0]
etat = decision["etat"] etat = decision["etat"]
@ -375,9 +388,9 @@ def make_xml_formsemestre_bulletinetud(
doc._push() doc._push()
doc.decision_ue( doc.decision_ue(
ue_id=ue["ue_id"], ue_id=ue["ue_id"],
numero=quote_xml_attr(ue["numero"]), numero=scu.quote_xml_attr(ue["numero"]),
acronyme=quote_xml_attr(ue["acronyme"]), acronyme=scu.quote_xml_attr(ue["acronyme"]),
titre=quote_xml_attr(ue["titre"]), titre=scu.quote_xml_attr(ue["titre"]),
code=decision["decisions_ue"][ue_id]["code"], code=decision["decisions_ue"][ue_id]["code"],
) )
doc._pop() doc._pop()
@ -396,5 +409,7 @@ def make_xml_formsemestre_bulletinetud(
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(quote_xml_attr(app["comment"]), date=DateDMYtoISO(app["date"])) doc.appreciation(
scu.quote_xml_attr(app["comment"]), date=ndb.DateDMYtoISO(app["date"])
)
return doc return doc