forked from ScoDoc/ScoDoc
UE capitalisées sur bulletins BUT PDF + code cleaning
This commit is contained in:
parent
94ec3266ed
commit
7eef38aefe
@ -286,7 +286,7 @@ def bulletin(
|
||||
if pdf:
|
||||
pdf_response, _ = do_formsemestre_bulletinetud(
|
||||
formsemestre,
|
||||
etud.id,
|
||||
etud,
|
||||
version=version,
|
||||
format="pdf",
|
||||
with_img_signatures_pdf=with_img_signatures_pdf,
|
||||
|
@ -187,6 +187,8 @@ class BulletinBUT:
|
||||
)
|
||||
if ue_capitalisee.formsemestre_id
|
||||
else None,
|
||||
"ressources": {}, # sans détail en BUT
|
||||
"saes": {},
|
||||
}
|
||||
if self.prefs["bul_show_ects"]:
|
||||
d[ue.acronyme]["ECTS"] = {
|
||||
@ -473,6 +475,7 @@ class BulletinBUT:
|
||||
|
||||
def bulletin_etud_complet(self, etud: Identite, version="long") -> dict:
|
||||
"""Bulletin dict complet avec toutes les infos pour les bulletins BUT pdf
|
||||
(pas utilisé pour json/html)
|
||||
Résultat compatible avec celui de sco_bulletins.formsemestre_bulletinetud_dict
|
||||
"""
|
||||
d = self.bulletin_etud(
|
||||
|
@ -5,6 +5,20 @@
|
||||
##############################################################################
|
||||
|
||||
"""Génération bulletin BUT au format PDF standard
|
||||
|
||||
La génération du bulletin PDF suit le chemin suivant:
|
||||
|
||||
- vue formsemestre_bulletinetud -> sco_bulletins.formsemestre_bulletinetud
|
||||
|
||||
bul_dict = bulletin_but.BulletinBUT(formsemestre).bulletin_etud_complet(etud)
|
||||
|
||||
- sco_bulletins_generator.make_formsemestre_bulletinetud(infos)
|
||||
- instance de BulletinGeneratorStandardBUT(infos)
|
||||
- BulletinGeneratorStandardBUT.generate(format="pdf")
|
||||
sco_bulletins_generator.BulletinGenerator.generate()
|
||||
.generate_pdf()
|
||||
.bul_table() (ci-dessous)
|
||||
|
||||
"""
|
||||
from reportlab.lib.colors import blue
|
||||
from reportlab.lib.units import cm, mm
|
||||
@ -65,7 +79,9 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
|
||||
|
||||
return objects
|
||||
|
||||
def but_table_synthese_ues(self, title_bg=(182, 235, 255)):
|
||||
def but_table_synthese_ues(
|
||||
self, title_bg=(182, 235, 255), title_ue_cap_bg=(150, 207, 147)
|
||||
):
|
||||
"""La table de synthèse; pour chaque UE, liste des ressources et SAÉs avec leurs notes
|
||||
et leurs coefs.
|
||||
Renvoie: colkeys, P, pdf_style, colWidths
|
||||
@ -74,6 +90,7 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
|
||||
- pdf_style : commandes table Platypus
|
||||
- largeurs de colonnes pour PDF
|
||||
"""
|
||||
# nb: self.infos a ici été donné par BulletinBUT.bulletin_etud_complet()
|
||||
col_widths = {
|
||||
"titre": None,
|
||||
"min": 1.5 * cm,
|
||||
@ -95,6 +112,7 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
|
||||
col_keys += ["coef", "moyenne"]
|
||||
# Couleur fond:
|
||||
title_bg = tuple(x / 255.0 for x in title_bg)
|
||||
title_ue_cap_bg = tuple(x / 255.0 for x in title_ue_cap_bg)
|
||||
# elems pour générer table avec gen_table (liste de dicts)
|
||||
rows = [
|
||||
# Ligne de titres
|
||||
@ -141,9 +159,13 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
|
||||
blue,
|
||||
),
|
||||
]
|
||||
|
||||
ues_capitalisees = self.infos.get("ues_capitalisees", {})
|
||||
for ue_acronym, ue in self.infos["ues"].items():
|
||||
self.ue_rows(rows, ue_acronym, ue, title_bg)
|
||||
self._ue_rows(rows, ue_acronym, ue, title_bg)
|
||||
if ue_acronym in ues_capitalisees:
|
||||
self._ue_rows(
|
||||
rows, ue_acronym, ues_capitalisees[ue_acronym], title_ue_cap_bg
|
||||
)
|
||||
|
||||
# Global pdf style commands:
|
||||
pdf_style = [
|
||||
@ -152,20 +174,18 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
|
||||
]
|
||||
return col_keys, rows, pdf_style, col_widths
|
||||
|
||||
def ue_rows(self, rows: list, ue_acronym: str, ue: dict, title_bg: tuple):
|
||||
def _ue_rows(self, rows: list, ue_acronym: str, ue: dict, title_bg: tuple):
|
||||
"Décrit une UE dans la table synthèse: titre, sous-titre et liste modules"
|
||||
if (ue["type"] == UE_SPORT) and len(ue.get("modules", [])) == 0:
|
||||
# ne mentionne l'UE que s'il y a des modules
|
||||
return
|
||||
# 1er ligne titre UE
|
||||
moy_ue = ue.get("moyenne")
|
||||
moy_ue = ue.get("moyenne", "-")
|
||||
if isinstance(moy_ue, dict):
|
||||
moy_ue = moy_ue.get("value", "-") if moy_ue is not None else "-"
|
||||
t = {
|
||||
"titre": f"{ue_acronym} - {ue['titre']}",
|
||||
"moyenne": Paragraph(
|
||||
f"""<para align=right><b>{moy_ue.get("value", "-")
|
||||
if moy_ue is not None else "-"
|
||||
}</b></para>"""
|
||||
),
|
||||
"moyenne": Paragraph(f"""<para align=right><b>{moy_ue}</b></para>"""),
|
||||
"_css_row_class": "note_bold",
|
||||
"_pdf_row_markup": ["b"],
|
||||
"_pdf_style": [
|
||||
@ -196,25 +216,40 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
|
||||
# case Bonus/Malus/Rang "bmr"
|
||||
fields_bmr = []
|
||||
try:
|
||||
value = float(ue["bonus"])
|
||||
value = float(ue.get("bonus", 0.0))
|
||||
if value != 0:
|
||||
fields_bmr.append(f"Bonus: {ue['bonus']}")
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
value = float(ue["malus"])
|
||||
value = float(ue.get("malus", 0.0))
|
||||
if value != 0:
|
||||
fields_bmr.append(f"Malus: {ue['malus']}")
|
||||
except ValueError:
|
||||
pass
|
||||
if self.preferences["bul_show_ue_rangs"]:
|
||||
fields_bmr.append(
|
||||
f"Rang: {ue['moyenne']['rang']} / {ue['moyenne']['total']}"
|
||||
|
||||
moy_ue = ue.get("moyenne", "-")
|
||||
if isinstance(moy_ue, dict): # UE non capitalisées
|
||||
if self.preferences["bul_show_ue_rangs"]:
|
||||
fields_bmr.append(
|
||||
f"Rang: {ue['moyenne']['rang']} / {ue['moyenne']['total']}"
|
||||
)
|
||||
ue_min, ue_max, ue_moy = (
|
||||
ue["moyenne"]["min"],
|
||||
ue["moyenne"]["max"],
|
||||
ue["moyenne"]["moy"],
|
||||
)
|
||||
else: # UE capitalisée
|
||||
ue_min, ue_max, ue_moy = "", "", moy_ue
|
||||
date_capitalisation = ue.get("date_capitalisation")
|
||||
if date_capitalisation:
|
||||
fields_bmr.append(
|
||||
f"""Capitalisée le {date_capitalisation.strftime("%d/%m/%Y")}"""
|
||||
)
|
||||
t = {
|
||||
"titre": " - ".join(fields_bmr),
|
||||
"coef": ects_txt,
|
||||
"_coef_pdf": Paragraph(f"""<para align=left>{ects_txt}</para>"""),
|
||||
"_coef_pdf": Paragraph(f"""<para align=right>{ects_txt}</para>"""),
|
||||
"_coef_colspan": 2,
|
||||
"_pdf_style": [
|
||||
("BACKGROUND", (0, 0), (-1, 0), title_bg),
|
||||
@ -222,9 +257,9 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
|
||||
# ligne au dessus du bonus/malus, gris clair
|
||||
("LINEABOVE", (0, 0), (-1, 0), self.PDF_LINEWIDTH, (0.7, 0.7, 0.7)),
|
||||
],
|
||||
"min": ue["moyenne"]["min"],
|
||||
"max": ue["moyenne"]["max"],
|
||||
"moy": ue["moyenne"]["moy"],
|
||||
"min": ue_min,
|
||||
"max": ue_max,
|
||||
"moy": ue_moy,
|
||||
}
|
||||
rows.append(t)
|
||||
|
||||
|
@ -234,7 +234,7 @@ class ResultatsSemestreBUT(NotesTableCompat):
|
||||
)
|
||||
# matrice de NaN: inscrits par défaut à AUCUNE UE:
|
||||
ues_inscr_parcours_df = pd.DataFrame(
|
||||
np.nan, index=etuds_parcour_id.keys(), columns=ue_ids, dtype=float # XXX
|
||||
np.nan, index=etuds_parcour_id.keys(), columns=ue_ids, dtype=float
|
||||
)
|
||||
# Construit pour chaque parcours du référentiel l'ensemble de ses UE
|
||||
# (considère aussi le cas des semestres sans parcours: None)
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
import datetime
|
||||
from functools import cached_property
|
||||
from operator import attrgetter
|
||||
|
||||
from flask import abort, has_request_context, url_for
|
||||
from flask import g, request
|
||||
import sqlalchemy
|
||||
@ -159,9 +161,19 @@ class Identite(db.Model):
|
||||
)
|
||||
|
||||
def get_first_email(self, field="email") -> str:
|
||||
"Le mail associé à la première adrese de l'étudiant, ou None"
|
||||
"Le mail associé à la première adresse de l'étudiant, ou None"
|
||||
return getattr(self.adresses[0], field) if self.adresses.count() > 0 else None
|
||||
|
||||
def get_formsemestres(self) -> list:
|
||||
"""Liste des formsemestres dans lesquels l'étudiant est (a été) inscrit,
|
||||
triée par date_debut
|
||||
"""
|
||||
return sorted(
|
||||
[ins.formsemestre for ins in self.formsemestre_inscriptions],
|
||||
key=attrgetter("date_debut"),
|
||||
reverse=True,
|
||||
)
|
||||
|
||||
def to_dict_short(self) -> dict:
|
||||
"""Les champs essentiels"""
|
||||
return {
|
||||
|
@ -82,11 +82,11 @@ def get_formsemestre_bulletin_etud_json(
|
||||
) -> str:
|
||||
"""Le JSON du bulletin d'un étudiant, quel que soit le type de formation."""
|
||||
if formsemestre.formation.is_apc():
|
||||
bul = bulletin_but.BulletinBUT(formsemestre)
|
||||
if not etud.id in bul.res.identdict:
|
||||
bulletins_sem = bulletin_but.BulletinBUT(formsemestre)
|
||||
if not etud.id in bulletins_sem.res.identdict:
|
||||
return json_error(404, "get_formsemestre_bulletin_etud_json: invalid etud")
|
||||
return jsonify(
|
||||
bul.bulletin_etud(
|
||||
bulletins_sem.bulletin_etud(
|
||||
etud,
|
||||
formsemestre,
|
||||
force_publishing=force_publishing,
|
||||
@ -746,7 +746,10 @@ def etud_descr_situation_semestre(
|
||||
infos["refcomp_specialite_long"] = ""
|
||||
if formsemestre.formation.is_apc():
|
||||
res: ResultatsSemestreBUT = res_sem.load_formsemestre_results(formsemestre)
|
||||
parcour: ApcParcours = ApcParcours.query.get(res.etuds_parcour_id[etudid])
|
||||
parcour_id = res.etuds_parcour_id[etudid]
|
||||
parcour: ApcParcours = (
|
||||
ApcParcours.query.get(parcour_id) if parcour_id is not None else None
|
||||
)
|
||||
if parcour:
|
||||
infos["parcours_titre"] = parcour.libelle or ""
|
||||
infos["parcours_code"] = parcour.code or ""
|
||||
@ -930,13 +933,14 @@ def formsemestre_bulletinetud(
|
||||
|
||||
bulletin = do_formsemestre_bulletinetud(
|
||||
formsemestre,
|
||||
etud.id,
|
||||
etud,
|
||||
format=format,
|
||||
version=version,
|
||||
xml_with_decisions=xml_with_decisions,
|
||||
force_publishing=force_publishing,
|
||||
prefer_mail_perso=prefer_mail_perso,
|
||||
)[0]
|
||||
|
||||
if format not in {"html", "pdfmail"}:
|
||||
filename = scu.bul_filename(formsemestre, etud, format)
|
||||
mime, suffix = scu.get_mime_suffix(format)
|
||||
@ -973,7 +977,7 @@ def can_send_bulletin_by_mail(formsemestre_id):
|
||||
|
||||
def do_formsemestre_bulletinetud(
|
||||
formsemestre: FormSemestre,
|
||||
etudid: int,
|
||||
etud: Identite,
|
||||
version="long", # short, long, selectedevals
|
||||
format=None,
|
||||
xml_with_decisions: bool = False,
|
||||
@ -1001,7 +1005,7 @@ def do_formsemestre_bulletinetud(
|
||||
if format == "xml":
|
||||
bul = sco_bulletins_xml.make_xml_formsemestre_bulletinetud(
|
||||
formsemestre.id,
|
||||
etudid,
|
||||
etud.id,
|
||||
xml_with_decisions=xml_with_decisions,
|
||||
force_publishing=force_publishing,
|
||||
version=version,
|
||||
@ -1012,7 +1016,7 @@ def do_formsemestre_bulletinetud(
|
||||
elif format == "json": # utilisé pour classic et "oldjson"
|
||||
bul = sco_bulletins_json.make_json_formsemestre_bulletinetud(
|
||||
formsemestre.id,
|
||||
etudid,
|
||||
etud.id,
|
||||
xml_with_decisions=xml_with_decisions,
|
||||
force_publishing=force_publishing,
|
||||
version=version,
|
||||
@ -1022,22 +1026,20 @@ def do_formsemestre_bulletinetud(
|
||||
version = version[:-4] # enlève le "_mat"
|
||||
|
||||
if formsemestre.formation.is_apc():
|
||||
etudiant = Identite.query.get(etudid)
|
||||
r = bulletin_but.BulletinBUT(formsemestre)
|
||||
infos = r.bulletin_etud_complet(etudiant, version=version)
|
||||
bulletins_sem = bulletin_but.BulletinBUT(formsemestre)
|
||||
bul_dict = bulletins_sem.bulletin_etud_complet(etud, version=version)
|
||||
else:
|
||||
infos = formsemestre_bulletinetud_dict(formsemestre.id, etudid)
|
||||
etud = infos["etud"]
|
||||
bul_dict = formsemestre_bulletinetud_dict(formsemestre.id, etud.id)
|
||||
|
||||
if format == "html":
|
||||
htm, _ = sco_bulletins_generator.make_formsemestre_bulletinetud(
|
||||
infos, version=version, format="html"
|
||||
bul_dict, version=version, format="html"
|
||||
)
|
||||
return htm, infos["filigranne"]
|
||||
return htm, bul_dict["filigranne"]
|
||||
|
||||
elif format == "pdf" or format == "pdfpart":
|
||||
bul, filename = sco_bulletins_generator.make_formsemestre_bulletinetud(
|
||||
infos,
|
||||
bul_dict,
|
||||
version=version,
|
||||
format="pdf",
|
||||
stand_alone=(format != "pdfpart"),
|
||||
@ -1046,10 +1048,10 @@ def do_formsemestre_bulletinetud(
|
||||
if format == "pdf":
|
||||
return (
|
||||
scu.sendPDFFile(bul, filename),
|
||||
infos["filigranne"],
|
||||
bul_dict["filigranne"],
|
||||
) # unused ret. value
|
||||
else:
|
||||
return bul, infos["filigranne"]
|
||||
return bul, bul_dict["filigranne"]
|
||||
|
||||
elif format == "pdfmail":
|
||||
# format pdfmail: envoie le pdf par mail a l'etud, et affiche le html
|
||||
@ -1058,24 +1060,28 @@ def do_formsemestre_bulletinetud(
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
|
||||
pdfdata, filename = sco_bulletins_generator.make_formsemestre_bulletinetud(
|
||||
infos, version=version, format="pdf"
|
||||
bul_dict, version=version, format="pdf"
|
||||
)
|
||||
|
||||
if prefer_mail_perso:
|
||||
recipient_addr = etud.get("emailperso", "") or etud.get("email", "")
|
||||
recipient_addr = (
|
||||
etud.get_first_email("emailperso") or etud.get_first_email()
|
||||
)
|
||||
else:
|
||||
recipient_addr = etud.get("email", "") or etud.get("emailperso", "")
|
||||
recipient_addr = etud.get_first_email() or etud.get_first_email(
|
||||
"emailperso"
|
||||
)
|
||||
|
||||
if not recipient_addr:
|
||||
flash(f"{etud['nomprenom']} n'a pas d'adresse e-mail !")
|
||||
return False, infos["filigranne"]
|
||||
flash(f"{etud.nomprenom} n'a pas d'adresse e-mail !")
|
||||
return False, bul_dict["filigranne"]
|
||||
else:
|
||||
mail_bulletin(formsemestre.id, infos, pdfdata, filename, recipient_addr)
|
||||
mail_bulletin(formsemestre.id, bul_dict, pdfdata, filename, recipient_addr)
|
||||
flash(f"mail envoyé à {recipient_addr}")
|
||||
|
||||
return True, infos["filigranne"]
|
||||
return True, bul_dict["filigranne"]
|
||||
|
||||
raise ValueError("do_formsemestre_bulletinetud: invalid format (%s)" % format)
|
||||
raise ValueError(f"do_formsemestre_bulletinetud: invalid format ({format})")
|
||||
|
||||
|
||||
def mail_bulletin(formsemestre_id, infos, pdfdata, filename, recipient_addr):
|
||||
|
@ -83,7 +83,7 @@ class BulletinGenerator:
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
infos,
|
||||
bul_dict,
|
||||
authuser=None,
|
||||
version="long",
|
||||
filigranne=None,
|
||||
@ -92,16 +92,18 @@ class BulletinGenerator:
|
||||
):
|
||||
from app.scodoc import sco_preferences
|
||||
|
||||
if not version in scu.BULLETINS_VERSIONS:
|
||||
if version not in scu.BULLETINS_VERSIONS:
|
||||
raise ValueError("invalid version code !")
|
||||
self.infos = infos
|
||||
self.authuser = authuser # nécessaire pour version HTML qui contient liens dépendant de l'utilisateur
|
||||
self.bul_dict = bul_dict
|
||||
self.infos = bul_dict # legacy code compat
|
||||
# authuser nécessaire pour version HTML qui contient liens dépendants de l'utilisateur
|
||||
self.authuser = authuser
|
||||
self.version = version
|
||||
self.filigranne = filigranne
|
||||
self.server_name = server_name
|
||||
self.with_img_signatures_pdf = with_img_signatures_pdf
|
||||
# Store preferences for convenience:
|
||||
formsemestre_id = self.infos["formsemestre_id"]
|
||||
formsemestre_id = self.bul_dict["formsemestre_id"]
|
||||
self.preferences = sco_preferences.SemPreferences(formsemestre_id)
|
||||
self.diagnostic = None # error message if any problem
|
||||
# Common PDF styles:
|
||||
@ -127,13 +129,13 @@ class BulletinGenerator:
|
||||
|
||||
def get_filename(self):
|
||||
"""Build a filename to be proposed to the web client"""
|
||||
sem = sco_formsemestre.get_formsemestre(self.infos["formsemestre_id"])
|
||||
return scu.bul_filename_old(sem, self.infos["etud"], "pdf")
|
||||
sem = sco_formsemestre.get_formsemestre(self.bul_dict["formsemestre_id"])
|
||||
return scu.bul_filename_old(sem, self.bul_dict["etud"], "pdf")
|
||||
|
||||
def generate(self, format="", stand_alone=True):
|
||||
"""Return bulletin in specified format"""
|
||||
if not format in self.supported_formats:
|
||||
raise ValueError("unsupported bulletin format (%s)" % format)
|
||||
raise ValueError(f"unsupported bulletin format ({format})")
|
||||
try:
|
||||
PDFLOCK.acquire() # this lock is necessary since reportlab is not re-entrant
|
||||
if format == "html":
|
||||
@ -141,7 +143,7 @@ class BulletinGenerator:
|
||||
elif format == "pdf":
|
||||
return self.generate_pdf(stand_alone=stand_alone)
|
||||
else:
|
||||
raise ValueError("invalid bulletin format (%s)" % format)
|
||||
raise ValueError(f"invalid bulletin format ({format})")
|
||||
finally:
|
||||
PDFLOCK.release()
|
||||
|
||||
@ -163,11 +165,12 @@ class BulletinGenerator:
|
||||
"""
|
||||
from app.scodoc import sco_preferences
|
||||
|
||||
formsemestre_id = self.infos["formsemestre_id"]
|
||||
formsemestre_id = self.bul_dict["formsemestre_id"]
|
||||
nomprenom = self.bul_dict["etud"]["nomprenom"]
|
||||
marque_debut_bulletin = sco_pdf.DebutBulletin(
|
||||
self.infos["etud"]["nomprenom"],
|
||||
filigranne=self.infos["filigranne"],
|
||||
footer_content=f"""ScoDoc - Bulletin de {self.infos["etud"]["nomprenom"]} - {time.strftime("%d/%m/%Y %H:%M")}""",
|
||||
nomprenom,
|
||||
filigranne=self.bul_dict["filigranne"],
|
||||
footer_content=f"""ScoDoc - Bulletin de {nomprenom} - {time.strftime("%d/%m/%Y %H:%M")}""",
|
||||
)
|
||||
story = []
|
||||
# partie haute du bulletin
|
||||
@ -208,8 +211,7 @@ class BulletinGenerator:
|
||||
document,
|
||||
author="%s %s (E. Viennet) [%s]"
|
||||
% (sco_version.SCONAME, sco_version.SCOVERSION, self.description),
|
||||
title="Bulletin %s de %s"
|
||||
% (sem["titremois"], self.infos["etud"]["nomprenom"]),
|
||||
title=f"""Bulletin {sem["titremois"]} de {nomprenom}""",
|
||||
subject="Bulletin de note",
|
||||
margins=self.margins,
|
||||
server_name=self.server_name,
|
||||
@ -247,7 +249,7 @@ class BulletinGenerator:
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
def make_formsemestre_bulletinetud(
|
||||
infos,
|
||||
bul_dict,
|
||||
version=None, # short, long, selectedevals
|
||||
format="pdf", # html, pdf
|
||||
stand_alone=True,
|
||||
@ -262,10 +264,10 @@ def make_formsemestre_bulletinetud(
|
||||
from app.scodoc import sco_preferences
|
||||
|
||||
version = version or "long"
|
||||
if not version in scu.BULLETINS_VERSIONS:
|
||||
if version not in scu.BULLETINS_VERSIONS:
|
||||
raise ValueError("invalid version code !")
|
||||
|
||||
formsemestre_id = infos["formsemestre_id"]
|
||||
formsemestre_id = bul_dict["formsemestre_id"]
|
||||
bul_class_name = sco_preferences.get_preference("bul_class_name", formsemestre_id)
|
||||
|
||||
gen_class = None
|
||||
@ -274,7 +276,7 @@ def make_formsemestre_bulletinetud(
|
||||
# si pas trouvé (modifs locales bizarres ,), ré-essaye avec la valeur par défaut
|
||||
bulletin_default_class_name(),
|
||||
):
|
||||
if infos.get("type") == "BUT" and format.startswith("pdf"):
|
||||
if bul_dict.get("type") == "BUT" and format.startswith("pdf"):
|
||||
gen_class = bulletin_get_class(bul_class_name + "BUT")
|
||||
if gen_class is None:
|
||||
gen_class = bulletin_get_class(bul_class_name)
|
||||
@ -285,10 +287,10 @@ def make_formsemestre_bulletinetud(
|
||||
try:
|
||||
PDFLOCK.acquire()
|
||||
bul_generator = gen_class(
|
||||
infos,
|
||||
bul_dict,
|
||||
authuser=current_user,
|
||||
version=version,
|
||||
filigranne=infos["filigranne"],
|
||||
filigranne=bul_dict["filigranne"],
|
||||
server_name=request.url_root,
|
||||
with_img_signatures_pdf=with_img_signatures_pdf,
|
||||
)
|
||||
@ -301,24 +303,22 @@ def make_formsemestre_bulletinetud(
|
||||
bul_class_name = bulletin_default_class_name()
|
||||
gen_class = bulletin_get_class(bul_class_name)
|
||||
bul_generator = gen_class(
|
||||
infos,
|
||||
bul_dict,
|
||||
authuser=current_user,
|
||||
version=version,
|
||||
filigranne=infos["filigranne"],
|
||||
filigranne=bul_dict["filigranne"],
|
||||
server_name=request.url_root,
|
||||
with_img_signatures_pdf=with_img_signatures_pdf,
|
||||
)
|
||||
|
||||
data = bul_generator.generate(format=format, stand_alone=stand_alone)
|
||||
finally:
|
||||
PDFLOCK.release()
|
||||
|
||||
if bul_generator.diagnostic:
|
||||
log("bul_error: %s" % bul_generator.diagnostic)
|
||||
log(f"bul_error: {bul_generator.diagnostic}")
|
||||
raise NoteProcessError(bul_generator.diagnostic)
|
||||
|
||||
filename = bul_generator.get_filename()
|
||||
|
||||
return data, filename
|
||||
|
||||
|
||||
|
@ -45,7 +45,7 @@ Pour définir un nouveau type de bulletin:
|
||||
(s'inspirer de sco_bulletins_pdf_default);
|
||||
- en fin du fichier sco_bulletins_pdf.py, ajouter la ligne
|
||||
import sco_bulletins_pdf_xxxx
|
||||
- votre type sera alors (après redémarrage de ScoDoc) proposé dans le formulaire de paramètrage ScoDoc.
|
||||
- votre type sera alors (après redémarrage de ScoDoc) proposé dans le formulaire de paramètrage.
|
||||
|
||||
Chaque semestre peut si nécessaire utiliser un type de bulletin différent.
|
||||
|
||||
@ -60,13 +60,12 @@ import traceback
|
||||
from flask import g, request
|
||||
|
||||
from app import log, ScoValueError
|
||||
from app.models import FormSemestre
|
||||
from app.models import FormSemestre, Identite
|
||||
|
||||
from app.scodoc import sco_cache
|
||||
from app.scodoc import codes_cursus
|
||||
from app.scodoc import sco_pdf
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc import sco_etud
|
||||
from app.scodoc.sco_logos import find_logo
|
||||
import app.scodoc.sco_utils as scu
|
||||
|
||||
@ -97,8 +96,8 @@ def assemble_bulletins_pdf(
|
||||
document.addPageTemplates(
|
||||
sco_pdf.ScoDocPageTemplate(
|
||||
document,
|
||||
author="%s %s (E. Viennet)" % (sco_version.SCONAME, sco_version.SCOVERSION),
|
||||
title="Bulletin %s" % bul_title,
|
||||
author=f"{sco_version.SCONAME} {sco_version.SCOVERSION} (E. Viennet)",
|
||||
title=f"Bulletin {bul_title}",
|
||||
subject="Bulletin de note",
|
||||
server_name=server_name,
|
||||
margins=margins,
|
||||
@ -125,11 +124,13 @@ def replacement_function(match):
|
||||
|
||||
|
||||
class WrapDict(object):
|
||||
"""Wrap a dict so that getitem returns '' when values are None"""
|
||||
"""Wrap a dict so that getitem returns '' when values are None
|
||||
and non existent keys returns an error message as value.
|
||||
"""
|
||||
|
||||
def __init__(self, adict, NoneValue=""):
|
||||
def __init__(self, adict, none_value=""):
|
||||
self.dict = adict
|
||||
self.NoneValue = NoneValue
|
||||
self.none_value = none_value
|
||||
|
||||
def __getitem__(self, key):
|
||||
try:
|
||||
@ -137,12 +138,11 @@ class WrapDict(object):
|
||||
except KeyError:
|
||||
return f"XXX {key} invalide XXX"
|
||||
if value is None:
|
||||
return self.NoneValue
|
||||
else:
|
||||
return value
|
||||
return self.none_value
|
||||
return value
|
||||
|
||||
|
||||
def process_field(field, cdict, style, suppress_empty_pars=False, format="pdf"):
|
||||
def process_field(field, cdict, style, suppress_empty_pars=False, fmt="pdf"):
|
||||
"""Process a field given in preferences, returns
|
||||
- if format = 'pdf': a list of Platypus objects
|
||||
- if format = 'html' : a string
|
||||
@ -183,7 +183,7 @@ def process_field(field, cdict, style, suppress_empty_pars=False, format="pdf"):
|
||||
)
|
||||
# remove unhandled or dangerous tags:
|
||||
text = re.sub(r"<\s*img", "", text)
|
||||
if format == "html":
|
||||
if fmt == "html":
|
||||
# convert <para>
|
||||
text = re.sub(r"<\s*para(\s*)(.*?)>", r"<p>", text)
|
||||
return text
|
||||
@ -219,7 +219,7 @@ def get_formsemestre_bulletins_pdf(formsemestre_id, version="selectedevals"):
|
||||
for etud in formsemestre.get_inscrits(include_demdef=True, order=True):
|
||||
frag, _ = sco_bulletins.do_formsemestre_bulletinetud(
|
||||
formsemestre,
|
||||
etud.id,
|
||||
etud,
|
||||
format="pdfpart",
|
||||
version=version,
|
||||
)
|
||||
@ -256,22 +256,21 @@ def get_etud_bulletins_pdf(etudid, version="selectedevals"):
|
||||
"Bulletins pdf de tous les semestres de l'étudiant, et filename"
|
||||
from app.scodoc import sco_bulletins
|
||||
|
||||
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
||||
etud: Identite = Identite.query.get_or_404(etudid)
|
||||
fragments = []
|
||||
bookmarks = {}
|
||||
filigrannes = {}
|
||||
i = 1
|
||||
for sem in etud["sems"]:
|
||||
formsemestre = FormSemestre.query.get(sem["formsemestre_id"])
|
||||
for formsemestre in etud.get_formsemestres():
|
||||
frag, filigranne = sco_bulletins.do_formsemestre_bulletinetud(
|
||||
formsemestre,
|
||||
etudid,
|
||||
etud,
|
||||
format="pdfpart",
|
||||
version=version,
|
||||
)
|
||||
fragments += frag
|
||||
filigrannes[i] = filigranne
|
||||
bookmarks[i] = sem["session_id"] # eg RT-DUT-FI-S1-2015
|
||||
bookmarks[i] = formsemestre.session_id() # eg RT-DUT-FI-S1-2015
|
||||
i = i + 1
|
||||
infos = {"DeptName": sco_preferences.get_preference("DeptName")}
|
||||
if request:
|
||||
@ -283,7 +282,7 @@ def get_etud_bulletins_pdf(etudid, version="selectedevals"):
|
||||
pdfdoc = assemble_bulletins_pdf(
|
||||
None,
|
||||
fragments,
|
||||
etud["nomprenom"],
|
||||
etud.nomprenom,
|
||||
infos,
|
||||
bookmarks,
|
||||
filigranne=filigrannes,
|
||||
@ -292,7 +291,7 @@ def get_etud_bulletins_pdf(etudid, version="selectedevals"):
|
||||
finally:
|
||||
sco_pdf.PDFLOCK.release()
|
||||
#
|
||||
filename = "bul-%s" % (etud["nomprenom"])
|
||||
filename = f"bul-{etud.nomprenom}"
|
||||
filename = (
|
||||
scu.unescape_html(filename).replace(" ", "_").replace("&", "").replace(".", "")
|
||||
+ ".pdf"
|
||||
|
@ -186,13 +186,13 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
|
||||
self.preferences["bul_pdf_caption"],
|
||||
self.infos,
|
||||
self.FieldStyle,
|
||||
format="pdf",
|
||||
fmt="pdf",
|
||||
)
|
||||
field = sco_bulletins_pdf.process_field(
|
||||
self.preferences["bul_pdf_caption"],
|
||||
self.infos,
|
||||
self.FieldStyle,
|
||||
format="html",
|
||||
fmt="html",
|
||||
)
|
||||
H.append('<div class="bul_decision">' + field + "</div>")
|
||||
|
||||
|
@ -939,7 +939,7 @@ def fill_etuds_info(etuds: list[dict], add_admission=True):
|
||||
def etud_inscriptions_infos(etudid: int, ne="") -> dict:
|
||||
"""Dict avec les informations sur les semestres passés et courant.
|
||||
{
|
||||
"sems" : ,
|
||||
"sems" : , # trie les semestres par date de debut, le plus recent d'abord
|
||||
"ins" : ,
|
||||
"cursem" : ,
|
||||
"inscription" : ,
|
||||
|
@ -380,8 +380,8 @@ def gen_formsemestre_recapcomplet_json(
|
||||
etudid = t[-1]
|
||||
if is_apc:
|
||||
etud = Identite.query.get(etudid)
|
||||
r = bulletin_but.BulletinBUT(formsemestre)
|
||||
bul = r.bulletin_etud(etud, formsemestre)
|
||||
bulletins_sem = bulletin_but.BulletinBUT(formsemestre)
|
||||
bul = bulletins_sem.bulletin_etud(etud, formsemestre)
|
||||
else:
|
||||
bul = sco_bulletins_json.formsemestre_bulletinetud_published_dict(
|
||||
formsemestre_id,
|
||||
|
@ -335,7 +335,8 @@ def formsemestre_bulletinetud(
|
||||
|
||||
if format == "oldjson":
|
||||
format = "json"
|
||||
r = sco_bulletins.formsemestre_bulletinetud(
|
||||
|
||||
response = sco_bulletins.formsemestre_bulletinetud(
|
||||
etud,
|
||||
formsemestre_id=formsemestre_id,
|
||||
format=format,
|
||||
@ -344,7 +345,8 @@ def formsemestre_bulletinetud(
|
||||
force_publishing=force_publishing,
|
||||
prefer_mail_perso=prefer_mail_perso,
|
||||
)
|
||||
if format == "pdfmail":
|
||||
|
||||
if format == "pdfmail": # ne renvoie rien dans ce cas (mails envoyés)
|
||||
return redirect(
|
||||
url_for(
|
||||
"notes.formsemestre_bulletinetud",
|
||||
@ -353,7 +355,7 @@ def formsemestre_bulletinetud(
|
||||
formsemestre_id=formsemestre_id,
|
||||
)
|
||||
)
|
||||
return r
|
||||
return response
|
||||
|
||||
|
||||
sco_publish(
|
||||
@ -2060,7 +2062,7 @@ def formsemestre_bulletins_mailetuds(
|
||||
for inscription in inscriptions:
|
||||
sent, _ = sco_bulletins.do_formsemestre_bulletinetud(
|
||||
formsemestre,
|
||||
inscription.etudid,
|
||||
inscription.etud,
|
||||
version=version,
|
||||
prefer_mail_perso=prefer_mail_perso,
|
||||
format="pdfmail",
|
||||
|
Loading…
Reference in New Issue
Block a user