diff --git a/app/api/__init__.py b/app/api/__init__.py index 7c544d63..70839a2c 100644 --- a/app/api/__init__.py +++ b/app/api/__init__.py @@ -2,7 +2,8 @@ """ from flask import Blueprint -from flask import request +from flask import request, g, jsonify +from app import db from app.scodoc import sco_utils as scu from app.scodoc.sco_exceptions import ScoException @@ -31,6 +32,22 @@ def requested_format(default_format="json", allowed_formats=None): return None +def get_model_api_object(model_cls: db.Model, model_id: int, join_cls: db.Model = None): + """ + Retourne une réponse contenant la représentation api de l'objet "Model[model_id]" + + Filtrage du département en fonction d'une classe de jointure (eg: Identite, Formsemstre) -> join_cls + + exemple d'utilisation : fonction "justificatif()" -> app/api/justificatifs.py + """ + query = model_cls.query.filter_by(id=model_id) + if g.scodoc_dept and join_cls is not None: + query = query.join(join_cls).filter_by(dept_id=g.scodoc_dept_id) + unique: model_cls = query.first_or_404() + + return jsonify(unique.to_dict(format_api=True)) + + from app.api import tokens from app.api import ( absences, @@ -42,7 +59,7 @@ from app.api import ( formations, formsemestres, jury, - justificatif, + justificatifs, logos, partitions, users, diff --git a/app/api/assiduites.py b/app/api/assiduites.py index ec67fd7c..44dae142 100644 --- a/app/api/assiduites.py +++ b/app/api/assiduites.py @@ -14,6 +14,7 @@ import app.scodoc.sco_utils as scu from app import db from app.api import api_bp as bp from app.api import api_web_bp +from app.api import get_model_api_object from app.decorators import permission_required, scodoc from app.models import Assiduite, FormSemestre, Identite, ModuleImpl from app.scodoc.sco_exceptions import ScoValueError @@ -40,7 +41,7 @@ def assiduite(assiduite_id: int = None): } """ - return scu.get_model_api_object(Assiduite, assiduite_id) + return get_model_api_object(Assiduite, assiduite_id, Identite) @bp.route("/assiduites//count", defaults={"with_query": False}) diff --git a/app/api/justificatif.py b/app/api/justificatifs.py similarity index 99% rename from app/api/justificatif.py rename to app/api/justificatifs.py index 3b025008..9af0c955 100644 --- a/app/api/justificatif.py +++ b/app/api/justificatifs.py @@ -15,6 +15,7 @@ import app.scodoc.sco_utils as scu from app import db from app.api import api_bp as bp from app.api import api_web_bp +from app.api import get_model_api_object from app.decorators import permission_required, scodoc from app.models import Identite, Justificatif from app.models.assiduites import is_period_conflicting @@ -56,7 +57,7 @@ def justificatif(justif_id: int = None): """ - return scu.get_model_api_object(Justificatif, justif_id) + return get_model_api_object(Justificatif, justif_id, Identite) @bp.route("/justificatifs/", defaults={"with_query": False}) diff --git a/app/models/assiduites.py b/app/models/assiduites.py index ea59c967..181739ba 100644 --- a/app/models/assiduites.py +++ b/app/models/assiduites.py @@ -55,7 +55,7 @@ class Assiduite(db.Model): etat = self.etat if format_api: - etat = EtatJustificatif.inverse().get(self.etat).name + etat = EtatAssiduite.inverse().get(self.etat).name data = { "assiduite_id": self.assiduite_id, "etudid": self.etudid, @@ -82,7 +82,6 @@ class Assiduite(db.Model): # Vérification de non duplication des périodes assiduites: list[Assiduite] = etud.assiduites.all() - assiduites: list[Justificatif] = etud.assiduites.all() if is_period_conflicting(date_debut, date_fin, assiduites): raise ScoValueError( "Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)" diff --git a/app/scodoc/sco_abs.py b/app/scodoc/sco_abs.py index 1e56ca87..f065a1f7 100644 --- a/app/scodoc/sco_abs.py +++ b/app/scodoc/sco_abs.py @@ -1026,7 +1026,7 @@ def get_abs_count(etudid, sem): """ return get_abs_count_in_interval(etudid, sem["date_debut_iso"], sem["date_fin_iso"]) - +# TODO: relier avec module assiduites def get_abs_count_in_interval(etudid, date_debut_iso, date_fin_iso): """Les comptes d'absences de cet étudiant entre ces deux dates, incluses: tuple (nb abs, nb abs justifiées) diff --git a/app/scodoc/sco_assiduites.py b/app/scodoc/sco_assiduites.py index edba0f10..0bdbfbaa 100644 --- a/app/scodoc/sco_assiduites.py +++ b/app/scodoc/sco_assiduites.py @@ -44,10 +44,10 @@ def get_assiduites_stats( def get_count(assiduites: Assiduite) -> dict[str, int or float]: output: dict[str, int or float] = {} - output["compte"] = assiduites.count() - output["heure"] = 0.0 - output["journee"] = 0 - output["demi"] = 0 + compte: int = assiduites.count() + heure: float = 0.0 + journee: int = 0 + demi: int = 0 all_assiduites: list[Assiduite] = assiduites.order_by(Assiduite.date_debut).all() @@ -62,22 +62,22 @@ def get_count(assiduites: Assiduite) -> dict[str, int or float]: for ass in all_assiduites: delta: timedelta = ass.date_fin - ass.date_debut - output["heure"] += delta.total_seconds() / 3600 + heure += delta.total_seconds() / 3600 ass_time: str = time_check(ass.date_debut) if current_day != ass.date_debut.date(): current_day = ass.date_debut.date() current_time = ass_time - output["demi"] += 1 - output["journee"] += 1 + demi += 1 + journee += 1 if current_time != ass_time: current_time = ass_time - output["demi"] += 1 + demi += 1 - output["heure"] = round(output["heure"], 2) - return output + heure = round(heure, 2) + return {"compte": compte, "journee": journee, "heure": heure, "demi": demi} def filter_assiduites_by_etat(assiduites: Assiduite, etat: str) -> Assiduite: diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py index a4edfb36..7d7ec436 100644 --- a/app/scodoc/sco_utils.py +++ b/app/scodoc/sco_utils.py @@ -88,17 +88,6 @@ ETATS_INSCRIPTION = { } -def get_model_api_object(model_cls: db.Model, model_id: int): - from app.models import Identite - - query = model_cls.query.filter_by(id=model_id) - if g.scodoc_dept: - query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id) - unique: model_cls = query.first_or_404() - - return jsonify(unique.to_dict(format_api=True)) - - class BiDirectionalEnum(Enum): """Permet la recherche inverse d'un enum Condition : les clés et les valeurs doivent être uniques @@ -134,18 +123,6 @@ class EtatAssiduite(int, BiDirectionalEnum): ABSENT = 2 -ETAT_ASSIDUITE_NAME = { - EtatAssiduite.PRESENT: "present", - EtatAssiduite.RETARD: "retard", - EtatAssiduite.ABSENT: "absent", -} -ETATS_ASSIDUITE = { - "present": EtatAssiduite.PRESENT, - "retard": EtatAssiduite.RETARD, - "absent": EtatAssiduite.ABSENT, -} - - class EtatJustificatif(int, BiDirectionalEnum): """Code des états des justificatifs""" diff --git a/tests/unit/test_assiduites.py b/tests/unit/test_assiduites.py index 50f7097a..bdbf930e 100644 --- a/tests/unit/test_assiduites.py +++ b/tests/unit/test_assiduites.py @@ -19,6 +19,22 @@ from app.scodoc.sco_exceptions import ScoValueError import app.scodoc.sco_utils as scu +class BiInt(int, scu.BiDirectionalEnum): + A = 1 + B = 2 + + +def test_bi_directional_enum(test_client): + """Test le bon fonctionnement de la classe BiDirectionalEnum""" + + assert BiInt.get("A") == BiInt.get("a") == BiInt.A == 1 + assert BiInt.get("B") == BiInt.get("b") == BiInt.B == 2 + assert BiInt.get("blabla") is None + assert BiInt.get("blabla", -1) == -1 + assert isinstance(BiInt.inverse(), dict) + assert BiInt.inverse()[1] == BiInt.A and BiInt.inverse()[2] == BiInt.B + + def test_general(test_client): """tests général du modèle assiduite"""