From 5bc4b47e1e5f6743fe53321f3f5cdfb9b06f1aa6 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Fri, 8 Jul 2022 23:58:27 +0200 Subject: [PATCH] =?UTF-8?q?Lettres=20de=20d=C3=A9cisions=20jury=20BUT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/but/jury_but_recap.py | 11 ++++- app/models/but_validations.py | 11 +++++ app/scodoc/notesdb.py | 4 +- app/scodoc/sco_bulletins.py | 12 ++---- app/scodoc/sco_edit_formation.py | 24 ++++++----- app/scodoc/sco_pvpdf.py | 71 ++++++++++++++++++++------------ 6 files changed, 84 insertions(+), 49 deletions(-) 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 = []