Lettres de décisions jury BUT

This commit is contained in:
Emmanuel Viennet 2022-07-08 23:58:27 +02:00
parent bf27fcbdc6
commit 5bc4b47e1e
6 changed files with 84 additions and 49 deletions

View File

@ -101,10 +101,17 @@ def formsemestre_saisie_jury_but(
f"""<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 class="table_jury_but_links">
<div> <div>
<a href="{url_for( <ul>
<li><a href="{url_for(
"notes.pvjury_table_but", "notes.pvjury_table_but",
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre2.id) scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre2.id)
}" class="stdlink">tableau PV de jury</a> }" class="stdlink">Tableau PV de jury</a>
</li>
<li><a href="{url_for(
"notes.formsemestre_lettres_individuelles",
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre2.id)
}" class="stdlink">Courriers individuels (classeur pdf)</a>
</li>
</div> </div>
</div> </div>
""" """

View File

@ -322,8 +322,19 @@ def dict_decision_jury(etud: Identite, formsemestre: FormSemestre) -> dict:
etudid=etud.id, formsemestre_id=formsemestre.id etudid=etud.id, formsemestre_id=formsemestre.id
) )
decisions["decision_rcue"] = [v.to_dict_bul() for v in validations_rcues] decisions["decision_rcue"] = [v.to_dict_bul() for v in validations_rcues]
decisions["descr_decisions_rcue"] = ", ".join(
[
f"""{dec_rcue["niveau"]["competence"]["titre"]} {dec_rcue["niveau"]["ordre"]}: {dec_rcue["code"]}"""
for dec_rcue in decisions["decision_rcue"]
]
)
decisions["descr_decisions_niveaux"] = (
"Niveaux de compétences: " + decisions["descr_decisions_rcue"]
)
else: else:
decisions["decision_rcue"] = [] decisions["decision_rcue"] = []
decisions["descr_decisions_rcue"] = ""
decisions["descr_decisions_niveaux"] = ""
# --- Année: prend la validation pour l'année scolaire de ce semestre # --- Année: prend la validation pour l'année scolaire de ce semestre
validation = ( validation = (
ApcValidationAnnee.query.filter_by( ApcValidationAnnee.query.filter_by(

View File

@ -265,9 +265,9 @@ def DBUpdateArgs(cnx, table, vals, where=None, commit=False, convert_empty_to_nu
cursor.execute(req, vals) cursor.execute(req, vals)
# log('req=%s\n'%req) # log('req=%s\n'%req)
# log('vals=%s\n'%vals) # log('vals=%s\n'%vals)
except psycopg2.errors.StringDataRightTruncation: except psycopg2.errors.StringDataRightTruncation as exc:
cnx.rollback() cnx.rollback()
raise ScoValueError("champs de texte trop long !") raise ScoValueError("champs de texte trop long !") from exc
except: except:
cnx.rollback() # get rid of this transaction cnx.rollback() # get rid of this transaction
log('Exception in DBUpdateArgs:\n\treq="%s"\n\tvals="%s"\n' % (req, vals)) log('Exception in DBUpdateArgs:\n\treq="%s"\n\tvals="%s"\n' % (req, vals))

View File

@ -817,15 +817,9 @@ def etud_descr_situation_semestre(
).get("code", "") ).get("code", "")
else: else:
infos["descr_decision_annee"] = "" infos["descr_decision_annee"] = ""
if pv.get("decision_rcue", []):
infos["descr_decisions_rcue"] = "Niveaux de compétences: " + ", ".join( infos["descr_decisions_rcue"] = pv.get("descr_decisions_rcue", "")
[ infos["descr_decisions_niveaux"] = pv.get("descr_decisions_niveaux", "")
f"""{dec_rcue["niveau"]["competence"]["titre"]} {dec_rcue["niveau"]["ordre"]}: {dec_rcue["code"]}"""
for dec_rcue in pv.get("decision_rcue", [])
]
)
else:
infos["descr_decisions_rcue"] = ""
infos["situation"] += " " + dec infos["situation"] += " " + dec
if not pv["validation_parcours"]: # parcours non terminé if not pv["validation_parcours"]: # parcours non terminé

View File

@ -292,21 +292,25 @@ def do_formation_create(args):
def do_formation_edit(args): def do_formation_edit(args):
"edit a formation" "edit a formation"
# log('do_formation_edit( args=%s )'%args)
# On autorise la modif de la formation meme si elle est verrouillee
# car cela ne change que du cosmetique, (sauf eventuellement le code formation ?)
# mais si verrouillée on ne peut changer le type de parcours
if sco_formations.formation_has_locked_sems(args["formation_id"]):
if "type_parcours" in args:
del args["type_parcours"]
# On ne peut jamais supprimer le code formation: # On ne peut jamais supprimer le code formation:
if "formation_code" in args and not args["formation_code"]: if "formation_code" in args and not args["formation_code"]:
del args["formation_code"] del args["formation_code"]
cnx = ndb.GetDBConnexion() formation: Formation = Formation.query.get_or_404(args["formation_id"])
sco_formations._formationEditor.edit(cnx, args) # On autorise la modif de la formation meme si elle est verrouillee
formation: Formation = Formation.query.get(args["formation_id"]) # car cela ne change que du cosmetique, (sauf eventuellement le code formation ?)
# mais si verrouillée on ne peut changer le type de parcours
if formation.has_locked_sems():
if "type_parcours" in args:
del args["type_parcours"]
for field in formation.__dict__:
if field and field[0] != "_" and field in args:
setattr(formation, field, args[field])
db.session.add(formation)
db.session.commit()
formation.invalidate_cached_sems() formation.invalidate_cached_sems()

View File

@ -43,13 +43,12 @@ from reportlab.lib import styles
from reportlab.lib.colors import Color from reportlab.lib.colors import Color
from flask import g from flask import g
from app.models.formsemestre import FormSemestre from app.models import FormSemestre, Identite
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app.scodoc import sco_bulletins_pdf from app.scodoc import sco_bulletins_pdf
from app.scodoc import sco_codes_parcours from app.scodoc import sco_codes_parcours
from app.scodoc import sco_etud from app.scodoc import sco_etud
from app.scodoc import sco_formsemestre
from app.scodoc import sco_pdf from app.scodoc import sco_pdf
from app.scodoc import sco_preferences from app.scodoc import sco_preferences
from app.scodoc.sco_logos import find_logo from app.scodoc.sco_logos import find_logo
@ -389,7 +388,7 @@ def pdf_lettres_individuelles(
etuds = [x["identite"] for x in dpv["decisions"]] etuds = [x["identite"] for x in dpv["decisions"]]
sco_etud.fill_etuds_info(etuds) sco_etud.fill_etuds_info(etuds)
# #
sem = sco_formsemestre.get_formsemestre(formsemestre_id) formsemestre: FormSemestre = FormSemestre.query.get(formsemestre_id)
prefs = sco_preferences.SemPreferences(formsemestre_id) prefs = sco_preferences.SemPreferences(formsemestre_id)
params = { params = {
"date_jury": date_jury, "date_jury": date_jury,
@ -400,18 +399,22 @@ def pdf_lettres_individuelles(
} }
# copie preferences # copie preferences
for name in sco_preferences.get_base_preferences().prefs_name: for name in sco_preferences.get_base_preferences().prefs_name:
params[name] = sco_preferences.get_preference(name, sem["formsemestre_id"]) params[name] = sco_preferences.get_preference(name, formsemestre_id)
bookmarks = {} bookmarks = {}
objects = [] # list of PLATYPUS objects objects = [] # list of PLATYPUS objects
npages = 0 npages = 0
for e in dpv["decisions"]: for decision in dpv["decisions"]:
if e["decision_sem"]: # decision prise if (
etud = sco_etud.get_etud_info(e["identite"]["etudid"], filled=True)[0] decision["decision_sem"]
params["nomEtud"] = etud["nomprenom"] or decision.get("decision_annee")
bookmarks[npages + 1] = scu.suppress_accents(etud["nomprenom"]) or decision.get("decision_rcue")
): # decision prise
etud: Identite = Identite.query.get(decision["identite"]["etudid"])
params["nomEtud"] = etud.nomprenom
bookmarks[npages + 1] = scu.suppress_accents(etud.nomprenom)
objects += pdf_lettre_individuelle( objects += pdf_lettre_individuelle(
dpv["formsemestre"], e, etud, params, signature dpv["formsemestre"], decision, etud, params, signature
) )
objects.append(PageBreak()) objects.append(PageBreak())
npages += 1 npages += 1
@ -432,7 +435,7 @@ def pdf_lettres_individuelles(
CourrierIndividuelTemplate( CourrierIndividuelTemplate(
document, document,
author=f"{sco_version.SCONAME} {sco_version.SCOVERSION} (E. Viennet)", author=f"{sco_version.SCONAME} {sco_version.SCOVERSION} (E. Viennet)",
title=f"Lettres décision {sem['titreannee']}", title=f"Lettres décision {formsemestre.titre_annee()}",
subject="Décision jury", subject="Décision jury",
margins=margins, margins=margins,
pagesbookmarks=bookmarks, pagesbookmarks=bookmarks,
@ -445,17 +448,22 @@ def pdf_lettres_individuelles(
return data return data
def _descr_jury(sem, diplome): def _descr_jury(formsemestre: FormSemestre, diplome):
if not diplome: if not diplome:
t = f"""passage de Semestre {sem["semestre_id"]} en Semestre {sem["semestre_id"] + 1}""" if formsemestre.formation.is_apc():
s = "passage de semestre" t = f"""BUT{(formsemestre.semestre_id+1)//2}"""
s = t
else:
t = f"""passage de Semestre {formsemestre.semestre_id} en Semestre {formsemestre.semestre_id + 1}"""
s = "passage de semestre"
else: else:
t = "délivrance du diplôme" t = "délivrance du diplôme"
s = t s = t
return t, s # titre long, titre court return t, s # titre long, titre court
def pdf_lettre_individuelle(sem, decision, etud, params, signature=None): def pdf_lettre_individuelle(sem, decision, etud: Identite, params, signature=None):
""" """
Renvoie une liste d'objets PLATYPUS pour intégration Renvoie une liste d'objets PLATYPUS pour intégration
dans un autre document. dans un autre document.
@ -464,7 +472,9 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None):
formsemestre_id = sem["formsemestre_id"] formsemestre_id = sem["formsemestre_id"]
formsemestre = FormSemestre.query.get(formsemestre_id) formsemestre = FormSemestre.query.get(formsemestre_id)
Se: SituationEtudCursus = decision["Se"] Se: SituationEtudCursus = decision["Se"]
t, s = _descr_jury(sem, Se.parcours_validated() or not Se.semestre_non_terminal) t, s = _descr_jury(
formsemestre, Se.parcours_validated() or not Se.semestre_non_terminal
)
objects = [] objects = []
style = reportlab.lib.styles.ParagraphStyle({}) style = reportlab.lib.styles.ParagraphStyle({})
style.fontSize = 14 style.fontSize = 14
@ -492,13 +502,6 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None):
params["prev_decision_sem_txt"] = "" params["prev_decision_sem_txt"] = ""
params["decision_orig"] = "" params["decision_orig"] = ""
if formsemestre.formation.is_apc():
# ajout champs spécifiques PV BUT
add_apc_infos(formsemestre, params, decision)
else:
# ajout champs spécifiques PV DUT
add_classic_infos(formsemestre, params, decision)
params.update(decision["identite"]) params.update(decision["identite"])
# fix domicile # fix domicile
if params["domicile"]: if params["domicile"]:
@ -530,7 +533,7 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None):
params[ params[
"autorisations_txt" "autorisations_txt"
] = """Vous êtes autorisé%s à continuer dans le%s semestre%s : <b>%s</b>""" % ( ] = """Vous êtes autorisé%s à continuer dans le%s semestre%s : <b>%s</b>""" % (
etud["ne"], etud.e,
s, s,
s, s,
decision["autorisations_descr"], decision["autorisations_descr"],
@ -545,6 +548,14 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None):
else: else:
params["diplome_txt"] = "" params["diplome_txt"] = ""
# Les fonctions ci-dessous ajoutent ou modifient des champs:
if formsemestre.formation.is_apc():
# ajout champs spécifiques PV BUT
add_apc_infos(formsemestre, params, decision)
else:
# ajout champs spécifiques PV DUT
add_classic_infos(formsemestre, params, decision)
# Corps de la lettre: # Corps de la lettre:
objects += sco_bulletins_pdf.process_field( objects += sco_bulletins_pdf.process_field(
sco_preferences.get_preference("PV_LETTER_TEMPLATE", sem["formsemestre_id"]), sco_preferences.get_preference("PV_LETTER_TEMPLATE", sem["formsemestre_id"]),
@ -615,7 +626,14 @@ def add_classic_infos(formsemestre: FormSemestre, params: dict, decision: dict):
def add_apc_infos(formsemestre: FormSemestre, params: dict, decision: dict): def add_apc_infos(formsemestre: FormSemestre, params: dict, decision: dict):
"""Ajoute les champs pour les formations APC (BUT), donc avec codes RCUE et année""" """Ajoute les champs pour les formations APC (BUT), donc avec codes RCUE et année"""
pass # TODO XXX annee_but = (formsemestre.semestre_id + 1) // 2
params["decision_orig"] = f"année BUT{annee_but}"
params["decision_sem_descr"] = decision.get("decision_annee", {}).get("code", "")
params[
"decision_ue_txt"
] = f"""{params["decision_ue_txt"]}<br/>
<b>Niveaux de compétences:</b><br/> {decision.get("descr_decisions_rcue", "")}
"""
# ---------------------------------------------- # ----------------------------------------------
@ -715,7 +733,8 @@ def _pvjury_pdf_type(
sem = dpv["formsemestre"] sem = dpv["formsemestre"]
formsemestre_id = sem["formsemestre_id"] formsemestre_id = sem["formsemestre_id"]
titre_jury, _ = _descr_jury(sem, diplome) formsemestre: FormSemestre = FormSemestre.query.get(formsemestre_id)
titre_jury, _ = _descr_jury(formsemestre, diplome)
titre_diplome = pv_title or dpv["formation"]["titre_officiel"] titre_diplome = pv_title or dpv["formation"]["titre_officiel"]
objects = [] objects = []