Fix: déclaration table Identite / Unicite codes

This commit is contained in:
Emmanuel Viennet 2023-03-12 21:22:19 +01:00
parent e745a7938e
commit b5b606b1f6
4 changed files with 117 additions and 16 deletions

View File

@ -27,6 +27,7 @@ class Identite(db.Model):
__table_args__ = ( __table_args__ = (
db.UniqueConstraint("dept_id", "code_nip"), db.UniqueConstraint("dept_id", "code_nip"),
db.UniqueConstraint("dept_id", "code_ine"), db.UniqueConstraint("dept_id", "code_ine"),
db.CheckConstraint("civilite IN ('M', 'F', 'X')"),
) )
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
@ -36,10 +37,8 @@ class Identite(db.Model):
nom = db.Column(db.Text()) nom = db.Column(db.Text())
prenom = db.Column(db.Text()) prenom = db.Column(db.Text())
nom_usuel = db.Column(db.Text()) nom_usuel = db.Column(db.Text())
# optionnel (si present, affiché à la place du nom) "optionnel (si present, affiché à la place du nom)"
civilite = db.Column(db.String(1), nullable=False) civilite = db.Column(db.String(1), nullable=False)
__table_args__ = (db.CheckConstraint("civilite IN ('M', 'F', 'X')"),)
date_naissance = db.Column(db.Date) date_naissance = db.Column(db.Date)
lieu_naissance = db.Column(db.Text()) lieu_naissance = db.Column(db.Text())
dept_naissance = db.Column(db.Text()) dept_naissance = db.Column(db.Text())

View File

@ -301,24 +301,27 @@ def check_nom_prenom(cnx, nom="", prenom="", etudid=None):
def _check_duplicate_code(cnx, args, code_name, disable_notify=False, edit=True): def _check_duplicate_code(cnx, args, code_name, disable_notify=False, edit=True):
"""Vérifie que le code n'est pas dupliqué"""
etudid = args.get("etudid", None) etudid = args.get("etudid", None)
if args.get(code_name, None): if args.get(code_name, None):
etuds = identite_list(cnx, {code_name: str(args[code_name])}) etuds = identite_list(cnx, {code_name: str(args[code_name])})
# log('etuds=%s'%etuds) duplicate = False
nb_max = 0
if edit: if edit:
nb_max = 1 duplicate = (len(etuds) > 1) or (
if len(etuds) > nb_max: (len(etuds) == 1) and etuds[0]["id"] != args["etudid"]
)
else:
duplicate = len(etuds) > 0
if duplicate:
listh = [] # liste des doubles listh = [] # liste des doubles
for e in etuds: for e in etuds:
listh.append( listh.append(
"""Autre étudiant: <a href="%s">""" f"""Autre étudiant: <a href="{
% url_for( url_for(
"scolar.ficheEtud", "scolar.ficheEtud",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
etudid=e["etudid"], etudid=e["etudid"]
) )}">{e['nom']} {e['prenom']}</a>"""
+ """%(nom)s %(prenom)s</a>""" % e
) )
if etudid: if etudid:
OK = "retour à la fiche étudiant" OK = "retour à la fiche étudiant"
@ -349,7 +352,7 @@ def _check_duplicate_code(cnx, args, code_name, disable_notify=False, edit=True)
""" """
else: else:
err_page = f"""<h3>Code étudiant ({code_name}) dupliqué !</h3>""" err_page = f"""<h3>Code étudiant ({code_name}) dupliqué !</h3>"""
log("*** error: code %s duplique: %s" % (code_name, args[code_name])) log(f"*** error: code {code_name} duplique: {args[code_name]}")
raise ScoGenError(err_page) raise ScoGenError(err_page)

View File

@ -1732,7 +1732,9 @@ def _etudident_create_or_edit_form(edit):
formsemestre_id=formsemestre_id formsemestre_id=formsemestre_id
) # > etudident_create_or_edit ) # > etudident_create_or_edit
# #
return flask.redirect("ficheEtud?etudid=" + str(etudid)) return flask.redirect(
url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid)
)
@bp.route("/etudident_delete", methods=["GET", "POST"]) @bp.route("/etudident_delete", methods=["GET", "POST"])

View File

@ -0,0 +1,97 @@
"""contraintes identite
Revision ID: ae9bb0feea7a
Revises: 5731e904baac
Create Date: 2023-03-12 19:00:58.544873
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.orm import sessionmaker # added by ev
# revision identifiers, used by Alembic.
revision = "ae9bb0feea7a"
down_revision = "5731e904baac"
branch_labels = None
depends_on = None
Session = sessionmaker()
def upgrade():
# On répare une erreur (typo) dans la déclaration de la table Identite
# qui faisait que les contraintes d'unicité des couples (ine, dept)
# et (nip, dept) n'était pas prises en compte.
# On commence par chercher les éventuels (rares) doublons, changer leurs codes
# avant de créer les contraintes.
bind = op.get_bind()
session = Session(bind=bind)
# Corrige NIP
dups = session.execute(
"""SELECT dept_id, code_nip
FROM identite
WHERE code_nip IS NOT NULL
GROUP BY dept_id, code_nip
HAVING COUNT(*) > 1;"""
).all()
for dept_id, code_nip in dups:
etuds_dups = session.execute(
"""SELECT id, nom, prenom FROM identite
WHERE code_nip=:code_nip""",
{"code_nip": code_nip},
).all()
for i, (etudid, nom, prenom) in enumerate(etuds_dups[1:], start=1):
session.execute(
"""UPDATE identite SET code_nip=:code_nip WHERE id=:etudid""",
{
"code_nip": f"{code_nip}-{i}",
"etudid": etudid,
},
)
print(
f"Warning: duplication de code NIP détectée: vérifier {nom} {prenom} NIP={code_nip}"
)
session.commit()
# Corrige INE
dups = session.execute(
"""SELECT dept_id, code_ine
FROM identite
WHERE code_ine IS NOT NULL
GROUP BY dept_id, code_ine
HAVING COUNT(*) > 1;"""
).all()
for dept_id, code_ine in dups:
etuds_dups = session.execute(
"""SELECT id, nom, prenom FROM identite
WHERE code_ine=:code_ine""",
{"code_ine": code_ine},
).all()
for i, (etudid, nom, prenom) in enumerate(etuds_dups[1:], start=1):
session.execute(
"""UPDATE identite SET code_ine=:code_ine WHERE id=:etudid""",
{
"code_ine": f"{code_ine}-{i}",
"etudid": etudid,
},
)
print(
f"Warning: duplication de code INE détectée: vérifier {nom} {prenom} NIP={code_ine}"
)
session.commit()
# CREATION DES CONTRAINTES
op.create_unique_constraint(
"identite_dept_id_code_nip_key", "identite", ["dept_id", "code_nip"]
)
op.create_unique_constraint(
"identite_dept_id_code_ine_key", "identite", ["dept_id", "code_ine"]
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint("identite_dept_id_code_nip_key", "identite", type_="unique")
op.drop_constraint("identite_dept_id_code_ine_key", "identite", type_="unique")
# ### end Alembic commands ###