From cab5a719254021e19baad8a2c40a2b40a85577de Mon Sep 17 00:00:00 2001 From: iziram Date: Sun, 30 Jul 2023 16:34:05 +0200 Subject: [PATCH] Assiduites : optimisation justification --- app/api/assiduites.py | 37 +++++++++++++++++++++- app/api/justificatifs.py | 22 +++++++------ app/models/assiduites.py | 50 ++++++++++++++---------------- tools/migrate_abs_to_assiduites.py | 3 -- 4 files changed, 73 insertions(+), 39 deletions(-) diff --git a/app/api/assiduites.py b/app/api/assiduites.py index d8d45462..0bd13486 100644 --- a/app/api/assiduites.py +++ b/app/api/assiduites.py @@ -17,7 +17,14 @@ import app.scodoc.sco_utils as scu from app.api import api_bp as bp from app.api import api_web_bp, get_model_api_object, tools from app.decorators import permission_required, scodoc -from app.models import Assiduite, FormSemestre, Identite, ModuleImpl, Scolog +from app.models import ( + Assiduite, + FormSemestre, + Identite, + ModuleImpl, + Scolog, + Justificatif, +) from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_permissions import Permission from app.scodoc.sco_utils import json_error @@ -47,6 +54,34 @@ def assiduite(assiduite_id: int = None): return get_model_api_object(Assiduite, assiduite_id, Identite) +@bp.route("/assiduite//justificatifs") +@api_web_bp.route("/assiduite//justificatifs") +@scodoc +@permission_required(Permission.ScoView) +@as_json +def assiduite_justificatifs(assiduite_id: int = None): + """Retourne la liste des justificatifs qui justifie cette assiduitée + + Exemple de résultat: + [ + 1, + 2, + 3, + ... + ] + """ + + assi: Assiduite = Assiduite.query.get_or_404(assiduite_id) + + justifs: Justificatif = Justificatif.query.filter( + Justificatif.etudid == assi.etudid, + Justificatif.date_debut <= assi.date_debut, + Justificatif.date_fin >= assi.date_fin, + ) + + return [j.justif_id for j in justifs] + + # etudid @bp.route("/assiduites//count", defaults={"with_query": False}) @api_web_bp.route("/assiduites//count", defaults={"with_query": False}) diff --git a/app/api/justificatifs.py b/app/api/justificatifs.py index 6810fd0f..c3e4442a 100644 --- a/app/api/justificatifs.py +++ b/app/api/justificatifs.py @@ -19,7 +19,9 @@ from app.api import api_web_bp from app.api import get_model_api_object, tools from app.decorators import permission_required, scodoc from app.models import Identite, Justificatif, Departement -from app.models.assiduites import compute_assiduites_justified +from app.models.assiduites import ( + compute_assiduites_justified, +) from app.scodoc.sco_archives_justificatifs import JustificatifArchiver from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_permissions import Permission @@ -197,14 +199,16 @@ def justif_create(etudid: int = None, nip=None, ine=None): errors: list = [] success: list = [] + justifs: list = [] for i, data in enumerate(create_list): - code, obj = _create_singular(data, etud) + code, obj, justi = _create_singular(data, etud) if code == 404: errors.append({"indice": i, "message": obj}) else: success.append({"indice": i, "message": obj}) + justifs.append(justi) scass.simple_invalidate_cache(data, etud.id) - compute_assiduites_justified(Justificatif.query.filter_by(etudid=etudid), True) + compute_assiduites_justified(etudid, justifs, True) return {"errors": errors, "success": success} @@ -246,7 +250,7 @@ def _create_singular( if errors: err: str = ", ".join(errors) - return (404, err) + return (404, err, None) # TOUT EST OK @@ -269,6 +273,7 @@ def _create_singular( "justif_id": nouv_justificatif.id, "couverture": scass.justifies(nouv_justificatif), }, + nouv_justificatif, ) except ScoValueError as excp: return ( @@ -358,7 +363,8 @@ def justif_edit(justif_id: int): "couverture": { "avant": avant_ids, "après": compute_assiduites_justified( - Justificatif.query.filter_by(etudid=justificatif_unique.etudid), + justificatif_unique.etudid, + [justificatif_unique], True, ), } @@ -420,13 +426,11 @@ def _delete_singular(justif_id: int, database): archiver.delete_justificatif(justificatif_unique.etudid, archive_name) except ValueError: pass - database.session.delete(justificatif_unique) - compute_assiduites_justified( - Justificatif.query.filter_by(etudid=justificatif_unique.etudid), True + justificatif_unique.etudid, [justificatif_unique], True ) - scass.simple_invalidate_cache(justificatif_unique.to_dict()) + database.session.delete(justificatif_unique) return (200, "OK") diff --git a/app/models/assiduites.py b/app/models/assiduites.py index 86f4d94d..6a42b344 100644 --- a/app/models/assiduites.py +++ b/app/models/assiduites.py @@ -308,38 +308,36 @@ def is_period_conflicting( def compute_assiduites_justified( - justificatifs: Justificatif = Justificatif, reset: bool = False + etudid: int, justificatifs: list[Justificatif] = None, reset: bool = False ) -> list[int]: - """Calcule et modifie les champs "est_just" de chaque assiduité lié à l'étud - retourne la liste des assiduite_id justifiées - - Si reset alors : met à false toutes les assiduités non justifiées par les justificatifs donnés """ + compute_assiduites_justified_faster - list_assiduites_id: set[int] = set() - for justi in justificatifs: - assiduites: Assiduite = ( - Assiduite.query.join(Justificatif, Justificatif.etudid == Assiduite.etudid) - .filter(justi.etat == EtatJustificatif.VALIDE) - .filter( - Assiduite.date_debut < justi.date_fin, - Assiduite.date_fin > justi.date_debut, - ) - ) + 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. - for assi in assiduites: + Returns: + list[int]: la liste des assiduités qui ont été justifiées. + """ + if justificatifs is None: + justificatifs: Justificatif = Justificatif.query.filter_by(etudid=etudid).all() + + assiduites: Assiduite = Assiduite.query.filter_by(etudid=etudid) + + assiduites_justifiees: list[int] = [] + + for assi in assiduites: + if any( + assi.date_debut >= j.date_debut and assi.date_fin <= j.date_fin + for j in justificatifs + ): assi.est_just = True - list_assiduites_id.add(assi.id) + assiduites_justifiees.append(assi.assiduite_id) db.session.add(assi) - - if reset: - un_justified: Assiduite = Assiduite.query.filter( - Assiduite.id.not_in(list_assiduites_id) - ).join(Justificatif, Justificatif.etudid == Assiduite.etudid) - - for assi in un_justified: + elif reset: assi.est_just = False db.session.add(assi) - db.session.commit() - return list(list_assiduites_id) + return assiduites_justifiees diff --git a/tools/migrate_abs_to_assiduites.py b/tools/migrate_abs_to_assiduites.py index d4eae657..0234a518 100644 --- a/tools/migrate_abs_to_assiduites.py +++ b/tools/migrate_abs_to_assiduites.py @@ -21,9 +21,6 @@ from app.models import ( from app.models.config import ScoDocSiteConfig -from app.models.assiduites import ( - compute_assiduites_justified, -) from app.profiler import Profiler from app.scodoc.sco_utils import ( EtatAssiduite,