forked from ScoDoc/ScoDoc
177 lines
6.4 KiB
Python
177 lines
6.4 KiB
Python
##############################################################################
|
|
# ScoDoc
|
|
# Copyright (c) 1999 - 2023 Emmanuel Viennet. All rights reserved.
|
|
# See LICENSE
|
|
##############################################################################
|
|
|
|
"""Jury BUT: table synthèse résultats semestre / PV
|
|
"""
|
|
from flask import g, request, url_for
|
|
|
|
from openpyxl.styles import Font, Border, Side, Alignment, PatternFill
|
|
|
|
from app import log
|
|
from app.but import jury_but
|
|
from app.but.cursus_but import but_ects_valides
|
|
from app.models.etudiants import Identite
|
|
from app.models.formsemestre import FormSemestre
|
|
from app.scodoc.gen_tables import GenTable
|
|
from app.scodoc import sco_excel
|
|
from app.scodoc.sco_exceptions import ScoValueError
|
|
from app.scodoc import sco_preferences
|
|
from app.scodoc import sco_utils as scu
|
|
|
|
|
|
def _descr_cursus_but(etud: Identite) -> str:
|
|
"description de la liste des semestres BUT suivis"
|
|
# prend simplement tous les semestre de type APC, ce qui sera faux si
|
|
# l'étudiant change de spécialité au sein du même département
|
|
# (ce qui ne peut normalement pas se produire)
|
|
inscriptions = sorted(
|
|
[
|
|
ins
|
|
for ins in etud.formsemestre_inscriptions
|
|
if ins.formsemestre.formation.is_apc()
|
|
],
|
|
key=lambda i: i.formsemestre.date_debut,
|
|
)
|
|
indices = [
|
|
ins.formsemestre.semestre_id if ins.formsemestre.semestre_id is not None else -1
|
|
for ins in inscriptions
|
|
]
|
|
|
|
return ", ".join(f"S{indice}" for indice in indices)
|
|
|
|
|
|
def pvjury_page_but(formsemestre_id: int, fmt="html"):
|
|
"""Page récapitulant les décisions de jury BUT
|
|
formsemestre peut être pair ou impair
|
|
"""
|
|
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
|
assert formsemestre.formation.is_apc()
|
|
title = "Procès-verbal de jury BUT"
|
|
if fmt == "html":
|
|
line_sep = "<br>"
|
|
else:
|
|
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(fmt=fmt, javascripts=["js/etud_info.js"], init_qtip=True)
|
|
|
|
|
|
def pvjury_table_but(
|
|
formsemestre: FormSemestre,
|
|
etudids: list[int] = None,
|
|
line_sep: str = "\n",
|
|
only_diplome=False,
|
|
anonymous=False,
|
|
with_paragraph_nom=False,
|
|
) -> tuple[list[dict], dict]:
|
|
"""Table avec résultats jury BUT pour PV.
|
|
Si etudids est None, prend tous les étudiants inscrits.
|
|
"""
|
|
# remplace pour le BUT la fonction sco_pv_forms.pvjury_table
|
|
annee_but = (formsemestre.semestre_id + 1) // 2
|
|
referentiel_competence_id = formsemestre.formation.referentiel_competence_id
|
|
if referentiel_competence_id is None:
|
|
raise ScoValueError(
|
|
"pas de référentiel de compétences associé à la formation de ce semestre !"
|
|
)
|
|
titles = {
|
|
"nom": "Code" if anonymous else "Nom",
|
|
"cursus": "Cursus",
|
|
"ects": "ECTS",
|
|
"ues": "UE validées",
|
|
"niveaux": "Niveaux de compétences validés",
|
|
"decision_but": f"Décision BUT{annee_but}",
|
|
"diplome": "Résultat au diplôme",
|
|
"devenir": "Devenir",
|
|
"observations": "Observations",
|
|
}
|
|
rows = []
|
|
formsemestre_etudids = formsemestre.etuds_inscriptions.keys()
|
|
if etudids is None:
|
|
etudids = formsemestre_etudids
|
|
for etudid in etudids:
|
|
if not etudid in formsemestre_etudids:
|
|
continue # garde fou
|
|
etud = Identite.get_etud(etudid)
|
|
try:
|
|
deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre)
|
|
if deca.annee_but != annee_but: # wtf ?
|
|
log(
|
|
f"pvjury_table_but: inconsistent annee_but {deca.annee_but} != {annee_but}"
|
|
)
|
|
continue
|
|
except ScoValueError:
|
|
deca = None
|
|
|
|
row = {
|
|
"nom": etud.code_ine or etud.code_nip or etud.id
|
|
if anonymous # Mode anonyme: affiche INE ou sinon NIP, ou id
|
|
else etud.etat_civil_pv(
|
|
line_sep=line_sep, with_paragraph=with_paragraph_nom
|
|
),
|
|
"_nom_order": etud.sort_key,
|
|
"_nom_target_attrs": f'class="etudinfo" id="{etud.id}"',
|
|
"_nom_td_attrs": f'id="{etud.id}" class="etudinfo"',
|
|
"_nom_target": url_for(
|
|
"scolar.ficheEtud",
|
|
scodoc_dept=g.scodoc_dept,
|
|
etudid=etud.id,
|
|
),
|
|
"cursus": _descr_cursus_but(etud),
|
|
"ects": f"""{deca.ects_annee():g}<br><br>Tot. {but_ects_valides(etud, referentiel_competence_id ):g}""",
|
|
"ues": deca.descr_ues_validation(line_sep=line_sep) if deca else "-",
|
|
"niveaux": deca.descr_niveaux_validation(line_sep=line_sep)
|
|
if deca
|
|
else "-",
|
|
"decision_but": deca.code_valide if deca else "",
|
|
"devenir": ", ".join([f"S{i}" for i in deca.get_autorisations_passage()])
|
|
if deca
|
|
else "",
|
|
}
|
|
if deca.valide_diplome() or not only_diplome:
|
|
rows.append(row)
|
|
|
|
rows.sort(key=lambda x: x["_nom_order"])
|
|
return rows, titles
|