1
0
forked from ScoDoc/ScoDoc

PV jury BUT pdf

This commit is contained in:
Emmanuel Viennet 2023-02-18 18:49:52 +01:00
parent 1d6145010b
commit 52f98b66c1
7 changed files with 211 additions and 139 deletions

View File

@ -242,7 +242,7 @@ class DecisionsProposeesAnnee(DecisionsProposees):
# Si on part d'un semestre IMPAIR, il n'y aura pas de décision année proposée # Si on part d'un semestre IMPAIR, il n'y aura pas de décision année proposée
# (mais on pourra évidemment valider des UE et même des RCUE) # (mais on pourra évidemment valider des UE et même des RCUE)
self.jury_annuel: bool = formsemestre.semestre_id in (2, 4, 6) self.jury_annuel: bool = formsemestre.semestre_id in (2, 4, 6)
"vrai si jury de fin d'année scolaire (propose code annuel)" "vrai si jury de fin d'année scolaire (sem. pair, propose code annuel)"
self.formsemestre_impair = formsemestre_impair self.formsemestre_impair = formsemestre_impair
"le 1er semestre du groupement (S1, S3, S5)" "le 1er semestre du groupement (S1, S3, S5)"
@ -634,6 +634,17 @@ class DecisionsProposeesAnnee(DecisionsProposees):
d[dec_rcue.rcue.ue_2.id] = dec_rcue d[dec_rcue.rcue.ue_2.id] = dec_rcue
return d return d
def formsemestre_ects(self) -> float:
"ECTS validés dans le formsemestre de départ du deca"
ues = self.ues_impair if self.formsemestre.semestre_id % 2 else self.ues_pair
return sum(
[
self.decisions_ues[ue.id].ects_acquis()
for ue in ues
if ue.id in self.decisions_ues
]
)
def next_semestre_ids(self, code: str) -> set[int]: def next_semestre_ids(self, code: str) -> set[int]:
"""Les indices des semestres dans lequels l'étudiant est autorisé """Les indices des semestres dans lequels l'étudiant est autorisé
à poursuivre après le semestre courant. à poursuivre après le semestre courant.
@ -1331,6 +1342,14 @@ class DecisionsProposeesUE(DecisionsProposees):
return f"{self.ue.acronyme}" return f"{self.ue.acronyme}"
return "" return ""
def ects_acquis(self) -> float:
"""ECTS enregistrés pour cette UE
(0 si pas de validation enregistrée)
"""
if self.validation and self.code_valide in sco_codes.CODES_UE_VALIDES:
return self.ue.ects
return 0.0
class BUTCursusEtud: # WIP TODO class BUTCursusEtud: # WIP TODO
"""Validation du cursus d'un étudiant""" """Validation du cursus d'un étudiant"""

View File

@ -38,7 +38,7 @@ def _descr_cursus_but(etud: Identite) -> str:
return ", ".join(f"S{indice}" for indice in indices) return ", ".join(f"S{indice}" for indice in indices)
def pvjury_table_but(formsemestre_id: int, format="html"): def pvjury_page_but(formsemestre_id: int, fmt="html"):
"""Page récapitulant les décisions de jury BUT """Page récapitulant les décisions de jury BUT
formsemestre peut être pair ou impair formsemestre peut être pair ou impair
""" """
@ -46,15 +46,62 @@ def pvjury_table_but(formsemestre_id: int, format="html"):
assert formsemestre.formation.is_apc() assert formsemestre.formation.is_apc()
title = "Procès-verbal de jury BUT annuel" title = "Procès-verbal de jury BUT annuel"
if format == "html": if fmt == "html":
line_sep = "<br>" line_sep = "<br>"
else: else:
line_sep = "\n" line_sep = "\n"
rows, titles = pvjury_table_but(formsemestre, line_sep=line_sep)
# Style excel... passages à la ligne sur \n
xls_style_base = sco_excel.excel_make_style()
xls_style_base["alignment"] = Alignment(wrapText=True, vertical="top")
tab = GenTable(
base_url=f"{request.base_url}?formsemestre_id={formsemestre_id}",
caption=title,
columns_ids=titles.keys(),
html_caption=title,
html_class="pvjury_table_but table_leftalign",
html_title=f"""<div style="margin-bottom: 8px;"><span style="font-size: 120%; font-weight: bold;">{title}</span>
<span style="padding-left: 20px;">
<a href="{url_for("notes.pvjury_page_but",
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, fmt="xlsx")}"
class="stdlink">version excel</a></span></div>
""",
html_with_td_classes=True,
origin=f"Généré par {scu.sco_version.SCONAME} le {scu.timedate_human_repr()}",
page_title=title,
pdf_title=title,
preferences=sco_preferences.SemPreferences(),
rows=rows,
table_id="formation_table_recap",
titles=titles,
xls_columns_width={
"nom": 32,
"cursus": 12,
"ues": 32,
"niveaux": 32,
"decision_but": 14,
"diplome": 17,
"devenir": 8,
"observations": 12,
},
xls_style_base=xls_style_base,
)
return tab.make_page(format=fmt, javascripts=["js/etud_info.js"], init_qtip=True)
def pvjury_table_but(
formsemestre: FormSemestre, line_sep: str = "\n"
) -> tuple[list[dict], dict]:
"table avec résultats jury BUT pour PV"
# remplace pour le BUT la fonction sco_pvjury.pvjury_table # remplace pour le BUT la fonction sco_pvjury.pvjury_table
annee_but = (formsemestre.semestre_id + 1) // 2 annee_but = (formsemestre.semestre_id + 1) // 2
titles = { titles = {
"nom": "Nom", "nom": "Nom",
"cursus": "Cursus", "cursus": "Cursus",
"ects": "ECTS",
"ues": "UE validées", "ues": "UE validées",
"niveaux": "Niveaux de compétences validés", "niveaux": "Niveaux de compétences validés",
"decision_but": f"Décision BUT{annee_but}", "decision_but": f"Décision BUT{annee_but}",
@ -85,6 +132,7 @@ def pvjury_table_but(formsemestre_id: int, format="html"):
etudid=etud.id, etudid=etud.id,
), ),
"cursus": _descr_cursus_but(etud), "cursus": _descr_cursus_but(etud),
"ects": f"{deca.formsemestre_ects():g}",
"ues": deca.descr_ues_validation(line_sep=line_sep) if deca else "-", "ues": deca.descr_ues_validation(line_sep=line_sep) if deca else "-",
"niveaux": deca.descr_niveaux_validation(line_sep=line_sep) "niveaux": deca.descr_niveaux_validation(line_sep=line_sep)
if deca if deca
@ -98,42 +146,4 @@ def pvjury_table_but(formsemestre_id: int, format="html"):
rows.append(row) rows.append(row)
rows.sort(key=lambda x: x["_nom_order"]) rows.sort(key=lambda x: x["_nom_order"])
return rows, titles
# Style excel... passages à la ligne sur \n
xls_style_base = sco_excel.excel_make_style()
xls_style_base["alignment"] = Alignment(wrapText=True, vertical="top")
tab = GenTable(
base_url=f"{request.base_url}?formsemestre_id={formsemestre_id}",
caption=title,
columns_ids=titles.keys(),
html_caption=title,
html_class="pvjury_table_but table_leftalign",
html_title=f"""<div style="margin-bottom: 8px;"><span style="font-size: 120%; font-weight: bold;">{title}</span>
<span style="padding-left: 20px;">
<a href="{url_for("notes.pvjury_table_but",
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, format="xlsx")}"
class="stdlink">version excel</a></span></div>
""",
html_with_td_classes=True,
origin=f"Généré par {scu.sco_version.SCONAME} le {scu.timedate_human_repr()}",
page_title=title,
pdf_title=title,
preferences=sco_preferences.SemPreferences(),
rows=rows,
table_id="formation_table_recap",
titles=titles,
xls_columns_width={
"nom": 32,
"cursus": 12,
"ues": 32,
"niveaux": 32,
"decision_but": 14,
"diplome": 17,
"devenir": 8,
"observations": 12,
},
xls_style_base=xls_style_base,
)
return tab.make_page(format=format, javascripts=["js/etud_info.js"], init_qtip=True)

View File

@ -363,7 +363,7 @@ def do_formsemestre_archive(
PVArchive.store(archive_id, "Bulletins.json", data_js) PVArchive.store(archive_id, "Bulletins.json", data_js)
# Décisions de jury, en XLS # Décisions de jury, en XLS
if formsemestre.formation.is_apc(): if formsemestre.formation.is_apc():
response = jury_but_pv.pvjury_table_but(formsemestre_id, format="xls") response = jury_but_pv.pvjury_page_but(formsemestre_id, fmt="xls")
data = response.get_data() data = response.get_data()
else: # formations classiques else: # formations classiques
data = sco_pvjury.formsemestre_pvjury( data = sco_pvjury.formsemestre_pvjury(

View File

@ -228,7 +228,7 @@ def dict_pvjury(
'decisions_dict' : { etudid : decision (comme ci-dessus) }, 'decisions_dict' : { etudid : decision (comme ci-dessus) },
} }
""" """
formsemestre = FormSemestre.query.get_or_404(formsemestre_id) formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
if etudids is None: if etudids is None:
etudids = nt.get_etudids() etudids = nt.get_etudids()
@ -510,7 +510,9 @@ def pvjury_table(
return lines, titles, columns_ids return lines, titles, columns_ids
def formsemestre_pvjury(formsemestre_id, format="html", publish=True): # XXX TODO cette page a vocation a disparaitre,
# remplacée par formsemestre_recapcomplet en mode jury (déjà le cas pour les BUT)
def formsemestre_pvjury(formsemestre_id, format="html", publish=True): # XXX
"""Page récapitulant les décisions de jury""" """Page récapitulant les décisions de jury"""
formsemestre = FormSemestre.query.get_or_404(formsemestre_id) formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
is_apc = formsemestre.formation.is_apc() is_apc = formsemestre.formation.is_apc()
@ -621,21 +623,21 @@ def formsemestre_pvjury(formsemestre_id, format="html", publish=True):
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def formsemestre_pvjury_pdf(formsemestre_id, group_ids=[], etudid=None): def formsemestre_pvjury_pdf(formsemestre_id, group_ids: list[int] = None, etudid=None):
"""Generation PV jury en PDF: saisie des paramètres """Generation PV jury en PDF: saisie des paramètres
Si etudid, PV pour un seul etudiant. Sinon, tout les inscrits au groupe indiqué. Si etudid, PV pour un seul etudiant. Sinon, tout les inscrits au groupe indiqué.
""" """
group_ids = group_ids or []
sem = sco_formsemestre.get_formsemestre(formsemestre_id) sem = sco_formsemestre.get_formsemestre(formsemestre_id)
# Mise à jour des groupes d'étapes: # Mise à jour des groupes d'étapes:
sco_groups.create_etapes_partition(formsemestre_id) sco_groups.create_etapes_partition(formsemestre_id)
groups_infos = None groups_infos = None
if etudid: if etudid:
# PV pour ce seul étudiant: # PV pour ce seul étudiant:
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0] etud = Identite.query.get_or_404(etudid)
etuddescr = '<a class="discretelink" href="ficheEtud?etudid=%s">%s</a>' % ( etuddescr = f"""<a class="discretelink" href="{
etudid, url_for("notes.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid)
etud["nomprenom"], }">{etud.nomprenom}</a>"""
)
etudids = [etudid] etudids = [etudid]
else: else:
etuddescr = "" etuddescr = ""
@ -650,18 +652,22 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids=[], etudid=None):
H = [ H = [
html_sco_header.html_sem_header( html_sco_header.html_sem_header(
"Edition du PV de jury %s" % etuddescr, f"Édition du PV de jury {etuddescr}",
javascripts=sco_groups_view.JAVASCRIPTS, javascripts=sco_groups_view.JAVASCRIPTS,
cssstyles=sco_groups_view.CSSSTYLES, cssstyles=sco_groups_view.CSSSTYLES,
init_qtip=True, init_qtip=True,
), ),
"""<p class="help">Utiliser cette page pour éditer des versions provisoires des PV. f"""<div class="help">Utiliser cette page pour éditer des versions provisoires des PV.
<span class="fontred">Il est recommandé d'archiver les versions définitives: <a href="formsemestre_archive?formsemestre_id=%s">voir cette page</a></span> <span class="fontred">Il est recommandé d'archiver les versions définitives:
</p>""" <a class="stdlink" href="{url_for(
% formsemestre_id, 'notes.formsemestre_archive',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
}">voir cette page</a></span>
</div>""",
] ]
F = [ F = [
"""<p><em>Voir aussi si besoin les réglages sur la page "Paramétrage" (accessible à l'administrateur du département).</em> """<p><em>Voir aussi si besoin les réglages sur la page "Paramétrage"
(accessible à l'administrateur du département).</em>
</p>""", </p>""",
html_sco_header.sco_footer(), html_sco_header.sco_footer(),
] ]
@ -692,7 +698,11 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids=[], etudid=None):
return "\n".join(H) + "\n" + tf[1] + "\n".join(F) return "\n".join(H) + "\n" + tf[1] + "\n".join(F)
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect( return flask.redirect(
"formsemestre_pvjury?formsemestre_id=%s" % (formsemestre_id) url_for(
"notes.formsemestre_pvjury",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id,
)
) )
else: else:
# submit # submit
@ -721,12 +731,12 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids=[], etudid=None):
finally: finally:
PDFLOCK.release() PDFLOCK.release()
sem = sco_formsemestre.get_formsemestre(formsemestre_id) sem = sco_formsemestre.get_formsemestre(formsemestre_id)
dt = time.strftime("%Y-%m-%d") date_iso = time.strftime("%Y-%m-%d")
if groups_infos: if groups_infos:
groups_filename = "-" + groups_infos.groups_filename groups_filename = "-" + groups_infos.groups_filename
else: else:
groups_filename = "" groups_filename = ""
filename = "PV-%s%s-%s.pdf" % (sem["titre_num"], groups_filename, dt) filename = f"""PV-{sem["titre_num"]}{groups_filename}-{date_iso}.pdf"""
return scu.sendPDFFile(pdfdoc, filename) return scu.sendPDFFile(pdfdoc, filename)

View File

@ -679,10 +679,10 @@ def pvjury_pdf(
dpv, dpv,
only_diplome=False, only_diplome=False,
date_commission=date_commission, date_commission=date_commission,
numeroArrete=numeroArrete, numero_arrete=numeroArrete,
VDICode=VDICode, code_vdi=VDICode,
date_jury=date_jury, date_jury=date_jury,
showTitle=showTitle, show_title=showTitle,
pv_title=pv_title, pv_title=pv_title,
with_paragraph_nom=with_paragraph_nom, with_paragraph_nom=with_paragraph_nom,
anonymous=anonymous, anonymous=anonymous,
@ -690,7 +690,8 @@ def pvjury_pdf(
jury_de_diplome = not dpv["semestre_non_terminal"] jury_de_diplome = not dpv["semestre_non_terminal"]
# Si Jury de passage et qu'un étudiant valide le parcours (car il a validé antérieurement le dernier semestre) # Si Jury de passage et qu'un étudiant valide le parcours
# (car il a validé antérieurement le dernier semestre)
# alors on génère aussi un PV de diplome (à la suite dans le même doc PDF) # alors on génère aussi un PV de diplome (à la suite dans le même doc PDF)
if not jury_de_diplome: if not jury_de_diplome:
validations_parcours = [x["validation_parcours"] for x in dpv["decisions"]] validations_parcours = [x["validation_parcours"] for x in dpv["decisions"]]
@ -702,9 +703,9 @@ def pvjury_pdf(
only_diplome=True, only_diplome=True,
date_commission=date_commission, date_commission=date_commission,
date_jury=date_jury, date_jury=date_jury,
numeroArrete=numeroArrete, numero_arrete=numeroArrete,
VDICode=VDICode, code_vdi=VDICode,
showTitle=showTitle, show_title=showTitle,
pv_title=pv_title, pv_title=pv_title,
with_paragraph_nom=with_paragraph_nom, with_paragraph_nom=with_paragraph_nom,
anonymous=anonymous, anonymous=anonymous,
@ -729,14 +730,39 @@ def pvjury_pdf(
return data return data
def _make_pv_styles(formsemestre: FormSemestre):
style = reportlab.lib.styles.ParagraphStyle({})
style.fontSize = 12
style.fontName = sco_preferences.get_preference("PV_FONTNAME", formsemestre.id)
style.leading = 18
style.alignment = TA_JUSTIFY
indent = 1 * cm
style_bullet = reportlab.lib.styles.ParagraphStyle({})
style_bullet.fontSize = 12
style_bullet.fontName = sco_preferences.get_preference(
"PV_FONTNAME", formsemestre.id
)
style_bullet.leading = 12
style_bullet.alignment = TA_JUSTIFY
style_bullet.firstLineIndent = 0
style_bullet.leftIndent = indent
style_bullet.bulletIndent = indent
style_bullet.bulletFontName = "Times-Roman"
style_bullet.bulletFontSize = 11
style_bullet.spaceBefore = 5 * mm
style_bullet.spaceAfter = 5 * mm
return style, style_bullet
def _pvjury_pdf_type( def _pvjury_pdf_type(
dpv, dpv,
only_diplome=False, only_diplome=False,
date_commission=None, date_commission=None,
date_jury=None, date_jury=None,
numeroArrete=None, numero_arrete=None,
VDICode=None, code_vdi=None,
showTitle=False, show_title=False,
pv_title=None, pv_title=None,
anonymous=False, anonymous=False,
with_paragraph_nom=False, with_paragraph_nom=False,
@ -745,6 +771,7 @@ def _pvjury_pdf_type(
dpv: result of dict_pvjury dpv: result of dict_pvjury
""" """
from app.scodoc import sco_pvjury from app.scodoc import sco_pvjury
from app.but import jury_but_pv
# Jury de diplome si sem. terminal OU que l'on demande les diplomés d'un semestre antérieur # Jury de diplome si sem. terminal OU que l'on demande les diplomés d'un semestre antérieur
diplome = (not dpv["semestre_non_terminal"]) or only_diplome diplome = (not dpv["semestre_non_terminal"]) or only_diplome
@ -756,83 +783,63 @@ def _pvjury_pdf_type(
titre_diplome = pv_title or dpv["formation"]["titre_officiel"] titre_diplome = pv_title or dpv["formation"]["titre_officiel"]
objects = [] objects = []
style = reportlab.lib.styles.ParagraphStyle({}) style, style_bullet = _make_pv_styles(formsemestre)
style.fontSize = 12
style.fontName = sco_preferences.get_preference("PV_FONTNAME", formsemestre_id)
style.leading = 18
style.alignment = TA_JUSTIFY
indent = 1 * cm
bulletStyle = reportlab.lib.styles.ParagraphStyle({})
bulletStyle.fontSize = 12
bulletStyle.fontName = sco_preferences.get_preference(
"PV_FONTNAME", formsemestre_id
)
bulletStyle.leading = 12
bulletStyle.alignment = TA_JUSTIFY
bulletStyle.firstLineIndent = 0
bulletStyle.leftIndent = indent
bulletStyle.bulletIndent = indent
bulletStyle.bulletFontName = "Times-Roman"
bulletStyle.bulletFontSize = 11
bulletStyle.spaceBefore = 5 * mm
bulletStyle.spaceAfter = 5 * mm
objects += [Spacer(0, 5 * mm)] objects += [Spacer(0, 5 * mm)]
objects += sco_pdf.make_paras( objects += sco_pdf.make_paras(
""" f"""
<para align="center"><b>Procès-verbal de %s du département %s - Session unique %s</b></para> <para align="center"><b>Procès-verbal de {titre_jury} du département {
""" sco_preferences.get_preference("DeptName", formsemestre_id) or "(sans nom)"
% ( } - Session unique {sem["anneescolaire"]}</b></para>
titre_jury, """,
sco_preferences.get_preference("DeptName", formsemestre_id) or "(sans nom)",
sem["anneescolaire"],
),
style, style,
) )
objects += sco_pdf.make_paras( objects += sco_pdf.make_paras(
""" f"""<para align="center"><b><i>{titre_diplome}</i></b></para>""",
<para align="center"><b><i>%s</i></b></para>
"""
% titre_diplome,
style, style,
) )
if showTitle: if show_title:
objects += sco_pdf.make_paras( objects += sco_pdf.make_paras(
"""<para align="center"><b>Semestre: %s</b></para>""" % sem["titre"], style f"""<para align="center"><b>Semestre: {formsemestre.titre}</b></para>""",
style,
) )
if sco_preferences.get_preference("PV_TITLE_WITH_VDI", formsemestre_id): if sco_preferences.get_preference("PV_TITLE_WITH_VDI", formsemestre_id):
objects += sco_pdf.make_paras( objects += sco_pdf.make_paras(
"""<para align="center">VDI et Code: %s</para>""" % (VDICode or ""), style f"""<para align="center">VDI et Code: {(code_vdi or "")}</para>""", style
) )
if date_jury: if date_jury:
objects += sco_pdf.make_paras( objects += sco_pdf.make_paras(
"""<para align="center">Jury tenu le %s</para>""" % date_jury, style f"""<para align="center">Jury tenu le {date_jury}</para>""", style
) )
objects += sco_pdf.make_paras( objects += sco_pdf.make_paras(
"<para>" "<para>"
+ (sco_preferences.get_preference("PV_INTRO", formsemestre_id) or "") + (sco_preferences.get_preference("PV_INTRO", formsemestre_id) or "")
% { % {
"Decnum": numeroArrete, "Decnum": numero_arrete,
"VDICode": VDICode, "VDICode": code_vdi,
"UnivName": sco_preferences.get_preference("UnivName", formsemestre_id), "UnivName": sco_preferences.get_preference("UnivName", formsemestre_id),
"Type": titre_jury, "Type": titre_jury,
"Date": date_commission, # deprecated "Date": date_commission, # deprecated
"date_commission": date_commission, "date_commission": date_commission,
} }
+ "</para>", + "</para>",
bulletStyle, style_bullet,
) )
objects += sco_pdf.make_paras( objects += sco_pdf.make_paras(
"""<para>Le jury propose les décisions suivantes :</para>""", style """<para>Le jury propose les décisions suivantes :</para>""", style
) )
objects += [Spacer(0, 4 * mm)] objects += [Spacer(0, 4 * mm)]
lines, titles, columns_ids = sco_pvjury.pvjury_table(
if formsemestre.formation.is_apc():
rows, titles = jury_but_pv.pvjury_table_but(formsemestre)
columns_ids = list(titles.keys())
else:
rows, titles, columns_ids = sco_pvjury.pvjury_table(
dpv, dpv,
only_diplome=only_diplome, only_diplome=only_diplome,
anonymous=anonymous, anonymous=anonymous,
@ -840,7 +847,7 @@ def _pvjury_pdf_type(
) )
# convert to lists of tuples: # convert to lists of tuples:
columns_ids = ["etudid"] + columns_ids columns_ids = ["etudid"] + columns_ids
lines = [[line.get(x, "") for x in columns_ids] for line in lines] rows = [[line.get(x, "") for x in columns_ids] for line in rows]
titles = [titles.get(x, "") for x in columns_ids] titles = [titles.get(x, "") for x in columns_ids]
# Make a new cell style and put all cells in paragraphs # Make a new cell style and put all cells in paragraphs
cell_style = styles.ParagraphStyle({}) cell_style = styles.ParagraphStyle({})
@ -863,7 +870,7 @@ def _pvjury_pdf_type(
("GRID", (0, 0), (-1, -1), LINEWIDTH, Color(0, 0, 0)), ("GRID", (0, 0), (-1, -1), LINEWIDTH, Color(0, 0, 0)),
("VALIGN", (0, 0), (-1, -1), "TOP"), ("VALIGN", (0, 0), (-1, -1), "TOP"),
] ]
titles = ["<para><b>%s</b></para>" % x for x in titles] titles = [f"<para><b>{x}</b></para>" for x in titles]
def _format_pv_cell(x): def _format_pv_cell(x):
"""convert string to paragraph""" """convert string to paragraph"""
@ -872,22 +879,31 @@ def _pvjury_pdf_type(
else: else:
return x return x
Pt = [[_format_pv_cell(x) for x in line[1:]] for line in ([titles] + lines)] widths_by_id = {
widths = [6 * cm, 2.8 * cm, 2.8 * cm, None, None, None, None] "nom": 5 * cm,
if dpv["has_prev"]: "cursus": 2.8 * cm,
widths[2:2] = [2.8 * cm] "ects": 1.4 * cm,
if sco_preferences.get_preference("bul_show_mention", formsemestre_id): "devenir": 1.8 * cm,
widths += [None] "decision_but": 1.8 * cm,
objects.append(Table(Pt, repeatRows=1, colWidths=widths, style=table_style)) }
table_cells = [[_format_pv_cell(x) for x in line[1:]] for line in ([titles] + rows)]
widths = [widths_by_id.get(col_id) for col_id in columns_ids[1:]]
# if dpv["has_prev"]:
# widths[2:2] = [2.8 * cm]
# if sco_preferences.get_preference("bul_show_mention", formsemestre_id):
# widths += [None]
objects.append(
Table(table_cells, repeatRows=1, colWidths=widths, style=table_style)
)
# Signature du directeur # Signature du directeur
objects += sco_pdf.make_paras( objects += sco_pdf.make_paras(
"""<para spaceBefore="10mm" align="right"> f"""<para spaceBefore="10mm" align="right">{
%s, %s</para>""" sco_preferences.get_preference("DirectorName", formsemestre_id) or ""
% ( }, {
sco_preferences.get_preference("DirectorName", formsemestre_id) or "", sco_preferences.get_preference("DirectorTitle", formsemestre_id) or ""
sco_preferences.get_preference("DirectorTitle", formsemestre_id) or "", }</para>""",
),
style, style,
) )

View File

@ -166,6 +166,7 @@ def formsemestre_recapcomplet(
if len(formsemestre.inscriptions) > 0: if len(formsemestre.inscriptions) > 0:
H.append("""<div class="links_under_recap"><ul>""") H.append("""<div class="links_under_recap"><ul>""")
if not mode_jury:
H.append( H.append(
f"""<li><a class="stdlink" href="{url_for('notes.formsemestre_recapcomplet', f"""<li><a class="stdlink" href="{url_for('notes.formsemestre_recapcomplet',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, mode_jury=1) scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, mode_jury=1)
@ -186,6 +187,22 @@ def formsemestre_recapcomplet(
</li> </li>
""" """
) )
if mode_jury:
H.append(
f"""<li><a class="stdlink" href="{
url_for('notes.formsemestre_lettres_individuelles',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, mode_jury=1)
}">Courriers individuels (classeur pdf)</a>
</li>
"""
)
H.append(
f"""<li><a class="stdlink" href="{url_for('notes.formsemestre_pvjury_pdf',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, mode_jury=1)
}">PV officiel (pdf)</a>
</li>
"""
)
H.append("</ul></div>") H.append("</ul></div>")
if sco_preferences.get_preference("use_ue_coefs", formsemestre_id): if sco_preferences.get_preference("use_ue_coefs", formsemestre_id):

View File

@ -2805,7 +2805,7 @@ def formsemestre_validation_suppress_etud(
# ------------- PV de JURY et archives # ------------- PV de JURY et archives
sco_publish("/formsemestre_pvjury", sco_pvjury.formsemestre_pvjury, Permission.ScoView) sco_publish("/formsemestre_pvjury", sco_pvjury.formsemestre_pvjury, Permission.ScoView)
sco_publish("/pvjury_table_but", jury_but_pv.pvjury_table_but, Permission.ScoView) sco_publish("/pvjury_page_but", jury_but_pv.pvjury_page_but, Permission.ScoView)
@bp.route("/formsemestre_saisie_jury") @bp.route("/formsemestre_saisie_jury")