forked from ScoDoc/ScoDoc
PV jury annuel BUT
This commit is contained in:
parent
372a6e6ed6
commit
e8e27dd964
@ -667,6 +667,30 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
||||
db.session.delete(validation)
|
||||
db.session.flush()
|
||||
|
||||
def get_autorisations_passage(self) -> list[int]:
|
||||
"""Les liste des indices de semestres auxquels on est autorisé à
|
||||
s'inscrire depuis cette année"""
|
||||
formsemestre = self.formsemestre_pair or self.formsemestre_impair
|
||||
if not formsemestre:
|
||||
return []
|
||||
return [
|
||||
a.semestre_id
|
||||
for a in ScolarAutorisationInscription.query.filter_by(
|
||||
etudid=self.etud.id,
|
||||
origin_formsemestre_id=formsemestre.id,
|
||||
)
|
||||
]
|
||||
|
||||
def descr_niveaux_validation(self, line_sep: str = "\n") -> str:
|
||||
"""Description textuelle des niveaux validés (enregistrés)
|
||||
pour PV jurys
|
||||
"""
|
||||
validations = [
|
||||
dec_rcue.descr_validation()
|
||||
for dec_rcue in self.decisions_rcue_by_niveau.values()
|
||||
]
|
||||
return line_sep.join([v for v in validations if v])
|
||||
|
||||
|
||||
class DecisionsProposeesRCUE(DecisionsProposees):
|
||||
"""Liste des codes de décisions que l'on peut proposer pour
|
||||
@ -742,6 +766,21 @@ class DecisionsProposeesRCUE(DecisionsProposees):
|
||||
db.session.delete(validation)
|
||||
db.session.flush()
|
||||
|
||||
def descr_validation(self) -> str:
|
||||
"""Description validation niveau enregistrée, pour PV jury.
|
||||
Si le niveau est validé, done son acronyme, sinon chaine vide.
|
||||
"""
|
||||
if self.code_valide in sco_codes.CODES_RCUE_VALIDES:
|
||||
if (
|
||||
self.rcue and self.rcue.ue_1 and self.rcue.ue_1.niveau_competence
|
||||
): # prudence !
|
||||
niveau_titre = self.rcue.ue_1.niveau_competence.competence.titre or ""
|
||||
ordre = self.rcue.ue_1.niveau_competence.ordre
|
||||
else:
|
||||
return "?" # oups ?
|
||||
return f"{niveau_titre} niv. {ordre}"
|
||||
return ""
|
||||
|
||||
|
||||
class DecisionsProposeesUE(DecisionsProposees):
|
||||
"""Décisions de jury sur une UE du BUT
|
||||
@ -859,6 +898,14 @@ class DecisionsProposeesUE(DecisionsProposees):
|
||||
db.session.delete(validation)
|
||||
db.session.flush()
|
||||
|
||||
def descr_validation(self) -> str:
|
||||
"""Description validation niveau enregistrée, pour PV jury.
|
||||
Si l'UE est validé, done son acronyme, sinon chaine vide.
|
||||
"""
|
||||
if self.code_valide in sco_codes.CODES_UE_VALIDES:
|
||||
return f"{self.ue.acronyme}"
|
||||
return ""
|
||||
|
||||
|
||||
class BUTCursusEtud: # WIP TODO
|
||||
"""Validation du cursus d'un étudiant"""
|
||||
|
106
app/but/jury_but_pv.py
Normal file
106
app/but/jury_but_pv.py
Normal file
@ -0,0 +1,106 @@
|
||||
##############################################################################
|
||||
# ScoDoc
|
||||
# Copyright (c) 1999 - 2022 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.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)
|
||||
indices = [
|
||||
ins.formsemestre.semestre_id
|
||||
for ins in etud.formsemestre_inscriptions
|
||||
if ins.formsemestre.formation.is_apc()
|
||||
]
|
||||
return ", ".join(f"S{indice}" for indice in indices)
|
||||
|
||||
|
||||
def pvjury_table_but(formsemestre_id: int, format="html") -> list[dict]:
|
||||
"""Page récapitulant les décisions de jury BUT
|
||||
formsemestre peut être pair ou impair
|
||||
"""
|
||||
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||
assert formsemestre.formation.is_apc()
|
||||
title = "Jury BUT annuel"
|
||||
|
||||
if format == "html":
|
||||
line_sep = "<br/>"
|
||||
else:
|
||||
line_sep = "\n"
|
||||
# remplace pour le BUT la fonction sco_pvjury.pvjury_table
|
||||
annee_but = (formsemestre.semestre_id + 1) // 2
|
||||
titles = {
|
||||
"nom": "Nom",
|
||||
"cursus": "Cursus",
|
||||
"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 = []
|
||||
for etudid in formsemestre.etuds_inscriptions:
|
||||
etud: Identite = Identite.query.get(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.etat_civil_pv(line_sep=line_sep),
|
||||
"cursus": _descr_cursus_but(etud),
|
||||
"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()]),
|
||||
}
|
||||
|
||||
rows.append(row)
|
||||
|
||||
# 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(
|
||||
columns_ids=titles.keys(),
|
||||
rows=rows,
|
||||
titles=titles,
|
||||
origin=f"Généré par {scu.sco_version.SCONAME} le {scu.timedate_human_repr()}",
|
||||
caption=title,
|
||||
html_caption=title,
|
||||
html_class="pvjury_table_but table_leftalign",
|
||||
# html_class_ignore_default=True,
|
||||
html_with_td_classes=True,
|
||||
xls_style_base=xls_style_base,
|
||||
base_url=f"{request.base_url}?formsemestre_id={formsemestre_id}",
|
||||
page_title=title,
|
||||
html_title=f"<h2>{title}</h2>",
|
||||
pdf_title=title,
|
||||
preferences=sco_preferences.SemPreferences(),
|
||||
table_id="formation_table_recap",
|
||||
)
|
||||
return tab.make_page(format=format, javascripts=[])
|
@ -98,7 +98,16 @@ def formsemestre_saisie_jury_but(
|
||||
]
|
||||
if mode == "recap":
|
||||
H.append(
|
||||
"""<h3>Décisions de jury enregistrées pour les étudiants de ce semestre</h3>"""
|
||||
f"""<h3>Décisions de jury enregistrées pour les étudiants de ce semestre</h3>
|
||||
<div class="table_jury_but_links">
|
||||
<div>
|
||||
<a href="{url_for(
|
||||
"notes.pvjury_table_but",
|
||||
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre2.id)
|
||||
}" class="stdlink">tableau PV de jury</a>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
)
|
||||
H.append(
|
||||
f"""
|
||||
|
@ -195,7 +195,7 @@ class RegroupementCoherentUE:
|
||||
"Si ce RCUE est ADM, CMP ou ADJ, la validation. Sinon, None"
|
||||
validation = self.query_validations().first()
|
||||
if (validation is not None) and (
|
||||
validation.code in {sco_codes.ADM, sco_codes.ADJ, sco_codes.CMP}
|
||||
validation.code in sco_codes.CODES_RCUE_VALIDES
|
||||
):
|
||||
return validation
|
||||
return None
|
||||
|
@ -365,6 +365,15 @@ class Identite(db.Model):
|
||||
|
||||
return situation
|
||||
|
||||
def etat_civil_pv(self, line_sep="\n") -> str:
|
||||
"""Présentation, pour PV jury
|
||||
M. Pierre Dupont
|
||||
n° 12345678
|
||||
né(e) le 7/06/1974
|
||||
à Paris
|
||||
"""
|
||||
return f"""{self.nomprenom}{line_sep}n°{self.code_nip or ""}{line_sep}né{self.e} le {self.date_naissance.strftime("%d/%m/%Y") if self.date_naissance else ""}{line_sep}à {self.lieu_naissance or ""}"""
|
||||
|
||||
def photo_html(self, title=None, size="small") -> str:
|
||||
"""HTML img tag for the photo, either in small size (h90)
|
||||
or original size (size=="orig")
|
||||
|
@ -127,6 +127,7 @@ class GenTable(object):
|
||||
filename="table", # filename, without extension
|
||||
xls_sheet_name="feuille",
|
||||
xls_before_table=[], # liste de cellules a placer avant la table
|
||||
xls_style_base=None, # style excel pour les cellules
|
||||
pdf_title="", # au dessus du tableau en pdf
|
||||
pdf_table_style=None,
|
||||
pdf_col_widths=None,
|
||||
@ -151,6 +152,7 @@ class GenTable(object):
|
||||
self.page_title = page_title
|
||||
self.pdf_link = pdf_link
|
||||
self.xls_link = xls_link
|
||||
self.xls_style_base = xls_style_base
|
||||
self.xml_link = xml_link
|
||||
# HTML parameters:
|
||||
if not table_id: # random id
|
||||
@ -495,7 +497,8 @@ class GenTable(object):
|
||||
sheet = wb.create_sheet(sheet_name=self.xls_sheet_name)
|
||||
sheet.rows += self.xls_before_table
|
||||
style_bold = sco_excel.excel_make_style(bold=True)
|
||||
style_base = sco_excel.excel_make_style()
|
||||
style_base = self.xls_style_base or sco_excel.excel_make_style()
|
||||
|
||||
sheet.append_row(sheet.make_row(self.get_titles_list(), style_bold))
|
||||
for line in self.get_data_list(xls_mode=True):
|
||||
sheet.append_row(sheet.make_row(line, style_base))
|
||||
|
@ -189,7 +189,7 @@ CODES_SEM_ATTENTES = {ATT: True, ATB: True, ATJ: True} # semestre en attente
|
||||
CODES_SEM_REO = {NAR: 1} # reorientation
|
||||
|
||||
CODES_UE_VALIDES = {ADM: True, CMP: True, ADJ: True} # UE validée
|
||||
|
||||
CODES_RCUE_VALIDES = CODES_UE_VALIDES # Niveau RCUE validé
|
||||
# Pour le BUT:
|
||||
CODES_ANNEE_ARRET = {DEF, DEM, ABAN, ABL}
|
||||
CODES_RCUE = {ADM, AJ, CMP}
|
||||
|
@ -59,7 +59,7 @@ class COLORS(Enum):
|
||||
LIGHT_YELLOW = "FFFFFF99"
|
||||
|
||||
|
||||
# Un style est enregistré comme un dictionnaire qui précise la valeur d'un attributdans la liste suivante:
|
||||
# Un style est enregistré comme un dictionnaire qui précise la valeur d'un attribut dans la liste suivante:
|
||||
# font, border, number_format, fill,...
|
||||
# (cf https://openpyxl.readthedocs.io/en/stable/styles.html#working-with-styles)
|
||||
|
||||
@ -288,7 +288,7 @@ class ScoExcelSheet:
|
||||
value -- contenu de la cellule (texte, numérique, booléen ou date)
|
||||
style -- style par défaut (dictionnaire cf. excel_make_style) de la feuille si non spécifié
|
||||
"""
|
||||
# adapatation des valeurs si nécessaire
|
||||
# adaptation des valeurs si nécessaire
|
||||
if value is None:
|
||||
value = ""
|
||||
elif value is True:
|
||||
|
@ -42,6 +42,7 @@ from flask_login import current_user
|
||||
|
||||
from app.but import jury_but, jury_but_validation_auto
|
||||
from app.but.forms import jury_but_forms
|
||||
from app.but import jury_but_pv
|
||||
from app.but import jury_but_view
|
||||
from app.comp import res_sem
|
||||
from app.comp.res_but import ResultatsSemestreBUT
|
||||
@ -2564,6 +2565,8 @@ def formsemestre_validation_suppress_etud(
|
||||
# ------------- PV de JURY et archives
|
||||
sco_publish("/formsemestre_pvjury", sco_pvjury.formsemestre_pvjury, Permission.ScoView)
|
||||
|
||||
sco_publish("/pvjury_table_but", jury_but_pv.pvjury_table_but, Permission.ScoView)
|
||||
|
||||
|
||||
@bp.route("/formsemestre_saisie_jury")
|
||||
@scodoc
|
||||
|
Loading…
Reference in New Issue
Block a user