forked from ScoDoc/ScoDoc
Assiduité : optimisation justification assiduités
This commit is contained in:
parent
21b2e0f582
commit
5158bd0c8f
@ -22,7 +22,6 @@ from app.api import get_model_api_object, tools
|
||||
from app.decorators import permission_required, scodoc
|
||||
from app.models import Identite, Justificatif, Departement, FormSemestre, Scolog
|
||||
from app.models.assiduites import (
|
||||
compute_assiduites_justified,
|
||||
get_formsemestre_from_data,
|
||||
)
|
||||
from app.scodoc.sco_archives_justificatifs import JustificatifArchiver
|
||||
@ -310,7 +309,6 @@ def justif_create(etudid: int = None, nip=None, ine=None):
|
||||
|
||||
errors: list[dict] = []
|
||||
success: list[dict] = []
|
||||
justifs: list[Justificatif] = []
|
||||
|
||||
# énumération des justificatifs
|
||||
for i, data in enumerate(create_list):
|
||||
@ -322,11 +320,9 @@ def justif_create(etudid: int = None, nip=None, ine=None):
|
||||
errors.append({"indice": i, "message": obj})
|
||||
else:
|
||||
success.append({"indice": i, "message": obj})
|
||||
justifs.append(justi)
|
||||
justi.justifier_assiduites()
|
||||
scass.simple_invalidate_cache(data, etud.id)
|
||||
|
||||
# Actualisation des assiduités justifiées en fonction de tous les nouveaux justificatifs
|
||||
compute_assiduites_justified(etud.etudid, justifs)
|
||||
return {"errors": errors, "success": success}
|
||||
|
||||
|
||||
@ -495,6 +491,7 @@ def justif_edit(justif_id: int):
|
||||
return json_error(404, err)
|
||||
|
||||
# Mise à jour du justificatif
|
||||
justificatif_unique.dejustifier_assiduites()
|
||||
db.session.add(justificatif_unique)
|
||||
db.session.commit()
|
||||
|
||||
@ -511,11 +508,7 @@ def justif_edit(justif_id: int):
|
||||
retour = {
|
||||
"couverture": {
|
||||
"avant": avant_ids,
|
||||
"apres": compute_assiduites_justified(
|
||||
justificatif_unique.etudid,
|
||||
[justificatif_unique],
|
||||
True,
|
||||
),
|
||||
"apres": justificatif_unique.justifier_assiduites(),
|
||||
}
|
||||
}
|
||||
# Invalide le cache
|
||||
@ -592,14 +585,10 @@ def _delete_one(justif_id: int) -> tuple[int, str]:
|
||||
|
||||
# On invalide le cache
|
||||
scass.simple_invalidate_cache(justificatif_unique.to_dict())
|
||||
# On actualise les assiduités justifiées de l'étudiant concerné
|
||||
justificatif_unique.dejustifier_assiduites()
|
||||
# On supprime le justificatif
|
||||
db.session.delete(justificatif_unique)
|
||||
# On actualise les assiduités justifiées de l'étudiant concerné
|
||||
compute_assiduites_justified(
|
||||
justificatif_unique.etudid,
|
||||
Justificatif.query.filter_by(etudid=justificatif_unique.etudid).all(),
|
||||
True,
|
||||
)
|
||||
|
||||
return (200, "OK")
|
||||
|
||||
|
@ -574,11 +574,7 @@ class Justificatif(ScoDocModel):
|
||||
db.session.delete(self)
|
||||
db.session.commit()
|
||||
# On actualise les assiduités justifiées de l'étudiant concerné
|
||||
compute_assiduites_justified(
|
||||
self.etudid,
|
||||
Justificatif.query.filter_by(etudid=self.etudid).all(),
|
||||
True,
|
||||
)
|
||||
self.dejustifier_assiduites()
|
||||
|
||||
def get_fichiers(self) -> tuple[list[str], int]:
|
||||
"""Renvoie la liste des noms de fichiers justicatifs
|
||||
@ -600,6 +596,64 @@ class Justificatif(ScoDocModel):
|
||||
accessible_filenames.append(filename[0])
|
||||
return accessible_filenames, len(filenames)
|
||||
|
||||
def justifier_assiduites(
|
||||
self,
|
||||
) -> list[int]:
|
||||
"""Justifie les assiduités sur la période de validité du justificatif"""
|
||||
log(f"justifier_assiduites: {self}")
|
||||
assiduites_justifiees: list[int] = []
|
||||
if self.etat != EtatJustificatif.VALIDE:
|
||||
return []
|
||||
# On récupère les assiduités de l'étudiant sur la période donnée
|
||||
assiduites: Query = self.etudiant.assiduites.filter(
|
||||
Assiduite.date_debut >= self.date_debut,
|
||||
Assiduite.date_fin <= self.date_fin,
|
||||
Assiduite.etat != EtatAssiduite.PRESENT,
|
||||
)
|
||||
# Pour chaque assiduité, on la justifie
|
||||
for assi in assiduites:
|
||||
assi.est_just = True
|
||||
assiduites_justifiees.append(assi.assiduite_id)
|
||||
db.session.add(assi)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
return assiduites_justifiees
|
||||
|
||||
def dejustifier_assiduites(self) -> list[int]:
|
||||
"""
|
||||
Déjustifie les assiduités sur la période du justificatif
|
||||
"""
|
||||
assiduites_dejustifiees: list[int] = []
|
||||
|
||||
# On récupère les assiduités de l'étudiant sur la période donnée
|
||||
assiduites: Query = self.etudiant.assiduites.filter(
|
||||
Assiduite.date_debut >= self.date_debut,
|
||||
Assiduite.date_fin <= self.date_fin,
|
||||
Assiduite.etat != EtatAssiduite.PRESENT,
|
||||
)
|
||||
assi: Assiduite
|
||||
for assi in assiduites:
|
||||
# On récupère les justificatifs qui justifient l'assiduité `assi`
|
||||
assi_justifs: list[int] = get_justifs_from_date(
|
||||
self.etudiant.etudid,
|
||||
assi.date_debut,
|
||||
assi.date_fin,
|
||||
long=False,
|
||||
valid=True,
|
||||
)
|
||||
# Si il n'y a pas d'autre justificatif valide, on déjustifie l'assiduité
|
||||
if len(assi_justifs) == 0 or (
|
||||
len(assi_justifs) == 1 and assi_justifs[0] == self.justif_id
|
||||
):
|
||||
assi.est_just = False
|
||||
assiduites_dejustifiees.append(assi.assiduite_id)
|
||||
db.session.add(assi)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
return assiduites_dejustifiees
|
||||
|
||||
|
||||
def is_period_conflicting(
|
||||
date_debut: datetime,
|
||||
@ -623,72 +677,6 @@ def is_period_conflicting(
|
||||
return count > 0
|
||||
|
||||
|
||||
def compute_assiduites_justified(
|
||||
etudid: int, justificatifs: list[Justificatif] = None, reset: bool = False
|
||||
) -> list[int]:
|
||||
"""
|
||||
Args:
|
||||
etudid (int): l'identifiant de l'étudiant
|
||||
justificatifs (list[Justificatif]): La liste des justificatifs qui seront utilisés
|
||||
reset (bool, optional): remet à false les assiduites non justifiés. Defaults to False.
|
||||
|
||||
Returns:
|
||||
list[int]: la liste des assiduités qui ont été justifiées.
|
||||
"""
|
||||
# TODO à optimiser (car très long avec 40000 assiduités)
|
||||
# On devrait :
|
||||
# - récupérer uniquement les assiduités qui sont sur la période des justificatifs donnés
|
||||
# - Pour chaque assiduité trouvée, il faut récupérer les justificatifs qui la justifie
|
||||
# - Si au moins un justificatif valide couvre la période de l'assiduité alors on la justifie
|
||||
|
||||
# Si on ne donne pas de justificatifs on prendra par défaut tous les justificatifs de l'étudiant
|
||||
if justificatifs is None:
|
||||
justificatifs: list[Justificatif] = Justificatif.query.filter_by(
|
||||
etudid=etudid
|
||||
).all()
|
||||
|
||||
# On ne prend que les justificatifs valides
|
||||
justificatifs = [j for j in justificatifs if j.etat == EtatJustificatif.VALIDE]
|
||||
|
||||
# On récupère les assiduités de l'étudiant
|
||||
assiduites: Assiduite = Assiduite.query.filter_by(etudid=etudid)
|
||||
|
||||
assiduites_justifiees: list[int] = []
|
||||
|
||||
for assi in assiduites:
|
||||
# On ne justifie pas les Présences
|
||||
if assi.etat == EtatAssiduite.PRESENT:
|
||||
continue
|
||||
|
||||
# On récupère les justificatifs qui justifient l'assiduité `assi`
|
||||
assi_justificatifs = Justificatif.query.filter(
|
||||
Justificatif.etudid == assi.etudid,
|
||||
Justificatif.date_debut <= assi.date_debut,
|
||||
Justificatif.date_fin >= assi.date_fin,
|
||||
Justificatif.etat == EtatJustificatif.VALIDE,
|
||||
).all()
|
||||
|
||||
# Si au moins un justificatif possède une période qui couvre l'assiduité
|
||||
if any(
|
||||
assi.date_debut >= j.date_debut and assi.date_fin <= j.date_fin
|
||||
for j in justificatifs + assi_justificatifs
|
||||
):
|
||||
# On justifie l'assiduité
|
||||
# On ajoute l'id de l'assiduité à la liste des assiduités justifiées
|
||||
assi.est_just = True
|
||||
assiduites_justifiees.append(assi.assiduite_id)
|
||||
db.session.add(assi)
|
||||
elif reset:
|
||||
# Si le paramètre reset est Vrai alors les assiduités non justifiées
|
||||
# sont remise en "non justifiée"
|
||||
assi.est_just = False
|
||||
db.session.add(assi)
|
||||
# On valide la session
|
||||
db.session.commit()
|
||||
# On renvoie la liste des assiduite_id des assiduités justifiées
|
||||
return assiduites_justifiees
|
||||
|
||||
|
||||
def get_assiduites_justif(assiduite_id: int, long: bool) -> list[int | dict]:
|
||||
"""
|
||||
get_assiduites_justif Récupération des justificatifs d'une assiduité
|
||||
|
@ -17,7 +17,7 @@ from app.models import (
|
||||
ModuleImplInscription,
|
||||
ScoDocSiteConfig,
|
||||
)
|
||||
from app.models.assiduites import Assiduite, Justificatif, compute_assiduites_justified
|
||||
from app.models.assiduites import Assiduite, Justificatif
|
||||
from app.scodoc import sco_formsemestre_inscriptions
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc import sco_cache
|
||||
@ -111,9 +111,9 @@ class CountCalculator:
|
||||
evening if evening else ScoDocSiteConfig.get("assi_afternoon_time", "18:00")
|
||||
)
|
||||
|
||||
self.non_work_days: list[scu.NonWorkDays] = (
|
||||
scu.NonWorkDays.get_all_non_work_days(dept_id=g.scodoc_dept_id)
|
||||
)
|
||||
self.non_work_days: list[
|
||||
scu.NonWorkDays
|
||||
] = scu.NonWorkDays.get_all_non_work_days(dept_id=g.scodoc_dept_id)
|
||||
|
||||
# Sera utilisé pour les assiduités longues (> 1 journée)
|
||||
self.nb_heures_par_jour = (
|
||||
@ -661,7 +661,7 @@ def create_absence_billet(
|
||||
db.session.add(justi)
|
||||
db.session.commit()
|
||||
|
||||
compute_assiduites_justified(etud.id, [justi])
|
||||
justi.justifier_assiduites()
|
||||
|
||||
calculator: CountCalculator = CountCalculator()
|
||||
calculator.compute_assiduites([assiduite_unique])
|
||||
|
@ -64,7 +64,7 @@ from app.models import (
|
||||
)
|
||||
from app.scodoc.codes_cursus import UE_STANDARD
|
||||
from app.auth.models import User
|
||||
from app.models.assiduites import get_assiduites_justif, compute_assiduites_justified
|
||||
from app.models.assiduites import get_assiduites_justif
|
||||
from app.tables.list_etuds import RowEtud, TableEtud
|
||||
import app.tables.liste_assiduites as liste_assi
|
||||
|
||||
@ -468,7 +468,7 @@ def _record_assiduite_etud(
|
||||
)
|
||||
|
||||
# On met à jour les assiduités en fonction du nouveau justificatif
|
||||
compute_assiduites_justified(etud.id, [justi])
|
||||
justi.justifier_assiduites()
|
||||
|
||||
# Invalider cache
|
||||
scass.simple_invalidate_cache(ass.to_dict(), etud.id)
|
||||
@ -778,6 +778,7 @@ def _record_justificatif_etud(
|
||||
form.date_debut.data = dt_debut_tz_server
|
||||
form.date_fin.data = dt_fin_tz_server
|
||||
form.entry_date.data = dt_entry_date_tz_server
|
||||
justif.dejustifier_assiduites()
|
||||
if justif.edit_from_form(form):
|
||||
message = "Justificatif modifié"
|
||||
|
||||
@ -792,7 +793,6 @@ def _record_justificatif_etud(
|
||||
)
|
||||
else:
|
||||
message = "Pas de modification"
|
||||
|
||||
else:
|
||||
justif = Justificatif.create_justificatif(
|
||||
etud,
|
||||
@ -816,7 +816,7 @@ def _record_justificatif_etud(
|
||||
# pour utiliser le "reset" (remise en "non_just") des assiduités
|
||||
# (à terme, il faudrait ne recalculer que les assiduités impactées)
|
||||
# VOIR TODO dans compute_assiduites_justified
|
||||
compute_assiduites_justified(etud.id, reset=True)
|
||||
justif.justifier_assiduites()
|
||||
scass.simple_invalidate_cache(justif.to_dict(), etud.id)
|
||||
flash(message)
|
||||
return True
|
||||
@ -1595,7 +1595,7 @@ def tableau_assiduite_actions():
|
||||
user_id=current_user.id,
|
||||
)
|
||||
|
||||
compute_assiduites_justified(objet.etudiant.id, [justificatif_correspondant])
|
||||
justificatif_correspondant.justifier_assiduites()
|
||||
scass.simple_invalidate_cache(
|
||||
justificatif_correspondant.to_dict(), objet.etudiant.id
|
||||
)
|
||||
@ -1707,9 +1707,10 @@ def _action_modifier_justificatif(justi: Justificatif):
|
||||
|
||||
justi.fichier = archive_name
|
||||
|
||||
justi.dejustifier_assiduites()
|
||||
db.session.add(justi)
|
||||
db.session.commit()
|
||||
scass.compute_assiduites_justified(justi.etudid, reset=True)
|
||||
justi.justifier_assiduites()
|
||||
scass.simple_invalidate_cache(justi.to_dict(True), justi.etudid)
|
||||
|
||||
|
||||
|
@ -20,7 +20,6 @@ from app.models import (
|
||||
ModuleImpl,
|
||||
Absence,
|
||||
)
|
||||
from app.models.assiduites import compute_assiduites_justified
|
||||
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
from tests.unit import sco_fake_gen
|
||||
@ -498,10 +497,9 @@ def ajouter_justificatifs(etud):
|
||||
)
|
||||
db.session.add(just_obj)
|
||||
db.session.commit()
|
||||
just_obj.justifier_assiduites()
|
||||
justificatifs.append(just_obj)
|
||||
|
||||
compute_assiduites_justified(etud.etudid, justificatifs)
|
||||
|
||||
# Vérification de la création des justificatifs
|
||||
assert [
|
||||
justi for justi in justificatifs if not isinstance(justi, Justificatif)
|
||||
@ -1462,7 +1460,7 @@ def test_cas_justificatifs(test_client):
|
||||
etat=scu.EtatJustificatif.VALIDE,
|
||||
)
|
||||
|
||||
compute_assiduites_justified(etud_1.etudid, [justif_2])
|
||||
justif_2.justifier_assiduites()
|
||||
|
||||
assert len(scass.justifies(justif_2)) == 1, "Justification non prise en compte (b1)"
|
||||
|
||||
@ -1496,7 +1494,8 @@ def test_cas_justificatifs(test_client):
|
||||
)
|
||||
|
||||
# Mise à jour de l'assiduité
|
||||
compute_assiduites_justified(etud_1.etudid, [justif_3, justif_4])
|
||||
justif_3.justifier_assiduites()
|
||||
justif_4.justifier_assiduites()
|
||||
|
||||
assert (
|
||||
len(scass.justifies(justif_3)) == 1
|
||||
|
@ -33,7 +33,6 @@ from app.scodoc import sco_formsemestre_validation
|
||||
from app.scodoc import sco_cursus_dut
|
||||
from app.scodoc import sco_saisie_notes
|
||||
from app.scodoc.sco_utils import EtatAssiduite, EtatJustificatif, localize_datetime
|
||||
from app.models.assiduites import compute_assiduites_justified
|
||||
|
||||
DEPT = TestConfig.DEPT_TEST
|
||||
|
||||
@ -267,8 +266,5 @@ def _signal_absences_justificatifs(etudid: int):
|
||||
etat=EtatJustificatif.VALIDE,
|
||||
)
|
||||
db.session.add(justif)
|
||||
compute_assiduites_justified(
|
||||
etud.etudid,
|
||||
[justif],
|
||||
)
|
||||
db.session.commit()
|
||||
justif.justifier_assiduites()
|
||||
|
Loading…
Reference in New Issue
Block a user