module assiduites & justificatifs : révisions

module assiduites : révisions 

module assiduites/justificatifs : révisions 
This commit is contained in:
iziram 2023-02-03 16:17:39 +01:00
parent 4d72fec42d
commit 61d4186ad3
8 changed files with 51 additions and 40 deletions

View File

@ -2,7 +2,8 @@
""" """
from flask import Blueprint 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 import sco_utils as scu
from app.scodoc.sco_exceptions import ScoException from app.scodoc.sco_exceptions import ScoException
@ -31,6 +32,22 @@ def requested_format(default_format="json", allowed_formats=None):
return 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 tokens
from app.api import ( from app.api import (
absences, absences,
@ -42,7 +59,7 @@ from app.api import (
formations, formations,
formsemestres, formsemestres,
jury, jury,
justificatif, justificatifs,
logos, logos,
partitions, partitions,
users, users,

View File

@ -14,6 +14,7 @@ import app.scodoc.sco_utils as scu
from app import db from app import db
from app.api import api_bp as bp from app.api import api_bp as bp
from app.api import api_web_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.decorators import permission_required, scodoc
from app.models import Assiduite, FormSemestre, Identite, ModuleImpl from app.models import Assiduite, FormSemestre, Identite, ModuleImpl
from app.scodoc.sco_exceptions import ScoValueError 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/<int:etudid>/count", defaults={"with_query": False}) @bp.route("/assiduites/<int:etudid>/count", defaults={"with_query": False})

View File

@ -15,6 +15,7 @@ import app.scodoc.sco_utils as scu
from app import db from app import db
from app.api import api_bp as bp from app.api import api_bp as bp
from app.api import api_web_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.decorators import permission_required, scodoc
from app.models import Identite, Justificatif from app.models import Identite, Justificatif
from app.models.assiduites import is_period_conflicting 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/<int:etudid>", defaults={"with_query": False}) @bp.route("/justificatifs/<int:etudid>", defaults={"with_query": False})

View File

@ -55,7 +55,7 @@ class Assiduite(db.Model):
etat = self.etat etat = self.etat
if format_api: if format_api:
etat = EtatJustificatif.inverse().get(self.etat).name etat = EtatAssiduite.inverse().get(self.etat).name
data = { data = {
"assiduite_id": self.assiduite_id, "assiduite_id": self.assiduite_id,
"etudid": self.etudid, "etudid": self.etudid,
@ -82,7 +82,6 @@ class Assiduite(db.Model):
# Vérification de non duplication des périodes # Vérification de non duplication des périodes
assiduites: list[Assiduite] = etud.assiduites.all() assiduites: list[Assiduite] = etud.assiduites.all()
assiduites: list[Justificatif] = etud.assiduites.all()
if is_period_conflicting(date_debut, date_fin, assiduites): if is_period_conflicting(date_debut, date_fin, assiduites):
raise ScoValueError( raise ScoValueError(
"Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)" "Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)"

View File

@ -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"]) 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): 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: """Les comptes d'absences de cet étudiant entre ces deux dates, incluses:
tuple (nb abs, nb abs justifiées) tuple (nb abs, nb abs justifiées)

View File

@ -44,10 +44,10 @@ def get_assiduites_stats(
def get_count(assiduites: Assiduite) -> dict[str, int or float]: def get_count(assiduites: Assiduite) -> dict[str, int or float]:
output: dict[str, int or float] = {} output: dict[str, int or float] = {}
output["compte"] = assiduites.count() compte: int = assiduites.count()
output["heure"] = 0.0 heure: float = 0.0
output["journee"] = 0 journee: int = 0
output["demi"] = 0 demi: int = 0
all_assiduites: list[Assiduite] = assiduites.order_by(Assiduite.date_debut).all() 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: for ass in all_assiduites:
delta: timedelta = ass.date_fin - ass.date_debut 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) ass_time: str = time_check(ass.date_debut)
if current_day != ass.date_debut.date(): if current_day != ass.date_debut.date():
current_day = ass.date_debut.date() current_day = ass.date_debut.date()
current_time = ass_time current_time = ass_time
output["demi"] += 1 demi += 1
output["journee"] += 1 journee += 1
if current_time != ass_time: if current_time != ass_time:
current_time = ass_time current_time = ass_time
output["demi"] += 1 demi += 1
output["heure"] = round(output["heure"], 2) heure = round(heure, 2)
return output return {"compte": compte, "journee": journee, "heure": heure, "demi": demi}
def filter_assiduites_by_etat(assiduites: Assiduite, etat: str) -> Assiduite: def filter_assiduites_by_etat(assiduites: Assiduite, etat: str) -> Assiduite:

View File

@ -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): class BiDirectionalEnum(Enum):
"""Permet la recherche inverse d'un enum """Permet la recherche inverse d'un enum
Condition : les clés et les valeurs doivent être uniques Condition : les clés et les valeurs doivent être uniques
@ -134,18 +123,6 @@ class EtatAssiduite(int, BiDirectionalEnum):
ABSENT = 2 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): class EtatJustificatif(int, BiDirectionalEnum):
"""Code des états des justificatifs""" """Code des états des justificatifs"""

View File

@ -19,6 +19,22 @@ from app.scodoc.sco_exceptions import ScoValueError
import app.scodoc.sco_utils as scu 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): def test_general(test_client):
"""tests général du modèle assiduite""" """tests général du modèle assiduite"""