diff --git a/app/but/cursus_but.py b/app/but/cursus_but.py
index 6626d20e5..e3ae8bb61 100644
--- a/app/but/cursus_but.py
+++ b/app/but/cursus_but.py
@@ -21,6 +21,8 @@ from flask import g, url_for
from app import db
from app import log
from app.comp.res_but import ResultatsSemestreBUT
+from app.comp.res_compat import NotesTableCompat
+
from app.comp import res_sem
from app.models import formsemestre
@@ -50,7 +52,16 @@ from app.scodoc.sco_exceptions import ScoException, ScoValueError
from app.scodoc import sco_cursus_dut
-class SituationEtudCursusBUT(sco_cursus_dut.SituationEtudCursus):
+class SituationEtudCursusBUT(sco_cursus_dut.SituationEtudCursusClassic):
def __init__(self, etud: dict, formsemestre_id: int, res: ResultatsSemestreBUT):
- self.semestre_non_terminal = bool
- self.formation
+ super().__init__(etud, formsemestre_id, res)
+ # Ajustements pour le BUT
+ self.can_compensate_with_prev = False # jamais de compensation à la mode DUT
+
+ def check_compensation_dut(self, semc: dict, ntc: NotesTableCompat):
+ "Jamais de compensation façon DUT"
+ return False
+
+ def parcours_validated(self):
+ "True si le parcours est validé"
+ return False # XXX TODO
diff --git a/app/scodoc/sco_cursus_dut.py b/app/scodoc/sco_cursus_dut.py
index 5d2f31bfc..f4354c6f1 100644
--- a/app/scodoc/sco_cursus_dut.py
+++ b/app/scodoc/sco_cursus_dut.py
@@ -341,9 +341,7 @@ class SituationEtudCursusClassic(SituationEtudCursus):
)[0]["formation_code"]
# si sem peut servir à compenser le semestre courant, positionne
# can_compensate
- sem["can_compensate"] = check_compensation(
- self.etudid, self.sem, self.nt, sem, nt
- )
+ sem["can_compensate"] = self.check_compensation_dut(sem, nt)
self.ue_acros = list(ue_acros.keys())
self.ue_acros.sort()
@@ -655,6 +653,46 @@ class SituationEtudCursusClassic(SituationEtudCursus):
formsemestre_id=formsemestre_id
) # > modif decision jury
+ def check_compensation_dut(self, semc: dict, ntc: NotesTableCompat):
+ """Compensations DUT
+ Vérifie si le semestre sem peut se compenser en utilisant semc
+ - semc non utilisé par un autre semestre
+ - decision du jury prise ADM ou ADJ ou ATT ou ADC
+ - barres UE (moy ue > 8) dans sem et semc
+ - moyenne des moy_gen > 10
+ Return boolean
+ """
+ # -- deja utilise ?
+ decc = ntc.get_etud_decision_sem(self.etudid)
+ if (
+ decc
+ and decc["compense_formsemestre_id"]
+ and decc["compense_formsemestre_id"] != self.sem["formsemestre_id"]
+ ):
+ return False
+ # -- semestres consecutifs ?
+ if abs(self.sem["semestre_id"] - semc["semestre_id"]) != 1:
+ return False
+ # -- decision jury:
+ if decc and not decc["code"] in (ADM, ADJ, ATT, ADC):
+ return False
+ # -- barres UE et moyenne des moyennes:
+ moy_gen = self.nt.get_etud_moy_gen(self.etudid)
+ moy_genc = ntc.get_etud_moy_gen(self.etudid)
+ try:
+ moy_moy = (moy_gen + moy_genc) / 2
+ except: # un des semestres sans aucune note !
+ return False
+
+ if (
+ self.nt.etud_check_conditions_ues(self.etudid)[0]
+ and ntc.etud_check_conditions_ues(self.etudid)[0]
+ and moy_moy >= NOTES_BARRE_GEN_COMPENSATION
+ ):
+ return True
+ else:
+ return False
+
class SituationEtudCursusECTS(SituationEtudCursusClassic):
"""Gestion parcours basés sur ECTS"""
@@ -701,47 +739,6 @@ class SituationEtudCursusECTS(SituationEtudCursusClassic):
return choices
-#
-def check_compensation(etudid, sem, nt, semc, ntc):
- """Verifie si le semestre sem peut se compenser en utilisant semc
- - semc non utilisé par un autre semestre
- - decision du jury prise ADM ou ADJ ou ATT ou ADC
- - barres UE (moy ue > 8) dans sem et semc
- - moyenne des moy_gen > 10
- Return boolean
- """
- # -- deja utilise ?
- decc = ntc.get_etud_decision_sem(etudid)
- if (
- decc
- and decc["compense_formsemestre_id"]
- and decc["compense_formsemestre_id"] != sem["formsemestre_id"]
- ):
- return False
- # -- semestres consecutifs ?
- if abs(sem["semestre_id"] - semc["semestre_id"]) != 1:
- return False
- # -- decision jury:
- if decc and not decc["code"] in (ADM, ADJ, ATT, ADC):
- return False
- # -- barres UE et moyenne des moyennes:
- moy_gen = nt.get_etud_moy_gen(etudid)
- moy_genc = ntc.get_etud_moy_gen(etudid)
- try:
- moy_moy = (moy_gen + moy_genc) / 2
- except: # un des semestres sans aucune note !
- return False
-
- if (
- nt.etud_check_conditions_ues(etudid)[0]
- and ntc.etud_check_conditions_ues(etudid)[0]
- and moy_moy >= NOTES_BARRE_GEN_COMPENSATION
- ):
- return True
- else:
- return False
-
-
# -------------------------------------------------------------------------------------------
diff --git a/app/scodoc/sco_formsemestre.py b/app/scodoc/sco_formsemestre.py
index 32c2d9e34..ce7f2c10d 100644
--- a/app/scodoc/sco_formsemestre.py
+++ b/app/scodoc/sco_formsemestre.py
@@ -101,7 +101,7 @@ def get_formsemestre(formsemestre_id, raise_soft_exc=False):
return g.stored_get_formsemestre[formsemestre_id]
if not isinstance(formsemestre_id, int):
log(f"get_formsemestre: invalid id '{formsemestre_id}'")
- raise ScoInvalidIdType("formsemestre_id must be an integer !")
+ raise ScoInvalidIdType("get_formsemestre: formsemestre_id must be an integer !")
sems = do_formsemestre_list(args={"formsemestre_id": formsemestre_id})
if not sems:
log("get_formsemestre: invalid formsemestre_id (%s)" % formsemestre_id)
diff --git a/app/scodoc/sco_prepajury.py b/app/scodoc/sco_prepajury.py
index 81093af75..0afb1c415 100644
--- a/app/scodoc/sco_prepajury.py
+++ b/app/scodoc/sco_prepajury.py
@@ -103,14 +103,14 @@ def feuille_preparation_jury(formsemestre_id):
moy[etud.id] = nt.get_etud_moy_gen(etud.id)
for ue in nt.get_ues_stat_dict(filter_sport=True):
ue_status = nt.get_etud_ue_status(etud.id, ue["ue_id"])
- ue_code_s = ue["ue_code"] + "_%s" % nt.sem["semestre_id"]
+ ue_code_s = f'{ue["ue_code"]}_{nt.sem["semestre_id"]}'
moy_ue[ue_code_s][etud.id] = ue_status["moy"] if ue_status else ""
ue_acro[ue_code_s] = (ue["numero"], ue["acronyme"], ue["titre"])
if Se.prev:
try:
moy_inter[etud.id] = (moy[etud.id] + prev_moy[etud.id]) / 2.0
- except:
+ except (KeyError, TypeError):
pass
decision = nt.get_etud_decision_sem(etud.id)
@@ -120,10 +120,12 @@ def feuille_preparation_jury(formsemestre_id):
code[etud.id] += "+" # indique qu'il a servi a compenser
assidu[etud.id] = {False: "Non", True: "Oui"}.get(decision["assidu"], "")
- autorisations = ScolarAutorisationInscription.query.filter_by(
+ autorisations_etud = ScolarAutorisationInscription.query.filter_by(
etudid=etud.id, origin_formsemestre_id=formsemestre_id
).all()
- autorisations[etud.id] = ", ".join(["S{x.semestre_id}" for x in autorisations])
+ autorisations[etud.id] = ", ".join(
+ [f"S{x.semestre_id}" for x in autorisations_etud]
+ )
# parcours:
parcours[etud.id] = Se.get_parcours_descr()
# groupe principal (td)
@@ -154,11 +156,11 @@ def feuille_preparation_jury(formsemestre_id):
sid = sem["semestre_id"]
sn = sp = ""
if sid >= 0:
- sn = "S%s" % sid
+ sn = f"S{sid}"
if prev_moy: # si qq chose dans precedent
- sp = "S%s" % (sid - 1)
+ sp = f"S{sid - 1}"
- ws = sco_excel.ScoExcelSheet(sheet_name="Prepa Jury %s" % sn)
+ sheet = sco_excel.ScoExcelSheet(sheet_name=f"Prepa Jury {sn}")
# génération des styles
style_bold = sco_excel.excel_make_style(size=10, bold=True)
style_center = sco_excel.excel_make_style(halign="center")
@@ -174,10 +176,10 @@ def feuille_preparation_jury(formsemestre_id):
)
# Première ligne
- ws.append_single_cell_row(
+ sheet.append_single_cell_row(
"Feuille préparation Jury %s" % scu.unescape_html(sem["titreannee"]), style_bold
)
- ws.append_blank_row()
+ sheet.append_blank_row()
# Ligne de titre
titles = ["Rang"]
@@ -199,25 +201,25 @@ def feuille_preparation_jury(formsemestre_id):
]
if prev_moy: # si qq chose dans precedent
titles += [prev_ue_acro[x][1] for x in ue_prev_codes] + [
- "Moy %s" % sp,
- "Décision %s" % sp,
+ f"Moy {sp}",
+ f"Décision {sp}",
]
- titles += [ue_acro[x][1] for x in ue_codes] + ["Moy %s" % sn]
+ titles += [ue_acro[x][1] for x in ue_codes] + [f"Moy {sn}"]
if moy_inter:
- titles += ["Moy %s-%s" % (sp, sn)]
+ titles += [f"Moy {sp}-{sn}"]
titles += ["Abs", "Abs Injust."]
if code:
- titles.append("Proposit. %s" % sn)
+ titles.append("Proposit. {sn}")
if autorisations:
titles.append("Autorisations")
# titles.append('Assidu')
- ws.append_row(ws.make_row(titles, style_boldcenter))
- if prev_moy:
- tit_prev_moy = "Moy " + sp
- col_prev_moy = titles.index(tit_prev_moy)
- tit_moy = "Moy " + sn
- col_moy = titles.index(tit_moy)
- col_abs = titles.index("Abs")
+ sheet.append_row(sheet.make_row(titles, style_boldcenter))
+ # if prev_moy:
+ # tit_prev_moy = "Moy " + sp
+ # # col_prev_moy = titles.index(tit_prev_moy)
+ # tit_moy = "Moy " + sn
+ # col_moy = titles.index(tit_moy)
+ # col_abs = titles.index("Abs")
def fmt(x):
"reduit les notes a deux chiffres"
@@ -230,13 +232,13 @@ def feuille_preparation_jury(formsemestre_id):
i = 1 # numero etudiant
for etud in etuds:
cells = []
- cells.append(ws.make_cell(str(i)))
+ cells.append(sheet.make_cell(str(i)))
if sco_preferences.get_preference("prepa_jury_nip"):
- cells.append(ws.make_cell(etud.code_nip))
+ cells.append(sheet.make_cell(etud.code_nip))
if sco_preferences.get_preference("prepa_jury_ine"):
- cells.append(ws.make_cell(etud.code_ine))
+ cells.append(sheet.make_cell(etud.code_ine))
admission = etud.admission.first()
- cells += ws.make_row(
+ cells += sheet.make_row(
[
etud.id,
etud.civilite_str,
@@ -254,50 +256,52 @@ def feuille_preparation_jury(formsemestre_id):
if prev_moy:
for ue_acro in ue_prev_codes:
cells.append(
- ws.make_cell(
+ sheet.make_cell(
fmt(prev_moy_ue.get(ue_acro, {}).get(etud.id, "")), style_note
)
)
co += 1
cells.append(
- ws.make_cell(fmt(prev_moy.get(etud.id, "")), style_bold)
+ sheet.make_cell(fmt(prev_moy.get(etud.id, "")), style_bold)
) # moy gen prev
cells.append(
- ws.make_cell(fmt(prev_code.get(etud.id, "")), style_moy)
+ sheet.make_cell(fmt(prev_code.get(etud.id, "")), style_moy)
) # decision prev
co += 2
for ue_acro in ue_codes:
cells.append(
- ws.make_cell(fmt(moy_ue.get(ue_acro, {}).get(etud.id, "")), style_note)
+ sheet.make_cell(
+ fmt(moy_ue.get(ue_acro, {}).get(etud.id, "")), style_note
+ )
)
co += 1
cells.append(
- ws.make_cell(fmt(moy.get(etud.id, "")), style_note_bold)
+ sheet.make_cell(fmt(moy.get(etud.id, "")), style_note_bold)
) # moy gen
co += 1
if moy_inter:
- cells.append(ws.make_cell(fmt(moy_inter.get(etud.id, "")), style_note))
- cells.append(ws.make_cell(str(nbabs.get(etud.id, "")), style_center))
- cells.append(ws.make_cell(str(nbabsjust.get(etud.id, "")), style_center))
+ cells.append(sheet.make_cell(fmt(moy_inter.get(etud.id, "")), style_note))
+ cells.append(sheet.make_cell(str(nbabs.get(etud.id, "")), style_center))
+ cells.append(sheet.make_cell(str(nbabsjust.get(etud.id, "")), style_center))
if code:
- cells.append(ws.make_cell(code.get(etud.id, ""), style_moy))
- cells.append(ws.make_cell(autorisations.get(etud.id, ""), style_moy))
+ cells.append(sheet.make_cell(code.get(etud.id, ""), style_moy))
+ cells.append(sheet.make_cell(autorisations.get(etud.id, ""), style_moy))
# l.append(assidu.get(etud.id, ''))
- ws.append_row(cells)
+ sheet.append_row(cells)
i += 1
#
- ws.append_blank_row()
+ sheet.append_blank_row()
# Explications des codes
codes = list(sco_codes_parcours.CODES_EXPL.keys())
codes.sort()
- ws.append_single_cell_row("Explication des codes")
+ sheet.append_single_cell_row("Explication des codes")
for code in codes:
- ws.append_row(
- ws.make_row(["", "", "", code, sco_codes_parcours.CODES_EXPL[code]])
+ sheet.append_row(
+ sheet.make_row(["", "", "", code, sco_codes_parcours.CODES_EXPL[code]])
)
- ws.append_row(
- ws.make_row(
+ sheet.append_row(
+ sheet.make_row(
[
"",
"",
@@ -308,16 +312,16 @@ def feuille_preparation_jury(formsemestre_id):
)
)
# UE : Correspondances acronyme et titre complet
- ws.append_blank_row()
- ws.append_single_cell_row("Titre des UE")
+ sheet.append_blank_row()
+ sheet.append_single_cell_row("Titre des UE")
if prev_moy:
for ue in ntp.get_ues_stat_dict(filter_sport=True):
- ws.append_row(ws.make_row(["", "", "", ue["acronyme"], ue["titre"]]))
+ sheet.append_row(sheet.make_row(["", "", "", ue["acronyme"], ue["titre"]]))
for ue in nt.get_ues_stat_dict(filter_sport=True):
- ws.append_row(ws.make_row(["", "", "", ue["acronyme"], ue["titre"]]))
+ sheet.append_row(sheet.make_row(["", "", "", ue["acronyme"], ue["titre"]]))
#
- ws.append_blank_row()
- ws.append_single_cell_row(
+ sheet.append_blank_row()
+ sheet.append_single_cell_row(
"Préparé par %s le %s sur %s pour %s"
% (
sco_version.SCONAME,
@@ -326,7 +330,7 @@ def feuille_preparation_jury(formsemestre_id):
current_user,
)
)
- xls = ws.generate()
+ xls = sheet.generate()
flash("Feuille préparation jury générée")
return scu.send_file(
xls,
diff --git a/app/scodoc/sco_pvpdf.py b/app/scodoc/sco_pvpdf.py
index d889277e5..dba7801bd 100644
--- a/app/scodoc/sco_pvpdf.py
+++ b/app/scodoc/sco_pvpdf.py
@@ -30,6 +30,8 @@
import io
import re
+from PIL import Image as PILImage
+
import reportlab
from reportlab.lib.units import cm, mm
from reportlab.lib.enums import TA_RIGHT, TA_JUSTIFY
@@ -41,6 +43,7 @@ from reportlab.lib import styles
from reportlab.lib.colors import Color
from flask import g
+from app.models.formsemestre import FormSemestre
import app.scodoc.sco_utils as scu
from app.scodoc import sco_bulletins_pdf
@@ -125,6 +128,7 @@ def page_footer(canvas, doc, logo, preferences, with_page_numbers=True):
def page_header(canvas, doc, logo, preferences, only_on_first_page=False):
+ "Ajoute au canvas le frame avec le logo"
if only_on_first_page and int(doc.page) > 1:
return
height = doc.pagesize[1]
@@ -147,12 +151,12 @@ def page_header(canvas, doc, logo, preferences, only_on_first_page=False):
class CourrierIndividuelTemplate(PageTemplate):
- """Template pour courrier avisant des decisions de jury (1 page /etudiant)"""
+ """Template pour courrier avisant des decisions de jury (1 page par étudiant)"""
def __init__(
self,
document,
- pagesbookmarks={},
+ pagesbookmarks=None,
author=None,
title=None,
subject=None,
@@ -163,7 +167,7 @@ class CourrierIndividuelTemplate(PageTemplate):
template_name="CourrierJuryTemplate",
):
"""Initialise our page template."""
- self.pagesbookmarks = pagesbookmarks
+ self.pagesbookmarks = pagesbookmarks or {}
self.pdfmeta_author = author
self.pdfmeta_title = title
self.pdfmeta_subject = subject
@@ -237,32 +241,32 @@ class CourrierIndividuelTemplate(PageTemplate):
width=LOGO_HEADER_WIDTH,
)
- def beforeDrawPage(self, canvas, doc):
+ def beforeDrawPage(self, canv, doc):
"""Draws a logo and an contribution message on each page."""
# ---- Add some meta data and bookmarks
if self.pdfmeta_author:
- canvas.setAuthor(SU(self.pdfmeta_author))
+ canv.setAuthor(SU(self.pdfmeta_author))
if self.pdfmeta_title:
- canvas.setTitle(SU(self.pdfmeta_title))
+ canv.setTitle(SU(self.pdfmeta_title))
if self.pdfmeta_subject:
- canvas.setSubject(SU(self.pdfmeta_subject))
+ canv.setSubject(SU(self.pdfmeta_subject))
bm = self.pagesbookmarks.get(doc.page, None)
if bm != None:
key = bm
txt = SU(bm)
- canvas.bookmarkPage(key)
- canvas.addOutlineEntry(txt, bm)
+ canv.bookmarkPage(key)
+ canv.addOutlineEntry(txt, bm)
# ---- Background image
if self.background_image_filename and self.with_page_background:
- canvas.drawImage(
+ canv.drawImage(
self.background_image_filename, 0, 0, doc.pagesize[0], doc.pagesize[1]
)
# ---- Header/Footer
if self.with_header:
page_header(
- canvas,
+ canv,
doc,
self.logo_header,
self.preferences,
@@ -270,7 +274,7 @@ class CourrierIndividuelTemplate(PageTemplate):
)
if self.with_footer:
page_footer(
- canvas,
+ canv,
doc,
self.logo_footer,
self.preferences,
@@ -332,6 +336,39 @@ class PVTemplate(CourrierIndividuelTemplate):
# self.__pageNum += 1
+def _simulate_br(paragraph_txt: str, para="") -> str:
+ """Reportlab bug turnaround (could be removed in a future version).
+ p is a string with Reportlab intra-paragraph XML tags.
+ Replaces
(currently ignored by Reportlab) by
+ """
+ return ("" + para).join(re.split(r"<.*?br.*?/>", paragraph_txt))
+
+
+def _make_signature_image(signature, leftindent, formsemestre_id) -> Table:
+ "crée un paragraphe avec l'image signature"
+ # cree une image PIL pour avoir la taille (W,H)
+
+ f = io.BytesIO(signature)
+ img = PILImage.open(f)
+ width, height = img.size
+ pdfheight = (
+ 1.0
+ * sco_preferences.get_preference("pv_sig_image_height", formsemestre_id)
+ * mm
+ )
+ f.seek(0, 0)
+
+ style = styles.ParagraphStyle({})
+ style.leading = 1.0 * sco_preferences.get_preference(
+ "SCOLAR_FONT_SIZE", formsemestre_id
+ ) # vertical space
+ style.leftIndent = leftindent
+ return Table(
+ [("", Image(f, width=width * pdfheight / float(height), height=pdfheight))],
+ colWidths=(9 * cm, 7 * cm),
+ )
+
+
def pdf_lettres_individuelles(
formsemestre_id,
etudids=None,
@@ -394,8 +431,8 @@ def pdf_lettres_individuelles(
document.addPageTemplates(
CourrierIndividuelTemplate(
document,
- author="%s %s (E. Viennet)" % (sco_version.SCONAME, sco_version.SCOVERSION),
- title="Lettres décision %s" % sem["titreannee"],
+ author=f"{sco_version.SCONAME} {sco_version.SCOVERSION} (E. Viennet)",
+ title=f"Lettres décision {sem['titreannee']}",
subject="Décision jury",
margins=margins,
pagesbookmarks=bookmarks,
@@ -410,10 +447,7 @@ def pdf_lettres_individuelles(
def _descr_jury(sem, diplome):
if not diplome:
- t = "passage de Semestre %d en Semestre %d" % (
- sem["semestre_id"],
- sem["semestre_id"] + 1,
- )
+ t = f"""passage de Semestre {sem["semestre_id"]} en Semestre {sem["semestre_id"] + 1}"""
s = "passage de semestre"
else:
t = "délivrance du diplôme"
@@ -428,6 +462,7 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None):
"""
#
formsemestre_id = sem["formsemestre_id"]
+ formsemestre = FormSemestre.query.get(formsemestre_id)
Se: SituationEtudCursus = decision["Se"]
t, s = _descr_jury(sem, Se.parcours_validated() or not Se.semestre_non_terminal)
objects = []
@@ -437,7 +472,7 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None):
style.leading = 18
style.alignment = TA_JUSTIFY
- params["semestre_id"] = sem["semestre_id"]
+ params["semestre_id"] = formsemestre.semestre_id
params["decision_sem_descr"] = decision["decision_sem_descr"]
params["type_jury"] = t # type de jury (passage ou delivrance)
params["type_jury_abbrv"] = s # idem, abbrégé
@@ -450,28 +485,25 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None):
params["INSTITUTION_CITY"] = (
sco_preferences.get_preference("INSTITUTION_CITY", formsemestre_id) or ""
)
+
if decision["prev_decision_sem"]:
params["prev_semestre_id"] = decision["prev"]["semestre_id"]
- params["prev_code_descr"] = decision["prev_code_descr"]
+
+ params["prev_decision_sem_txt"] = ""
+ params["decision_orig"] = ""
+
+ if formsemestre.formation.is_apc():
+ # ajout champs spécifiques PV BUT
+ add_apc_infos(formsemestre, params, decision)
+ else:
+ # ajout champs spécifiques PV DUT
+ add_classic_infos(formsemestre, params, decision)
params.update(decision["identite"])
# fix domicile
if params["domicile"]:
params["domicile"] = params["domicile"].replace("\\n", "
")
- # Décision semestre courant:
- if sem["semestre_id"] >= 0:
- params["decision_orig"] = "du semestre S%s" % sem["semestre_id"]
- else:
- params["decision_orig"] = ""
-
- if decision["prev_decision_sem"]:
- params["prev_decision_sem_txt"] = (
- """Décision du semestre antérieur S%(prev_semestre_id)s : %(prev_code_descr)s"""
- % params
- )
- else:
- params["prev_decision_sem_txt"] = ""
# UE capitalisées:
if decision["decisions_ue"] and decision["decisions_ue_descr"]:
params["decision_ue_txt"] = (
@@ -567,39 +599,23 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None):
return objects
-def _simulate_br(p, para=""):
- """Reportlab bug turnaround (could be removed in a future version).
- p is a string with Reportlab intra-paragraph XML tags.
- Replaces
(currently ignored by Reportlab) by
- """
- l = re.split(r"<.*?br.*?/>", p)
- return ("" + para).join(l)
+def add_classic_infos(formsemestre: FormSemestre, params: dict, decision: dict):
+ """Ajoute les champs pour les formations classiques, donc avec codes semestres"""
+ if decision["prev_decision_sem"]:
+ params["prev_code_descr"] = decision["prev_code_descr"]
+ params[
+ "prev_decision_sem_txt"
+ ] = f"""Décision du semestre antérieur S{params['prev_semestre_id']} : {params['prev_code_descr']}"""
+ # Décision semestre courant:
+ if formsemestre.semestre_id >= 0:
+ params["decision_orig"] = f"du semestre S{formsemestre.semestre_id}"
+ else:
+ params["decision_orig"] = ""
-def _make_signature_image(signature, leftindent, formsemestre_id):
- "cree un paragraphe avec l'image signature"
- # cree une image PIL pour avoir la taille (W,H)
- from PIL import Image as PILImage
-
- f = io.BytesIO(signature)
- im = PILImage.open(f)
- width, height = im.size
- pdfheight = (
- 1.0
- * sco_preferences.get_preference("pv_sig_image_height", formsemestre_id)
- * mm
- )
- f.seek(0, 0)
-
- style = styles.ParagraphStyle({})
- style.leading = 1.0 * sco_preferences.get_preference(
- "SCOLAR_FONT_SIZE", formsemestre_id
- ) # vertical space
- style.leftIndent = leftindent
- return Table(
- [("", Image(f, width=width * pdfheight / float(height), height=pdfheight))],
- colWidths=(9 * cm, 7 * cm),
- )
+def add_apc_infos(formsemestre: FormSemestre, params: dict, decision: dict):
+ """Ajoute les champs pour les formations APC (BUT), donc avec codes RCUE et année"""
+ pass # TODO XXX
# ----------------------------------------------
diff --git a/app/views/notes.py b/app/views/notes.py
index c1715c927..4485c1d5c 100644
--- a/app/views/notes.py
+++ b/app/views/notes.py
@@ -296,7 +296,9 @@ def formsemestre_bulletinetud(
format = format or "html"
if not isinstance(formsemestre_id, int):
- raise ScoInvalidIdType("formsemestre_id must be an integer !")
+ raise ScoInvalidIdType(
+ "formsemestre_bulletinetud: formsemestre_id must be an integer !"
+ )
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
if etudid:
etud = models.Identite.query.get_or_404(etudid)
@@ -826,7 +828,9 @@ def XMLgetFormsemestres(etape_apo=None, formsemestre_id=None):
if not formsemestre_id:
return flask.abort(404, "argument manquant: formsemestre_id")
if not isinstance(formsemestre_id, int):
- return flask.abort(404, "formsemestre_id must be an integer !")
+ return flask.abort(
+ 404, "XMLgetFormsemestres: formsemestre_id must be an integer !"
+ )
args = {}
if etape_apo:
args["etape_apo"] = etape_apo