diff --git a/app/models/etudiants.py b/app/models/etudiants.py index 95f30d1842..17cd213d0f 100644 --- a/app/models/etudiants.py +++ b/app/models/etudiants.py @@ -192,11 +192,10 @@ class Identite(db.Model, models.ScoDocModel): @classmethod def create_etud(cls, **args) -> "Identite": - "Crée un étudiant, avec admission et adresse vides." - etud: Identite = cls(**args) - etud.adresses.append(Adresse(typeadresse="domicile")) - etud.admission = Admission() - return etud + """Crée un étudiant, avec admission et adresse vides. + (added to session but not flushed nor commited) + """ + return cls.create_from_dict(args) @classmethod def create_from_dict(cls, data) -> "Identite": @@ -324,7 +323,8 @@ class Identite(db.Model, models.ScoDocModel): args: dict with args in application. returns: dict to store in model's db. """ - fs_uppercase = {"nom", "prenom", "prenom_etat_civil"} + # Les champs qui sont toujours stockés en majuscules: + fs_uppercase = {"nom", "nom_usuel", "prenom", "prenom_etat_civil"} fs_empty_stored_as_nulls = { "nom", "prenom", diff --git a/app/scodoc/sco_etud.py b/app/scodoc/sco_etud.py index a90b54d3b1..21b5859922 100644 --- a/app/scodoc/sco_etud.py +++ b/app/scodoc/sco_etud.py @@ -244,6 +244,7 @@ _identiteEditor = ndb.EditableTable( sortkey="nom", input_formators={ "nom": force_uppercase, + "nom_usuel": force_uppercase, "prenom": force_uppercase, "prenom_etat_civil": force_uppercase, "civilite": input_civilite, @@ -616,7 +617,7 @@ def log_unknown_etud(): def get_etud_info(etudid=False, code_nip=False, filled=False) -> list[dict]: - """infos sur un etudiant (API). If not found, returns empty list. + """infos sur un etudiant. If not found, returns empty list. On peut spécifier etudid ou code_nip ou bien cherche dans les arguments de la requête courante: etudid, code_nip, code_ine (dans cet ordre). @@ -850,7 +851,9 @@ def fill_etuds_info(etuds: list[dict], add_admission=True): # Admission if add_admission and "nomlycee" not in etud: admission = ( - Admission.query.filter_by(etudid=etudid).first().to_dict(no_nulls=True) + Admission.query.filter_by(id=etud["admission_id"]) + .first() + .to_dict(no_nulls=True) ) del admission["id"] # pour garder id == etudid dans etud etud.update(admission) diff --git a/tests/ressources/misc/ImportEtudiants.xlsx b/tests/ressources/misc/ImportEtudiants.xlsx index 4aed711631..142cab00be 100644 Binary files a/tests/ressources/misc/ImportEtudiants.xlsx and b/tests/ressources/misc/ImportEtudiants.xlsx differ diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py index dc5a532f1a..e8363bc104 100644 --- a/tests/unit/__init__.py +++ b/tests/unit/__init__.py @@ -15,3 +15,8 @@ def call_view(view_function, *args, **kwargs): ) assert func return func(*args, **kwargs) + + +def dict_include(d: dict, ref: dict) -> bool: + """Checks that all keys in ref are in d, and with the same value.""" + return all((k in d) and (d[k] == ref[k]) for k in ref) diff --git a/tests/unit/test_etudiants.py b/tests/unit/test_etudiants.py index ce96c6024f..15739a1879 100644 --- a/tests/unit/test_etudiants.py +++ b/tests/unit/test_etudiants.py @@ -12,12 +12,14 @@ from pathlib import Path from flask import current_app +import app from app import db from app.models import Admission, Adresse, Departement, FormSemestre, Identite from app.scodoc import sco_etud from app.scodoc import sco_import_etuds +from config import TestConfig -from tests.unit import setup +from tests.unit import setup, dict_include def test_identite(test_client): @@ -39,6 +41,13 @@ def test_identite(test_client): e = Identite.create_etud(**args) db.session.add(e) db.session.flush() + # + assert e.nom == "NOM" + assert e.nom_usuel == "NOM_USUEL" + assert e.prenom == "PRENOM" + assert e.prenom_etat_civil == "PRENOM_ETAT_CIVIL" + assert e.dept_naissance == "dept_naissance" + # admission_id = e.admission_id admission = db.session.get(Admission, admission_id) assert admission is not None @@ -140,21 +149,22 @@ def test_import_etuds_xlsx(test_client): ) formsemestre = db.session.get(FormSemestre, formsemestre_id) # Vérifie tous les champs du premier étudiant - etud = formsemestre.etuds.first() - assert etud.code_nip == "nip1" - assert etud.code_ine == "ine1" - assert etud.nom == "NOM1" - assert etud.nom_usuel == "nom_usuel1" - assert etud.prenom == "PRÉNOM1" - assert etud.civilite == "M" - assert etud.prenom_etat_civil == "PRÉNOM_CIVIL1" - assert etud.civilite_etat_civil == "M" - assert etud.date_naissance == datetime.date(2001, 5, 1) - assert etud.lieu_naissance == "Paris" - assert etud.nationalite == "Belge" - assert etud.boursier is True + e1 = formsemestre.etuds.filter_by(code_ine="ine1").first() + assert e1 + assert e1.code_nip == "nip1" + assert e1.code_ine == "ine1" + assert e1.nom == "NOM1" + assert e1.nom_usuel == "NOM_USUEL1" + assert e1.prenom == "PRÉNOM1" + assert e1.civilite == "M" + assert e1.prenom_etat_civil == "PRÉNOM_CIVIL1" + assert e1.civilite_etat_civil == "M" + assert e1.date_naissance == datetime.date(2001, 5, 1) + assert e1.lieu_naissance == "Paris" + assert e1.nationalite == "Belge" + assert e1.boursier is True # Admission - adm = etud.admission + adm = e1.admission assert adm.bac == "C" assert adm.specialite == "SPÉ" assert adm.annee_bac == 2023 @@ -170,7 +180,7 @@ def test_import_etuds_xlsx(test_client): assert adm.nomlycee == "nomlycée" assert adm.codepostallycee == "75005" # Adresse - adresse: Adresse = etud.adresses.first() + adresse: Adresse = e1.adresses.first() assert adresse.email == "etud1@etud.no" assert adresse.emailperso == "etud1@perso.no" assert adresse.domicile == "1 rue A" @@ -180,3 +190,180 @@ def test_import_etuds_xlsx(test_client): assert adresse.telephone == "102030405" assert adresse.telephonemobile == "605040302" # + # + e2 = formsemestre.etuds.filter_by(code_ine="ine2").first() + assert e2 + assert e2.civilite == "M" + assert e2.civilite_etat_civil is None + assert e2.civilite_str == "M." + assert e2.civilite_etat_civil_str == "M." + assert e2.nomprenom == "M. Prénom2 NOM2" + # + e3 = formsemestre.etuds.filter_by(code_ine="ine3").first() + assert e3 + assert e3.civilite == "F" + assert e3.civilite_etat_civil is None + assert e3.civilite_str == "Mme" + assert e3.civilite_etat_civil_str == "Mme" + assert e3.nomprenom == "Mme Prénom3 NOM3" + # + e4 = formsemestre.etuds.filter_by(code_ine="ine4").first() + assert e4 + assert e4.civilite == "X" + assert e4.civilite_etat_civil is None + assert e4.civilite_str == "" + assert e4.civilite_etat_civil_str == "" + assert e4.nomprenom == "Prénom4 NOM4" + # + e5 = formsemestre.etuds.filter_by(code_ine="ine5").first() + assert e5 + assert e5.civilite == "M" + assert e5.civilite_etat_civil == "F" + assert e5.civilite_str == "M." + assert e5.civilite_etat_civil_str == "Mme" + assert e5.nomprenom == "M. Prénom5 NOM5" + # + e6 = formsemestre.etuds.filter_by(code_ine="ine6").first() + assert e6 + assert e6.civilite == "F" + assert e6.civilite_etat_civil == "F" + assert e6.civilite_str == "Mme" + assert e6.civilite_etat_civil_str == "Mme" + assert e6.nomprenom == "Mme Prénom6 NOM6" + # + e7 = formsemestre.etuds.filter_by(code_ine="ine7").first() + assert e7 + assert e7.civilite == "X" + assert e7.civilite_etat_civil == "F" + assert e7.civilite_str == "" + assert e7.civilite_etat_civil_str == "Mme" + assert e7.nomprenom == "Prénom7 NOM7" + # + e8 = formsemestre.etuds.filter_by(code_ine="ine8").first() + assert e8 + assert e8.civilite == "X" + assert e8.civilite_etat_civil == "F" + assert e8.prenom_etat_civil == "PRÉNOM_CIVIL8" + assert e8.nomprenom == "Prénom8 NOM8" + # e9 + e9 = formsemestre.etuds.filter_by(code_ine="ine9").first() + assert e9 + assert e9.civilite == "X" + assert e9.civilite_etat_civil is None + assert e9.prenom == "PRÉNOM9" + assert e9.prenom_etat_civil == "PRÉNOM_CIVIL9" + assert e9.nomprenom == "Prénom9 NOM9" + # + e10 = formsemestre.etuds.filter_by(code_ine="ine10").first() + assert e10 + assert e10.nom_usuel == "NOM_USUEL10" + assert e10.nomprenom == "Prénom10 NOM_USUEL10" + # Vérification conversion dict + e10_dict = e10.to_dict_bul() + assert dict_include( + e10_dict, + { + "boursier": "", + "civilite_etat_civil": "F", + "civilite": "X", + "code_ine": "ine10", + "code_nip": "nip10", + "date_naissance": "", + "dept_acronym": "TEST_", + "dept_naissance": "", + "email": "", + "emailperso": "", + "etat_civil": "Mme PRÉNOM_CIVIL10 NOM10", + "etudid": 10, + "lieu_naissance": "", + "nationalite": "", + "nom": "NOM_USUEL10 (NOM10)", + "nomprenom": "Prénom10 NOM_USUEL10", + "prenom_etat_civil": "PRÉNOM_CIVIL10", + "prenom": "PRÉNOM10", + "domicile": "", + "villedomicile": "", + "telephone": "", + "fax": "", + "codepostaldomicile": "", + "paysdomicile": "", + "telephonemobile": "", + "typeadresse": "domicile", + }, + ) + # Test fonction sco_etud ScoDoc7 legacy + app.set_sco_dept(TestConfig.DEPT_TEST) + e10_dict["admission_id"] = e10.admission_id + sco_etud.fill_etuds_info([e10_dict]) + assert dict_include( + e10_dict, + { + "boursier": "", + "civilite_etat_civil": "F", + "civilite": "X", + "code_ine": "ine10", + "code_nip": "nip10", + "date_naissance": "", + "dept_acronym": "TEST_", + "dept_naissance": "", + "email": "", + "emailperso": "", + "etat_civil": "Mme Prénom_civil10 NOM_USUEL10 (NOM10)", + "lieu_naissance": "", + "nationalite": "", + "nom": "NOM_USUEL10 (NOM10)", + "nomprenom": "Prénom10 NOM_USUEL10 (NOM10)", + "prenom_etat_civil": "Prénom_civil10", + "prenom": "Prénom10", + "domicile": "", + "villedomicile": "", + "telephone": "", + "fax": "", + "description": "(infos admission)", + "id": 10, + "codepostaldomicile": "", + "paysdomicile": "", + "telephonemobile": "", + "typeadresse": "domicile", + "admission_id": 10, + "dept": "TEST_", + "bac": "", + "rang": 0, + "codepostallycee": "", + "qualite": None, + "codelycee": "", + "rapporteur": "", + "type_admission": "", + "annee_bac": 0, + "decision": "", + "boursier_prec": False, + "math": "", + "score": None, + "classement": 0, + "physique": "", + "commentaire": "", + "apb_groupe": "", + "anglais": "", + "nomlycee": "", + "apb_classement_gr": 0, + "villelycee": "", + "annee": 2023, + "specialite": "", + "francais": "", + "nom_usuel": "", + "civilite_str": "", + "civilite_etat_civil_str": "Mme", + "nom_disp": "NOM_USUEL10 (NOM10)", + "ne": "(e)", + "email_default": "", + "inscription": "ancien", + "situation": "ancien élève", + "inscriptionstr": "ancien", + "inscription_formsemestre_id": None, + "etatincursem": "?", + "ilycee": "", + "rap": "", + "telephonestr": "", + "telephonemobilestr": "", + }, + )