Update opolka/ScoDoc from ScoDoc/ScoDoc #2

Merged
opolka merged 1272 commits from ScoDoc/ScoDoc:master into master 2024-05-27 09:11:04 +02:00
7 changed files with 472 additions and 172 deletions
Showing only changes of commit 5af3e8d14d - Show all commits

View File

@ -59,7 +59,13 @@ def get_model_api_object(model_cls: db.Model, model_id: int, join_cls: db.Model
query = model_cls.query.filter_by(id=model_id) query = model_cls.query.filter_by(id=model_id)
if g.scodoc_dept and join_cls is not None: if g.scodoc_dept and join_cls is not None:
query = query.join(join_cls).filter_by(dept_id=g.scodoc_dept_id) query = query.join(join_cls).filter_by(dept_id=g.scodoc_dept_id)
unique: model_cls = query.first_or_404() unique: model_cls = query.first()
if unique is None:
return scu.json_error(
404,
message=f"{model_cls.__name__} inexistant(e)",
)
return unique.to_dict(format_api=True) return unique.to_dict(format_api=True)

View File

@ -39,6 +39,7 @@ from app.scodoc.sco_utils import json_error
@api_web_bp.route("/assiduite/<int:assiduite_id>") @api_web_bp.route("/assiduite/<int:assiduite_id>")
@scodoc @scodoc
@permission_required(Permission.ScoView) @permission_required(Permission.ScoView)
@as_json
def assiduite(assiduite_id: int = None): def assiduite(assiduite_id: int = None):
"""Retourne un objet assiduité à partir de son id """Retourne un objet assiduité à partir de son id
@ -172,6 +173,7 @@ def count_assiduites(
404, 404,
message="étudiant inconnu", message="étudiant inconnu",
) )
g.scodoc_dept_id = etud.dept_id
# Les filtres qui seront appliqués au comptage (type, date, etudid...) # Les filtres qui seront appliqués au comptage (type, date, etudid...)
filtered: dict[str, object] = {} filtered: dict[str, object] = {}
@ -444,6 +446,8 @@ def count_assiduites_formsemestre(
if formsemestre is None: if formsemestre is None:
return json_error(404, "le paramètre 'formsemestre_id' n'existe pas") return json_error(404, "le paramètre 'formsemestre_id' n'existe pas")
g.scodoc_dept_id = formsemestre.dept_id
# Récupération des étudiants du formsemestre # Récupération des étudiants du formsemestre
etuds = formsemestre.etuds.all() etuds = formsemestre.etuds.all()
etuds_id = [etud.id for etud in etuds] etuds_id = [etud.id for etud in etuds]
@ -833,9 +837,9 @@ def assiduite_edit(assiduite_id: int):
""" """
# Récupération de l'assiduité à modifier # Récupération de l'assiduité à modifier
assiduite_unique: Assiduite = Assiduite.query.filter_by( assiduite_unique: Assiduite = Assiduite.query.filter_by(id=assiduite_id).first()
id=assiduite_id if assiduite_unique is None:
).first_or_404() return json_error(404, "Assiduité non existante")
# Récupération des valeurs à modifier # Récupération des valeurs à modifier
data = request.get_json(force=True) data = request.get_json(force=True)

View File

@ -154,7 +154,9 @@ def justificatifs_dept(dept_id: int = None, with_query: bool = False):
"""XXX TODO missing doc""" """XXX TODO missing doc"""
# Récupération du département et des étudiants du département # Récupération du département et des étudiants du département
dept: Departement = Departement.query.get_or_404(dept_id) dept: Departement = Departement.query.get(dept_id)
if dept is None:
json_error(404, "Assiduité non existante")
etuds: list[int] = [etud.id for etud in dept.etudiants] etuds: list[int] = [etud.id for etud in dept.etudiants]
# Récupération des justificatifs des étudiants du département # Récupération des justificatifs des étudiants du département

View File

@ -81,6 +81,9 @@ def GET(path: str, headers: dict = None, errmsg=None, dept=None):
timeout=SCO_TEST_API_TIMEOUT, timeout=SCO_TEST_API_TIMEOUT,
) )
if reply.status_code != 200: if reply.status_code != 200:
print("url", SCODOC_URL)
print("url", url)
print("reply", reply.text)
raise APIError( raise APIError(
errmsg or f"""erreur status={reply.status_code} !""", reply.json() errmsg or f"""erreur status={reply.status_code} !""", reply.json()
) )
@ -153,7 +156,7 @@ def check_failure_get(path: str, headers: dict, err: str = None):
""" """
try: try:
GET(path=path, headers=headers) GET(path=path, headers=headers, dept=DEPT_ACRONYM)
# ^ Renvoi un 404 # ^ Renvoi un 404
except APIError as api_err: except APIError as api_err:
if err is not None: if err is not None:
@ -177,7 +180,7 @@ def check_failure_post(path: str, headers: dict, data: dict, err: str = None):
""" """
try: try:
data = POST_JSON(path=path, headers=headers, data=data) data = POST_JSON(path=path, headers=headers, data=data, dept=DEPT_ACRONYM)
# ^ Renvoie un 404 # ^ Renvoie un 404
except APIError as api_err: except APIError as api_err:
if err is not None: if err is not None:

View File

@ -11,6 +11,7 @@ from types import NoneType
from tests.api.setup_test_api import ( from tests.api.setup_test_api import (
GET, GET,
POST_JSON, POST_JSON,
DEPT_ACRONYM,
APIError, APIError,
api_headers, api_headers,
api_admin_headers, api_admin_headers,
@ -45,7 +46,7 @@ ASSIDUITES_FIELDS = {
CREATE_FIELD = {"assiduite_id": int} CREATE_FIELD = {"assiduite_id": int}
BATCH_FIELD = {"errors": list, "success": list} BATCH_FIELD = {"errors": list, "success": list}
COUNT_FIELDS = {"compte": int, "journee": int, "demi": int, "heure": float} COUNT_FIELDS = {"compte": int, "journee": int, "demi": int, "heure": int | float}
TO_REMOVE = [] TO_REMOVE = []
@ -81,7 +82,7 @@ def test_route_assiduite(api_headers):
"""test de la route /assiduite/<assiduite_id:int>""" """test de la route /assiduite/<assiduite_id:int>"""
# Bon fonctionnement == id connu # Bon fonctionnement == id connu
data = GET(path="/assiduite/1", headers=api_headers) data = GET(path="/assiduite/1", headers=api_headers, dept=DEPT_ACRONYM)
check_fields(data, fields=ASSIDUITES_FIELDS) check_fields(data, fields=ASSIDUITES_FIELDS)
# Mauvais Fonctionnement == id inconnu # Mauvais Fonctionnement == id inconnu
@ -97,13 +98,16 @@ def test_route_count_assiduites(api_headers):
# Bon fonctionnement # Bon fonctionnement
data = GET(path=f"/assiduites/{ETUDID}/count", headers=api_headers) data = GET(
path=f"/assiduites/{ETUDID}/count", headers=api_headers, dept=DEPT_ACRONYM
)
check_fields(data, COUNT_FIELDS) check_fields(data, COUNT_FIELDS)
metrics = {"heure", "compte"} metrics = {"heure", "compte"}
data = GET( data = GET(
path=f"/assiduites/{ETUDID}/count/query?metric={','.join(metrics)}", path=f"/assiduites/{ETUDID}/count/query?metric={','.join(metrics)}",
headers=api_headers, headers=api_headers,
dept=DEPT_ACRONYM,
) )
assert set(data.keys()) == metrics assert set(data.keys()) == metrics
@ -118,12 +122,14 @@ def test_route_assiduites(api_headers):
# Bon fonctionnement # Bon fonctionnement
data = GET(path=f"/assiduites/{ETUDID}", headers=api_headers) data = GET(path=f"/assiduites/{ETUDID}", headers=api_headers, dept=DEPT_ACRONYM)
assert isinstance(data, list) assert isinstance(data, list)
for ass in data: for ass in data:
check_fields(ass, ASSIDUITES_FIELDS) check_fields(ass, ASSIDUITES_FIELDS)
data = GET(path=f"/assiduites/{ETUDID}/query?", headers=api_headers) data = GET(
path=f"/assiduites/{ETUDID}/query?", headers=api_headers, dept=DEPT_ACRONYM
)
assert isinstance(data, list) assert isinstance(data, list)
for ass in data: for ass in data:
check_fields(ass, ASSIDUITES_FIELDS) check_fields(ass, ASSIDUITES_FIELDS)
@ -138,13 +144,19 @@ def test_route_formsemestre_assiduites(api_headers):
# Bon fonctionnement # Bon fonctionnement
data = GET(path=f"/assiduites/formsemestre/{FORMSEMESTREID}", headers=api_headers) data = GET(
path=f"/assiduites/formsemestre/{FORMSEMESTREID}",
headers=api_headers,
dept=DEPT_ACRONYM,
)
assert isinstance(data, list) assert isinstance(data, list)
for ass in data: for ass in data:
check_fields(ass, ASSIDUITES_FIELDS) check_fields(ass, ASSIDUITES_FIELDS)
data = GET( data = GET(
path=f"/assiduites/formsemestre/{FORMSEMESTREID}/query?", headers=api_headers path=f"/assiduites/formsemestre/{FORMSEMESTREID}/query?",
headers=api_headers,
dept=DEPT_ACRONYM,
) )
assert isinstance(data, list) assert isinstance(data, list)
for ass in data: for ass in data:
@ -169,13 +181,19 @@ def test_route_count_formsemestre_assiduites(api_headers):
# Bon fonctionnement # Bon fonctionnement
data = GET( data = GET(
path=f"/assiduites/formsemestre/{FORMSEMESTREID}/count", headers=api_headers path=f"/assiduites/formsemestre/{FORMSEMESTREID}/count",
headers=api_headers,
dept=DEPT_ACRONYM,
) )
print("data: ", data)
check_fields(data, COUNT_FIELDS) check_fields(data, COUNT_FIELDS)
metrics = {"heure", "compte"} metrics = {"heure", "compte"}
data = GET( data = GET(
path=f"/assiduites/formsemestre/{FORMSEMESTREID}/count/query?metric={','.join(metrics)}", path=f"/assiduites/formsemestre/{FORMSEMESTREID}/count/query?metric={','.join(metrics)}",
headers=api_headers, headers=api_headers,
dept=DEPT_ACRONYM,
) )
assert set(data.keys()) == metrics assert set(data.keys()) == metrics
@ -198,9 +216,11 @@ def test_route_create(api_admin_headers):
# -== Unique ==- # -== Unique ==-
# Bon fonctionnement # Bon fonctionnement
data = create_data("present", "01") data = create_data("present", "03")
res = POST_JSON(f"/assiduite/{ETUDID}/create", [data], api_admin_headers) res = POST_JSON(
f"/assiduite/{ETUDID}/create", [data], api_admin_headers, dept=DEPT_ACRONYM
)
check_fields(res, BATCH_FIELD) check_fields(res, BATCH_FIELD)
assert len(res["success"]) == 1 assert len(res["success"]) == 1
@ -208,11 +228,14 @@ def test_route_create(api_admin_headers):
data = GET( data = GET(
path=f'/assiduite/{res["success"][0]["message"]["assiduite_id"]}', path=f'/assiduite/{res["success"][0]["message"]["assiduite_id"]}',
headers=api_admin_headers, headers=api_admin_headers,
dept=DEPT_ACRONYM,
) )
check_fields(data, fields=ASSIDUITES_FIELDS) check_fields(data, fields=ASSIDUITES_FIELDS)
data2 = create_data("absent", "02", MODULE, "desc") data2 = create_data("absent", "04", MODULE, "desc")
res = POST_JSON(f"/assiduite/{ETUDID}/create", [data2], api_admin_headers) res = POST_JSON(
f"/assiduite/{ETUDID}/create", [data2], api_admin_headers, dept=DEPT_ACRONYM
)
check_fields(res, BATCH_FIELD) check_fields(res, BATCH_FIELD)
assert len(res["success"]) == 1 assert len(res["success"]) == 1
@ -221,7 +244,9 @@ def test_route_create(api_admin_headers):
# Mauvais fonctionnement # Mauvais fonctionnement
check_failure_post(f"/assiduite/{FAUX}/create", api_admin_headers, [data]) check_failure_post(f"/assiduite/{FAUX}/create", api_admin_headers, [data])
res = POST_JSON(f"/assiduite/{ETUDID}/create", [data], api_admin_headers) res = POST_JSON(
f"/assiduite/{ETUDID}/create", [data], api_admin_headers, dept=DEPT_ACRONYM
)
check_fields(res, BATCH_FIELD) check_fields(res, BATCH_FIELD)
assert len(res["errors"]) == 1 assert len(res["errors"]) == 1
assert ( assert (
@ -231,8 +256,9 @@ def test_route_create(api_admin_headers):
res = POST_JSON( res = POST_JSON(
f"/assiduite/{ETUDID}/create", f"/assiduite/{ETUDID}/create",
[create_data("absent", "03", FAUX)], [create_data("absent", "05", FAUX)],
api_admin_headers, api_admin_headers,
dept=DEPT_ACRONYM,
) )
check_fields(res, BATCH_FIELD) check_fields(res, BATCH_FIELD)
assert len(res["errors"]) == 1 assert len(res["errors"]) == 1
@ -245,10 +271,12 @@ def test_route_create(api_admin_headers):
etats = ["present", "absent", "retard"] etats = ["present", "absent", "retard"]
data = [ data = [
create_data(etats[d % 3], 10 + d, MODULE if d % 2 else None) create_data(etats[d % 3], 10 + d, MODULE if d % 2 else None)
for d in range(randint(3, 5)) for d in range(randint(2, 4))
] ]
res = POST_JSON(f"/assiduite/{ETUDID}/create", data, api_admin_headers) res = POST_JSON(
f"/assiduite/{ETUDID}/create", data, api_admin_headers, dept=DEPT_ACRONYM
)
check_fields(res, BATCH_FIELD) check_fields(res, BATCH_FIELD)
for dat in res["success"]: for dat in res["success"]:
check_fields(dat["message"], CREATE_FIELD) check_fields(dat["message"], CREATE_FIELD)
@ -257,15 +285,18 @@ def test_route_create(api_admin_headers):
# Mauvais Fonctionnement # Mauvais Fonctionnement
data2 = [ data2 = [
create_data("present", "01"), create_data("present", "03"),
create_data("present", "25", FAUX), create_data("present", "25", FAUX),
create_data("blabla", 26), create_data("blabla", 26),
create_data("absent", 32), create_data("absent", 32),
create_data("absent", "01"),
] ]
res = POST_JSON(f"/assiduite/{ETUDID}/create", data2, api_admin_headers) res = POST_JSON(
f"/assiduite/{ETUDID}/create", data2, api_admin_headers, dept=DEPT_ACRONYM
)
check_fields(res, BATCH_FIELD) check_fields(res, BATCH_FIELD)
assert len(res["errors"]) == 4 assert len(res["errors"]) == 5
assert ( assert (
res["errors"][0]["message"] res["errors"][0]["message"]
@ -277,6 +308,7 @@ def test_route_create(api_admin_headers):
res["errors"][3]["message"] res["errors"][3]["message"]
== "param 'date_debut': format invalide, param 'date_fin': format invalide" == "param 'date_debut': format invalide, param 'date_fin': format invalide"
) )
assert res["errors"][4]["message"] == "La date de début n'est pas un jour travaillé"
def test_route_edit(api_admin_headers): def test_route_edit(api_admin_headers):
@ -285,11 +317,15 @@ def test_route_edit(api_admin_headers):
# Bon fonctionnement # Bon fonctionnement
data = {"etat": "retard", "moduleimpl_id": MODULE} data = {"etat": "retard", "moduleimpl_id": MODULE}
res = POST_JSON(f"/assiduite/{TO_REMOVE[0]}/edit", data, api_admin_headers) res = POST_JSON(
f"/assiduite/{TO_REMOVE[0]}/edit", data, api_admin_headers, dept=DEPT_ACRONYM
)
assert res == {"OK": True} assert res == {"OK": True}
data["moduleimpl_id"] = None data["moduleimpl_id"] = None
res = POST_JSON(f"/assiduite/{TO_REMOVE[1]}/edit", data, api_admin_headers) res = POST_JSON(
f"/assiduite/{TO_REMOVE[1]}/edit", data, api_admin_headers, dept=DEPT_ACRONYM
)
assert res == {"OK": True} assert res == {"OK": True}
# Mauvais fonctionnement # Mauvais fonctionnement
@ -311,13 +347,13 @@ def test_route_delete(api_admin_headers):
# Bon fonctionnement # Bon fonctionnement
data = TO_REMOVE[0] data = TO_REMOVE[0]
res = POST_JSON("/assiduite/delete", [data], api_admin_headers) res = POST_JSON("/assiduite/delete", [data], api_admin_headers, dept=DEPT_ACRONYM)
check_fields(res, BATCH_FIELD) check_fields(res, BATCH_FIELD)
for dat in res["success"]: for dat in res["success"]:
assert dat["message"] == "OK" assert dat["message"] == "OK"
# Mauvais fonctionnement # Mauvais fonctionnement
res = POST_JSON("/assiduite/delete", [data], api_admin_headers) res = POST_JSON("/assiduite/delete", [data], api_admin_headers, dept=DEPT_ACRONYM)
check_fields(res, BATCH_FIELD) check_fields(res, BATCH_FIELD)
assert len(res["errors"]) == 1 assert len(res["errors"]) == 1
@ -327,7 +363,7 @@ def test_route_delete(api_admin_headers):
data = TO_REMOVE[1:] data = TO_REMOVE[1:]
res = POST_JSON("/assiduite/delete", data, api_admin_headers) res = POST_JSON("/assiduite/delete", data, api_admin_headers, dept=DEPT_ACRONYM)
check_fields(res, BATCH_FIELD) check_fields(res, BATCH_FIELD)
for dat in res["success"]: for dat in res["success"]:
assert dat["message"] == "OK" assert dat["message"] == "OK"
@ -340,7 +376,7 @@ def test_route_delete(api_admin_headers):
FAUX + 2, FAUX + 2,
] ]
res = POST_JSON("/assiduite/delete", data2, api_admin_headers) res = POST_JSON("/assiduite/delete", data2, api_admin_headers, dept=DEPT_ACRONYM)
check_fields(res, BATCH_FIELD) check_fields(res, BATCH_FIELD)
assert len(res["errors"]) == 3 assert len(res["errors"]) == 3

View File

@ -50,106 +50,30 @@ def test_bi_directional_enum(test_client):
def test_general(test_client): def test_general(test_client):
"""tests général du modèle assiduite""" """tests général du modèle assiduite"""
g_fake = sco_fake_gen.ScoFake(verbose=False) data: dict = _setup_fake_db(
dates_formsemestre=[
# Création d'une formation (1) ("01/09/2022", "31/12/2022"),
("01/01/2023", "31/07/2023"),
formation_id = g_fake.create_formation() ("01/01/2024", "31/07/2024"),
ue_id = g_fake.create_ue( ],
formation_id=formation_id, acronyme="T1", titre="UE TEST 1" nb_modules=2,
nb_etuds=3,
) )
matiere_id = g_fake.create_matiere(ue_id=ue_id, titre="test matière") etuds, moduleimpls, etud_faux, formsemestres = (
module_id_1 = g_fake.create_module( data["etuds"],
matiere_id=matiere_id, code="Mo1", coefficient=1.0, titre="test module" data["moduleimpls"],
data["etud_faux"],
data["formsemestres"],
) )
module_id_2 = g_fake.create_module(
matiere_id=matiere_id, code="Mo2", coefficient=1.0, titre="test module2"
)
# Création semestre (2)
formsemestre_id_1 = g_fake.create_formsemestre(
formation_id=formation_id,
semestre_id=1,
date_debut="01/09/2022",
date_fin="31/12/2022",
)
formsemestre_id_2 = g_fake.create_formsemestre(
formation_id=formation_id,
semestre_id=2,
date_debut="01/01/2023",
date_fin="31/07/2023",
)
formsemestre_id_3 = g_fake.create_formsemestre(
formation_id=formation_id,
semestre_id=3,
date_debut="01/01/2024",
date_fin="31/07/2024",
)
formsemestre_1 = FormSemestre.get_formsemestre(formsemestre_id_1)
formsemestre_2 = FormSemestre.get_formsemestre(formsemestre_id_2)
formsemestre_3 = FormSemestre.get_formsemestre(formsemestre_id_3)
# Création des modulesimpls (4, 2 par semestre)
moduleimpl_1_1 = g_fake.create_moduleimpl(
module_id=module_id_1,
formsemestre_id=formsemestre_id_1,
)
moduleimpl_1_2 = g_fake.create_moduleimpl(
module_id=module_id_2,
formsemestre_id=formsemestre_id_1,
)
moduleimpl_2_1 = g_fake.create_moduleimpl(
module_id=module_id_1,
formsemestre_id=formsemestre_id_2,
)
moduleimpl_2_2 = g_fake.create_moduleimpl(
module_id=module_id_2,
formsemestre_id=formsemestre_id_2,
)
moduleimpls = [
moduleimpl_1_1,
moduleimpl_1_2,
moduleimpl_2_1,
moduleimpl_2_2,
]
moduleimpls = [
ModuleImpl.query.filter_by(id=mi_id).first() for mi_id in moduleimpls
]
# Création de 3 étudiants
etud_0 = g_fake.create_etud(prenom="etud0")
etud_1 = g_fake.create_etud(prenom="etud1")
etud_2 = g_fake.create_etud(prenom="etud2")
etuds_dict = [etud_0, etud_1, etud_2]
# etuds_dict = [g_fake.create_etud(prenom=f"etud{i}") for i in range(3)]
etuds = []
for etud in etuds_dict:
g_fake.inscrit_etudiant(formsemestre_id=formsemestre_id_1, etud=etud)
g_fake.inscrit_etudiant(formsemestre_id=formsemestre_id_2, etud=etud)
etuds.append(Identite.query.filter_by(id=etud["etudid"]).first())
assert None not in etuds, "Problème avec la conversion en Identite"
# Etudiant faux
etud_faux_dict = g_fake.create_etud(prenom="etudfaux")
etud_faux = Identite.query.filter_by(id=etud_faux_dict["etudid"]).first()
verif_migration_abs_assiduites() verif_migration_abs_assiduites()
ajouter_assiduites(etuds, moduleimpls, etud_faux) ajouter_assiduites(etuds, moduleimpls, etud_faux)
justificatifs: list[Justificatif] = ajouter_justificatifs(etuds[0]) justificatifs: list[Justificatif] = ajouter_justificatifs(etuds[0])
verifier_comptage_et_filtrage_assiduites( verifier_comptage_et_filtrage_assiduites(etuds, moduleimpls[:4], formsemestres)
etuds, moduleimpls, (formsemestre_1, formsemestre_2, formsemestre_3)
)
verifier_filtrage_justificatifs(etuds[0], justificatifs) verifier_filtrage_justificatifs(etuds[0], justificatifs)
essais_cache(etuds[0].etudid, (formsemestre_1, formsemestre_2), moduleimpls) essais_cache(etuds[0].etudid, formsemestres[:2], moduleimpls)
editer_supprimer_assiduites(etuds, moduleimpls) editer_supprimer_assiduites(etuds, moduleimpls)
editer_supprimer_justificatif(etuds[0]) editer_supprimer_justificatif(etuds[0])
@ -531,8 +455,8 @@ def ajouter_justificatifs(etud):
obj_justificatifs = [ obj_justificatifs = [
{ {
"etat": scu.EtatJustificatif.ATTENTE, "etat": scu.EtatJustificatif.ATTENTE,
"deb": "2022-09-03T08:00+01:00", "deb": "2022-09-05T08:00+01:00",
"fin": "2022-09-03T09:59:59+01:00", "fin": "2022-09-05T09:59:59+01:00",
"raison": None, "raison": None,
}, },
{ {
@ -543,14 +467,14 @@ def ajouter_justificatifs(etud):
}, },
{ {
"etat": scu.EtatJustificatif.VALIDE, "etat": scu.EtatJustificatif.VALIDE,
"deb": "2022-09-03T10:00:00+01:00", "deb": "2022-09-05T10:00:00+01:00",
"fin": "2022-09-03T12:00+01:00", "fin": "2022-09-05T12:00+01:00",
"raison": None, "raison": None,
}, },
{ {
"etat": scu.EtatJustificatif.NON_VALIDE, "etat": scu.EtatJustificatif.NON_VALIDE,
"deb": "2022-09-03T14:00:00+01:00", "deb": "2022-09-05T14:00:00+01:00",
"fin": "2022-09-03T15:00+01:00", "fin": "2022-09-05T15:00+01:00",
"raison": "Description", "raison": "Description",
}, },
{ {
@ -581,14 +505,6 @@ def ajouter_justificatifs(etud):
justi for justi in justificatifs if not isinstance(justi, Justificatif) justi for justi in justificatifs if not isinstance(justi, Justificatif)
] == [], "La création des justificatifs de base n'est pas OK" ] == [], "La création des justificatifs de base n'est pas OK"
# Vérification de la gestion des erreurs
test_assiduite = {
"etat": scu.EtatJustificatif.ATTENTE,
"deb": "2023-01-03T11:00:01+01:00",
"fin": "2023-01-03T12:00+01:00",
"raison": "Description",
}
return justificatifs return justificatifs
@ -646,19 +562,19 @@ def verifier_filtrage_justificatifs(etud: Identite, justificatifs: list[Justific
== 5 == 5
), "Filtrage 'Toute Date' mauvais 2" ), "Filtrage 'Toute Date' mauvais 2"
date = scu.localize_datetime("2022-09-03T08:00+01:00") date = scu.localize_datetime("2022-09-05T08:00+01:00")
assert ( assert (
scass.filter_by_date(etud.justificatifs, Justificatif, date_deb=date).count() scass.filter_by_date(etud.justificatifs, Justificatif, date_deb=date).count()
== 5 == 5
), "Filtrage 'date début' mauvais 3" ), "Filtrage 'date début' mauvais 3"
date = scu.localize_datetime("2022-09-03T08:00:01+01:00") date = scu.localize_datetime("2022-09-05T08:00:01+01:00")
assert ( assert (
scass.filter_by_date(etud.justificatifs, Justificatif, date_deb=date).count() scass.filter_by_date(etud.justificatifs, Justificatif, date_deb=date).count()
== 5 == 5
), "Filtrage 'date début' mauvais 4" ), "Filtrage 'date début' mauvais 4"
date = scu.localize_datetime("2022-09-03T10:00+01:00") date = scu.localize_datetime("2022-09-05T10:00+01:00")
assert ( assert (
scass.filter_by_date(etud.justificatifs, Justificatif, date_deb=date).count() scass.filter_by_date(etud.justificatifs, Justificatif, date_deb=date).count()
== 4 == 4
@ -668,25 +584,25 @@ def verifier_filtrage_justificatifs(etud: Identite, justificatifs: list[Justific
assert ( assert (
scass.filter_by_date(etud.justificatifs, Justificatif, date_fin=date).count() scass.filter_by_date(etud.justificatifs, Justificatif, date_fin=date).count()
== 0 == 0
), "Filtrage 'Toute Date' mauvais 6" ), "Filtrage 'date fin' mauvais 6"
date = scu.localize_datetime("2022-09-03T08:00+01:00") date = scu.localize_datetime("2022-09-05T08:00+01:00")
assert ( assert (
scass.filter_by_date(etud.justificatifs, Justificatif, date_fin=date).count() scass.filter_by_date(etud.justificatifs, Justificatif, date_fin=date).count()
== 1 == 1
), "Filtrage 'date début' mauvais 7" ), "Filtrage 'date fin' mauvais 7"
date = scu.localize_datetime("2022-09-03T10:00:01+01:00") date = scu.localize_datetime("2022-09-05T10:00:01+01:00")
assert ( assert (
scass.filter_by_date(etud.justificatifs, Justificatif, date_fin=date).count() scass.filter_by_date(etud.justificatifs, Justificatif, date_fin=date).count()
== 2 == 2
), "Filtrage 'date début' mauvais 8" ), "Filtrage 'date fin' mauvais 8"
date = scu.localize_datetime("2023-01-03T12:00+01:00") date = scu.localize_datetime("2023-01-03T12:00+01:00")
assert ( assert (
scass.filter_by_date(etud.justificatifs, Justificatif, date_fin=date).count() scass.filter_by_date(etud.justificatifs, Justificatif, date_fin=date).count()
== 5 == 5
), "Filtrage 'date début' mauvais 9" ), "Filtrage 'date fin' mauvais 9"
# Justifications des assiduites # Justifications des assiduites
@ -785,8 +701,8 @@ def ajouter_assiduites(
obj_assiduites = [ obj_assiduites = [
{ {
"etat": scu.EtatAssiduite.PRESENT, "etat": scu.EtatAssiduite.PRESENT,
"deb": "2022-09-03T08:00+01:00", "deb": "2022-09-05T08:00+01:00",
"fin": "2022-09-03T10:00+01:00", "fin": "2022-09-05T10:00+01:00",
"moduleimpl": None, "moduleimpl": None,
"desc": None, "desc": None,
}, },
@ -799,15 +715,15 @@ def ajouter_assiduites(
}, },
{ {
"etat": scu.EtatAssiduite.ABSENT, "etat": scu.EtatAssiduite.ABSENT,
"deb": "2022-09-03T10:00:01+01:00", "deb": "2022-09-05T10:00:01+01:00",
"fin": "2022-09-03T11:00+01:00", "fin": "2022-09-05T11:00+01:00",
"moduleimpl": moduleimpls[0], "moduleimpl": moduleimpls[0],
"desc": None, "desc": None,
}, },
{ {
"etat": scu.EtatAssiduite.ABSENT, "etat": scu.EtatAssiduite.ABSENT,
"deb": "2022-09-03T14:00:00+01:00", "deb": "2022-09-05T14:00:00+01:00",
"fin": "2022-09-03T15:00+01:00", "fin": "2022-09-05T15:00+01:00",
"moduleimpl": moduleimpls[1], "moduleimpl": moduleimpls[1],
"desc": "Description", "desc": "Description",
}, },
@ -877,6 +793,44 @@ def ajouter_assiduites(
excp.args[0] excp.args[0]
== "Duplication: la période rentre en conflit avec une plage enregistrée" == "Duplication: la période rentre en conflit avec une plage enregistrée"
) )
try:
test_assiduite2 = {
"etat": scu.EtatAssiduite.RETARD,
"deb": "2022-09-03T11:00:01+01:00",
"fin": "2022-09-03T12:00+01:00",
"moduleimpl": moduleimpls[3],
"desc": "Description",
}
Assiduite.create_assiduite(
etuds[0],
scu.is_iso_formated(test_assiduite2["deb"], True),
scu.is_iso_formated(test_assiduite2["fin"], True),
test_assiduite2["etat"],
test_assiduite2["moduleimpl"],
test_assiduite2["desc"],
)
except ScoValueError as excp:
assert excp.args[0] == "La date de début n'est pas un jour travaillé"
try:
test_assiduite2 = {
"etat": scu.EtatAssiduite.RETARD,
"deb": "2022-09-02T11:00:01+01:00",
"fin": "2022-09-03T12:00+01:00",
"moduleimpl": moduleimpls[3],
"desc": "Description",
}
Assiduite.create_assiduite(
etuds[0],
scu.is_iso_formated(test_assiduite2["deb"], True),
scu.is_iso_formated(test_assiduite2["fin"], True),
test_assiduite2["etat"],
test_assiduite2["moduleimpl"],
test_assiduite2["desc"],
)
except ScoValueError as excp:
assert excp.args[0] == "La date de fin n'est pas un jour travaillé"
try: try:
Assiduite.create_assiduite( Assiduite.create_assiduite(
etud_faux, etud_faux,
@ -904,20 +858,6 @@ def verifier_comptage_et_filtrage_assiduites(
mod11, mod12, mod21, mod22 = moduleimpls mod11, mod12, mod21, mod22 = moduleimpls
# Vérification du comptage classique
comptage = scass.get_assiduites_stats(etu1.assiduites)
assert comptage["compte"] == 6 + 1, "la métrique 'Comptage' n'est pas bien calculée"
assert (
comptage["journee"] == 3 + 22
), "la métrique 'Journée' n'est pas bien calculée"
assert (
comptage["demi"] == 4 + 43
), "la métrique 'Demi-Journée' n'est pas bien calculée"
assert comptage["heure"] == float(
8 + 169
), "la métrique 'Heure' n'est pas bien calculée"
# Vérification du filtrage classique # Vérification du filtrage classique
# Etat # Etat
@ -993,12 +933,12 @@ def verifier_comptage_et_filtrage_assiduites(
scass.filter_by_date(etu2.assiduites, Assiduite, date_deb=date).count() == 7 scass.filter_by_date(etu2.assiduites, Assiduite, date_deb=date).count() == 7
), "Filtrage 'Date début' mauvais 2" ), "Filtrage 'Date début' mauvais 2"
date = scu.localize_datetime("2022-09-03T10:00+01:00") date = scu.localize_datetime("2022-09-05T10:00+01:00")
assert ( assert (
scass.filter_by_date(etu2.assiduites, Assiduite, date_deb=date).count() == 7 scass.filter_by_date(etu2.assiduites, Assiduite, date_deb=date).count() == 7
), "Filtrage 'Date début' mauvais 3" ), "Filtrage 'Date début' mauvais 3"
date = scu.localize_datetime("2022-09-03T16:00+01:00") date = scu.localize_datetime("2022-09-05T16:00+01:00")
assert ( assert (
scass.filter_by_date(etu2.assiduites, Assiduite, date_deb=date).count() == 4 scass.filter_by_date(etu2.assiduites, Assiduite, date_deb=date).count() == 4
), "Filtrage 'Date début' mauvais 4" ), "Filtrage 'Date début' mauvais 4"
@ -1010,17 +950,17 @@ def verifier_comptage_et_filtrage_assiduites(
scass.filter_by_date(etu2.assiduites, Assiduite, date_fin=date).count() == 0 scass.filter_by_date(etu2.assiduites, Assiduite, date_fin=date).count() == 0
), "Filtrage 'Date fin' mauvais 1" ), "Filtrage 'Date fin' mauvais 1"
date = scu.localize_datetime("2022-09-03T10:00+01:00") date = scu.localize_datetime("2022-09-05T10:00+01:00")
assert ( assert (
scass.filter_by_date(etu2.assiduites, Assiduite, date_fin=date).count() == 1 scass.filter_by_date(etu2.assiduites, Assiduite, date_fin=date).count() == 1
), "Filtrage 'Date fin' mauvais 2" ), "Filtrage 'Date fin' mauvais 2"
date = scu.localize_datetime("2022-09-03T10:00:01+01:00") date = scu.localize_datetime("2022-09-05T10:00:01+01:00")
assert ( assert (
scass.filter_by_date(etu2.assiduites, Assiduite, date_fin=date).count() == 2 scass.filter_by_date(etu2.assiduites, Assiduite, date_fin=date).count() == 2
), "Filtrage 'Date fin' mauvais 3" ), "Filtrage 'Date fin' mauvais 3"
date = scu.localize_datetime("2022-09-03T16:00+01:00") date = scu.localize_datetime("2022-09-05T16:00+01:00")
assert ( assert (
scass.filter_by_date(etu2.assiduites, Assiduite, date_fin=date).count() == 3 scass.filter_by_date(etu2.assiduites, Assiduite, date_fin=date).count() == 3
), "Filtrage 'Date fin' mauvais 4" ), "Filtrage 'Date fin' mauvais 4"
@ -1112,3 +1052,310 @@ def _create_abs(
db.session.add_all(abs_list) db.session.add_all(abs_list)
db.session.commit() db.session.commit()
def _setup_fake_db(
dates_formsemestre: list[tuple[str, str]],
nb_modules: int = 0,
nb_etuds: int = 1,
) -> dict:
g_fake = sco_fake_gen.ScoFake(verbose=False)
# Création d'une formation
formation_id = g_fake.create_formation()
ue_id = g_fake.create_ue(
formation_id=formation_id, acronyme="T1", titre="UE TEST 1"
)
matiere_id = g_fake.create_matiere(ue_id=ue_id, titre="test matière")
module_ids: list[int] = [
g_fake.create_module(
matiere_id=matiere_id,
code=f"Mo{i}",
coefficient=1.0,
titre=f"test module{i}",
)
for i in range(nb_modules)
]
# Création semestre
formsemestre_ids: list[int] = [
g_fake.create_formsemestre(
formation_id=formation_id,
semestre_id=1,
date_debut=deb,
date_fin=fin,
)
for deb, fin in dates_formsemestre
]
formsemestres: list[FormSemestre] = list(
map(FormSemestre.get_formsemestre, formsemestre_ids)
)
# Création des modulesimpls (2 par semestre)
moduleimpls: list[int] = []
for i in range(len(dates_formsemestre)):
for j in range(nb_modules):
mod, form = module_ids[j], formsemestres[i]
moduleimpl_id: int = g_fake.create_moduleimpl(
module_id=mod,
formsemestre_id=form.id,
)
moduleimpls.append(ModuleImpl.query.filter_by(id=moduleimpl_id).first())
# Création de 3 étudiants
etud_0 = g_fake.create_etud(prenom="etud0")
etud_1 = g_fake.create_etud(prenom="etud1")
etud_2 = g_fake.create_etud(prenom="etud2")
etuds_dict = [etud_0, etud_1, etud_2]
etud_dicts: list[dict] = [
g_fake.create_etud(prenom=f"etud{i}") for i in range(nb_etuds)
]
etuds = []
for etud in etuds_dict:
for form_id in formsemestre_ids:
g_fake.inscrit_etudiant(formsemestre_id=form_id, etud=etud)
etuds.append(Identite.query.filter_by(id=etud["etudid"]).first())
# Etudiant faux
etud_faux_dict = g_fake.create_etud(prenom="etudfaux")
etud_faux = Identite.query.filter_by(id=etud_faux_dict["etudid"]).first()
return {
"moduleimpls": moduleimpls,
"formsemestres": formsemestres,
"etuds": etuds,
"etud_faux": etud_faux,
}
def test_calcul_assiduites(test_client):
"""Vérification du bon calcul des assiduités"""
data: dict = _setup_fake_db([("01/12/2023", "31/12/2023")])
formsemestre: FormSemestre = data["formsemestres"][0]
etud: Identite = data["etuds"][0]
"""
Exemple tuple:
(
"12-04T08:00", # Date de début
"12-04T09:00", # Date de fin
scu.EtatAssiduite.ABSENT, # Etat
False # est_just
)
"""
assiduites: list[tuple] = [
# Journée du 04/12
(
"12-04T08:00",
"12-04T10:00",
scu.EtatAssiduite.ABSENT,
False,
),
(
"12-04T10:15",
"12-04T12:15",
scu.EtatAssiduite.RETARD,
False,
),
(
"12-04T13:15",
"12-04T15:15",
scu.EtatAssiduite.PRESENT,
False,
),
(
"12-04T15:15",
"12-04T17:00",
scu.EtatAssiduite.ABSENT,
True,
),
# 05/12
(
"12-05T08:00",
"12-05T09:00",
scu.EtatAssiduite.RETARD,
True,
),
(
"12-05T09:00",
"12-05T10:00",
scu.EtatAssiduite.PRESENT,
False,
),
(
"12-05T10:15",
"12-05T12:15",
scu.EtatAssiduite.PRESENT,
False,
),
(
"12-05T13:15",
"12-05T14:30",
scu.EtatAssiduite.ABSENT,
False,
),
(
"12-05T14:30",
"12-05T16:30",
scu.EtatAssiduite.RETARD,
False,
),
(
"12-05T16:30",
"12-05T17:00",
scu.EtatAssiduite.PRESENT,
False,
),
# 06/12
(
"12-06T08:00",
"12-06T10:00",
scu.EtatAssiduite.PRESENT,
False,
),
(
"12-06T10:15",
"12-06T12:15",
scu.EtatAssiduite.RETARD,
False,
),
(
"12-06T13:15",
"12-06T13:45",
scu.EtatAssiduite.ABSENT,
True,
),
(
"12-06T13:45",
"12-06T15:00",
scu.EtatAssiduite.PRESENT,
False,
),
(
"12-06T15:00",
"12-06T17:00",
scu.EtatAssiduite.RETARD,
False,
),
# 07/12
(
"12-07T08:00",
"12-07T08:30",
scu.EtatAssiduite.RETARD,
True,
),
(
"12-07T08:30",
"12-07T10:00",
scu.EtatAssiduite.PRESENT,
False,
),
(
"12-07T10:15",
"12-07T12:15",
scu.EtatAssiduite.ABSENT,
True,
),
# 08/12
(
"12-08T08:00",
"12-08T10:00",
scu.EtatAssiduite.PRESENT,
False,
),
(
"12-08T10:15",
"12-08T12:15",
scu.EtatAssiduite.ABSENT,
False,
),
(
"12-08T13:15",
"12-08T14:15",
scu.EtatAssiduite.RETARD,
True,
),
(
"12-08T14:15",
"12-08T15:15",
scu.EtatAssiduite.PRESENT,
False,
),
(
"12-08T15:15",
"12-08T17:00",
scu.EtatAssiduite.ABSENT,
False,
),
# 11/12 -> 15/12
(
"12-11T08:00",
"12-15T17:00",
scu.EtatAssiduite.ABSENT,
False,
),
]
for ass in assiduites:
ass_obj = Assiduite.create_assiduite(
etud=etud,
date_debut=scu.is_iso_formated("2023-" + ass[0], True),
date_fin=scu.is_iso_formated("2023-" + ass[1], True),
etat=ass[2],
est_just=ass[3],
)
db.session.add(ass_obj)
db.session.commit()
calculator = scass.CountCalculator(
morning="08:00", noon="12:15", evening="17:00", nb_heures_par_jour=8
)
calculator.compute_assiduites(etud.assiduites)
result: dict = calculator.to_dict(only_total=False)
# Résultat attendu :
# (les additions dans les absences corresponde à (compte_assiduite + compte_assiduite_longue))
resultat_attendu: dict = {
"present": {"journee": 5, "demi": 8, "heure": 13.25, "compte": 9},
"absent": {
"journee": 5 + 5,
"demi": 7 + 10,
"heure": 11.25 + 42,
"compte": 7 + 1,
},
"absent_just": {"journee": 3, "demi": 3, "heure": 4.25, "compte": 3},
"absent_non_just": {
"journee": 3 + 5,
"demi": 4 + 10,
"heure": 7 + 42,
"compte": 4 + 1,
},
"retard": {
"journee": 5,
"demi": 7,
"heure": 10.5,
"compte": 7,
},
"retard_just": {"journee": 3, "demi": 3, "heure": 2.5, "compte": 3},
"retard_non_just": {"journee": 3, "demi": 4, "heure": 8.0, "compte": 4},
"total": {"journee": 10, "demi": 19, "heure": 77.0, "compte": 24},
}
for key in resultat_attendu:
for key2 in resultat_attendu[key]:
assert (
result[key][key2] == resultat_attendu[key][key2]
), f"Le calcul [{key}][{key2}] est faux (attendu > {resultat_attendu[key][key2]}{result[key][key2]} < obtenu)"

View File

@ -388,7 +388,9 @@ def ajouter_assiduites_justificatifs(formsemestre: FormSemestre):
MODS.append(None) MODS.append(None)
for etud in formsemestre.etuds: for etud in formsemestre.etuds:
base_date = datetime.datetime(2022, 9, random.randint(1, 30), 8, 0, 0) base_date = datetime.datetime(
2022, 9, [5, 12, 19, 26][random.randint(0, 3)], 8, 0, 0
)
base_date = localize_datetime(base_date) base_date = localize_datetime(base_date)
for i in range(random.randint(1, 5)): for i in range(random.randint(1, 5)):