forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -31,7 +31,7 @@ from flask import render_template, url_for
|
|||||||
from flask import g, request
|
from flask import g, request
|
||||||
|
|
||||||
from app.but.bulletin_but import BulletinBUT
|
from app.but.bulletin_but import BulletinBUT
|
||||||
from app.but import cursus_but, validations_view
|
from app.but import bulletin_but_court_pdf, cursus_but, validations_view
|
||||||
from app.decorators import (
|
from app.decorators import (
|
||||||
scodoc,
|
scodoc,
|
||||||
permission_required,
|
permission_required,
|
||||||
@ -40,14 +40,18 @@ from app.models import FormSemestre, FormSemestreInscription, Identite
|
|||||||
from app.scodoc.sco_exceptions import ScoNoReferentielCompetences
|
from app.scodoc.sco_exceptions import ScoNoReferentielCompetences
|
||||||
from app.scodoc.sco_logos import find_logo
|
from app.scodoc.sco_logos import find_logo
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
import app.scodoc.sco_utils as scu
|
||||||
from app.views import notes_bp as bp
|
from app.views import notes_bp as bp
|
||||||
from app.views import ScoData
|
from app.views import ScoData
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/bulletin_but/<int:formsemestre_id>/<int:etudid>")
|
@bp.route("/bulletin_but/<int:formsemestre_id>/<int:etudid>")
|
||||||
|
@bp.route(
|
||||||
|
"/bulletin_but/<int:formsemestre_id>/<int:etudid>/pdf", defaults={"fmt": "pdf"}
|
||||||
|
)
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
def bulletin_but(formsemestre_id: int, etudid: int = None):
|
def bulletin_but(formsemestre_id: int, etudid: int = None, fmt="html"):
|
||||||
"""Page HTML affichant le bulletin BUT simplifié"""
|
"""Page HTML affichant le bulletin BUT simplifié"""
|
||||||
etud: Identite = Identite.query.get_or_404(etudid)
|
etud: Identite = Identite.query.get_or_404(etudid)
|
||||||
formsemestre: FormSemestre = (
|
formsemestre: FormSemestre = (
|
||||||
@ -70,19 +74,27 @@ def bulletin_but(formsemestre_id: int, etudid: int = None):
|
|||||||
|
|
||||||
logo = find_logo(logoname="header", dept_id=g.scodoc_dept_id)
|
logo = find_logo(logoname="header", dept_id=g.scodoc_dept_id)
|
||||||
|
|
||||||
|
args = {
|
||||||
|
"bul": bul,
|
||||||
|
"cursus": cursus,
|
||||||
|
"decision_ues": decision_ues,
|
||||||
|
"ects_total": ects_total,
|
||||||
|
"etud": etud,
|
||||||
|
"formsemestre": formsemestre,
|
||||||
|
"logo": logo,
|
||||||
|
"title": f"Bul. {etud.nom_disp()} BUT (court)",
|
||||||
|
"ue_validation_by_niveau": ue_validation_by_niveau,
|
||||||
|
}
|
||||||
|
|
||||||
|
if fmt == "pdf":
|
||||||
|
filename = scu.bul_filename(formsemestre, etud, prefix="bul-but")
|
||||||
|
bul_pdf = bulletin_but_court_pdf.make_bulletin_but_court_pdf(**args)
|
||||||
|
return scu.sendPDFFile(bul_pdf, filename)
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"but/bulletin_court_page.j2",
|
"but/bulletin_court_page.j2",
|
||||||
bul=bul,
|
|
||||||
bulletins_sem=bulletins_sem,
|
|
||||||
cursus=cursus,
|
|
||||||
datetime=datetime,
|
datetime=datetime,
|
||||||
decision_ues=decision_ues,
|
|
||||||
ects_total=ects_total,
|
|
||||||
etud=etud,
|
|
||||||
formsemestre=formsemestre,
|
|
||||||
logo=logo,
|
|
||||||
sco=ScoData(formsemestre=formsemestre, etud=etud),
|
sco=ScoData(formsemestre=formsemestre, etud=etud),
|
||||||
time=time,
|
time=time,
|
||||||
title=f"Bul. {etud.nom_disp()} BUT (court)",
|
**args,
|
||||||
ue_validation_by_niveau=ue_validation_by_niveau,
|
|
||||||
)
|
)
|
||||||
|
122
app/but/bulletin_but_court_pdf.py
Normal file
122
app/but/bulletin_but_court_pdf.py
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2023 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
"""Génération bulletin BUT PDF synthétique en une page
|
||||||
|
|
||||||
|
On génère du PDF avec reportLab en utilisant les classes
|
||||||
|
ScoDoc BulletinGenerator et GenTable.
|
||||||
|
|
||||||
|
"""
|
||||||
|
from flask_login import current_user
|
||||||
|
|
||||||
|
from reportlab.lib.colors import blue
|
||||||
|
from reportlab.lib.units import cm, mm
|
||||||
|
from reportlab.platypus import Paragraph, Spacer
|
||||||
|
|
||||||
|
from app.but import cursus_but
|
||||||
|
from app.models import FormSemestre, Identite, ScolarFormSemestreValidation
|
||||||
|
|
||||||
|
from app.scodoc.sco_bulletins_standard import BulletinGeneratorStandard
|
||||||
|
from app.scodoc.sco_logos import Logo
|
||||||
|
from app.scodoc import gen_tables, sco_pdf, sco_preferences
|
||||||
|
from app.scodoc.sco_pdf import PDFLOCK
|
||||||
|
|
||||||
|
|
||||||
|
def make_bulletin_but_court_pdf(
|
||||||
|
bul: dict = None,
|
||||||
|
cursus: cursus_but.EtudCursusBUT = None,
|
||||||
|
decision_ues: dict = None,
|
||||||
|
ects_total: float = 0.0,
|
||||||
|
etud: Identite = None,
|
||||||
|
formsemestre: FormSemestre = None,
|
||||||
|
logo: Logo = None,
|
||||||
|
title: str = "",
|
||||||
|
ue_validation_by_niveau: dict[tuple[int, str], ScolarFormSemestreValidation] = None,
|
||||||
|
) -> bytes:
|
||||||
|
# A priori ce verrou n'est plus nécessaire avec Flask (multi-process)
|
||||||
|
# mais...
|
||||||
|
try:
|
||||||
|
PDFLOCK.acquire()
|
||||||
|
bul_generator = BulletinGeneratorBUTCourt(**locals())
|
||||||
|
bul_pdf = bul_generator.generate(format="pdf")
|
||||||
|
finally:
|
||||||
|
PDFLOCK.release()
|
||||||
|
return bul_pdf
|
||||||
|
|
||||||
|
|
||||||
|
class BulletinGeneratorBUTCourt(BulletinGeneratorStandard):
|
||||||
|
"""Ce générateur de bulletin BUT court est assez différent des autres bulletins.
|
||||||
|
Ne génére que du PDF.
|
||||||
|
Il reprend la mise en page et certains éléments (pied de page, signature).
|
||||||
|
"""
|
||||||
|
|
||||||
|
# spécialisation du BulletinGeneratorStandard, ne pas présenter à l'utilisateur:
|
||||||
|
list_in_menu = False
|
||||||
|
scale_table_in_page = True # pas de mise à l'échelle pleine page auto
|
||||||
|
multi_pages = False # une page par bulletin
|
||||||
|
small_fontsize = "8"
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
bul: dict = None,
|
||||||
|
cursus: cursus_but.EtudCursusBUT = None,
|
||||||
|
decision_ues: dict = None,
|
||||||
|
ects_total: float = 0.0,
|
||||||
|
etud: Identite = None,
|
||||||
|
formsemestre: FormSemestre = None,
|
||||||
|
logo: Logo = None,
|
||||||
|
title: str = "",
|
||||||
|
ue_validation_by_niveau: dict[
|
||||||
|
tuple[int, str], ScolarFormSemestreValidation
|
||||||
|
] = None,
|
||||||
|
):
|
||||||
|
# données pour anciens codes bulletins... à moderniser
|
||||||
|
infos = {
|
||||||
|
"etud": etud.to_dict_bul(),
|
||||||
|
"filigranne": None,
|
||||||
|
"formsemestre_id": formsemestre.id,
|
||||||
|
"nbabs": 0,
|
||||||
|
"nbabsjust": 0,
|
||||||
|
}
|
||||||
|
super().__init__(infos, authuser=current_user)
|
||||||
|
self.bul = bul
|
||||||
|
self.cursus = cursus
|
||||||
|
self.decision_ues = decision_ues
|
||||||
|
self.ects_total = ects_total
|
||||||
|
self.etud = etud
|
||||||
|
self.formsemestre = formsemestre
|
||||||
|
self.logo = logo
|
||||||
|
self.title = title
|
||||||
|
self.ue_validation_by_niveau = ue_validation_by_niveau
|
||||||
|
|
||||||
|
def bul_table(self, fmt=None):
|
||||||
|
"""Génère la table centrale du bulletin de notes
|
||||||
|
Renvoie: une liste d'objets PLATYPUS (eg instance de Table).
|
||||||
|
L'argument fmt est ici ignoré (toujours en PDF)
|
||||||
|
"""
|
||||||
|
ue_table = self.build_ue_table()
|
||||||
|
|
||||||
|
return ue_table.gen(format="pdf")
|
||||||
|
|
||||||
|
def build_ue_table(self) -> gen_tables.GenTable:
|
||||||
|
"""Table avec les résultats d'UE du semestre courant"""
|
||||||
|
columns_ids = ("titre", "UE1", "UE2")
|
||||||
|
rows = [
|
||||||
|
{"titre": "ligne 1", "UE1": "12.", "UE2": "13"},
|
||||||
|
{"titre": "ligne 2", "UE1": "14.", "UE2": "15"},
|
||||||
|
]
|
||||||
|
pdf_style = [
|
||||||
|
("VALIGN", (0, 0), (-1, -1), "TOP"),
|
||||||
|
("BOX", (0, 0), (-1, -1), 0.4, blue), # ajoute cadre extérieur bleu
|
||||||
|
]
|
||||||
|
col_widths = {"titre": 3 * cm, "UE1": 1 * cm, "UE2": 1 * cm}
|
||||||
|
return gen_tables.GenTable(
|
||||||
|
rows=rows,
|
||||||
|
columns_ids=columns_ids,
|
||||||
|
pdf_table_style=pdf_style,
|
||||||
|
pdf_col_widths=[col_widths[k] for k in columns_ids],
|
||||||
|
preferences=sco_preferences.SemPreferences(self.formsemestre.id),
|
||||||
|
)
|
@ -887,10 +887,10 @@ def bul_filename_old(sem: dict, etud: dict, format):
|
|||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
|
||||||
def bul_filename(formsemestre, etud):
|
def bul_filename(formsemestre, etud, prefix="bul"):
|
||||||
"""Build a filename for this bulletin (without suffix)"""
|
"""Build a filename for this bulletin (without suffix)"""
|
||||||
dt = time.strftime("%Y-%m-%d")
|
dt = time.strftime("%Y-%m-%d")
|
||||||
filename = f"bul-{formsemestre.titre_num()}-{dt}-{etud.nom}"
|
filename = f"{prefix}-{formsemestre.titre_num()}-{dt}-{etud.nom}"
|
||||||
filename = make_filename(filename)
|
filename = make_filename(filename)
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user