diff --git a/app/api/assiduites.py b/app/api/assiduites.py index 7d46ddfe..b1386ca7 100644 --- a/app/api/assiduites.py +++ b/app/api/assiduites.py @@ -21,6 +21,7 @@ from app.api import api_web_bp, get_model_api_object, tools from app.decorators import permission_required, scodoc from app.models import ( Assiduite, + Evaluation, FormSemestre, Identite, ModuleImpl, @@ -282,6 +283,7 @@ def assiduites(etudid: int = None, nip=None, ine=None, with_query: bool = False) 404, message="étudiant inconnu", ) + # Récupération des assiduités de l'étudiant assiduites_query: Query = etud.assiduites @@ -304,6 +306,89 @@ def assiduites(etudid: int = None, nip=None, ine=None, with_query: bool = False) return data_set +@bp.route("/assiduites//evaluations") +@api_web_bp.route("/assiduites//evaluations") +# etudid +@bp.route("/assiduites/etudid//evaluations") +@api_web_bp.route("/assiduites/etudid//evaluations") +# ine +@bp.route("/assiduites/ine//evaluations") +@api_web_bp.route("/assiduites/ine//evaluations") +# nip +@bp.route("/assiduites/nip//evaluations") +@api_web_bp.route("/assiduites/nip//evaluations") +@login_required +@scodoc +@as_json +@permission_required(Permission.ScoView) +def assiduites_evaluations(etudid: int = None, nip=None, ine=None): + """ + Retourne la liste de toutes les évaluations de l'étudiant + Pour chaque évaluation, retourne la liste des objets assiduités + sur la plage de l'évaluation + + Présentation du retour : + [ + { + "evaluation_id": 1234, + "assiduites": [ + { + "assiduite_id":1234, + ... + }, + ] + } + ] + + """ + # Récupération de l'étudiant + etud: Identite = tools.get_etud(etudid, nip, ine) + if etud is None: + return json_error( + 404, + message="étudiant inconnu", + ) + + # Récupération des évaluations et des assidiutés + etud_evaluations_assiduites: list[dict] = scass.get_etud_evaluations_assiduites( + etud + ) + + return etud_evaluations_assiduites + + +@api_web_bp.route("/evaluation//assiduites") +@bp.route("/evaluation//assiduites") +@login_required +@scodoc +@as_json +@permission_required(Permission.ScoView) +def evaluation_assiduites(evaluation_id): + """ + Retourne les objets assiduités de chaque étudiant sur la plage de l'évaluation + Présentation du retour : + { + "" : [ + { + "assiduite_id":1234, + ... + }, + ] + } + """ + # Récupération de l'évaluation + evaluation: Evaluation = Evaluation.get_evaluation(evaluation_id) + + evaluation_assiduites_par_etudid: dict[int, list[Assiduite]] = {} + for assi in scass.get_evaluation_assiduites(evaluation): + etudid: str = str(assi.etudid) + etud_assiduites = evaluation_assiduites_par_etudid.get(etudid, []) + etud_assiduites.append(assi.to_dict(format_api=True)) + evaluation_assiduites_par_etudid[etudid] = etud_assiduites + + return evaluation_assiduites_par_etudid + + @bp.route("/assiduites/group/query", defaults={"with_query": True}) @api_web_bp.route("/assiduites/group/query", defaults={"with_query": True}) @login_required diff --git a/app/scodoc/sco_assiduites.py b/app/scodoc/sco_assiduites.py index ff2088fc..1383f6ba 100644 --- a/app/scodoc/sco_assiduites.py +++ b/app/scodoc/sco_assiduites.py @@ -10,6 +10,7 @@ from flask_sqlalchemy.query import Query from app import log, db, set_sco_dept from app.models import ( + Evaluation, Identite, FormSemestre, FormSemestreInscription, @@ -731,6 +732,95 @@ def create_absence_billet( return calculator.to_dict()["demi"] +def get_evaluation_assiduites(evaluation: Evaluation) -> Query: + """ + Renvoie une query d'assiduité en fonction des étudiants inscrits à l'évaluation + et de la date de l'évaluation. + + Attention : Si l'évaluation n'a pas de date, renvoie None + """ + + # Evaluation sans date + if evaluation.date_debut is None: + return None + + # Récupération des étudiants inscrits à l'évaluation + etuds: Query = Identite.query.join( + ModuleImplInscription, Identite.id == ModuleImplInscription.etudid + ).filter(ModuleImplInscription.moduleimpl_id == evaluation.moduleimpl_id) + + etudids: list[int] = [etud.id for etud in etuds] + + # Récupération des assiduités des étudiants inscrits à l'évaluation + date_debut: datetime = evaluation.date_debut + date_fin: datetime + + if evaluation.date_fin is not None: + date_fin = evaluation.date_fin + else: + # On met à la fin de la journée de date_debut + date_fin = datetime.combine(date_debut.date(), time.max) + + # Filtrage par rapport à la plage de l'évaluation + assiduites: Query = Assiduite.query.filter( + Assiduite.date_debut >= date_debut, + Assiduite.date_fin <= date_fin, + Assiduite.etudid.in_(etudids), + ) + + return assiduites + + +def get_etud_evaluations_assiduites(etud: Identite) -> list[dict]: + """ + Retourne la liste des évaluations d'un étudiant. Pour chaque évaluation, + retourne la liste des assiduités concernant la plage de l'évaluation. + """ + + etud_evaluations_assiduites: list[dict] = [] + + # On récupère les moduleimpls puis les évaluations liés aux moduleimpls + modsimpl_ids: list[int] = [ + modimp_inscr.moduleimpl_id + for modimp_inscr in ModuleImplInscription.query.filter_by(etudid=etud.id) + ] + evaluations: Query = Evaluation.query.filter( + Evaluation.moduleimpl_id.in_(modsimpl_ids) + ) + # Pour chaque évaluation, on récupère l'assiduité de l'étudiant sur la plage + # de l'évaluation + + for evaluation in evaluations: + eval_assis: dict = {"evaluation_id": evaluation.id, "assiduites": []} + # Pas d'assiduités si pas de date + if evaluation.date_debut is None: + continue + + date_debut: datetime = evaluation.date_debut + date_fin: datetime + + if evaluation.date_fin is not None: + date_fin = evaluation.date_fin + else: + # On met à la fin de la journée de date_debut + date_fin = datetime.combine(date_debut.date(), time.max) + + # Filtrage par rapport à la plage de l'évaluation + assiduites: Query = etud.assiduites.filter( + Assiduite.date_debut >= date_debut, + Assiduite.date_fin <= date_fin, + ) + # On récupère les assiduités et on met à jour le dictionnaire + eval_assis["assiduites"] = [ + assi.to_dict(format_api=True) for assi in assiduites + ] + + # On ajoute le dictionnaire à la liste des évaluations + etud_evaluations_assiduites.append(eval_assis) + + return etud_evaluations_assiduites + + # Gestion du cache def get_assiduites_count(etudid: int, sem: dict) -> tuple[int, int, int]: """Les comptes d'absences de cet étudiant dans ce semestre: