2023-08-02 00:13:31 +02:00
|
|
|
##############################################################################
|
|
|
|
# ScoDoc
|
2023-12-31 23:04:06 +01:00
|
|
|
# Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved.
|
2023-08-02 00:13:31 +02:00
|
|
|
# See LICENSE
|
|
|
|
##############################################################################
|
|
|
|
|
2023-08-30 16:03:36 +02:00
|
|
|
"""Génération bulletin BUT HTML synthétique en une page
|
2023-08-02 00:13:31 +02:00
|
|
|
|
2023-08-30 16:03:36 +02:00
|
|
|
On génère du HTML à partir d'un template Jinja.
|
2023-08-02 00:13:31 +02:00
|
|
|
|
|
|
|
## Données
|
|
|
|
|
|
|
|
Ces données sont des objets passés au template.
|
|
|
|
|
|
|
|
- `etud: Identite` : l'étudiant
|
|
|
|
- `formsemestre: FormSemestre` : le formsemestre d'où est émis ce bulletin
|
|
|
|
- `bulletins_sem: BulletinBUT` les données bulletins pour tous les étudiants
|
|
|
|
- `bul: dict` : le bulletin (dict, même structure que le json publié)
|
|
|
|
- `cursus: EtudCursusBUT`: infos sur le cursus BUT (niveaux validés etc)
|
|
|
|
- `decision_ues: dict`: `{ acronyme_ue : { 'code' : 'ADM' }}` accès aux décisions
|
2023-12-06 20:04:40 +01:00
|
|
|
de jury d'UE
|
2023-08-02 00:13:31 +02:00
|
|
|
- `ects_total` : nombre d'ECTS validées dans ce cursus
|
|
|
|
- `ue_validation_by_niveau : dict` : les validations d'UE de chaque niveau du cursus
|
|
|
|
"""
|
|
|
|
import datetime
|
|
|
|
import time
|
|
|
|
|
2023-09-01 14:38:41 +02:00
|
|
|
from flask import render_template
|
|
|
|
from flask import g
|
2023-08-02 00:13:31 +02:00
|
|
|
|
|
|
|
from app.but.bulletin_but import BulletinBUT
|
2023-08-30 15:59:11 +02:00
|
|
|
from app.but import bulletin_but_court_pdf, cursus_but, validations_view
|
2023-08-02 00:13:31 +02:00
|
|
|
from app.decorators import (
|
|
|
|
scodoc,
|
|
|
|
permission_required,
|
|
|
|
)
|
|
|
|
from app.models import FormSemestre, FormSemestreInscription, Identite
|
2023-09-01 14:38:41 +02:00
|
|
|
from app.scodoc.codes_cursus import UE_STANDARD
|
2023-09-02 15:53:30 +02:00
|
|
|
from app.scodoc.sco_exceptions import ScoNoReferentielCompetences, ScoValueError
|
2023-08-02 00:13:31 +02:00
|
|
|
from app.scodoc.sco_logos import find_logo
|
|
|
|
from app.scodoc.sco_permissions import Permission
|
2024-07-07 22:07:27 +02:00
|
|
|
from app.scodoc.sco_pv_lettres_inviduelles import add_dut120_infos
|
2023-08-30 15:59:11 +02:00
|
|
|
import app.scodoc.sco_utils as scu
|
2023-08-02 00:13:31 +02:00
|
|
|
from app.views import notes_bp as bp
|
|
|
|
from app.views import ScoData
|
|
|
|
|
|
|
|
|
2023-08-30 15:59:11 +02:00
|
|
|
@bp.route(
|
2023-09-01 18:14:22 +02:00
|
|
|
"/bulletin_but/<int:formsemestre_id>/<int:etudid>", endpoint="bulletin_but_html"
|
|
|
|
)
|
|
|
|
@bp.route(
|
|
|
|
"/bulletin_but/<int:formsemestre_id>/<int:etudid>/pdf",
|
|
|
|
defaults={"fmt": "pdf"},
|
|
|
|
endpoint="bulletin_but_pdf",
|
2023-08-30 15:59:11 +02:00
|
|
|
)
|
2023-08-02 00:13:31 +02:00
|
|
|
@scodoc
|
|
|
|
@permission_required(Permission.ScoView)
|
2023-08-30 15:59:11 +02:00
|
|
|
def bulletin_but(formsemestre_id: int, etudid: int = None, fmt="html"):
|
2023-08-02 00:13:31 +02:00
|
|
|
"""Page HTML affichant le bulletin BUT simplifié"""
|
|
|
|
etud: Identite = Identite.query.get_or_404(etudid)
|
|
|
|
formsemestre: FormSemestre = (
|
|
|
|
FormSemestre.query.filter_by(id=formsemestre_id)
|
|
|
|
.join(FormSemestreInscription)
|
|
|
|
.filter_by(etudid=etudid)
|
|
|
|
.first_or_404()
|
|
|
|
)
|
2023-09-02 15:53:30 +02:00
|
|
|
if not formsemestre.formation.is_apc():
|
|
|
|
raise ScoValueError("formation non BUT")
|
2023-12-06 20:04:40 +01:00
|
|
|
|
|
|
|
args = _build_bulletin_but_infos(etud, formsemestre, fmt=fmt)
|
|
|
|
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 + ".pdf")
|
|
|
|
|
|
|
|
return render_template(
|
|
|
|
"but/bulletin_court_page.j2",
|
|
|
|
datetime=datetime,
|
|
|
|
sco=ScoData(formsemestre=formsemestre, etud=etud),
|
|
|
|
time=time,
|
|
|
|
version="butcourt",
|
|
|
|
**args,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2023-12-06 20:40:55 +01:00
|
|
|
def bulletin_but_court_pdf_frag(
|
|
|
|
etud: Identite, formsemestre: FormSemestre, stand_alone=False
|
|
|
|
) -> bytes:
|
2023-12-06 20:04:40 +01:00
|
|
|
"""Le code PDF d'un bulletin BUT court, à intégrer dans un document
|
|
|
|
(pour les classeurs de tous les bulletins)
|
|
|
|
"""
|
|
|
|
args = _build_bulletin_but_infos(etud, formsemestre)
|
2023-12-06 20:40:55 +01:00
|
|
|
return bulletin_but_court_pdf.make_bulletin_but_court_pdf(
|
|
|
|
args, stand_alone=stand_alone
|
|
|
|
)
|
2023-12-06 20:04:40 +01:00
|
|
|
|
|
|
|
|
|
|
|
def _build_bulletin_but_infos(
|
|
|
|
etud: Identite, formsemestre: FormSemestre, fmt="pdf"
|
|
|
|
) -> dict:
|
|
|
|
"""Réuni toutes les information pour le contenu d'un bulletin BUT court.
|
|
|
|
On indique le format ("html" ou "pdf") car il y a moins d'infos en HTML.
|
|
|
|
"""
|
2023-08-02 00:13:31 +02:00
|
|
|
bulletins_sem = BulletinBUT(formsemestre)
|
2023-09-01 14:38:41 +02:00
|
|
|
if fmt == "pdf":
|
|
|
|
bul: dict = bulletins_sem.bulletin_etud_complet(etud)
|
2024-01-17 23:52:14 +01:00
|
|
|
filigranne = bul["filigranne"]
|
2023-09-01 14:38:41 +02:00
|
|
|
else: # la même chose avec un peu moins d'infos
|
2023-09-05 15:36:10 +02:00
|
|
|
bul: dict = bulletins_sem.bulletin_etud(etud, force_publishing=True)
|
2024-01-17 23:52:14 +01:00
|
|
|
filigranne = ""
|
2023-09-02 15:53:30 +02:00
|
|
|
decision_ues = (
|
|
|
|
{x["acronyme"]: x for x in bul["semestre"]["decision_ue"]}
|
2023-09-04 06:39:35 +02:00
|
|
|
if "semestre" in bul and "decision_ue" in bul["semestre"]
|
2023-09-02 15:53:30 +02:00
|
|
|
else {}
|
|
|
|
)
|
2023-09-05 15:36:10 +02:00
|
|
|
if "ues" not in bul:
|
2023-09-04 06:39:35 +02:00
|
|
|
raise ScoValueError("Aucune UE à afficher")
|
2023-08-02 00:13:31 +02:00
|
|
|
cursus = cursus_but.EtudCursusBUT(etud, formsemestre.formation)
|
|
|
|
refcomp = formsemestre.formation.referentiel_competence
|
|
|
|
if refcomp is None:
|
|
|
|
raise ScoNoReferentielCompetences(formation=formsemestre.formation)
|
2024-02-20 21:30:08 +01:00
|
|
|
|
|
|
|
warn_html = cursus_but.formsemestre_warning_apc_setup(
|
|
|
|
formsemestre, bulletins_sem.res
|
|
|
|
)
|
|
|
|
if warn_html:
|
2024-05-20 10:46:36 +02:00
|
|
|
raise ScoValueError(
|
|
|
|
"<b>Formation mal configurée pour le BUT</b>" + warn_html, safe=True
|
|
|
|
)
|
2023-08-02 00:13:31 +02:00
|
|
|
ue_validation_by_niveau = validations_view.get_ue_validation_by_niveau(
|
|
|
|
refcomp, etud
|
|
|
|
)
|
|
|
|
ects_total = sum((v.ects() for v in ue_validation_by_niveau.values()))
|
|
|
|
|
|
|
|
logo = find_logo(logoname="header", dept_id=g.scodoc_dept_id)
|
|
|
|
|
2023-09-02 15:53:30 +02:00
|
|
|
ue_acronyms = bul["ues"].keys()
|
2023-08-30 15:59:11 +02:00
|
|
|
args = {
|
|
|
|
"bul": bul,
|
|
|
|
"cursus": cursus,
|
|
|
|
"decision_ues": decision_ues,
|
|
|
|
"ects_total": ects_total,
|
|
|
|
"etud": etud,
|
2024-01-17 23:52:14 +01:00
|
|
|
"filigranne": filigranne,
|
2023-08-30 15:59:11 +02:00
|
|
|
"formsemestre": formsemestre,
|
|
|
|
"logo": logo,
|
2023-10-18 17:53:42 +02:00
|
|
|
"prefs": bulletins_sem.prefs,
|
2023-08-30 15:59:11 +02:00
|
|
|
"title": f"Bul. {etud.nom_disp()} BUT (court)",
|
|
|
|
"ue_validation_by_niveau": ue_validation_by_niveau,
|
2023-09-01 14:38:41 +02:00
|
|
|
"ues_acronyms": [
|
2023-09-02 15:53:30 +02:00
|
|
|
ue.acronyme
|
|
|
|
for ue in bulletins_sem.res.ues
|
|
|
|
if ue.type == UE_STANDARD and ue.acronyme in ue_acronyms
|
2023-09-01 14:38:41 +02:00
|
|
|
],
|
2023-08-30 15:59:11 +02:00
|
|
|
}
|
2024-07-07 22:07:27 +02:00
|
|
|
add_dut120_infos(formsemestre, etud.id, args)
|
2023-12-06 20:04:40 +01:00
|
|
|
return args
|