forked from ScoDoc/ScoDoc
Assiduité : XXX todo #831 (non fini)
This commit is contained in:
parent
b6940e4882
commit
79e973f06d
@ -372,12 +372,38 @@ def str_to_time(time_str: str) -> time:
|
|||||||
def get_assiduites_stats(
|
def get_assiduites_stats(
|
||||||
assiduites: Query, metric: str = "all", filtered: dict[str, object] = None
|
assiduites: Query, metric: str = "all", filtered: dict[str, object] = None
|
||||||
) -> dict[str, int | float]:
|
) -> dict[str, int | float]:
|
||||||
"""Compte les assiduités en fonction des filtres"""
|
"""
|
||||||
# XXX TODO-assiduite : documenter !!!
|
Calcule les statistiques sur les assiduités
|
||||||
# Que sont les filtres ? Quelles valeurs ?
|
(nombre de jours, demi-journées et heures passées,
|
||||||
# documenter permet de faire moins de bug: qualité du code non satisfaisante.
|
non justifiées, justifiées et total)
|
||||||
#
|
|
||||||
# + on se perd entre les clés en majuscules et en minuscules. Pourquoi
|
Les filtres :
|
||||||
|
- etat : filtre les assiduités par leur état
|
||||||
|
valeur : (absent, present, retard)
|
||||||
|
- date_debut/date_fin : prend les assiduités qui se trouvent entre les dates
|
||||||
|
valeur : datetime.datetime
|
||||||
|
- moduleimpl_id : filtre les assiduités en fonction du moduleimpl_id
|
||||||
|
valeur : int | None
|
||||||
|
- formsemestre : prend les assiduités du formsemestre donné
|
||||||
|
valeur : FormSemestre
|
||||||
|
- formsemestre_modimpls : prend les assiduités avec un moduleimpl du formsemestre
|
||||||
|
valeur : FormSemestre
|
||||||
|
- est_just : filtre les assiduités en fonction de si elles sont justifiées ou non
|
||||||
|
valeur : bool
|
||||||
|
- user_id : filtre les assiduités en fonction de l'utilisateur qui les a créées
|
||||||
|
valeur : int
|
||||||
|
- split : effectue un comptage par état d'assiduité
|
||||||
|
valeur : str (du moment que la clé est présente dans filtered)
|
||||||
|
|
||||||
|
Les métriques :
|
||||||
|
- journee : comptage en nombre de journée
|
||||||
|
- demi : comptage en nombre de demi journée
|
||||||
|
- heure : comptage en heure
|
||||||
|
- compte : nombre d'objets
|
||||||
|
- all : renvoi toute les métriques
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
if filtered is not None:
|
if filtered is not None:
|
||||||
deb, fin = None, None
|
deb, fin = None, None
|
||||||
@ -414,34 +440,71 @@ def get_assiduites_stats(
|
|||||||
calculator: CountCalculator = CountCalculator()
|
calculator: CountCalculator = CountCalculator()
|
||||||
calculator.compute_assiduites(assiduites)
|
calculator.compute_assiduites(assiduites)
|
||||||
|
|
||||||
|
# S'il n'y a pas de filtre ou que le filtre split n'est pas dans les filtres
|
||||||
if filtered is None or "split" not in filtered:
|
if filtered is None or "split" not in filtered:
|
||||||
|
# On récupère le comptage total
|
||||||
|
# only_total permet de ne récupérer que le total
|
||||||
count: dict = calculator.to_dict(only_total=True)
|
count: dict = calculator.to_dict(only_total=True)
|
||||||
|
|
||||||
|
# On ne garde que les métriques demandées
|
||||||
for key, val in count.items():
|
for key, val in count.items():
|
||||||
if key in metrics:
|
if key in metrics:
|
||||||
output[key] = val
|
output[key] = val
|
||||||
|
# On renvoie le total si on a rien demandé (ou que metrics == ["all"])
|
||||||
return output if output else count
|
return output if output else count
|
||||||
|
|
||||||
# Récupération des états
|
|
||||||
etats: list[str] = (
|
|
||||||
filtered["etat"].split(",") if "etat" in filtered else scu.EtatAssiduite.all()
|
|
||||||
)
|
|
||||||
|
|
||||||
# être sur que les états sont corrects
|
|
||||||
etats = [etat for etat in etats if etat.upper() in scu.EtatAssiduite.all()]
|
|
||||||
|
|
||||||
# Préparation du dictionnaire de retour avec les valeurs du calcul
|
# Préparation du dictionnaire de retour avec les valeurs du calcul
|
||||||
count: dict = calculator.to_dict(only_total=False)
|
count: dict = calculator.to_dict(only_total=False)
|
||||||
|
|
||||||
|
# Récupération des états depuis la saisie utilisateur
|
||||||
|
etats: list[str] = (
|
||||||
|
filtered["etat"].split(",") if "etat" in filtered else scu.EtatAssiduite.all()
|
||||||
|
)
|
||||||
for etat in etats:
|
for etat in etats:
|
||||||
# TODO-assiduite: on se perd entre les lower et upper.
|
# On vérifie que l'état est bien un état d'assiduité
|
||||||
# Pourquoi EtatAssiduite est en majuscules si tout le reste est en minuscules ?
|
# sinon on passe à l'état suivant
|
||||||
etat = etat.lower()
|
if not scu.EtatAssiduite.contains(etat):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# On récupère le comptage pour chaque état
|
||||||
if etat != "present":
|
if etat != "present":
|
||||||
output[etat] = count[etat]
|
output[etat] = count[etat]
|
||||||
output[etat]["justifie"] = count[etat + "_just"]
|
output[etat]["justifie"] = count[etat + "_just"]
|
||||||
output[etat]["non_justifie"] = count[etat + "_non_just"]
|
output[etat]["non_justifie"] = count[etat + "_non_just"]
|
||||||
else:
|
else:
|
||||||
output[etat] = count[etat]
|
output[etat] = count[etat]
|
||||||
|
|
||||||
output["total"] = count["total"]
|
output["total"] = count["total"]
|
||||||
|
|
||||||
|
# le dictionnaire devrait ressembler à :
|
||||||
|
# {
|
||||||
|
# "absent": {
|
||||||
|
# "journee": 1,
|
||||||
|
# "demi": 2,
|
||||||
|
# "heure": 3,
|
||||||
|
# "compte": 4,
|
||||||
|
# "justifie": {
|
||||||
|
# "journee": 1,
|
||||||
|
# "demi": 2,
|
||||||
|
# "heure": 3,
|
||||||
|
# "compte": 4
|
||||||
|
# },
|
||||||
|
# "non_justifie": {
|
||||||
|
# "journee": 1,
|
||||||
|
# "demi": 2,
|
||||||
|
# "heure": 3,
|
||||||
|
# "compte": 4
|
||||||
|
# }
|
||||||
|
# },
|
||||||
|
# ...
|
||||||
|
# "total": {
|
||||||
|
# "journee": 1,
|
||||||
|
# "demi": 2,
|
||||||
|
# "heure": 3,
|
||||||
|
# "compte": 4
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
@ -202,6 +202,7 @@ 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
|
||||||
les clés doivent être en MAJUSCULES
|
les clés doivent être en MAJUSCULES
|
||||||
|
=> (respect de la convention des constantes)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -213,10 +214,17 @@ class BiDirectionalEnum(Enum):
|
|||||||
return attr.upper() in cls._member_names_
|
return attr.upper() in cls._member_names_
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def all(cls, keys=True):
|
def all(cls, keys=True) -> tuple[str | object]:
|
||||||
"""Retourne toutes les clés de l'enum"""
|
"""Retourne toutes les clés de l'enum (en minuscules) ou les valeurs"""
|
||||||
# pylint: disable-next=no-member
|
return (
|
||||||
return cls._member_names_ if keys else list(cls._value2member_map_.keys())
|
tuple(
|
||||||
|
k.lower()
|
||||||
|
# pylint: disable-next=no-member
|
||||||
|
for k in cls._member_names_
|
||||||
|
) # renvoie les clés en minuscules
|
||||||
|
if keys
|
||||||
|
else tuple(cls._value2member_map_.keys()) # renvoie les valeurs
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(cls, attr: str, default: any = None):
|
def get(cls, attr: str, default: any = None):
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user