forked from ScoDoc/ScoDoc
203 lines
6.3 KiB
Python
203 lines
6.3 KiB
Python
from datetime import date, datetime, time, timedelta
|
|
|
|
import app.scodoc.sco_utils as scu
|
|
from app.models.assiduites import Assiduite, Justificatif
|
|
from app.models.etudiants import Identite
|
|
from app.models.formsemestre import FormSemestre, FormSemestreInscription
|
|
|
|
# TOTALK: Réfléchir sur le fractionnement d'une assiduite prolongée
|
|
|
|
|
|
def get_assiduites_stats(
|
|
assiduites: Assiduite, metric: str = "all", filtered: dict[str, object] = None
|
|
) -> Assiduite:
|
|
|
|
if filtered is not None:
|
|
for key in filtered:
|
|
if key == "etat":
|
|
assiduites = filter_assiduites_by_etat(assiduites, filtered[key])
|
|
elif key == "date_fin":
|
|
assiduites = filter_assiduites_by_date(
|
|
assiduites, filtered[key], sup=False
|
|
)
|
|
elif key == "date_debut":
|
|
assiduites = filter_assiduites_by_date(
|
|
assiduites, filtered[key], sup=True
|
|
)
|
|
elif key == "moduleimpl_id":
|
|
assiduites = filter_by_module_impl(assiduites, filtered[key])
|
|
elif key == "formsemestre":
|
|
assiduites = filter_by_formsemestre(assiduites, filtered[key])
|
|
|
|
count: dict = get_count(assiduites)
|
|
|
|
metrics: list[str] = metric.split(",")
|
|
|
|
output: dict = {}
|
|
|
|
for key, val in count.items():
|
|
if key in metrics:
|
|
output[key] = val
|
|
return output if output else count
|
|
|
|
|
|
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
|
|
|
|
all_assiduites: list[Assiduite] = assiduites.order_by(Assiduite.date_debut).all()
|
|
|
|
current_day: date = None
|
|
current_time: str = None
|
|
|
|
midnight: time = time(hour=0)
|
|
noon: time = time(hour=12)
|
|
|
|
def time_check(dtime):
|
|
return midnight <= dtime.time() <= noon
|
|
|
|
for ass in all_assiduites:
|
|
delta: timedelta = ass.date_fin - ass.date_debut
|
|
output["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
|
|
|
|
if current_time != ass_time:
|
|
current_time = ass_time
|
|
output["demi"] += 1
|
|
|
|
output["heure"] = round(output["heure"], 2)
|
|
return output
|
|
|
|
|
|
def filter_assiduites_by_etat(assiduites: Assiduite, etat: str) -> Assiduite:
|
|
"""
|
|
Filtrage d'une collection d'assiduites en fonction de leur état
|
|
"""
|
|
etats: list[str] = list(etat.split(","))
|
|
etats = [scu.EtatAssiduite.get(e, -1) for e in etats]
|
|
return assiduites.filter(Assiduite.etat.in_(etats))
|
|
|
|
|
|
def filter_assiduites_by_date(
|
|
assiduites: Assiduite, date_: datetime, sup: bool = True
|
|
) -> Assiduite:
|
|
"""
|
|
Filtrage d'une collection d'assiduites en fonction d'une date
|
|
|
|
Sup == True -> les assiduites doivent débuter après 'date'\n
|
|
Sup == False -> les assiduites doivent finir avant 'date'
|
|
"""
|
|
|
|
if date_.tzinfo is None:
|
|
first_assiduite: Assiduite = assiduites.first()
|
|
if first_assiduite is not None:
|
|
date_: datetime = date_.replace(tzinfo=first_assiduite.date_debut.tzinfo)
|
|
|
|
if sup:
|
|
return assiduites.filter(Assiduite.date_debut >= date_)
|
|
|
|
return assiduites.filter(Assiduite.date_fin <= date_)
|
|
|
|
|
|
def filter_justificatifs_by_etat(
|
|
justificatifs: Justificatif, etat: str
|
|
) -> Justificatif:
|
|
"""
|
|
Filtrage d'une collection de justificatifs en fonction de leur état
|
|
"""
|
|
etats: list[str] = list(etat.split(","))
|
|
etats = [scu.EtatJustificatif.get(e, -1) for e in etats]
|
|
return justificatifs.filter(Justificatif.etat.in_(etats))
|
|
|
|
|
|
def filter_justificatifs_by_date(
|
|
justificatifs: Justificatif, date_: datetime, sup: bool = True
|
|
) -> Assiduite:
|
|
"""
|
|
Filtrage d'une collection d'assiduites en fonction d'une date
|
|
|
|
Sup == True -> les assiduites doivent débuter après 'date'\n
|
|
Sup == False -> les assiduites doivent finir avant 'date'
|
|
"""
|
|
|
|
if date_.tzinfo is None:
|
|
first_justificatif: Justificatif = justificatifs.first()
|
|
if first_justificatif is not None:
|
|
date_: datetime = date_.replace(tzinfo=first_justificatif.date_debut.tzinfo)
|
|
|
|
if sup:
|
|
return justificatifs.filter(Justificatif.date_debut >= date_)
|
|
|
|
return justificatifs.filter(Justificatif.date_fin <= date_)
|
|
|
|
|
|
def filter_by_module_impl(
|
|
assiduites: Assiduite, module_impl_id: int or None
|
|
) -> Assiduite:
|
|
"""
|
|
Filtrage d'une collection d'assiduites en fonction de l'ID du module_impl
|
|
"""
|
|
return assiduites.filter(Assiduite.moduleimpl_id == module_impl_id)
|
|
|
|
|
|
def filter_by_formsemestre(assiduites_query: Assiduite, formsemestre: FormSemestre):
|
|
"""
|
|
Filtrage d'une collection d'assiduites en fonction d'un formsemestre
|
|
"""
|
|
|
|
if formsemestre is None:
|
|
return assiduites_query.filter(False)
|
|
|
|
assiduites_query = (
|
|
assiduites_query.join(Identite, Assiduite.etudid == Identite.id)
|
|
.join(
|
|
FormSemestreInscription,
|
|
Identite.id == FormSemestreInscription.etudid,
|
|
)
|
|
.filter(FormSemestreInscription.formsemestre_id == formsemestre.id)
|
|
)
|
|
|
|
assiduites_query = assiduites_query.filter(
|
|
Assiduite.date_debut >= formsemestre.date_debut
|
|
)
|
|
return assiduites_query.filter(Assiduite.date_fin <= formsemestre.date_fin)
|
|
|
|
|
|
def justifies(justi: Justificatif) -> list[int]:
|
|
"""
|
|
Retourne la liste des assiduite_id qui sont justifié par la justification
|
|
Une assiduité est justifiée si elle est STRICTEMENT comprise dans la plage du justificatif
|
|
et que l'état du justificatif est "validé"
|
|
"""
|
|
|
|
justified: list[int] = []
|
|
|
|
if justi.etat != scu.EtatJustificatif.VALIDE:
|
|
return justified
|
|
|
|
assiduites_query: Assiduite = Assiduite.query.join(
|
|
Justificatif, Assiduite.etudid == Justificatif.etudid
|
|
).filter(Assiduite.etat != scu.EtatAssiduite.PRESENT)
|
|
|
|
assiduites_query = filter_assiduites_by_date(
|
|
assiduites_query, justi.date_debut, True
|
|
)
|
|
assiduites_query = filter_assiduites_by_date(
|
|
assiduites_query, justi.date_fin, False
|
|
)
|
|
|
|
justified = [assi.id for assi in assiduites_query.all()]
|
|
|
|
return justified
|