Small fixes

This commit is contained in:
Emmanuel Viennet 2021-01-10 18:05:20 +01:00
parent 82f0612883
commit 3afec00b5e
2 changed files with 72 additions and 47 deletions

View File

@ -42,12 +42,22 @@ La préférence 'bul_pdf_class_name' est obsolete (inutilisée).
""" """
import time
import cStringIO
import collections import collections
import traceback
import reportlab
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Frame, PageBreak
from reportlab.platypus import Table, TableStyle, Image, KeepInFrame
import sco_utils
import VERSION
from sco_exceptions import NoteProcessError
import sco_preferences import sco_preferences
from notes_log import log from notes_log import log
import sco_formsemestre import sco_formsemestre
from sco_pdf import * import sco_pdf
from sco_pdf import PDFLOCK
BULLETIN_CLASSES = ( BULLETIN_CLASSES = (
collections.OrderedDict() collections.OrderedDict()
@ -145,7 +155,7 @@ class BulletinGenerator:
dt, dt,
self.infos["etud"]["nom"], self.infos["etud"]["nom"],
) )
filename = unescape_html(filename).replace(" ", "_").replace("&", "") filename = sco_utils.unescape_html(filename).replace(" ", "_").replace("&", "")
return filename return filename
def generate(self, format="", stand_alone=True): def generate(self, format="", stand_alone=True):
@ -166,8 +176,10 @@ class BulletinGenerator:
def generate_html(self): def generate_html(self):
"""Return bulletin as an HTML string""" """Return bulletin as an HTML string"""
H = ['<div class="notes_bulletin">'] H = ['<div class="notes_bulletin">']
H.append(self.bul_table(format="html")) # table des notes # table des notes:
H.append(self.bul_part_below(format="html")) # infos sous la table H.append(self.bul_table(format="html")) # pylint: disable=no-member
# infos sous la table:
H.append(self.bul_part_below(format="html")) # pylint: disable=no-member
H.append("</div>") H.append("</div>")
return "\n".join(H) return "\n".join(H)
@ -179,10 +191,14 @@ class BulletinGenerator:
""" """
formsemestre_id = self.infos["formsemestre_id"] formsemestre_id = self.infos["formsemestre_id"]
objects = self.bul_title_pdf() # partie haute du bulletin # partie haute du bulletin
objects += self.bul_table(format="pdf") # table des notes objects = self.bul_title_pdf() # pylint: disable=no-member
objects += self.bul_part_below(format="pdf") # infos sous la table # table des notes
objects += self.bul_signatures_pdf() # signatures objects += self.bul_table(format="pdf") # pylint: disable=no-member
# infos sous la table
objects += self.bul_part_below(format="pdf") # pylint: disable=no-member
# signatures
objects += self.bul_signatures_pdf() # pylint: disable=no-member
# Réduit sur une page # Réduit sur une page
objects = [KeepInFrame(0, 0, objects, mode="shrink")] objects = [KeepInFrame(0, 0, objects, mode="shrink")]
@ -194,13 +210,13 @@ class BulletinGenerator:
# Generation du document PDF # Generation du document PDF
sem = sco_formsemestre.get_formsemestre(self.context, formsemestre_id) sem = sco_formsemestre.get_formsemestre(self.context, formsemestre_id)
report = cStringIO.StringIO() # in-memory document, no disk file report = cStringIO.StringIO() # in-memory document, no disk file
document = BaseDocTemplate(report) document = sco_pdf.BaseDocTemplate(report)
document.addPageTemplates( document.addPageTemplates(
ScolarsPageTemplate( sco_pdf.ScolarsPageTemplate(
document, document,
context=self.context, context=self.context,
author="%s %s (E. Viennet) [%s]" author="%s %s (E. Viennet) [%s]"
% (SCONAME, SCOVERSION, self.description), % (VERSION.SCONAME, VERSION.SCOVERSION, self.description),
title="Bulletin %s de %s" title="Bulletin %s de %s"
% (sem["titremois"], self.infos["etud"]["nomprenom"]), % (sem["titremois"], self.infos["etud"]["nomprenom"]),
subject="Bulletin de note", subject="Bulletin de note",
@ -222,7 +238,9 @@ class BulletinGenerator:
""" """
try: try:
# put each table cell in a Paragraph # put each table cell in a Paragraph
Pt = [[Paragraph(SU(x), self.CellStyle) for x in line] for line in P] Pt = [
[Paragraph(sco_pdf.SU(x), self.CellStyle) for x in line] for line in P
]
except: except:
# enquête sur exception intermittente... # enquête sur exception intermittente...
log("*** bug in PDF buildTableObject:") log("*** bug in PDF buildTableObject:")

View File

@ -29,16 +29,22 @@
- statistiques decisions - statistiques decisions
- suivi cohortes - suivi cohortes
""" """
import os
import tempfile
import urllib
import re
import time
import mx
import mx.DateTime import mx.DateTime
from mx.DateTime import DateTime as mxDateTime from mx.DateTime import DateTime as mxDateTime
import tempfile, urllib, re
import sco_utils as scu
from notesdb import * import VERSION
from sco_utils import *
from notes_log import log from notes_log import log
from gen_tables import GenTable from gen_tables import GenTable
import sco_excel, sco_pdf import sco_excel, sco_pdf
from notesdb import DateDMYtoISO
from sco_exceptions import ScoValueError
import sco_codes_parcours import sco_codes_parcours
from sco_codes_parcours import code_semestre_validant from sco_codes_parcours import code_semestre_validant
import sco_parcours_dut import sco_parcours_dut
@ -129,7 +135,7 @@ def _results_by_category(
if Count.has_key(etud[category]): if Count.has_key(etud[category]):
Count[etud[category]][etud[result]] += 1 Count[etud[category]][etud[result]] += 1
else: else:
Count[etud[category]] = DictDefault(kv_dict={etud[result]: 1}) Count[etud[category]] = scu.DictDefault(kv_dict={etud[result]: 1})
# conversion en liste de dict # conversion en liste de dict
C = [Count[cat] for cat in categories] C = [Count[cat] for cat in categories]
# Totaux par lignes et colonnes # Totaux par lignes et colonnes
@ -214,9 +220,9 @@ def formsemestre_report(
formsemestre_id=formsemestre_id, formsemestre_id=formsemestre_id,
) )
# #
tab.filename = make_filename("stats " + sem["titreannee"]) tab.filename = scu.make_filename("stats " + sem["titreannee"])
tab.origin = "Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "" tab.origin = "Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + ""
tab.caption = "Répartition des résultats par %s, semestre %s" % ( tab.caption = "Répartition des résultats par %s, semestre %s" % (
category_name, category_name,
sem["titreannee"], sem["titreannee"],
@ -259,7 +265,7 @@ def formsemestre_report_counts(
Tableau comptage avec choix des categories Tableau comptage avec choix des categories
""" """
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
category_name = strcapitalize(category) category_name = scu.strcapitalize(category)
title = "Comptages " + category_name title = "Comptages " + category_name
etuds = formsemestre_etuds_stats(context, sem, only_primo=only_primo) etuds = formsemestre_etuds_stats(context, sem, only_primo=only_primo)
tab = formsemestre_report( tab = formsemestre_report(
@ -484,7 +490,7 @@ def table_suivi_cohorte(
indices_sems.sort() indices_sems.sort()
for p in P: for p in P:
p.nb_etuds = 0 # nombre total d'etudiants dans la periode p.nb_etuds = 0 # nombre total d'etudiants dans la periode
p.sems_by_id = DictDefault(defaultvalue=[]) p.sems_by_id = scu.DictDefault(defaultvalue=[])
for s in p.sems: for s in p.sems:
p.sems_by_id[s["semestre_id"]].append(s) p.sems_by_id[s["semestre_id"]].append(s)
p.nb_etuds += len(s["members"]) p.nb_etuds += len(s["members"])
@ -623,8 +629,8 @@ def table_suivi_cohorte(
rows=L, rows=L,
html_col_width="4em", html_col_width="4em",
html_sortable=True, html_sortable=True,
filename=make_filename("cohorte " + sem["titreannee"]), filename=scu.make_filename("cohorte " + sem["titreannee"]),
origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "", origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "",
caption="Suivi cohorte " + pp + sem["titreannee"] + dbac, caption="Suivi cohorte " + pp + sem["titreannee"] + dbac,
page_title="Suivi cohorte " + sem["titreannee"], page_title="Suivi cohorte " + sem["titreannee"],
html_class="table_cohorte", html_class="table_cohorte",
@ -666,7 +672,6 @@ def formsemestre_suivi_cohorte(
): ):
"""Affiche suivi cohortes par numero de semestre""" """Affiche suivi cohortes par numero de semestre"""
percent = int(percent) percent = int(percent)
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
tab, expl, bacs, bacspecialites, annee_bacs, sexes, statuts = table_suivi_cohorte( tab, expl, bacs, bacspecialites, annee_bacs, sexes, statuts = table_suivi_cohorte(
context, context,
formsemestre_id, formsemestre_id,
@ -1049,7 +1054,7 @@ def table_suivi_parcours(
etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = tsp_etud_list( etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = tsp_etud_list(
context, formsemestre_id, only_primo=only_primo context, formsemestre_id, only_primo=only_primo
) )
codes_etuds = DictDefault(defaultvalue=[]) codes_etuds = scu.DictDefault(defaultvalue=[])
for etud in etuds: for etud in etuds:
etud["codeparcours"], etud["decisions_jury"] = get_codeparcoursetud( etud["codeparcours"], etud["decisions_jury"] = get_codeparcoursetud(
context, etud context, etud
@ -1105,7 +1110,7 @@ def table_suivi_parcours(
columns_ids=columns_ids, columns_ids=columns_ids,
rows=L, rows=L,
titles=titles, titles=titles,
origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "", origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "",
caption="Parcours suivis, étudiants %s semestre " % primostr caption="Parcours suivis, étudiants %s semestre " % primostr
+ sem["titreannee"], + sem["titreannee"],
page_title="Parcours " + sem["titreannee"], page_title="Parcours " + sem["titreannee"],
@ -1164,7 +1169,6 @@ def formsemestre_suivi_parcours(
REQUEST=None, REQUEST=None,
): ):
"""Effectifs dans les differents parcours possibles.""" """Effectifs dans les differents parcours possibles."""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
tab = table_suivi_parcours( tab = table_suivi_parcours(
context, context,
formsemestre_id, formsemestre_id,
@ -1211,9 +1215,8 @@ def graph_parcours(
statut="", statut="",
): ):
"""""" """"""
if not WITH_PYDOT: if not scu.WITH_PYDOT:
raise ScoValueError("pydot module is not installed") raise ScoValueError("pydot module is not installed")
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = tsp_etud_list( etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = tsp_etud_list(
context, context,
formsemestre_id, formsemestre_id,
@ -1227,12 +1230,12 @@ def graph_parcours(
# log('graph_parcours: %s etuds (only_primo=%s)' % (len(etuds), only_primo)) # log('graph_parcours: %s etuds (only_primo=%s)' % (len(etuds), only_primo))
if not etuds: if not etuds:
return "", etuds, bacs, bacspecialites, annee_bacs, sexes, statuts return "", etuds, bacs, bacspecialites, annee_bacs, sexes, statuts
edges = DictDefault( edges = scu.DictDefault(
defaultvalue=set() defaultvalue=set()
) # {(formsemestre_id_origin, formsemestre_id_dest) : etud_set} ) # {(formsemestre_id_origin, formsemestre_id_dest) : etud_set}
sems = {} sems = {}
effectifs = DictDefault(defaultvalue=set()) # formsemestre_id : etud_set effectifs = scu.DictDefault(defaultvalue=set()) # formsemestre_id : etud_set
decisions = DictDefault(defaultvalue={}) # formsemestre_id : { code : nb_etud } decisions = scu.DictDefault(defaultvalue={}) # formsemestre_id : { code : nb_etud }
isolated_nodes = [] isolated_nodes = []
connected_nodes = set() connected_nodes = set()
diploma_nodes = [] diploma_nodes = []
@ -1279,7 +1282,11 @@ def graph_parcours(
dem_nodes[s["formsemestre_id"]] = nid dem_nodes[s["formsemestre_id"]] = nid
edges[(s["formsemestre_id"], nid)].add(etudid) edges[(s["formsemestre_id"], nid)].add(etudid)
# ajout noeud pour NAR (seulement pour noeud de depart) # ajout noeud pour NAR (seulement pour noeud de depart)
if s["formsemestre_id"] == formsemestre_id and dec and dec["code"] == NAR: if (
s["formsemestre_id"] == formsemestre_id
and dec
and dec["code"] == sco_codes_parcours.NAR
):
nid = "_nar_" + s["formsemestre_id"] nid = "_nar_" + s["formsemestre_id"]
nar_nodes[s["formsemestre_id"]] = nid nar_nodes[s["formsemestre_id"]] = nid
edges[(s["formsemestre_id"], nid)].add(etudid) edges[(s["formsemestre_id"], nid)].add(etudid)
@ -1295,10 +1302,10 @@ def graph_parcours(
edges[(s["formsemestre_id"], nid)].add(etudid) edges[(s["formsemestre_id"], nid)].add(etudid)
diploma_nodes.append(nid) diploma_nodes.append(nid)
# #
g = pydot.graph_from_edges(edges.keys()) g = scu.pydot.graph_from_edges(edges.keys())
for fid in isolated_nodes: for fid in isolated_nodes:
if not fid in connected_nodes: if not fid in connected_nodes:
n = pydot.Node(name=fid) n = scu.pydot.Node(name=fid)
g.add_node(n) g.add_node(n)
g.set("rankdir", "LR") # left to right g.set("rankdir", "LR") # left to right
g.set_fontname("Helvetica") g.set_fontname("Helvetica")
@ -1306,7 +1313,7 @@ def graph_parcours(
g.set_bgcolor("#fffff0") # ou 'transparent' g.set_bgcolor("#fffff0") # ou 'transparent'
# titres des semestres: # titres des semestres:
for s in sems.values(): for s in sems.values():
n = pydot_get_node(g, s["formsemestre_id"]) n = scu.pydot_get_node(g, s["formsemestre_id"])
log("s['formsemestre_id'] = %s" % s["formsemestre_id"]) log("s['formsemestre_id'] = %s" % s["formsemestre_id"])
log("n=%s" % n) log("n=%s" % n)
log("get=%s" % g.get_node(s["formsemestre_id"])) log("get=%s" % g.get_node(s["formsemestre_id"]))
@ -1324,31 +1331,31 @@ def graph_parcours(
s["annee_fin"][2:], s["annee_fin"][2:],
len(effectifs[s["formsemestre_id"]]), len(effectifs[s["formsemestre_id"]]),
) )
n.set("label", suppress_accents(label)) n.set("label", scu.suppress_accents(label))
n.set_fontname("Helvetica") n.set_fontname("Helvetica")
n.set_fontsize(8.0) n.set_fontsize(8.0)
n.set_width(1.2) n.set_width(1.2)
n.set_shape("box") n.set_shape("box")
n.set_URL("formsemestre_status?formsemestre_id=" + s["formsemestre_id"]) n.set_URL("formsemestre_status?formsemestre_id=" + s["formsemestre_id"])
# semestre de depart en vert # semestre de depart en vert
n = pydot_get_node(g, formsemestre_id) n = scu.pydot_get_node(g, formsemestre_id)
n.set_color("green") n.set_color("green")
# demissions en rouge, octagonal # demissions en rouge, octagonal
for nid in dem_nodes.values(): for nid in dem_nodes.values():
n = pydot_get_node(g, nid) n = scu.pydot_get_node(g, nid)
n.set_color("red") n.set_color("red")
n.set_shape("octagon") n.set_shape("octagon")
n.set("label", "Dem.") n.set("label", "Dem.")
# NAR en rouge, Mcircle # NAR en rouge, Mcircle
for nid in nar_nodes.values(): for nid in nar_nodes.values():
n = pydot_get_node(g, nid) n = scu.pydot_get_node(g, nid)
n.set_color("red") n.set_color("red")
n.set_shape("Mcircle") n.set_shape("Mcircle")
n.set("label", NAR) n.set("label", sco_codes_parcours.NAR)
# diplomes: # diplomes:
for nid in diploma_nodes: for nid in diploma_nodes:
n = pydot_get_node(g, nid) n = scu.pydot_get_node(g, nid)
n.set_color("red") n.set_color("red")
n.set_shape("ellipse") n.set_shape("ellipse")
n.set("label", "Diplome") # bug si accent (pas compris pourquoi) n.set("label", "Diplome") # bug si accent (pas compris pourquoi)
@ -1367,7 +1374,7 @@ def graph_parcours(
bubbles[src_id + ":" + dst_id] = etud_descr bubbles[src_id + ":" + dst_id] = etud_descr
e.set_URL("__xxxetudlist__?" + src_id + ":" + dst_id) e.set_URL("__xxxetudlist__?" + src_id + ":" + dst_id)
# Genere graphe # Genere graphe
f, path = tempfile.mkstemp(".gr") _, path = tempfile.mkstemp(".gr")
g.write(path=path, format=format) g.write(path=path, format=format)
data = open(path, "r").read() data = open(path, "r").read()
log("dot generated %d bytes in %s format" % (len(data), format)) log("dot generated %d bytes in %s format" % (len(data), format))
@ -1403,7 +1410,7 @@ def graph_parcours(
) )
return ( return (
'<a xlink:href="formsemestre_status?formsemestre_id=%s" xlink:title="%s"' '<a xlink:href="formsemestre_status?formsemestre_id=%s" xlink:title="%s"'
% (fid, suppress_accents(title)) % (fid, scu.suppress_accents(title))
) # evite accents car svg utf-8 vs page en latin1... ) # evite accents car svg utf-8 vs page en latin1...
data = exp1.sub(repl_title, data) data = exp1.sub(repl_title, data)
@ -1443,8 +1450,8 @@ def formsemestre_graph_parcours(
sexe=sexe, sexe=sexe,
statut=statut, statut=statut,
) )
filename = make_filename("flux " + sem["titreannee"]) filename = scu.make_filename("flux " + sem["titreannee"])
return sco_pdf.sendPDFFile(REQUEST, doc, filename + ".pdf") return scu.sendPDFFile(REQUEST, doc, filename + ".pdf")
elif format == "png": elif format == "png":
# #
doc, etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = graph_parcours( doc, etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = graph_parcours(
@ -1458,7 +1465,7 @@ def formsemestre_graph_parcours(
sexe=sexe, sexe=sexe,
statut=statut, statut=statut,
) )
filename = make_filename("flux " + sem["titreannee"]) filename = scu.make_filename("flux " + sem["titreannee"])
REQUEST.RESPONSE.setHeader( REQUEST.RESPONSE.setHeader(
"content-disposition", 'attachment; filename="%s"' % filename "content-disposition", 'attachment; filename="%s"' % filename
) )