diff --git a/app/but/jury_but_recap.py b/app/but/jury_but_recap.py
index 7d47cbe5..427c2d0f 100644
--- a/app/but/jury_but_recap.py
+++ b/app/but/jury_but_recap.py
@@ -101,10 +101,17 @@ def formsemestre_saisie_jury_but(
f"""
Décisions de jury enregistrées pour les étudiants de ce semestre
"""
diff --git a/app/models/but_validations.py b/app/models/but_validations.py
index 71b5f883..7213af3c 100644
--- a/app/models/but_validations.py
+++ b/app/models/but_validations.py
@@ -322,8 +322,19 @@ def dict_decision_jury(etud: Identite, formsemestre: FormSemestre) -> dict:
etudid=etud.id, formsemestre_id=formsemestre.id
)
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:
decisions["decision_rcue"] = []
+ decisions["descr_decisions_rcue"] = ""
+ decisions["descr_decisions_niveaux"] = ""
# --- Année: prend la validation pour l'année scolaire de ce semestre
validation = (
ApcValidationAnnee.query.filter_by(
diff --git a/app/scodoc/notesdb.py b/app/scodoc/notesdb.py
index 3de5c281..7ad7896a 100644
--- a/app/scodoc/notesdb.py
+++ b/app/scodoc/notesdb.py
@@ -265,9 +265,9 @@ def DBUpdateArgs(cnx, table, vals, where=None, commit=False, convert_empty_to_nu
cursor.execute(req, vals)
# log('req=%s\n'%req)
# log('vals=%s\n'%vals)
- except psycopg2.errors.StringDataRightTruncation:
+ except psycopg2.errors.StringDataRightTruncation as exc:
cnx.rollback()
- raise ScoValueError("champs de texte trop long !")
+ raise ScoValueError("champs de texte trop long !") from exc
except:
cnx.rollback() # get rid of this transaction
log('Exception in DBUpdateArgs:\n\treq="%s"\n\tvals="%s"\n' % (req, vals))
diff --git a/app/scodoc/sco_bulletins.py b/app/scodoc/sco_bulletins.py
index f737c4ee..83a51293 100644
--- a/app/scodoc/sco_bulletins.py
+++ b/app/scodoc/sco_bulletins.py
@@ -817,15 +817,9 @@ def etud_descr_situation_semestre(
).get("code", "")
else:
infos["descr_decision_annee"] = ""
- if pv.get("decision_rcue", []):
- infos["descr_decisions_rcue"] = "Niveaux de compétences: " + ", ".join(
- [
- 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["descr_decisions_rcue"] = pv.get("descr_decisions_rcue", "")
+ infos["descr_decisions_niveaux"] = pv.get("descr_decisions_niveaux", "")
infos["situation"] += " " + dec
if not pv["validation_parcours"]: # parcours non terminé
diff --git a/app/scodoc/sco_edit_formation.py b/app/scodoc/sco_edit_formation.py
index 62fc2bbf..d7ea5e97 100644
--- a/app/scodoc/sco_edit_formation.py
+++ b/app/scodoc/sco_edit_formation.py
@@ -292,21 +292,25 @@ def do_formation_create(args):
def do_formation_edit(args):
"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:
if "formation_code" in args and not args["formation_code"]:
del args["formation_code"]
- cnx = ndb.GetDBConnexion()
- sco_formations._formationEditor.edit(cnx, args)
- formation: Formation = Formation.query.get(args["formation_id"])
+ formation: Formation = Formation.query.get_or_404(args["formation_id"])
+ # 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 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()
diff --git a/app/scodoc/sco_pvpdf.py b/app/scodoc/sco_pvpdf.py
index dba7801b..ebfaefcf 100644
--- a/app/scodoc/sco_pvpdf.py
+++ b/app/scodoc/sco_pvpdf.py
@@ -43,13 +43,12 @@ from reportlab.lib import styles
from reportlab.lib.colors import Color
from flask import g
-from app.models.formsemestre import FormSemestre
+from app.models import FormSemestre, Identite
import app.scodoc.sco_utils as scu
from app.scodoc import sco_bulletins_pdf
from app.scodoc import sco_codes_parcours
from app.scodoc import sco_etud
-from app.scodoc import sco_formsemestre
from app.scodoc import sco_pdf
from app.scodoc import sco_preferences
from app.scodoc.sco_logos import find_logo
@@ -389,7 +388,7 @@ def pdf_lettres_individuelles(
etuds = [x["identite"] for x in dpv["decisions"]]
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)
params = {
"date_jury": date_jury,
@@ -400,18 +399,22 @@ def pdf_lettres_individuelles(
}
# copie preferences
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 = {}
objects = [] # list of PLATYPUS objects
npages = 0
- for e in dpv["decisions"]:
- if e["decision_sem"]: # decision prise
- etud = sco_etud.get_etud_info(e["identite"]["etudid"], filled=True)[0]
- params["nomEtud"] = etud["nomprenom"]
- bookmarks[npages + 1] = scu.suppress_accents(etud["nomprenom"])
+ for decision in dpv["decisions"]:
+ if (
+ decision["decision_sem"]
+ or decision.get("decision_annee")
+ 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(
- dpv["formsemestre"], e, etud, params, signature
+ dpv["formsemestre"], decision, etud, params, signature
)
objects.append(PageBreak())
npages += 1
@@ -432,7 +435,7 @@ def pdf_lettres_individuelles(
CourrierIndividuelTemplate(
document,
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",
margins=margins,
pagesbookmarks=bookmarks,
@@ -445,17 +448,22 @@ def pdf_lettres_individuelles(
return data
-def _descr_jury(sem, diplome):
+def _descr_jury(formsemestre: FormSemestre, diplome):
+
if not diplome:
- t = f"""passage de Semestre {sem["semestre_id"]} en Semestre {sem["semestre_id"] + 1}"""
- s = "passage de semestre"
+ if formsemestre.formation.is_apc():
+ 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:
t = "délivrance du diplôme"
s = t
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
dans un autre document.
@@ -464,7 +472,9 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None):
formsemestre_id = sem["formsemestre_id"]
formsemestre = FormSemestre.query.get(formsemestre_id)
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 = []
style = reportlab.lib.styles.ParagraphStyle({})
style.fontSize = 14
@@ -492,13 +502,6 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None):
params["prev_decision_sem_txt"] = ""
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"])
# fix domicile
if params["domicile"]:
@@ -530,7 +533,7 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None):
params[
"autorisations_txt"
] = """Vous êtes autorisé%s à continuer dans le%s semestre%s : %s""" % (
- etud["ne"],
+ etud.e,
s,
s,
decision["autorisations_descr"],
@@ -545,6 +548,14 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None):
else:
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:
objects += sco_bulletins_pdf.process_field(
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):
"""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"]}
+ Niveaux de compétences:
{decision.get("descr_decisions_rcue", "")}
+ """
# ----------------------------------------------
@@ -715,7 +733,8 @@ def _pvjury_pdf_type(
sem = dpv["formsemestre"]
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"]
objects = []