diff --git a/app/api/absences.py b/app/api/absences.py index ec564c449..0442877b2 100644 --- a/app/api/absences.py +++ b/app/api/absences.py @@ -53,10 +53,7 @@ def absences(etudid: int = None): """ etud = Identite.query.get(etudid) if etud is None: - return error_response( - 404, - message="id de l'étudiant (etudid, nip, ine) inconnu", - ) + return error_response(404, message="etudiant inexistant") # Absences de l'étudiant ndb.open_db_connection() abs_list = sco_abs.list_abs_date(etud.id) @@ -100,10 +97,7 @@ def absences_just(etudid: int = None): """ etud = Identite.query.get(etudid) if etud is None: - return error_response( - 404, - message="id de l'étudiant (etudid, nip, ine) inconnu", - ) + return error_response(404, message="etudiant inexistant") # Absences justifiées de l'étudiant abs_just = [ diff --git a/app/api/departements.py b/app/api/departements.py index b592397b3..a8d76d8c5 100644 --- a/app/api/departements.py +++ b/app/api/departements.py @@ -81,8 +81,8 @@ def dept_etudiants(acronym: str): [ { "civilite": "M", - "ine": "7899X61616", - "nip": "F6777H88", + "code_ine": "7899X61616", + "code_nip": "F6777H88", "date_naissance": null, "email": "toto@toto.fr", "emailperso": null, diff --git a/app/api/etudiants.py b/app/api/etudiants.py index 80b7eff08..c2bd40dae 100644 --- a/app/api/etudiants.py +++ b/app/api/etudiants.py @@ -11,14 +11,20 @@ from flask import g, jsonify from flask_login import current_user from flask_login import login_required -from sqlalchemy import or_ +from sqlalchemy import desc, or_ import app from app.api import api_bp as bp, api_web_bp from app.api.errors import error_response from app.api import tools from app.decorators import scodoc, permission_required -from app.models import Departement, FormSemestreInscription, FormSemestre, Identite +from app.models import ( + Admission, + Departement, + FormSemestreInscription, + FormSemestre, + Identite, +) from app.scodoc import sco_bulletins from app.scodoc import sco_groups from app.scodoc.sco_bulletins import do_formsemestre_bulletinetud @@ -55,8 +61,8 @@ def etudiants_courants(long=False): [ { "id": 1234, - "nip": "12345678", - "ine": null, + "code_nip": "12345678", + "code_ine": null, "nom": "JOHN", "nom_usuel": None, "prenom": "DEUF", @@ -259,28 +265,22 @@ def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None) ] """ if etudid is not None: - query = FormSemestre.query.filter( - FormSemestreInscription.etudid == etudid, - FormSemestreInscription.formsemestre_id == FormSemestre.id, - ) + q_etud = Identite.query.filter_by(id=etudid) elif nip is not None: - query = FormSemestre.query.filter( - Identite.code_nip == nip, - FormSemestreInscription.etudid == Identite.id, - FormSemestreInscription.formsemestre_id == FormSemestre.id, - ) + q_etud = Identite.query.filter_by(code_nip=nip) elif ine is not None: - query = FormSemestre.query.filter( - Identite.code_ine == ine, - FormSemestreInscription.etudid == Identite.id, - FormSemestreInscription.formsemestre_id == FormSemestre.id, - ) + q_etud = Identite.query.filter_by(code_ine=ine) else: - return error_response( - 404, - message="parametre manquant", - ) - + return error_response(404, message="parametre manquant") + if g.scodoc_dept is not None: + q_etud = q_etud.filter_by(dept_id=g.scodoc_dept_id) + etud = q_etud.join(Admission).order_by(desc(Admission.annee)).first() + if etud is None: + return error_response(404, message="etudiant inexistant") + query = FormSemestre.query.filter( + FormSemestreInscription.etudid == etud.id, + FormSemestreInscription.formsemestre_id == FormSemestre.id, + ) if g.scodoc_dept is not None: query = query.filter_by(dept_id=g.scodoc_dept_id) @@ -422,23 +422,17 @@ def etudiant_bulletin_semestre( elif ine is not None: query = Identite.query.filter_by(code_ine=ine, dept_id=dept.id) else: - return error_response( - 404, - message="parametre manquant", - ) + return error_response(404, message="parametre manquant") etud = query.first() if etud is None: - return error_response( - 404, - message="id de l'étudiant (etudid, nip, ine) inconnu", - ) + return error_response(404, message="etudiant inexistant") app.set_sco_dept(dept.acronym) if pdf: pdf_response, _ = do_formsemestre_bulletinetud( - formsemestre, etudid, version=version, format="pdf" + formsemestre, etud.id, version=version, format="pdf" ) return pdf_response diff --git a/app/api/formations.py b/app/api/formations.py index 44438b126..21b8a58f9 100644 --- a/app/api/formations.py +++ b/app/api/formations.py @@ -92,7 +92,7 @@ def formation_by_id(formation_id: int): defaults={"export_ids": False}, ) @bp.route( - "/formation//export/with_ids", + "/formation//export_with_ids", defaults={"export_ids": True}, ) @api_web_bp.route( @@ -100,7 +100,7 @@ def formation_by_id(formation_id: int): defaults={"export_ids": False}, ) @api_web_bp.route( - "/formation//export/with_ids", + "/formation//export_with_ids", defaults={"export_ids": True}, ) @login_required diff --git a/app/api/formsemestres.py b/app/api/formsemestres.py index b0ff13fb4..88c157eb4 100644 --- a/app/api/formsemestres.py +++ b/app/api/formsemestres.py @@ -23,6 +23,7 @@ from app.models import ( FormSemestre, FormSemestreEtape, ModuleImpl, + NotesNotes, ) from app.scodoc.sco_bulletins import get_formsemestre_bulletin_etud_json from app.scodoc import sco_groups @@ -101,11 +102,7 @@ def formsemestres_query(): dept_id = request.args.get("dept_id") formsemestres = FormSemestre.query if g.scodoc_dept: - query = query.filter_by(dept_id=g.scodoc_dept_id) - if etape_apo is not None: - formsemestres = formsemestres.join(FormSemestreEtape).filter( - FormSemestreEtape.etape_apo == etape_apo - ) + formsemestres = formsemestres.filter_by(dept_id=g.scodoc_dept_id) if annee_scolaire is not None: try: annee_scolaire_int = int(annee_scolaire) @@ -124,6 +121,10 @@ def formsemestres_query(): except ValueError: return error_response(404, "invalid dept_id: not int") formsemestres = formsemestres.filter_by(dept_id=dept_id) + if etape_apo is not None: + formsemestres = formsemestres.join(FormSemestreEtape).filter( + FormSemestreEtape.etape_apo == etape_apo + ) return jsonify([formsemestre.to_dict_api() for formsemestre in formsemestres]) @@ -371,7 +372,7 @@ def etat_evals(formsemestre_id: int): # Récupération de toutes les notes de l'évaluation # eval["notes"] = modimpl_results.get_eval_notes_dict(evaluation_id) - notes = models.NotesNotes.query.filter_by(evaluation_id=evaluation.id).all() + notes = NotesNotes.query.filter_by(evaluation_id=evaluation.id).all() date_debut = None date_fin = None diff --git a/app/models/etudiants.py b/app/models/etudiants.py index 30333a6b1..e4c6495b6 100644 --- a/app/models/etudiants.py +++ b/app/models/etudiants.py @@ -149,8 +149,9 @@ class Identite(db.Model): """Les champs essentiels""" return { "id": self.id, - "nip": self.code_nip, - "ine": self.code_ine, + "code_nip": self.code_nip, + "code_ine": self.code_ine, + "dept_id": self.dept_id, "nom": self.nom, "nom_usuel": self.nom_usuel, "prenom": self.prenom, diff --git a/app/pe/pe_jurype.py b/app/pe/pe_jurype.py index 48795edfc..66d19ef32 100644 --- a/app/pe/pe_jurype.py +++ b/app/pe/pe_jurype.py @@ -830,7 +830,7 @@ class JuryPE(object): else "" ), "bac": etudinfo["bac"], - "nip": etudinfo["code_nip"], # pour la photo + "code_nip": etudinfo["code_nip"], # pour la photo "entree": self.get_dateEntree(etudid), "promo": self.diplome, } diff --git a/app/pe/pe_tools.py b/app/pe/pe_tools.py index 5f58428bb..ad6e2aa2a 100644 --- a/app/pe/pe_tools.py +++ b/app/pe/pe_tools.py @@ -764,7 +764,7 @@ JURY_SYNTHESE_POUR_DEBUG = { }, }, "nbSemestres": 4, - "nip": "21414563", + "code_nip": "21414563", "prenom": "Baptiste", "age": "21", "lycee": "PONCET", diff --git a/sco_version.py b/sco_version.py index 9e9516d44..618b90d77 100644 --- a/sco_version.py +++ b/sco_version.py @@ -1,7 +1,7 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "9.3.23" +SCOVERSION = "9.3.24" SCONAME = "ScoDoc" diff --git a/tests/api/README.md b/tests/api/README.md new file mode 100644 index 000000000..d41c017bd --- /dev/null +++ b/tests/api/README.md @@ -0,0 +1,40 @@ +# Tests unitaires de l'API ScoDoc + +Démarche générale: + + 1. On génère une base SQL de test: voir + `tools/fakedatabase/create_test_api_database.py` + + + 1. modifier /opt/scodoc/.env pour indiquer + ``` + FLASK_ENV=test_api + FLASK_DEBUG=1 + ``` + + 2. En tant qu'utilisateur scodoc, lancer: + ``` + tools/create_database.sh --drop SCODOC_TEST_API + flask db upgrade + flask sco-db-init --erase + flask init-test-database + ``` + + 2. On lance le serveur ScoDoc sur cette base + ``` + flask run --host 0.0.0.0 + ``` + + 3. On lance les tests unitaires API +``` + pytest tests/api/test_api_departements.py +``` + +Rappel: pour interroger l'API, il fait avoir un utilisateur avec (au moins) la permission +ScoView dans tous les départements. Pour en créer un: +``` + flask user-create lecteur_api LecteurAPI @all + flask user-password lecteur_api + flask edit-role LecteurAPI -a ScoView + flask user-role lecteur_api -a LecteurAPI +``` diff --git a/tests/api/test_api_departements.py b/tests/api/test_api_departements.py index bd68fc03c..de442c9c6 100644 --- a/tests/api/test_api_departements.py +++ b/tests/api/test_api_departements.py @@ -24,7 +24,7 @@ from tests.api.tools_test_api import ( verify_fields, DEPARTEMENT_FIELDS, FORMSEMESTRE_FIELDS, - verify_occurences_ids_etus, + verify_occurences_ids_etuds, ) @@ -56,7 +56,7 @@ def test_departements(api_headers): # --- departement # Infos sur un département, accès par id r = requests.get( - f"{API_URL}/departement/{dept_id}", + f"{API_URL}/departement/id/{dept_id}", headers=api_headers, verify=CHECK_CERTIFICATE, ) @@ -97,7 +97,7 @@ def test_departements(api_headers): dept_ids_a = r.json() r = requests.get( - f"{API_URL}/departement/{dept_a['id']}/formsemestres_ids", + f"{API_URL}/departement/id/{dept_a['id']}/formsemestres_ids", headers=api_headers, verify=CHECK_CERTIFICATE, ) @@ -143,7 +143,7 @@ def test_departements(api_headers): def test_list_etudiants(api_headers): - fields = {"id", "nip", "ine", "nom", "nom_usuel", "prenom", "civilite"} + fields = {"id", "code_nip", "code_ine", "nom", "nom_usuel", "prenom", "civilite"} r = requests.get( API_URL + "/departement/TAPI/etudiants", @@ -154,7 +154,7 @@ def test_list_etudiants(api_headers): etud_a = r.json()[0] r = requests.get( - API_URL + "/departement/1/etudiants", + API_URL + "/departement/id/1/etudiants", headers=api_headers, verify=CHECK_CERTIFICATE, ) @@ -164,15 +164,15 @@ def test_list_etudiants(api_headers): assert etud_a == etud_b assert verify_fields(etud_a, fields) is True assert isinstance(etud_a["id"], int) - assert etud_a["nip"] is None or isinstance(etud_a["nip"], str) - assert etud_a["ine"] is None or isinstance(etud_a["ine"], str) + assert etud_a["code_nip"] is None or isinstance(etud_a["code_nip"], str) + assert etud_a["code_ine"] is None or isinstance(etud_a["code_ine"], str) assert etud_a["nom"] is None or isinstance(etud_a["nom"], str) assert etud_a["nom_usuel"] is None or isinstance(etud_a["nom_usuel"], str) assert etud_a["prenom"] is None or isinstance(etud_a["prenom"], str) assert isinstance(etud_a["civilite"], str) assert len(etud_a["civilite"]) == 1 - all_unique = verify_occurences_ids_etus(r.text) + all_unique = verify_occurences_ids_etuds(r.text) assert all_unique is True # Les erreurs @@ -197,7 +197,7 @@ def test_list_etudiants(api_headers): def test_semestres_courant(api_headers): dept_id = 1 r = requests.get( - f"{API_URL}/departement/{dept_id}", + f"{API_URL}/departement/id/{dept_id}", headers=api_headers, verify=CHECK_CERTIFICATE, ) @@ -216,7 +216,7 @@ def test_semestres_courant(api_headers): # accès via dept_id r = requests.get( - f"{API_URL}/departement/{dept['id']}/formsemestres_courants", + f"{API_URL}/departement/id/{dept['id']}/formsemestres_courants", headers=api_headers, verify=CHECK_CERTIFICATE, ) diff --git a/tests/api/test_api_etudiants.py b/tests/api/test_api_etudiants.py index 1167a9d75..190a4b255 100644 --- a/tests/api/test_api_etudiants.py +++ b/tests/api/test_api_etudiants.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""Test Logos +"""Test accès étudiants Utilisation : créer les variables d'environnement: (indiquer les valeurs @@ -22,7 +22,7 @@ import requests from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers from tests.api.tools_test_api import ( verify_fields, - verify_occurences_ids_etus, + verify_occurences_ids_etuds, BULLETIN_FIELDS, BULLETIN_ETUDIANT_FIELDS, BULLETIN_FORMATION_FIELDS, @@ -55,15 +55,15 @@ from tests.api.tools_test_api import ETUD_FIELDS, FSEM_FIELDS ETUDID = 1 -NIP = "1" -INE = "1" +NIP = "NIP2" +INE = "INE1" def test_etudiants_courant(api_headers): """ Route: /etudiants/courant """ - fields = {"id", "nip", "nom", "prenom", "civilite"} + fields = {"id", "code_nip", "nom", "prenom", "civilite"} r = requests.get( API_URL + "/etudiants/courants", @@ -77,12 +77,12 @@ def test_etudiants_courant(api_headers): etud = etudiants[-1] assert verify_fields(etud, fields) is True assert isinstance(etud["id"], int) - assert isinstance(etud["nip"], str) + assert isinstance(etud["code_nip"], str) assert isinstance(etud["nom"], str) assert isinstance(etud["prenom"], str) assert isinstance(etud["civilite"], str) - all_unique = verify_occurences_ids_etus(r.text) + all_unique = verify_occurences_ids_etuds(r.text) assert all_unique is True ########## Version long ################ @@ -263,7 +263,7 @@ def test_etudiant_formsemestres(api_headers): assert isinstance(formsemestre["date_debut_iso"], str) assert isinstance(formsemestre["date_fin_iso"], str) assert isinstance(formsemestre["responsables"], list) - assert isinstance(formsemestre["titre_formation"], str) + assert isinstance(formsemestre["formation"]["titre"], str) assert verify_fields(formsemestre, FSEM_FIELDS) is True @@ -611,7 +611,7 @@ def test_etudiant_bulletin_semestre(api_headers): assert ( verify_fields(bulletin_semestre["ECTS"], BULLETIN_SEMESTRE_ECTS_FIELDS) is True ) - assert isinstance(bulletin_semestre["ECTS"]["acquis"], int) + assert isinstance(bulletin_semestre["ECTS"]["acquis"], float) assert isinstance(bulletin_semestre["ECTS"]["total"], float) assert ( @@ -777,29 +777,3 @@ def test_etudiant_groups(api_headers): group = groups[0] fields_ok = verify_fields(group, fields) assert fields_ok is True - - ######### Test code nip ######### - r = requests.get( - API_URL + "/etudiant/nip/" + str(NIP) + "/formsemestre/1/groups", - headers=api_headers, - verify=CHECK_CERTIFICATE, - ) - assert r.status_code == 200 - groups = r.json() - assert len(groups) == 1 # dans un seul groupe - group = groups[0] - fields_ok = verify_fields(group, fields) - assert fields_ok is True - - ######### Test code ine ######### - r = requests.get( - API_URL + "/etudiant/ine/" + str(INE) + "/formsemestre/1/groups", - headers=api_headers, - verify=CHECK_CERTIFICATE, - ) - assert r.status_code == 200 - groups = r.json() - assert len(groups) == 1 # dans un seul groupe - group = groups[0] - fields_ok = verify_fields(group, fields) - assert fields_ok is True diff --git a/tests/api/test_api_evaluations.py b/tests/api/test_api_evaluations.py index b27afd548..2ece5461d 100644 --- a/tests/api/test_api_evaluations.py +++ b/tests/api/test_api_evaluations.py @@ -70,16 +70,18 @@ def test_evaluations(api_headers): assert eval["moduleimpl_id"] == moduleimpl_id -def test_evaluation_notes(api_headers): # XXX TODO changer la boucle pour parcourir le dict sans les indices +def test_evaluation_notes( + api_headers, +): # XXX TODO changer la boucle pour parcourir le dict sans les indices """ Test 'evaluation_notes' Route : - - /evaluation/eval_notes/ + - /evaluation//notes """ eval_id = 1 r = requests.get( - f"{API_URL}/evaluation/eval_notes/{eval_id}", + f"{API_URL}/evaluation/{eval_id}/notes", headers=api_headers, verify=CHECK_CERTIFICATE, ) diff --git a/tests/api/test_api_formations.py b/tests/api/test_api_formations.py index f2e4bfefd..1869fc985 100644 --- a/tests/api/test_api_formations.py +++ b/tests/api/test_api_formations.py @@ -104,10 +104,10 @@ def test_formations_by_id(api_headers): def test_formation_export(api_headers): """ - Route: /formation/formation_export/ + Route: /formation//export """ r = requests.get( - API_URL + "/formation/formation_export/1", + API_URL + "/formation/1/export", headers=api_headers, verify=CHECK_CERTIFICATE, ) @@ -185,7 +185,7 @@ def test_formation_export(api_headers): # ERROR id_formation_inexistant = 1516476846861656351 r_error = requests.get( - f"{API_URL}/formation/formation_export/{id_formation_inexistant}", + f"{API_URL}/formation/export/{id_formation_inexistant}", headers=api_headers, verify=CHECK_CERTIFICATE, ) @@ -198,7 +198,7 @@ def test_moduleimpl(api_headers): """ moduleimpl_id = 1 r = requests.get( - f"{API_URL}/formation/moduleimpl/{moduleimpl_id}", + f"{API_URL}/moduleimpl/{moduleimpl_id}", headers=api_headers, verify=CHECK_CERTIFICATE, ) @@ -240,7 +240,7 @@ def test_moduleimpl(api_headers): assert moduleimpl_id == moduleimpl["moduleimpl_id"] r1 = requests.get( - f"{API_URL}/formation/moduleimpl/{moduleimpl['moduleimpl_id']}", + f"{API_URL}/moduleimpl/{moduleimpl['moduleimpl_id']}", headers=api_headers, verify=CHECK_CERTIFICATE, ) diff --git a/tests/api/test_api_formsemestre.py b/tests/api/test_api_formsemestre.py index 533455c52..c17b01fe3 100644 --- a/tests/api/test_api_formsemestre.py +++ b/tests/api/test_api_formsemestre.py @@ -18,7 +18,6 @@ Utilisation : """ import requests -from app.api.formsemestres import formsemestre from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers @@ -27,7 +26,7 @@ from tests.api.tools_test_api import ( MODIMPL_FIELDS, EVAL_FIELDS, SAISIE_NOTES_FIELDS, - FORMSEMESTRE_ETUS_FIELDS, + FORMSEMESTRE_ETUD_FIELDS, FSEM_FIELDS, FSEM_FIELDS, UE_FIELDS, @@ -100,7 +99,6 @@ def test_formsemestre(api_headers): formsemestre["scodoc7_id"], int ) assert isinstance(formsemestre["semestre_id"], int) - assert isinstance(formsemestre["titre_formation"], str) assert isinstance(formsemestre["titre_num"], str) assert isinstance(formsemestre["titre"], str) @@ -116,11 +114,11 @@ def test_formsemestre(api_headers): def test_formsemestre_apo(api_headers): """ - Route: /formsemestre/apo/ + Route: formsemestres/query?etape_apo= """ etape_apo = "A1" r = requests.get( - f"{API_URL}/formsemestre/apo/{etape_apo}", + f"{API_URL}/formsemestres/query?etape_apo={etape_apo}", headers=api_headers, verify=CHECK_CERTIFICATE, ) @@ -160,7 +158,6 @@ def test_formsemestre_apo(api_headers): formsemestre["scodoc7_id"], int ) assert isinstance(formsemestre["semestre_id"], int) - assert isinstance(formsemestre["titre_formation"], str) assert isinstance(formsemestre["titre_num"], str) assert isinstance(formsemestre["titre"], str) @@ -458,7 +455,7 @@ def test_bulletins(api_headers): verify_fields(bulletin_semestre["ECTS"], BULLETIN_SEMESTRE_ECTS_FIELDS) is True ) - assert isinstance(bulletin_semestre["ECTS"]["acquis"], int) + assert isinstance(bulletin_semestre["ECTS"]["acquis"], float) assert isinstance(bulletin_semestre["ECTS"]["total"], float) assert ( @@ -503,17 +500,17 @@ def test_formsemestre_etudiants(api_headers): assert r.status_code == 200 formsemestre_etus = r.json() assert isinstance(formsemestre_etus, list) - for etu in formsemestre_etus: - assert verify_fields(etu, FORMSEMESTRE_ETUS_FIELDS) is True - assert isinstance(etu["id"], int) - assert isinstance(etu["nip"], str) - assert isinstance(etu["ine"], str) - assert isinstance(etu["nom"], str) - assert etu["nom_usuel"] is None or isinstance(etu["nom_usuel"], str) - assert isinstance(etu["prenom"], str) - assert isinstance(etu["civilite"], str) - assert isinstance(etu["groups"], list) - etu_groups = etu["groups"] + for etud in formsemestre_etus: + assert verify_fields(etud, FORMSEMESTRE_ETUD_FIELDS) is True + assert isinstance(etud["id"], int) + assert isinstance(etud["code_nip"], str) + assert isinstance(etud["code_ine"], str) + assert isinstance(etud["nom"], str) + assert etud["nom_usuel"] is None or isinstance(etud["nom_usuel"], str) + assert isinstance(etud["prenom"], str) + assert isinstance(etud["civilite"], str) + assert isinstance(etud["groups"], list) + etu_groups = etud["groups"] for group in etu_groups: assert isinstance(group["partition_id"], int) assert isinstance(group["id"], int) @@ -521,7 +518,7 @@ def test_formsemestre_etudiants(api_headers): assert group["partition_name"] is None or isinstance( group["partition_name"], str ) - assert isinstance(group["numero"], int) + assert (group["numero"] is None) or isinstance(group["numero"], int) assert isinstance(group["bul_show_rank"], bool) assert isinstance(group["show_in_lists"], bool) assert isinstance(group["group_id"], int) @@ -537,17 +534,17 @@ def test_formsemestre_etudiants(api_headers): formsemestre_etus = r_demissionnaires.json() assert isinstance(formsemestre_etus, list) - for etu in formsemestre_etus: - assert verify_fields(etu, FORMSEMESTRE_ETUS_FIELDS) is True - assert isinstance(etu["id"], int) - assert isinstance(etu["nip"], str) - assert isinstance(etu["ine"], str) - assert isinstance(etu["nom"], str) - assert etu["nom_usuel"] is None or isinstance(etu["nom_usuel"], str) - assert isinstance(etu["prenom"], str) - assert isinstance(etu["civilite"], str) - assert isinstance(etu["groups"], list) - etu_groups = etu["groups"] + for etud in formsemestre_etus: + assert verify_fields(etud, FORMSEMESTRE_ETUD_FIELDS) is True + assert isinstance(etud["id"], int) + assert isinstance(etud["code_nip"], str) + assert isinstance(etud["code_ine"], str) + assert isinstance(etud["nom"], str) + assert etud["nom_usuel"] is None or isinstance(etud["nom_usuel"], str) + assert isinstance(etud["prenom"], str) + assert isinstance(etud["civilite"], str) + assert isinstance(etud["groups"], list) + etu_groups = etud["groups"] for group in etu_groups: assert isinstance(group["partition_id"], int) assert isinstance(group["id"], int) @@ -555,7 +552,7 @@ def test_formsemestre_etudiants(api_headers): assert group["partition_name"] is None or isinstance( group["partition_name"], str ) - assert isinstance(group["numero"], int) + assert (group["numero"] is None) or isinstance(group["numero"], int) assert isinstance(group["bul_show_rank"], bool) assert isinstance(group["show_in_lists"], bool) assert isinstance(group["group_id"], int) @@ -571,17 +568,17 @@ def test_formsemestre_etudiants(api_headers): formsemestre_etus = r_defaillants.json() assert isinstance(formsemestre_etus, list) - for etu in formsemestre_etus: - assert verify_fields(etu, FORMSEMESTRE_ETUS_FIELDS) is True - assert isinstance(etu["id"], int) - assert isinstance(etu["nip"], str) - assert isinstance(etu["ine"], str) - assert isinstance(etu["nom"], str) - assert etu["nom_usuel"] is None or isinstance(etu["nom_usuel"], str) - assert isinstance(etu["prenom"], str) - assert isinstance(etu["civilite"], str) - assert isinstance(etu["groups"], list) - etu_groups = etu["groups"] + for etud in formsemestre_etus: + assert verify_fields(etud, FORMSEMESTRE_ETUD_FIELDS) is True + assert isinstance(etud["id"], int) + assert isinstance(etud["code_nip"], str) + assert isinstance(etud["code_ine"], str) + assert isinstance(etud["nom"], str) + assert etud["nom_usuel"] is None or isinstance(etud["nom_usuel"], str) + assert isinstance(etud["prenom"], str) + assert isinstance(etud["civilite"], str) + assert isinstance(etud["groups"], list) + etu_groups = etud["groups"] for group in etu_groups: assert isinstance(group["partition_id"], int) assert isinstance(group["id"], int) @@ -589,7 +586,7 @@ def test_formsemestre_etudiants(api_headers): assert group["partition_name"] is None or isinstance( group["partition_name"], str ) - assert isinstance(group["numero"], int) + assert (group["numero"] is None) or isinstance(group["numero"], int) assert isinstance(group["bul_show_rank"], bool) assert isinstance(group["show_in_lists"], bool) assert isinstance(group["group_id"], int) @@ -670,99 +667,65 @@ def test_etat_evals( etat_evals = r.json() - assert len(etat_evals) == 3 + assert len(etat_evals) == 21 - for ue in etat_evals.values(): - for module in ue: - assert isinstance(module["id"], int) - assert isinstance(module["titre"], str) - assert isinstance(module["evaluations"], list) + for etat_modimpl in etat_evals: + assert isinstance(etat_modimpl["id"], int) + assert isinstance(etat_modimpl["evaluations"], list) - for eval in module["evaluations"]: - assert verify_fields(eval, EVAL_FIELDS) - assert isinstance(eval["id"], int) - assert eval["description"] is None or isinstance( - eval["description"], str + for evaluation in etat_modimpl["evaluations"]: + assert verify_fields(evaluation, EVAL_FIELDS) + assert isinstance(evaluation["id"], int) + assert evaluation["description"] is None or isinstance( + evaluation["description"], str + ) + assert evaluation["jour"] is None or isinstance(evaluation["jour"], str) + assert isinstance(evaluation["heure_fin"], str) + assert isinstance(evaluation["coefficient"], float) + assert isinstance(evaluation["etat"], dict) + assert isinstance(evaluation["nb_inscrits"], int) + assert isinstance(evaluation["nb_notes_manquantes"], int) + assert isinstance(evaluation["nb_notes_abs"], int) + assert isinstance(evaluation["nb_notes_att"], int) + assert isinstance(evaluation["nb_notes_exc"], int) + assert isinstance(evaluation["saisie_notes"], dict) + + list_eval_id = [e["id"] for e in etat_modimpl["evaluations"]] + all_unique = True + for id in list_eval_id: + if list_eval_id.count(id) > 1: + all_unique = False + assert all_unique is True + + saisie_notes = evaluation["saisie_notes"] + assert verify_fields(saisie_notes, SAISIE_NOTES_FIELDS) + assert evaluation["saisie_notes"]["datetime_debut"] is None or isinstance( + evaluation["saisie_notes"]["datetime_debut"], str + ) + assert evaluation["saisie_notes"]["datetime_debut"] is None or isinstance( + evaluation["saisie_notes"]["datetime_fin"], str + ) + assert evaluation["saisie_notes"]["datetime_debut"] is None or isinstance( + evaluation["saisie_notes"]["datetime_mediane"], str + ) + + if ( + evaluation["saisie_notes"]["datetime_fin"] is not None + and evaluation["saisie_notes"]["datetime_mediane"] is not None + and evaluation["saisie_notes"]["datetime_debut"] is not None + ): + assert ( + evaluation["saisie_notes"]["datetime_fin"] + > evaluation["saisie_notes"]["datetime_mediane"] ) - assert eval["datetime_epreuve"] is None or isinstance( - eval["datetime_epreuve"], str + assert ( + evaluation["saisie_notes"]["datetime_fin"] + > evaluation["saisie_notes"]["datetime_debut"] ) - assert isinstance(eval["heure_fin"], str) - assert isinstance(eval["coefficient"], float) - assert isinstance(eval["comptee"], str) - assert isinstance(eval["inscrits"], int) - assert isinstance(eval["manquantes"], int) - assert isinstance(eval["ABS"], int) - assert isinstance(eval["ATT"], int) - assert isinstance(eval["EXC"], int) - assert isinstance(eval["saisie_notes"], dict) - - list_eval_id = [e["id"] for e in module["evaluations"]] - all_unique = True - for id in list_eval_id: - if list_eval_id.count(id) > 1: - all_unique = False - assert all_unique is True - - saisie_notes = eval["saisie_notes"] - assert verify_fields(saisie_notes, SAISIE_NOTES_FIELDS) - assert eval["saisie_notes"]["datetime_debut"] is None or isinstance( - eval["saisie_notes"]["datetime_debut"], str + assert ( + evaluation["saisie_notes"]["datetime_mediane"] + > evaluation["saisie_notes"]["datetime_debut"] ) - assert eval["saisie_notes"]["datetime_debut"] is None or isinstance( - eval["saisie_notes"]["datetime_fin"], str - ) - assert eval["saisie_notes"]["datetime_debut"] is None or isinstance( - eval["saisie_notes"]["datetime_mediane"], str - ) - - if ( - eval["saisie_notes"]["datetime_fin"] is not None - and eval["saisie_notes"]["datetime_mediane"] is not None - and eval["saisie_notes"]["datetime_debut"] is not None - ): - assert ( - eval["saisie_notes"]["datetime_fin"] - > eval["saisie_notes"]["datetime_mediane"] - ) - assert ( - eval["saisie_notes"]["datetime_fin"] - > eval["saisie_notes"]["datetime_debut"] - ) - assert ( - eval["saisie_notes"]["datetime_mediane"] - > eval["saisie_notes"]["datetime_debut"] - ) - - list_id_ue1 = [] - list_titre_ue1 = [] - - list_id_ue2 = [] - list_titre_ue2 = [] - - list_id_ue3 = [] - list_titre_ue3 = [] - i = 0 - for ue in etat_evals.values(): - i += 1 - for module in ue: - if i == 1: - list_id_ue1.append(module["id"]) - list_titre_ue1.append(module["id"]) - elif i == 2: - list_id_ue2.append(module["id"]) - list_titre_ue2.append(module["id"]) - elif i == 3: - list_id_ue3.append(module["id"]) - list_titre_ue3.append(module["id"]) - - assert list_id_ue1 != list_id_ue2 - assert list_id_ue1 != list_titre_ue3 - assert list_id_ue2 != list_titre_ue3 - - assert list_titre_ue1 != list_titre_ue2 - assert list_titre_ue1 != list_titre_ue3 - assert list_titre_ue2 != list_titre_ue3 ##### ERROR ##### fake_eval_id = 153165161656849846516511321651651 diff --git a/tests/api/test_api_logos.py b/tests/api/test_api_logos.py index 9e3ba5a31..3aee0c6da 100644 --- a/tests/api/test_api_logos.py +++ b/tests/api/test_api_logos.py @@ -28,7 +28,7 @@ from tests.unit.config_test_logos import ( def test_super_access(create_super_token): """ - Route: + Route: /logos """ dept1, dept2, dept3, token = create_super_token headers = {"Authorization": f"Bearer {token}"} diff --git a/tests/api/test_api_partitions.py b/tests/api/test_api_partitions.py index aef489ca0..9277b97f0 100644 --- a/tests/api/test_api_partitions.py +++ b/tests/api/test_api_partitions.py @@ -23,7 +23,7 @@ from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers from tests.api.tools_test_api import ( verify_fields, PARTITIONS_FIELDS, - PARTITIONS_GROUPS_ETU_FIELDS, + PARTITION_GROUPS_ETUD_FIELDS, ) @@ -32,24 +32,21 @@ def test_partition(api_headers): Test 'partition' Route : - - /partitions/ + - /partition/ """ partition_id = 1 r = requests.get( - f"{API_URL}/partitions/{partition_id}", + f"{API_URL}/partition/{partition_id}", headers=api_headers, verify=CHECK_CERTIFICATE, ) assert r.status_code == 200 - partitions = r.json() - assert len(partitions) == 1 - assert isinstance(partitions, list) - partition = partitions[0] + partition = r.json() assert isinstance(partition, dict) assert verify_fields(partition, PARTITIONS_FIELDS) is True - assert partition_id == partition["partition_id"] + assert partition_id == partition["id"] - assert isinstance(partition["partition_id"], int) + assert isinstance(partition["id"], int) assert isinstance(partition["id"], int) assert isinstance(partition["formsemestre_id"], int) assert partition["partition_name"] is None or isinstance( @@ -65,61 +62,32 @@ def test_etud_in_group(api_headers): Test 'etud_in_group' Routes : - - /partition/group/ - - /partition/group//etat/ + - /group//etudiants + - /group//etudiants/query?etat= """ group_id = 1 r = requests.get( - f"{API_URL}/partition/group/{group_id}", + f"{API_URL}/group/{group_id}/etudiants", headers=api_headers, verify=CHECK_CERTIFICATE, ) assert r.status_code == 200 assert isinstance(r.json(), list) - for etu in r.json(): - assert verify_fields(etu, PARTITIONS_GROUPS_ETU_FIELDS) - assert isinstance(etu["etudid"], int) - assert isinstance(etu["id"], int) - assert isinstance(etu["dept_id"], int) - assert isinstance(etu["nom"], str) - assert isinstance(etu["prenom"], str) - assert isinstance(etu["nom_usuel"], str) - assert isinstance(etu["civilite"], str) - assert etu["date_naissance"] is None or isinstance(etu["date_naissance"], str) - assert etu["lieu_naissance"] is None or isinstance(etu["lieu_naissance"], str) - assert etu["dept_naissance"] is None or isinstance(etu["dept_naissance"], str) - assert etu["nationalite"] is None or isinstance(etu["nationalite"], str) - assert etu["statut"] is None or isinstance(etu["statut"], str) - assert etu["boursier"] is None or isinstance(etu["boursier"], bool) - assert etu["photo_filename"] is None or isinstance(etu["photo_filename"], str) - assert isinstance(etu["code_nip"], str) - assert isinstance(etu["code_ine"], str) - assert etu["scodoc7_id"] is None or isinstance(etu["scodoc7_id"], int) - assert isinstance(etu["email"], str) - assert etu["emailperso"] is None or isinstance(etu["emailperso"], str) - assert etu["domicile"] is None or isinstance(etu["domicile"], str) - assert etu["codepostaldomicile"] is None or isinstance( - etu["codepostaldomicile"], str - ) - assert etu["villedomicile"] is None or isinstance(etu["villedomicile"], str) - assert etu["paysdomicile"] is None or isinstance(etu["paysdomicile"], str) - assert etu["telephone"] is None or isinstance(etu["telephone"], str) - assert etu["telephonemobile"] is None or isinstance(etu["telephonemobile"], str) - assert etu["fax"] is None or isinstance(etu["fax"], str) - assert isinstance(etu["typeadresse"], str) - assert etu["description"] is None or isinstance(etu["description"], int) - assert isinstance(etu["group_id"], int) - assert isinstance(etu["etat"], str) - assert isinstance(etu["civilite_str"], str) - assert isinstance(etu["nom_disp"], str) - assert isinstance(etu["nomprenom"], str) - assert isinstance(etu["ne"], str) - assert isinstance(etu["email_default"], str) + for etud in r.json(): + assert verify_fields(etud, PARTITION_GROUPS_ETUD_FIELDS) + assert isinstance(etud["id"], int) + assert isinstance(etud["dept_id"], int) + assert isinstance(etud["nom"], str) + assert isinstance(etud["prenom"], str) + assert etud["nom_usuel"] is None or isinstance(etud["nom_usuel"], str) + assert isinstance(etud["civilite"], str) + assert isinstance(etud["code_nip"], str) + assert isinstance(etud["code_ine"], str) etat = "I" r_etat = requests.get( - f"{API_URL}/partition/group/{group_id}/etat/{etat}", + f"{API_URL}/group/{group_id}/etudiants/query?etat={etat}", headers=api_headers, verify=CHECK_CERTIFICATE, ) @@ -127,47 +95,14 @@ def test_etud_in_group(api_headers): assert isinstance(r_etat.json(), list) - for etu in r_etat.json(): - assert verify_fields(etu, PARTITIONS_GROUPS_ETU_FIELDS) - assert isinstance(etu["etudid"], int) - assert isinstance(etu["id"], int) - assert isinstance(etu["dept_id"], int) - assert isinstance(etu["nom"], str) - assert isinstance(etu["prenom"], str) - assert isinstance(etu["nom_usuel"], str) - assert isinstance(etu["civilite"], str) - assert etu["date_naissance"] is None or isinstance(etu["date_naissance"], str) - assert etu["lieu_naissance"] is None or isinstance(etu["lieu_naissance"], str) - assert etu["dept_naissance"] is None or isinstance(etu["dept_naissance"], str) - assert etu["nationalite"] is None or isinstance(etu["nationalite"], str) - assert etu["statut"] is None or isinstance(etu["statut"], str) - assert etu["boursier"] is None or isinstance(etu["boursier"], bool) - assert etu["photo_filename"] is None or isinstance(etu["photo_filename"], str) - assert isinstance(etu["code_nip"], str) - assert isinstance(etu["code_ine"], str) - assert etu["scodoc7_id"] is None or isinstance(etu["scodoc7_id"], int) - assert isinstance(etu["email"], str) - assert etu["emailperso"] is None or isinstance(etu["emailperso"], str) - assert etu["domicile"] is None or isinstance(etu["domicile"], str) - assert etu["codepostaldomicile"] is None or isinstance( - etu["codepostaldomicile"], str - ) - assert etu["villedomicile"] is None or isinstance(etu["villedomicile"], str) - assert etu["paysdomicile"] is None or isinstance(etu["paysdomicile"], str) - assert etu["telephone"] is None or isinstance(etu["telephone"], str) - assert etu["telephonemobile"] is None or isinstance(etu["telephonemobile"], str) - assert etu["fax"] is None or isinstance(etu["fax"], str) - assert isinstance(etu["typeadresse"], str) - assert etu["description"] is None or isinstance(etu["description"], int) - assert isinstance(etu["group_id"], int) - assert isinstance(etu["etat"], str) - assert isinstance(etu["civilite_str"], str) - assert isinstance(etu["nom_disp"], str) - assert isinstance(etu["nomprenom"], str) - assert isinstance(etu["ne"], str) - assert isinstance(etu["email_default"], str) - - assert etat == etu["etat"] + for etud in r_etat.json(): + assert verify_fields(etud, PARTITION_GROUPS_ETUD_FIELDS) + assert isinstance(etud["id"], int) + assert isinstance(etud["dept_id"], int) + assert isinstance(etud["nom"], str) + assert isinstance(etud["prenom"], str) + assert etud["nom_usuel"] is None or isinstance(etud["nom_usuel"], str) + assert isinstance(etud["civilite"], str) # # set_groups diff --git a/tests/api/test_api_permissions.py b/tests/api/test_api_permissions.py index 960e5b423..dc9661aa8 100644 --- a/tests/api/test_api_permissions.py +++ b/tests/api/test_api_permissions.py @@ -40,8 +40,6 @@ def test_permissions(api_headers): assert len(api_rules) > 0 args = { "etudid": 1, - # "date_debut": - # "date_fin": "dept": "TAPI", "dept_ident": "TAPI", "dept_id": 1, @@ -51,7 +49,7 @@ def test_permissions(api_headers): "formation_id": 1, "formsemestre_id": 1, "group_id": 1, - "ine": "1", + "ine": "INE1", "module_id": 1, "moduleimpl_id": 1, "nip": 1, diff --git a/tests/api/tools_test_api.py b/tests/api/tools_test_api.py index bf50cbae0..6ee686e66 100644 --- a/tests/api/tools_test_api.py +++ b/tests/api/tools_test_api.py @@ -15,7 +15,7 @@ def verify_fields(json_response: dict, expected_fields: set) -> bool: return all(field in json_response for field in expected_fields) -def verify_occurences_ids_etus(json_response) -> bool: +def verify_occurences_ids_etuds(json_response) -> bool: """ Vérifie si il n'y a pas deux fois le même id dans la liste d'étudiant donnée en paramètres @@ -23,22 +23,17 @@ def verify_occurences_ids_etus(json_response) -> bool: Retourne True ou False """ - list_etu = json.loads(json_response) + etuds = json.loads(json_response) - list_ids = [etu["id"] for etu in list_etu] - list_nip = [etu["nip"] for etu in list_etu] - list_ine = [etu["ine"] for etu in list_etu] + ids = [etud["id"] for etud in etuds] + nips = [etud["code_nip"] for etud in etuds] + ines = [etud["code_ine"] for etud in etuds] - for id in list_ids: - if list_ids.count(id) > 1: - return False - for nip in list_nip: - if list_nip.count(nip) > 1: - return False - for ine in list_ine: - if list_ine.count(ine) > 1: - return False - return True + return ( + (len(set(ids)) == len(ids)) + and (len(set(nips)) == len(nips)) + and (len(set(ines)) == len(ines)) + ) DEPARTEMENT_FIELDS = [ @@ -200,7 +195,6 @@ FSEM_FIELDS = { "resp_can_edit", "responsables", "semestre_id", - "titre_formation", "titre_num", "titre", } @@ -494,15 +488,16 @@ BULLETIN_SEMESTRE_RANG_FIELDS = {"value", "total"} EVAL_FIELDS = { "id", "description", - "datetime_epreuve", + "jour", + "heure_debut", "heure_fin", "coefficient", - "comptee", - "inscrits", - "manquantes", - "ABS", - "ATT", - "EXC", + "etat", + "nb_inscrits", + "nb_notes_manquantes", + "nb_notes_abs", + "nb_notes_att", + "nb_notes_exc", "saisie_notes", } @@ -536,10 +531,10 @@ ABSENCES_FIELDS = { ABSENCES_GROUP_ETAT_FIELDS = {"etudid", "list_abs"} -FORMSEMESTRE_ETUS_FIELDS = { +FORMSEMESTRE_ETUD_FIELDS = { "id", - "nip", - "ine", + "code_nip", + "code_ine", "nom", "nom_usuel", "prenom", @@ -595,7 +590,6 @@ EVALUATION_FIELDS = { PARTITIONS_FIELDS = { - "partition_id", "id", "formsemestre_id", "partition_name", @@ -604,42 +598,15 @@ PARTITIONS_FIELDS = { "show_in_lists", } -PARTITIONS_GROUPS_ETU_FIELDS = { - "etudid", +PARTITION_GROUPS_ETUD_FIELDS = { "id", "dept_id", "nom", "prenom", "nom_usuel", "civilite", - "date_naissance", - "lieu_naissance", - "dept_naissance", - "nationalite", - "statut", - "boursier", - "photo_filename", "code_nip", "code_ine", - "scodoc7_id", - "email", - "emailperso", - "domicile", - "codepostaldomicile", - "villedomicile", - "paysdomicile", - "telephone", - "telephonemobile", - "fax", - "typeadresse", - "description", - "group_id", - "etat", - "civilite_str", - "nom_disp", - "nomprenom", - "ne", - "email_default", } FORMSEMESTRE_BULLETINS_FIELDS = { diff --git a/tools/fakedatabase/create_test_api_database.py b/tools/fakedatabase/create_test_api_database.py index a9a0f9868..54e074957 100644 --- a/tools/fakedatabase/create_test_api_database.py +++ b/tools/fakedatabase/create_test_api_database.py @@ -4,22 +4,7 @@ Création des départements, formations, semestres, étudiants, groupes... - utilisation: - 1) modifier /opt/scodoc/.env pour indiquer - FLASK_ENV=test_api - FLASK_DEBUG=1 - - 2) En tant qu'utilisateur scodoc, lancer: - tools/create_database.sh - flask db upgrade - flask sco-db-init --erase - flask init-test-database - - - 3) relancer ScoDoc: - flask run --host 0.0.0.0 - - 4) lancer client de test + Utilisation: voir tests/api/README.md """ import datetime @@ -249,34 +234,26 @@ def saisie_notes_evaluations(formsemestre: FormSemestre, user: User): 1 : all_notes_manquantes 2 : some_notes_manquantes """ - if condition == 0 or condition == 2: - if condition == 0: - for etu in list_etuds: - note = NotesNotes( - etu.id, - evaluation_id, - random.uniform(0, 20), - "", - date_debut + random.random() * (date_fin - date_debut), - user.id, - ) - db.session.add(note) - db.session.commit() - else: - percent = 80 / 100 - len_etuds = len(list_etuds) - new_list_etuds = random.sample(list_etuds, k=int(percent * len_etuds)) - for etu in new_list_etuds: - note = NotesNotes( - etu.id, - evaluation_id, - random.uniform(0, 20), - "", - date_debut + random.random() * (date_fin - date_debut), - user.id, - ) - db.session.add(note) - db.session.commit() + if condition == 2: + return # nothing to do + if condition == 0: + list_a_saisir = list_etuds + else: + percent = 80 / 100 + len_etuds = len(list_etuds) + list_a_saisir = random.sample(list_etuds, k=int(percent * len_etuds)) + + for etud in list_a_saisir: + note = NotesNotes( + etudid=etud.id, + evaluation_id=evaluation_id, + value=random.uniform(0, 20), + comment="", + date=date_debut + random.random() * (date_fin - date_debut), + uid=user.id, + ) + db.session.add(note) + db.session.commit() for ue in list_ues: mods = ue.modules @@ -433,21 +410,15 @@ def create_ref_comp(formation: Formation): # apc_referentiel_competences_formations = formation apc_referentiel_competences = ApcReferentielCompetences( - apc_referentiel_competences_id, - apc_referentiel_competences_dept_id, - apc_referentiel_competences_annexe, - apc_referentiel_competences_specialite, - apc_referentiel_competences_specialite_long, - apc_referentiel_competences_type_titre, - apc_referentiel_competences_type_structure, - apc_referentiel_competences_type_departement, - apc_referentiel_competences_version_orebut, - apc_referentiel_competences_xml_attribs, - # apc_referentiel_competences_scodoc_date_loaded, - apc_referentiel_competences_scodoc_orig_filename, - # apc_referentiel_competences_competences, - # apc_referentiel_competences_parcours, - # apc_referentiel_competences_formations, + dept_id=apc_referentiel_competences_dept_id, + annexe=apc_referentiel_competences_annexe, + specialite=apc_referentiel_competences_specialite, + specialite_long=apc_referentiel_competences_specialite_long, + type_titre=apc_referentiel_competences_type_titre, + type_structure=apc_referentiel_competences_type_structure, + type_departement=apc_referentiel_competences_type_departement, + version_orebut=apc_referentiel_competences_version_orebut, + scodoc_orig_filename=apc_referentiel_competences_scodoc_orig_filename, ) db.session.add(apc_referentiel_competences) db.session.commit() @@ -464,23 +435,27 @@ def add_absences(formsemestre: FormSemestre): date_fin = formsemestre.date_fin etuds = formsemestre.etuds - id_db = 1 for etu in etuds: aleatoire = random.randint(0, 1) if aleatoire == 1: nb_absences = random.randint(1, 5) for absence in range(0, nb_absences): - id = id_db etudid = etu.id jour = date_debut + random.random() * (date_fin - date_debut) estabs = True estjust = True if random.randint(0, 1) == 1 else False matin = True if random.randint(0, 1) == 1 else False description = "" - abs = Absence(id, etudid, jour, estabs, estjust, matin, description) - db.session.add(abs) - db.session.commit() - id_db += 1 + absence = Absence( + etudid=etudid, + jour=jour, + estabs=estabs, + estjust=estjust, + matin=matin, + description=description, + ) + db.session.add(absence) + db.session.commit() def create_etape_apo(formsemestre: FormSemestre):