From 464b51245ad2d624a0e1fcdfb9e64b0e46a75491 Mon Sep 17 00:00:00 2001 From: jmpla Date: Mon, 13 Mar 2023 06:39:36 +0100 Subject: [PATCH] =?UTF-8?q?Ajout=20=C3=A9tat-civil?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/but/bulletin_but.py | 1 + app/models/etudiants.py | 30 ++++++++++++++- app/scodoc/sco_bulletins_generator.py | 5 ++- app/scodoc/sco_etud.py | 13 +++++++ app/scodoc/sco_import_etuds.py | 2 + app/scodoc/sco_page_etud.py | 37 ++++++++++++------- app/views/scolar.py | 23 ++++++++++++ ...ca6f6_ajout_prenom_civilite__etat_civil.py | 33 +++++++++++++++++ tools/format_import_etudiants.txt | 2 + 9 files changed, 129 insertions(+), 17 deletions(-) create mode 100644 migrations/versions/cf29790ca6f6_ajout_prenom_civilite__etat_civil.py diff --git a/app/but/bulletin_but.py b/app/but/bulletin_but.py index 481393c5..eb71373f 100644 --- a/app/but/bulletin_but.py +++ b/app/but/bulletin_but.py @@ -484,6 +484,7 @@ class BulletinBUT: d["etudid"] = etud.id d["etud"] = d["etudiant"] d["etud"]["nomprenom"] = etud.nomprenom + d["etud"]["etat_civil"] = etud.etat_civil d.update(self.res.sem) etud_etat = self.res.get_etud_etat(etud.id) d["filigranne"] = sco_bulletins_pdf.get_filigranne( diff --git a/app/models/etudiants.py b/app/models/etudiants.py index e4b2e5bb..fb98e98b 100644 --- a/app/models/etudiants.py +++ b/app/models/etudiants.py @@ -30,6 +30,7 @@ class Identite(db.Model): db.UniqueConstraint("dept_id", "code_nip"), db.UniqueConstraint("dept_id", "code_ine"), db.CheckConstraint("civilite IN ('M', 'F', 'X')"), + db.CheckConstraint("civilite_etat_civil IN ('M', 'F', 'X')"), ) id = db.Column(db.Integer, primary_key=True) @@ -41,6 +42,12 @@ class Identite(db.Model): nom_usuel = db.Column(db.Text()) "optionnel (si present, affiché à la place du nom)" civilite = db.Column(db.String(1), nullable=False) + + # données d'état-civil. Si présent remplace les données d'usage dans les documents officiels (bulletins, PV) + # cf nomprenom_etat_civil() + civilite_etat_civil = db.Column(db.String(1), nullable=False, server_default="X") + prenom_etat_civil = db.Column(db.Text(), nullable=True) + date_naissance = db.Column(db.Date) lieu_naissance = db.Column(db.Text()) dept_naissance = db.Column(db.Text()) @@ -104,6 +111,13 @@ class Identite(db.Model): """ return {"M": "M.", "F": "Mme", "X": ""}[self.civilite] + @property + def civilite_etat_civil_str(self): + """returns 'M.' ou 'Mme' ou '' (pour le genre neutre, + personnes ne souhaitant pas d'affichage). + """ + return {"M": "M.", "F": "Mme", "X": ""}[self.civilite_etat_civil] + def sex_nom(self, no_accents=False) -> str: "'M. DUPONTÉ', ou si no_accents, 'M. DUPONTE'" s = f"{self.civilite_str} {(self.nom_usuel or self.nom).upper()}" @@ -150,6 +164,14 @@ class Identite(db.Model): r.append("-".join([x.lower().capitalize() for x in fields])) return " ".join(r) + @property + def etat_civil(self): + if self.prenom_etat_civil: + civ = {"M": "M.", "F": "Mme", "X": ""}[self.civilite_etat_civil] + return f"{civ} {self.prenom_etat_civil} {self.nom}" + else: + return self.nomprenom + @property def nom_short(self): "Nom et début du prénom pour table recap: 'DUPONT Pi.'" @@ -191,6 +213,8 @@ class Identite(db.Model): "nom_usuel": self.nom_usuel, "prenom": self.prenom, "sort_key": self.sort_key, + "civilite_etat_civil": self.civilite_etat_civil, + "prenom_etat_civil": self.prenom_etat_civil, } def to_dict_scodoc7(self) -> dict: @@ -234,6 +258,8 @@ class Identite(db.Model): "dept_naissance": self.dept_naissance or "", "nationalite": self.nationalite or "", "boursier": self.boursier or "", + "civilite_etat_civil": self.civilite_etat_civil, + "prenom_etat_civil": self.prenom_etat_civil, } if include_urls and has_request_context(): # test request context so we can use this func in tests under the flask shell @@ -450,10 +476,10 @@ class Identite(db.Model): M. Pierre Dupont """ if with_paragraph: - return f"""{self.nomprenom}{line_sep}n°{self.code_nip or ""}{line_sep}né{self.e} le { + return f"""{self.etat_civil}{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 ""}""" - return self.nomprenom + return self.etat_civil def photo_html(self, title=None, size="small") -> str: """HTML img tag for the photo, either in small size (h90) diff --git a/app/scodoc/sco_bulletins_generator.py b/app/scodoc/sco_bulletins_generator.py index ec5d258a..b122d7a4 100644 --- a/app/scodoc/sco_bulletins_generator.py +++ b/app/scodoc/sco_bulletins_generator.py @@ -167,8 +167,9 @@ class BulletinGenerator: formsemestre_id = self.bul_dict["formsemestre_id"] nomprenom = self.bul_dict["etud"]["nomprenom"] + etat_civil = self.bul_dict["etud"]["etat_civil"] marque_debut_bulletin = sco_pdf.DebutBulletin( - nomprenom, + self.bul_dict["etat_civil"], filigranne=self.bul_dict["filigranne"], footer_content=f"""ScoDoc - Bulletin de {nomprenom} - {time.strftime("%d/%m/%Y %H:%M")}""", ) @@ -211,7 +212,7 @@ class BulletinGenerator: document, author="%s %s (E. Viennet) [%s]" % (sco_version.SCONAME, sco_version.SCOVERSION, self.description), - title=f"""Bulletin {sem["titremois"]} de {nomprenom}""", + title=f"""Bulletin {sem["titremois"]} de {etat_civil}""", subject="Bulletin de note", margins=self.margins, server_name=self.server_name, diff --git a/app/scodoc/sco_etud.py b/app/scodoc/sco_etud.py index 5a2313fa..70b7b163 100644 --- a/app/scodoc/sco_etud.py +++ b/app/scodoc/sco_etud.py @@ -57,7 +57,12 @@ def format_etud_ident(etud): else: etud["nom_usuel"] = "" etud["prenom"] = format_prenom(etud["prenom"]) + if "prenom_etat_civil" in etud: + etud["prenom_etat_civil"] = format_prenom(etud["prenom_etat_civil"]) + else: + etud["prenom_etat_civil"] = "" etud["civilite_str"] = format_civilite(etud["civilite"]) + etud["civilite_etat_civil_str"] = format_civilite(etud["civilite_etat_civil"]) # Nom à afficher: if etud["nom_usuel"]: etud["nom_disp"] = etud["nom_usuel"] @@ -225,7 +230,12 @@ _identiteEditor = ndb.EditableTable( "nom", "nom_usuel", "prenom", + "prenom_etat_civil", + "cas_id", + "cas_allow_login", + "cas_allow_scodoc_login", "civilite", # 'M", "F", or "X" + "civilite_etat_civil", "date_naissance", "lieu_naissance", "dept_naissance", @@ -242,7 +252,9 @@ _identiteEditor = ndb.EditableTable( input_formators={ "nom": force_uppercase, "prenom": force_uppercase, + "prenom_etat_civil": force_uppercase, "civilite": input_civilite, + "civilite_etat_civil": input_civilite, "date_naissance": ndb.DateDMYtoISO, "boursier": bool, }, @@ -263,6 +275,7 @@ def identite_list(cnx, *a, **kw): else: o["annee_naissance"] = o["date_naissance"] o["civilite_str"] = format_civilite(o["civilite"]) + o["civilite_etat_civil_str"] = format_civilite(o["civilite_etat_civil"]) return objs diff --git a/app/scodoc/sco_import_etuds.py b/app/scodoc/sco_import_etuds.py index 110d95d8..2d67c08c 100644 --- a/app/scodoc/sco_import_etuds.py +++ b/app/scodoc/sco_import_etuds.py @@ -71,6 +71,8 @@ FORMAT_FILE = "format_import_etudiants.txt" ADMISSION_MODIFIABLE_FIELDS = ( "code_nip", "code_ine", + "prenom_etat_civil", + "civilite_etat_civil", "date_naissance", "lieu_naissance", "bac", diff --git a/app/scodoc/sco_page_etud.py b/app/scodoc/sco_page_etud.py index 6ac2b4bc..b6a3592d 100644 --- a/app/scodoc/sco_page_etud.py +++ b/app/scodoc/sco_page_etud.py @@ -176,6 +176,18 @@ def ficheEtud(etudid=None): sco_etud.fill_etuds_info([etud_]) # info = etud_ + if etud.prenom_etat_civil: + info["etat_civil"] = ( + "

Etat-civil: " + + etud.civilite_etat_civil_str + + " " + + etud.prenom_etat_civil + + " " + + etud.nom + + "

" + ) + else: + info["etat_civil"] = "" info["ScoURL"] = scu.ScoURL() info["authuser"] = authuser info["info_naissance"] = info["date_naissance"] @@ -325,18 +337,17 @@ def ficheEtud(etudid=None): if not sco_permissions_check.can_suppress_annotation(a["id"]): a["dellink"] = "" else: - a["dellink"] = ( - '%s' - % ( - etudid, - a["id"], - scu.icontag( - "delete_img", - border="0", - alt="suppress", - title="Supprimer cette annotation", - ), - ) + a[ + "dellink" + ] = '%s' % ( + etudid, + a["id"], + scu.icontag( + "delete_img", + border="0", + alt="suppress", + title="Supprimer cette annotation", + ), ) author = sco_users.user_info(a["author"]) alist.append( @@ -473,7 +484,7 @@ def ficheEtud(etudid=None):

%(nomprenom)s (%(inscription)s)

- +%(etat_civil)s %(emaillink)s
%(etudfoto)s diff --git a/app/views/scolar.py b/app/views/scolar.py index 6268c7e2..3a4e89d3 100644 --- a/app/views/scolar.py +++ b/app/views/scolar.py @@ -557,6 +557,7 @@ def etud_info(etudid=None, format="xml"): "nom_usuel", "prenom", "nomprenom", + "prenom_etat_civil", "email", "emailperso", "domicile", @@ -577,6 +578,9 @@ def etud_info(etudid=None, format="xml"): ): d[a] = etud[a] # ne pas quoter car ElementTree.tostring quote déjà d["civilite"] = etud["civilite_str"] # exception: ne sort pas la civilite brute + d["civilite_etat_civil"] = etud[ + "civilite_etat_civil_str" + ] # exception: ne sort pas la civilite brute d["sexe"] = d["civilite"] # backward compat pour anciens clients d["photo_url"] = sco_photos.etud_photo_url(etud) @@ -1442,6 +1446,25 @@ def _etudident_create_or_edit_form(edit): "title": "Civilité", }, ), + ( + "prenom_etat_civil", + { + "size": 25, + "title": "Prénom (état-civil)", + "allow_null": True, + "explanation": "Si précisé, remplace le prénom d'usage dans les documents officiels", + }, + ), + ( + "civilite_etat_civil", + { + "input_type": "menu", + "labels": ["Homme", "Femme", "Autre/neutre"], + "allowed_values": ["M", "F", "X"], + "title": "Civilité (état-civil)", + "explanation": "Si précisé: remplace la civilité d'usage dans les documents officiels", + }, + ), ( "date_naissance", { diff --git a/migrations/versions/cf29790ca6f6_ajout_prenom_civilite__etat_civil.py b/migrations/versions/cf29790ca6f6_ajout_prenom_civilite__etat_civil.py new file mode 100644 index 00000000..8b13136a --- /dev/null +++ b/migrations/versions/cf29790ca6f6_ajout_prenom_civilite__etat_civil.py @@ -0,0 +1,33 @@ +"""ajout (prenom,civilite)_etat_civil + +Revision ID: cf29790ca6f6 +Revises: 6520faf67508 +Create Date: 2023-02-25 10:55:42.831526 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "cf29790ca6f6" +down_revision = "6520faf67508" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - checked ### + op.add_column( + "identite", + sa.Column("civilite_etat_civil", sa.Text(), nullable=True, server_default="X"), + ) + op.add_column("identite", sa.Column("prenom_etat_civil", sa.Text(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - checked ### + op.drop_column("identite", "prenom_etat_civil") + op.drop_column("identite", "civilite_etat_civil") + # ### end Alembic commands ### diff --git a/tools/format_import_etudiants.txt b/tools/format_import_etudiants.txt index 3ba04f50..ad18c275 100644 --- a/tools/format_import_etudiants.txt +++ b/tools/format_import_etudiants.txt @@ -9,6 +9,8 @@ nom; text; identite; 0; nom de l'etudiant; nom_usuel; text; identite; 1; nom usuel (si different); prenom; text; identite; 0; prenom de l'etudiant civilite; text; identite; 1; sexe ('M', 'F', 'X');sexe;genre +prenom_etat_civil; text; identite; 1; prenom à l'état-civil (si différent);prenom_etat_civil +civilite_etat_civil; text; identite; 1; sexe ('M', 'F', 'X') à l'état civil;civilite_etat_civil date_naissance;text;identite; 1; date de naissance (jj/mm/aaaa) lieu_naissance;text;identite; 1; lieu de naissance nationalite; text; identite; 1; nationalite