forked from ScoDoc/ScoDoc
refactoring et préparatifs pour lettres individuelles BUT
This commit is contained in:
parent
206825c42c
commit
543c3759d9
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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="<para>") -> str:
|
||||
"""Reportlab bug turnaround (could be removed in a future version).
|
||||
p is a string with Reportlab intra-paragraph XML tags.
|
||||
Replaces <br/> (currently ignored by Reportlab) by </para><para>
|
||||
"""
|
||||
return ("</para>" + 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", "<br/>")
|
||||
|
||||
# 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"] = (
|
||||
"""<b>Décision du semestre antérieur S%(prev_semestre_id)s :</b> %(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="<para>"):
|
||||
"""Reportlab bug turnaround (could be removed in a future version).
|
||||
p is a string with Reportlab intra-paragraph XML tags.
|
||||
Replaces <br/> (currently ignored by Reportlab) by </para><para>
|
||||
"""
|
||||
l = re.split(r"<.*?br.*?/>", p)
|
||||
return ("</para>" + 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"""<b>Décision du semestre antérieur S{params['prev_semestre_id']} :</b> {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
|
||||
|
||||
|
||||
# ----------------------------------------------
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user