module assiduites & justificatifs : révisions ✅
module assiduites : révisions ✅ module assiduites/justificatifs : révisions ✅
This commit is contained in:
parent
4d72fec42d
commit
61d4186ad3
@ -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,
|
||||||
|
@ -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})
|
||||||
|
@ -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})
|
@ -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)"
|
||||||
|
@ -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)
|
||||||
|
@ -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:
|
||||||
|
@ -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"""
|
||||||
|
|
||||||
|
@ -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"""
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user