Merge pull request 'Ajout état-civil' (#629) from jmplace/ScoDoc-Lille:PR_etat-civil into master

Reviewed-on: https://scodoc.org/git/ScoDoc/ScoDoc/pulls/629
This commit is contained in:
Emmanuel Viennet 2023-05-11 14:04:38 +02:00
commit 590dd2e8b5
9 changed files with 129 additions and 17 deletions

View File

@ -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(

View File

@ -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}{self.code_nip or ""}{line_sep}{self.e} le {
return f"""{self.etat_civil}{line_sep}{self.code_nip or ""}{line_sep}{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)

View File

@ -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,

View File

@ -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

View File

@ -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",

View File

@ -176,6 +176,18 @@ def ficheEtud(etudid=None):
sco_etud.fill_etuds_info([etud_])
#
info = etud_
if etud.prenom_etat_civil:
info["etat_civil"] = (
"<h3>Etat-civil: "
+ etud.civilite_etat_civil_str
+ " "
+ etud.prenom_etat_civil
+ " "
+ etud.nom
+ "</h3>"
)
else:
info["etat_civil"] = ""
info["ScoURL"] = scu.ScoURL()
info["authuser"] = authuser
info["info_naissance"] = info["date_naissance"]
@ -325,9 +337,9 @@ def ficheEtud(etudid=None):
if not sco_permissions_check.can_suppress_annotation(a["id"]):
a["dellink"] = ""
else:
a["dellink"] = (
'<td class="annodel"><a href="doSuppressAnnotation?etudid=%s&annotation_id=%s">%s</a></td>'
% (
a[
"dellink"
] = '<td class="annodel"><a href="doSuppressAnnotation?etudid=%s&annotation_id=%s">%s</a></td>' % (
etudid,
a["id"],
scu.icontag(
@ -337,7 +349,6 @@ def ficheEtud(etudid=None):
title="Supprimer cette annotation",
),
)
)
author = sco_users.user_info(a["author"])
alist.append(
f"""<tr><td><span class="annodate">Le {a['date']} par {author['prenomnom']} :
@ -473,7 +484,7 @@ def ficheEtud(etudid=None):
<div class="ficheEtud" id="ficheEtud"><table>
<tr><td>
<h2>%(nomprenom)s (%(inscription)s)</h2>
%(etat_civil)s
<span>%(emaillink)s</span>
</td><td class="photocell">
<a href="etud_photo_orig_page?etudid=%(etudid)s">%(etudfoto)s</a>

View File

@ -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",
{

View File

@ -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 ###

View File

@ -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