Assiduités : fix view_module_abs #688

This commit is contained in:
iziram 2023-09-05 14:25:38 +02:00
parent 4387727d2f
commit 6c77f7faca
5 changed files with 88 additions and 46 deletions

View File

@ -350,11 +350,15 @@ def compute_assiduites_justified(
if justificatifs is None: if justificatifs is None:
justificatifs: Justificatif = Justificatif.query.filter_by(etudid=etudid).all() justificatifs: Justificatif = Justificatif.query.filter_by(etudid=etudid).all()
justificatifs = [j for j in justificatifs if j.etat == EtatJustificatif.VALIDE]
assiduites: Assiduite = Assiduite.query.filter_by(etudid=etudid) assiduites: Assiduite = Assiduite.query.filter_by(etudid=etudid)
assiduites_justifiees: list[int] = [] assiduites_justifiees: list[int] = []
for assi in assiduites: for assi in assiduites:
if assi.etat == EtatAssiduite.PRESENT:
continue
if any( if any(
assi.date_debut >= j.date_debut and assi.date_fin <= j.date_fin assi.date_debut >= j.date_debut and assi.date_fin <= j.date_fin
for j in justificatifs for j in justificatifs

View File

@ -212,7 +212,7 @@ def get_assiduites_stats(
output: dict = {} output: dict = {}
calculator: CountCalculator = CountCalculator() calculator: CountCalculator = CountCalculator()
if "split" not in filtered: if filtered is None or "split" not in filtered:
calculator.compute_assiduites(assiduites) calculator.compute_assiduites(assiduites)
count: dict = calculator.to_dict() count: dict = calculator.to_dict()
@ -382,7 +382,10 @@ def justifies(justi: Justificatif, obj: bool = False) -> list[int] or Query:
def get_all_justified( def get_all_justified(
etudid: int, date_deb: datetime = None, date_fin: datetime = None etudid: int,
date_deb: datetime = None,
date_fin: datetime = None,
moduleimpl_id: int = None,
) -> Query: ) -> Query:
"""Retourne toutes les assiduités justifiées sur une période""" """Retourne toutes les assiduités justifiées sur une période"""
@ -393,7 +396,9 @@ def get_all_justified(
date_deb = scu.localize_datetime(date_deb) date_deb = scu.localize_datetime(date_deb)
date_fin = scu.localize_datetime(date_fin) date_fin = scu.localize_datetime(date_fin)
justified = Assiduite.query.filter_by(est_just=True, etudid=etudid) justified: Query = Assiduite.query.filter_by(est_just=True, etudid=etudid)
if moduleimpl_id is not None:
justified = justified.filter_by(moduleimpl_id=moduleimpl_id)
after = filter_by_date( after = filter_by_date(
justified, justified,
Assiduite, Assiduite,
@ -419,7 +424,7 @@ def get_assiduites_count(etudid: int, sem: dict) -> tuple[int, int]:
def formsemestre_get_assiduites_count( def formsemestre_get_assiduites_count(
etudid: int, formsemestre: FormSemestre etudid: int, formsemestre: FormSemestre, moduleimpl_id: int = None
) -> tuple[int, int]: ) -> tuple[int, int]:
"""Les comptes d'absences de cet étudiant dans ce semestre: """Les comptes d'absences de cet étudiant dans ce semestre:
tuple (nb abs non justifiées, nb abs justifiées) tuple (nb abs non justifiées, nb abs justifiées)
@ -428,9 +433,14 @@ def formsemestre_get_assiduites_count(
metrique = sco_preferences.get_preference("assi_metrique", formsemestre.id) metrique = sco_preferences.get_preference("assi_metrique", formsemestre.id)
return get_assiduites_count_in_interval( return get_assiduites_count_in_interval(
etudid, etudid,
date_debut=formsemestre.date_debut, date_debut=scu.localize_datetime(
date_fin=formsemestre.date_fin, datetime.combine(formsemestre.date_debut, time(8, 0))
),
date_fin=scu.localize_datetime(
datetime.combine(formsemestre.date_fin, time(18, 0))
),
metrique=scu.translate_assiduites_metric(metrique), metrique=scu.translate_assiduites_metric(metrique),
moduleimpl_id=moduleimpl_id,
) )
@ -441,6 +451,7 @@ def get_assiduites_count_in_interval(
metrique="demi", metrique="demi",
date_debut: datetime = None, date_debut: datetime = None,
date_fin: datetime = None, date_fin: datetime = None,
moduleimpl_id: int = None,
): ):
"""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)
@ -452,30 +463,41 @@ def get_assiduites_count_in_interval(
key = f"{etudid}_{date_debut_iso}_{date_fin_iso}{metrique}_assiduites" key = f"{etudid}_{date_debut_iso}_{date_fin_iso}{metrique}_assiduites"
r = sco_cache.AbsSemEtudCache.get(key) r = sco_cache.AbsSemEtudCache.get(key)
if not r: if not r or moduleimpl_id is not None:
date_debut: datetime = date_debut or datetime.fromisoformat(date_debut_iso) date_debut: datetime = date_debut or datetime.fromisoformat(date_debut_iso)
date_fin: datetime = date_fin or datetime.fromisoformat(date_fin_iso) date_fin: datetime = date_fin or datetime.fromisoformat(date_fin_iso)
assiduites: Assiduite = Assiduite.query.filter_by(etudid=etudid) log(f"deb : {date_debut.isoformat()} fin: {date_fin.isoformat()}")
assiduites: Query = Assiduite.query.filter_by(etudid=etudid)
assiduites = assiduites.filter(Assiduite.etat == scu.EtatAssiduite.ABSENT) assiduites = assiduites.filter(Assiduite.etat == scu.EtatAssiduite.ABSENT)
justificatifs: Justificatif = Justificatif.query.filter_by(etudid=etudid) justificatifs: Justificatif = Justificatif.query.filter_by(etudid=etudid)
assiduites = filter_by_date(assiduites, Assiduite, date_debut, date_fin) assiduites = filter_by_date(assiduites, Assiduite, date_debut, date_fin)
if moduleimpl_id is not None:
assiduites = assiduites.filter_by(moduleimpl_id=moduleimpl_id)
justificatifs = filter_by_date( justificatifs = filter_by_date(
justificatifs, Justificatif, date_debut, date_fin justificatifs, Justificatif, date_debut, date_fin
) )
log(f"---assi---\n{[a.assiduite_id for a in assiduites]}")
calculator: CountCalculator = CountCalculator() calculator: CountCalculator = CountCalculator()
calculator.compute_assiduites(assiduites) calculator.compute_assiduites(assiduites)
nb_abs: dict = calculator.to_dict()[metrique] nb_abs: dict = calculator.to_dict()[metrique]
abs_just: list[Assiduite] = get_all_justified(etudid, date_debut, date_fin) abs_just: list[Assiduite] = get_all_justified(
etudid, date_debut, date_fin, moduleimpl_id
)
log(f"---justi---\n{[a.assiduite_id for a in abs_just]}")
calculator.reset() calculator.reset()
calculator.compute_assiduites(abs_just) calculator.compute_assiduites(abs_just)
nb_abs_just: dict = calculator.to_dict()[metrique] nb_abs_just: dict = calculator.to_dict()[metrique]
r = (nb_abs, nb_abs_just) r = (nb_abs, nb_abs_just)
if moduleimpl_id is None:
ans = sco_cache.AbsSemEtudCache.set(key, r) ans = sco_cache.AbsSemEtudCache.set(key, r)
if not ans: if not ans:
log("warning: get_assiduites_count failed to cache") log("warning: get_assiduites_count failed to cache")

View File

@ -237,7 +237,7 @@ def localize_datetime(date: datetime.datetime or str) -> datetime.datetime:
new_date: datetime.datetime = date new_date: datetime.datetime = date
if new_date.tzinfo is None: if new_date.tzinfo is None:
try: try:
new_date = timezone("Europe/Paris").localize(date) new_date = TIME_ZONE.localize(date)
except OverflowError: except OverflowError:
new_date = timezone("UTC").localize(date) new_date = timezone("UTC").localize(date)
return new_date return new_date

View File

@ -1174,22 +1174,9 @@ def view_module_abs(moduleimpl_id, fmt="html"):
rows = [] rows = []
for etud in inscrits: for etud in inscrits:
# TODO-ASSIDUITE ne va pas car ne filtre pas sur le moduleimpl nb_abs, nb_abs_just = sco_assiduites.formsemestre_get_assiduites_count(
# nb_abs, nb_abs_just = sco_assiduites.formsemestre_get_assiduites_count(etud.id, modimpl.formsemestre) etud.id, modimpl.formsemestre, moduleimpl_id=modimpl.id
nb_abs, nb_abs_just = 0, 0 # XXX TODO-ASSIDUITE )
# nb_abs = sco_abs.count_abs(
# etudid=etud.id,
# debut=debut_sem,
# fin=fin_sem,
# moduleimpl_id=moduleimpl_id,
# )
# if nb_abs:
# nb_abs_just = sco_abs.count_abs_just(
# etudid=etud.id,
# debut=debut_sem,
# fin=fin_sem,
# moduleimpl_id=moduleimpl_id,
# )
rows.append( rows.append(
{ {
"nomprenom": etud.nomprenom, "nomprenom": etud.nomprenom,

View File

@ -13,8 +13,7 @@ import app.scodoc.sco_assiduites as scass
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app import db from app import db
from app.models import Assiduite, FormSemestre, Identite, Justificatif, ModuleImpl from app.models import Assiduite, FormSemestre, Identite, Justificatif, ModuleImpl
from app.models.assiduites import compute_assiduites_justified
# from app.scodoc import sco_abs_views, sco_formsemestre TODO-ASSIDUITE
from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_exceptions import ScoValueError
from tests.unit import sco_fake_gen from tests.unit import sco_fake_gen
@ -39,7 +38,7 @@ def test_bi_directional_enum(test_client):
assert BiInt.inverse()[1] == BiInt.A and BiInt.inverse()[2] == BiInt.B assert BiInt.inverse()[1] == BiInt.A and BiInt.inverse()[2] == BiInt.B
@pytest.mark.skip # XXX TODO-ASSIDUITE (issue #690) # @pytest.mark.skip # XXX TODO-ASSIDUITE (issue #690)
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"""
@ -80,11 +79,11 @@ def test_general(test_client):
date_fin="31/07/2024", date_fin="31/07/2024",
) )
formsemestre_1 = sco_formsemestre.get_formsemestre( formsemestre_1 = FormSemestre.get_formsemestre(
formsemestre_id_1 formsemestre_id_1
) # Utiliser plutot FormSemestre de nos jours TODO-ASSIDUITE ) # Utiliser plutot FormSemestre de nos jours TODO-ASSIDUITE
formsemestre_2 = sco_formsemestre.get_formsemestre(formsemestre_id_2) formsemestre_2 = FormSemestre.get_formsemestre(formsemestre_id_2)
formsemestre_3 = sco_formsemestre.get_formsemestre(formsemestre_id_3) formsemestre_3 = FormSemestre.get_formsemestre(formsemestre_id_3)
# Création des modulesimpls (4, 2 par semestre) # Création des modulesimpls (4, 2 par semestre)
@ -145,11 +144,14 @@ def test_general(test_client):
etuds, moduleimpls, (formsemestre_1, formsemestre_2, formsemestre_3) etuds, moduleimpls, (formsemestre_1, formsemestre_2, formsemestre_3)
) )
verifier_filtrage_justificatifs(etuds[0], justificatifs) verifier_filtrage_justificatifs(etuds[0], justificatifs)
essais_cache(etuds[0].etudid, (formsemestre_1, formsemestre_2), moduleimpls)
editer_supprimer_assiduites(etuds, moduleimpls) editer_supprimer_assiduites(etuds, moduleimpls)
editer_supprimer_justificatif(etuds[0]) editer_supprimer_justificatif(etuds[0])
@pytest.mark.skip # XXX TODO-ASSIDUITE (issue #696) # XXX TODO-ASSIDUITE (issue #696)
def verif_migration_abs_assiduites(): def verif_migration_abs_assiduites():
"""Vérification que le script de migration fonctionne correctement""" """Vérification que le script de migration fonctionne correctement"""
downgrade_module(assiduites=True, justificatifs=True) downgrade_module(assiduites=True, justificatifs=True)
@ -476,11 +478,11 @@ def _get_justi(
).first() ).first()
def essais_cache(etudid): def essais_cache(etudid, sems: tuple[FormSemestre], moduleimpls: list[ModuleImpl]):
"""Vérification des fonctionnalités du cache""" """Vérification des fonctionnalités du cache"""
date_deb: str = "2023-01-01T07:00" date_deb: str = "2022-09-01T07:00"
date_fin: str = "2023-03-31T19:00" date_fin: str = "2023-01-31T19:00"
assiduites_count_no_cache = scass.get_assiduites_count_in_interval( assiduites_count_no_cache = scass.get_assiduites_count_in_interval(
etudid, date_deb, date_fin etudid, date_deb, date_fin
@ -490,8 +492,36 @@ def essais_cache(etudid):
) )
assert ( assert (
assiduites_count_cache == assiduites_count_no_cache == (34, 15) assiduites_count_cache == assiduites_count_no_cache == (2, 1)
), "Erreur cache" ), "Erreur cache classique"
assert scass.formsemestre_get_assiduites_count(etudid, sems[0]) == (
2,
1,
), "Erreur formsemestre_get_assiduites_count (sans module) A"
assert scass.formsemestre_get_assiduites_count(etudid, sems[1]) == (
0,
0,
), "Erreur formsemestre_get_assiduites_count (sans module) B"
assert scass.formsemestre_get_assiduites_count(
etudid, sems[0], moduleimpl_id=moduleimpls[0].id
) == (
1,
1,
), "Erreur formsemestre_get_assiduites_count (avec module) A"
assert scass.formsemestre_get_assiduites_count(
etudid, sems[0], moduleimpl_id=moduleimpls[1].id
) == (
1,
0,
), "Erreur formsemestre_get_assiduites_count (avec module) A"
assert scass.formsemestre_get_assiduites_count(
etudid, sems[0], moduleimpl_id=moduleimpls[2].id
) == (
0,
0,
), "Erreur formsemestre_get_assiduites_count (avec module) A"
def ajouter_justificatifs(etud): def ajouter_justificatifs(etud):
@ -543,6 +573,8 @@ def ajouter_justificatifs(etud):
db.session.commit() db.session.commit()
justificatifs.append(just_obj) justificatifs.append(just_obj)
compute_assiduites_justified(etud.etudid, justificatifs)
# Vérification de la création des justificatifs # Vérification de la création des justificatifs
assert [ assert [
justi for justi in justificatifs if not isinstance(justi, Justificatif) justi for justi in justificatifs if not isinstance(justi, Justificatif)
@ -858,7 +890,7 @@ def ajouter_assiduites(
def verifier_comptage_et_filtrage_assiduites( def verifier_comptage_et_filtrage_assiduites(
etuds: list[Identite], moduleimpls: list[int], formsemestres: tuple[int] etuds: list[Identite], moduleimpls: list[int], formsemestres: tuple[FormSemestre]
): ):
""" """
Deuxième partie: Deuxième partie:
@ -931,9 +963,6 @@ def verifier_comptage_et_filtrage_assiduites(
), "Filtrage par 'Moduleimpl' mauvais" ), "Filtrage par 'Moduleimpl' mauvais"
# Formsemestre # Formsemestre
formsemestres = [
FormSemestre.query.filter_by(id=fms["id"]).first() for fms in formsemestres
]
assert ( assert (
scass.filter_by_formsemestre( scass.filter_by_formsemestre(
etu1.assiduites, Assiduite, formsemestres[0] etu1.assiduites, Assiduite, formsemestres[0]