2023-04-17 15:35:42 +02:00
|
|
|
##############################################################################
|
|
|
|
# ScoDoc
|
|
|
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
|
|
|
# See LICENSE
|
|
|
|
##############################################################################
|
2024-06-20 17:56:12 +02:00
|
|
|
"""ScoDoc 9 API : Justificatifs"""
|
|
|
|
|
2023-04-17 15:35:42 +02:00
|
|
|
from datetime import datetime
|
|
|
|
|
2023-05-17 21:16:23 +02:00
|
|
|
from flask_json import as_json
|
2023-09-07 23:09:39 +02:00
|
|
|
from flask import g, request
|
2023-04-17 15:35:42 +02:00
|
|
|
from flask_login import login_required, current_user
|
2023-09-07 23:09:39 +02:00
|
|
|
from flask_sqlalchemy.query import Query
|
2023-12-22 15:25:58 +01:00
|
|
|
from werkzeug.exceptions import NotFound
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
import app.scodoc.sco_assiduites as scass
|
|
|
|
import app.scodoc.sco_utils as scu
|
2024-01-18 00:27:17 +01:00
|
|
|
from app import db, set_sco_dept
|
2023-04-17 15:35:42 +02:00
|
|
|
from app.api import api_bp as bp
|
|
|
|
from app.api import api_web_bp
|
2023-07-27 14:58:57 +02:00
|
|
|
from app.api import get_model_api_object, tools
|
2024-07-17 12:03:08 +02:00
|
|
|
from app.api import api_permission_required as permission_required
|
|
|
|
from app.decorators import scodoc
|
2024-02-28 11:33:23 +01:00
|
|
|
from app.models import Identite, Justificatif, Departement, FormSemestre, Scolog
|
2023-07-30 16:34:05 +02:00
|
|
|
from app.models.assiduites import (
|
2023-10-27 16:05:40 +02:00
|
|
|
get_formsemestre_from_data,
|
2023-07-30 16:34:05 +02:00
|
|
|
)
|
2023-04-17 15:35:42 +02:00
|
|
|
from app.scodoc.sco_archives_justificatifs import JustificatifArchiver
|
|
|
|
from app.scodoc.sco_exceptions import ScoValueError
|
|
|
|
from app.scodoc.sco_permissions import Permission
|
|
|
|
from app.scodoc.sco_utils import json_error
|
2023-09-13 15:19:21 +02:00
|
|
|
from app.scodoc.sco_groups import get_group_members
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
# Partie Modèle
|
|
|
|
@bp.route("/justificatif/<int:justif_id>")
|
|
|
|
@api_web_bp.route("/justificatif/<int:justif_id>")
|
|
|
|
@scodoc
|
|
|
|
@permission_required(Permission.ScoView)
|
|
|
|
def justificatif(justif_id: int = None):
|
2024-07-25 11:08:06 +02:00
|
|
|
"""Retourne un objet justificatif à partir de son id.
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
Exemple de résultat:
|
2024-07-25 11:08:06 +02:00
|
|
|
|
|
|
|
```json
|
2023-04-17 15:35:42 +02:00
|
|
|
{
|
|
|
|
"justif_id": 1,
|
|
|
|
"etudid": 2,
|
|
|
|
"date_debut": "2022-10-31T08:00+01:00",
|
|
|
|
"date_fin": "2022-10-31T10:00+01:00",
|
|
|
|
"etat": "valide",
|
|
|
|
"fichier": "archive_id",
|
2024-01-21 18:07:56 +01:00
|
|
|
"raison": "une raison", // VIDE si pas le droit
|
2023-04-17 15:35:42 +02:00
|
|
|
"entry_date": "2022-10-31T08:00+01:00",
|
|
|
|
"user_id": 1 or null,
|
|
|
|
}
|
2024-07-25 11:08:06 +02:00
|
|
|
```
|
2024-07-25 13:03:10 +02:00
|
|
|
|
|
|
|
SAMPLES
|
|
|
|
-------
|
|
|
|
/justificatif/1;
|
|
|
|
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
|
|
|
|
2024-01-21 18:07:56 +01:00
|
|
|
return get_model_api_object(
|
|
|
|
Justificatif,
|
|
|
|
justif_id,
|
|
|
|
Identite,
|
|
|
|
restrict=not current_user.has_permission(Permission.AbsJustifView),
|
|
|
|
)
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
|
2023-07-27 14:58:57 +02:00
|
|
|
# etudid
|
2023-10-11 16:37:13 +02:00
|
|
|
@bp.route("/justificatifs/<int:etudid>", defaults={"with_query": False})
|
|
|
|
@api_web_bp.route("/justificatifs/<int:etudid>", defaults={"with_query": False})
|
|
|
|
@bp.route("/justificatifs/<int:etudid>/query", defaults={"with_query": True})
|
|
|
|
@api_web_bp.route("/justificatifs/<int:etudid>/query", defaults={"with_query": True})
|
|
|
|
@bp.route("/justificatifs/etudid/<int:etudid>", defaults={"with_query": False})
|
|
|
|
@api_web_bp.route("/justificatifs/etudid/<int:etudid>", defaults={"with_query": False})
|
|
|
|
@bp.route("/justificatifs/etudid/<int:etudid>/query", defaults={"with_query": True})
|
|
|
|
@api_web_bp.route(
|
|
|
|
"/justificatifs/etudid/<int:etudid>/query", defaults={"with_query": True}
|
|
|
|
)
|
2023-07-27 14:58:57 +02:00
|
|
|
# nip
|
|
|
|
@bp.route("/justificatifs/nip/<nip>", defaults={"with_query": False})
|
|
|
|
@api_web_bp.route("/justificatifs/nip/<nip>", defaults={"with_query": False})
|
|
|
|
@bp.route("/justificatifs/nip/<nip>/query", defaults={"with_query": True})
|
|
|
|
@api_web_bp.route("/justificatifs/nip/<nip>/query", defaults={"with_query": True})
|
|
|
|
# ine
|
|
|
|
@bp.route("/justificatifs/ine/<ine>", defaults={"with_query": False})
|
|
|
|
@api_web_bp.route("/justificatifs/ine/<ine>", defaults={"with_query": False})
|
|
|
|
@bp.route("/justificatifs/ine/<ine>/query", defaults={"with_query": True})
|
|
|
|
@api_web_bp.route("/justificatifs/ine/<ine>/query", defaults={"with_query": True})
|
|
|
|
#
|
2023-04-17 15:35:42 +02:00
|
|
|
@login_required
|
|
|
|
@scodoc
|
2023-05-17 21:16:23 +02:00
|
|
|
@as_json
|
2023-04-17 15:35:42 +02:00
|
|
|
@permission_required(Permission.ScoView)
|
2023-07-27 14:58:57 +02:00
|
|
|
def justificatifs(etudid: int = None, nip=None, ine=None, with_query: bool = False):
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
|
|
|
Retourne toutes les assiduités d'un étudiant
|
2024-07-24 11:07:57 +02:00
|
|
|
|
2024-06-20 17:56:12 +02:00
|
|
|
QUERY
|
|
|
|
-----
|
|
|
|
user_id:<int:user_id>
|
|
|
|
date_debut:<string:date_debut_iso>
|
|
|
|
date_fin:<string:date_fin_iso>
|
|
|
|
etat:<array[string]:etat>
|
|
|
|
order:<bool:order>
|
|
|
|
courant:<bool:courant>
|
|
|
|
group_id:<int:group_id>
|
2024-07-24 11:07:57 +02:00
|
|
|
|
|
|
|
PARAMS
|
|
|
|
-----
|
|
|
|
user_id:l'id de l'auteur du justificatif
|
|
|
|
date_debut:date de début du justificatif (supérieur ou égal)
|
|
|
|
date_fin:date de fin du justificatif (inférieur ou égal)
|
|
|
|
etat:etat du justificatif → valide, non_valide, attente, modifie
|
|
|
|
order:retourne les justificatifs dans l'ordre décroissant (non vide = True)
|
|
|
|
courant:retourne les justificatifs de l'année courante (bool : v/t ou f)
|
|
|
|
group_id:<int:group_id>
|
2024-07-25 13:03:10 +02:00
|
|
|
|
|
|
|
SAMPLES
|
|
|
|
-------
|
|
|
|
/justificatifs/1;
|
|
|
|
/justificatifs/1/query?etat=attente;
|
|
|
|
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
2023-10-27 16:05:40 +02:00
|
|
|
# Récupération de l'étudiant
|
2023-07-27 14:58:57 +02:00
|
|
|
etud: Identite = tools.get_etud(etudid, nip, ine)
|
2023-04-17 15:35:42 +02:00
|
|
|
|
2023-07-27 14:58:57 +02:00
|
|
|
if etud is None:
|
|
|
|
return json_error(
|
|
|
|
404,
|
|
|
|
message="étudiant inconnu",
|
|
|
|
)
|
2023-10-27 16:05:40 +02:00
|
|
|
|
|
|
|
# Récupération des justificatifs de l'étudiant
|
2023-04-17 15:35:42 +02:00
|
|
|
justificatifs_query = etud.justificatifs
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Filtrage des justificatifs en fonction de la requête
|
2023-04-17 15:35:42 +02:00
|
|
|
if with_query:
|
|
|
|
justificatifs_query = _filter_manager(request, justificatifs_query)
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Mise en forme des données puis retour en JSON
|
2023-04-17 15:35:42 +02:00
|
|
|
data_set: list[dict] = []
|
2024-01-21 18:07:56 +01:00
|
|
|
restrict = not current_user.has_permission(Permission.AbsJustifView)
|
2023-04-17 15:35:42 +02:00
|
|
|
for just in justificatifs_query.all():
|
2024-01-21 18:07:56 +01:00
|
|
|
data = just.to_dict(format_api=True, restrict=restrict)
|
2023-04-17 15:35:42 +02:00
|
|
|
data_set.append(data)
|
|
|
|
|
2023-05-17 21:16:23 +02:00
|
|
|
return data_set
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
|
2023-06-28 17:15:24 +02:00
|
|
|
@api_web_bp.route("/justificatifs/dept/<int:dept_id>", defaults={"with_query": False})
|
|
|
|
@api_web_bp.route(
|
|
|
|
"/justificatifs/dept/<int:dept_id>/query", defaults={"with_query": True}
|
|
|
|
)
|
2023-09-12 14:58:01 +02:00
|
|
|
@bp.route("/justificatifs/dept/<int:dept_id>", defaults={"with_query": False})
|
|
|
|
@bp.route("/justificatifs/dept/<int:dept_id>/query", defaults={"with_query": True})
|
2023-06-28 17:15:24 +02:00
|
|
|
@login_required
|
|
|
|
@scodoc
|
|
|
|
@as_json
|
|
|
|
@permission_required(Permission.ScoView)
|
2023-06-30 15:34:50 +02:00
|
|
|
def justificatifs_dept(dept_id: int = None, with_query: bool = False):
|
2024-01-19 17:06:01 +01:00
|
|
|
"""
|
2024-01-20 20:19:50 +01:00
|
|
|
Renvoie tous les justificatifs d'un département
|
2024-07-27 13:30:02 +02:00
|
|
|
(en ajoutant un champ "`formsemestre`" si possible).
|
2024-06-20 17:56:12 +02:00
|
|
|
|
|
|
|
QUERY
|
|
|
|
-----
|
|
|
|
user_id:<int:user_id>
|
|
|
|
est_just:<bool:est_just>
|
|
|
|
date_debut:<string:date_debut_iso>
|
|
|
|
date_fin:<string:date_fin_iso>
|
|
|
|
etat:<array[string]:etat>
|
|
|
|
order:<bool:order>
|
|
|
|
courant:<bool:courant>
|
|
|
|
group_id:<int:group_id>
|
2024-07-24 11:07:57 +02:00
|
|
|
|
|
|
|
PARAMS
|
|
|
|
-----
|
|
|
|
user_id:l'id de l'auteur du justificatif
|
|
|
|
date_debut:date de début du justificatif (supérieur ou égal)
|
|
|
|
date_fin:date de fin du justificatif (inférieur ou égal)
|
|
|
|
etat:etat du justificatif → valide, non_valide, attente, modifie
|
|
|
|
order:retourne les justificatifs dans l'ordre décroissant (non vide = True)
|
|
|
|
courant:retourne les justificatifs de l'année courante (bool : v/t ou f)
|
|
|
|
group_id:<int:group_id>
|
2024-07-25 13:03:10 +02:00
|
|
|
|
|
|
|
SAMPLES
|
|
|
|
-------
|
|
|
|
/justificatifs/dept/1;
|
|
|
|
|
2024-01-19 17:06:01 +01:00
|
|
|
"""
|
2023-06-28 17:15:24 +02:00
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Récupération du département et des étudiants du département
|
2024-08-06 23:18:17 +02:00
|
|
|
dept: Departement = db.session.get(Departement, dept_id)
|
2024-01-05 13:42:55 +01:00
|
|
|
if dept is None:
|
2024-01-05 23:20:32 +01:00
|
|
|
return json_error(404, "Assiduité non existante")
|
2023-10-27 16:05:40 +02:00
|
|
|
etuds: list[int] = [etud.id for etud in dept.etudiants]
|
|
|
|
|
|
|
|
# Récupération des justificatifs des étudiants du département
|
|
|
|
justificatifs_query: Query = Justificatif.query.filter(
|
|
|
|
Justificatif.etudid.in_(etuds)
|
|
|
|
)
|
2023-06-28 17:15:24 +02:00
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Filtrage des justificatifs
|
2023-06-28 17:15:24 +02:00
|
|
|
if with_query:
|
2023-10-27 16:05:40 +02:00
|
|
|
justificatifs_query: Query = _filter_manager(request, justificatifs_query)
|
2023-09-13 15:19:21 +02:00
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Mise en forme des données et retour JSON
|
2024-01-21 18:07:56 +01:00
|
|
|
restrict = not current_user.has_permission(Permission.AbsJustifView)
|
2023-06-28 17:15:24 +02:00
|
|
|
data_set: list[dict] = []
|
2023-09-13 15:19:21 +02:00
|
|
|
for just in justificatifs_query:
|
2024-01-21 18:07:56 +01:00
|
|
|
data_set.append(_set_sems(just, restrict=restrict))
|
2023-06-28 17:15:24 +02:00
|
|
|
|
|
|
|
return data_set
|
|
|
|
|
|
|
|
|
2024-01-21 18:07:56 +01:00
|
|
|
def _set_sems(justi: Justificatif, restrict: bool) -> dict:
|
2023-10-27 16:05:40 +02:00
|
|
|
"""
|
2024-07-27 13:30:02 +02:00
|
|
|
_set_sems Ajoute le formsemestre associé au justificatif s'il existe.
|
2023-10-27 16:05:40 +02:00
|
|
|
|
2024-07-27 13:30:02 +02:00
|
|
|
Si le formsemestre n'existe pas, renvoie la simple représentation du justificatif.
|
2023-10-27 16:05:40 +02:00
|
|
|
|
|
|
|
Args:
|
|
|
|
justi (Justificatif): Le justificatif
|
2023-09-13 15:19:21 +02:00
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
Returns:
|
|
|
|
dict: La représentation de l'assiduité en dictionnaire
|
|
|
|
"""
|
|
|
|
# Conversion du justificatif en dictionnaire
|
2024-01-21 18:07:56 +01:00
|
|
|
data = justi.to_dict(format_api=True, restrict=restrict)
|
2023-09-13 15:19:21 +02:00
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Récupération du formsemestre de l'assiduité
|
|
|
|
formsemestre: FormSemestre = get_formsemestre_from_data(justi.to_dict())
|
|
|
|
# Si le formsemestre existe on l'ajoute au dictionnaire
|
2023-09-13 15:19:21 +02:00
|
|
|
if formsemestre:
|
|
|
|
data["formsemestre"] = {
|
|
|
|
"id": formsemestre.id,
|
|
|
|
"title": formsemestre.session_id(),
|
|
|
|
}
|
|
|
|
return data
|
|
|
|
|
|
|
|
|
2023-09-12 13:40:03 +02:00
|
|
|
@bp.route(
|
|
|
|
"/justificatifs/formsemestre/<int:formsemestre_id>", defaults={"with_query": False}
|
|
|
|
)
|
|
|
|
@api_web_bp.route(
|
|
|
|
"/justificatifs/formsemestre/<int:formsemestre_id>", defaults={"with_query": False}
|
|
|
|
)
|
|
|
|
@bp.route(
|
|
|
|
"/justificatifs/formsemestre/<int:formsemestre_id>/query",
|
|
|
|
defaults={"with_query": True},
|
|
|
|
)
|
|
|
|
@api_web_bp.route(
|
|
|
|
"/justificatifs/formsemestre/<int:formsemestre_id>/query",
|
|
|
|
defaults={"with_query": True},
|
|
|
|
)
|
|
|
|
@login_required
|
|
|
|
@scodoc
|
|
|
|
@as_json
|
|
|
|
@permission_required(Permission.ScoView)
|
|
|
|
def justificatifs_formsemestre(formsemestre_id: int, with_query: bool = False):
|
2024-07-27 13:30:02 +02:00
|
|
|
"""Retourne tous les justificatifs du formsemestre.
|
2024-06-20 17:56:12 +02:00
|
|
|
|
|
|
|
QUERY
|
|
|
|
-----
|
|
|
|
user_id:<int:user_id>
|
|
|
|
est_just:<bool:est_just>
|
|
|
|
date_debut:<string:date_debut_iso>
|
|
|
|
date_fin:<string:date_fin_iso>
|
|
|
|
etat:<array[string]:etat>
|
|
|
|
order:<bool:order>
|
|
|
|
courant:<bool:courant>
|
|
|
|
group_id:<int:group_id>
|
2024-07-24 11:07:57 +02:00
|
|
|
|
|
|
|
PARAMS
|
|
|
|
-----
|
|
|
|
user_id:l'id de l'auteur du justificatif
|
|
|
|
date_debut:date de début du justificatif (supérieur ou égal)
|
|
|
|
date_fin:date de fin du justificatif (inférieur ou égal)
|
|
|
|
etat:etat du justificatif → valide, non_valide, attente, modifie
|
|
|
|
order:retourne les justificatifs dans l'ordre décroissant (non vide = True)
|
|
|
|
courant:retourne les justificatifs de l'année courante (bool : v/t ou f)
|
|
|
|
group_id:<int:group_id>
|
2024-07-25 13:03:10 +02:00
|
|
|
|
|
|
|
SAMPLES
|
|
|
|
-------
|
|
|
|
/justificatifs/formsemestre/1;
|
|
|
|
|
2024-06-20 17:56:12 +02:00
|
|
|
"""
|
2023-10-27 16:05:40 +02:00
|
|
|
|
|
|
|
# Récupération du formsemestre
|
2023-09-12 13:40:03 +02:00
|
|
|
formsemestre: FormSemestre = None
|
|
|
|
formsemestre_id = int(formsemestre_id)
|
2023-10-27 16:05:40 +02:00
|
|
|
formsemestre: FormSemestre = FormSemestre.query.filter_by(
|
|
|
|
id=formsemestre_id
|
|
|
|
).first()
|
2023-09-12 13:40:03 +02:00
|
|
|
|
|
|
|
if formsemestre is None:
|
|
|
|
return json_error(404, "le paramètre 'formsemestre_id' n'existe pas")
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Récupération des justificatifs du semestre
|
|
|
|
justificatifs_query: Query = scass.filter_by_formsemestre(
|
2023-09-12 13:40:03 +02:00
|
|
|
Justificatif.query, Justificatif, formsemestre
|
|
|
|
)
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Filtrage des justificatifs
|
2023-09-12 13:40:03 +02:00
|
|
|
if with_query:
|
2023-10-27 16:05:40 +02:00
|
|
|
justificatifs_query: Query = _filter_manager(request, justificatifs_query)
|
2023-09-12 13:40:03 +02:00
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Retour des justificatifs en JSON
|
2024-01-21 18:07:56 +01:00
|
|
|
restrict = not current_user.has_permission(Permission.AbsJustifView)
|
2023-09-12 13:40:03 +02:00
|
|
|
data_set: list[dict] = []
|
|
|
|
for justi in justificatifs_query.all():
|
2024-01-21 18:07:56 +01:00
|
|
|
data = justi.to_dict(format_api=True, restrict=restrict)
|
2023-09-12 13:40:03 +02:00
|
|
|
data_set.append(data)
|
|
|
|
|
|
|
|
return data_set
|
|
|
|
|
|
|
|
|
2023-04-17 15:35:42 +02:00
|
|
|
@bp.route("/justificatif/<int:etudid>/create", methods=["POST"])
|
|
|
|
@api_web_bp.route("/justificatif/<int:etudid>/create", methods=["POST"])
|
2023-10-11 16:37:13 +02:00
|
|
|
@bp.route("/justificatif/etudid/<int:etudid>/create", methods=["POST"])
|
|
|
|
@api_web_bp.route("/justificatif/etudid/<int:etudid>/create", methods=["POST"])
|
2023-07-30 15:27:31 +02:00
|
|
|
# nip
|
|
|
|
@bp.route("/justificatif/nip/<nip>/create", methods=["POST"])
|
|
|
|
@api_web_bp.route("/justificatif/nip/<nip>/create", methods=["POST"])
|
|
|
|
# ine
|
|
|
|
@bp.route("/justificatif/ine/<ine>/create", methods=["POST"])
|
|
|
|
@api_web_bp.route("/justificatif/ine/<ine>/create", methods=["POST"])
|
2023-04-17 15:35:42 +02:00
|
|
|
@scodoc
|
|
|
|
@login_required
|
2023-05-17 21:16:23 +02:00
|
|
|
@as_json
|
2023-09-29 21:17:31 +02:00
|
|
|
@permission_required(Permission.AbsChange)
|
2023-07-27 18:00:40 +02:00
|
|
|
def justif_create(etudid: int = None, nip=None, ine=None):
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
2024-07-27 13:30:02 +02:00
|
|
|
Création d'un justificatif pour l'étudiant.
|
2024-07-24 11:07:57 +02:00
|
|
|
|
|
|
|
DATA
|
|
|
|
----
|
|
|
|
```json
|
2023-04-17 15:35:42 +02:00
|
|
|
[
|
|
|
|
{
|
|
|
|
"date_debut": str,
|
|
|
|
"date_fin": str,
|
|
|
|
"etat": str,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"date_debut": str,
|
|
|
|
"date_fin": str,
|
|
|
|
"etat": str,
|
|
|
|
"raison":str,
|
|
|
|
}
|
|
|
|
...
|
|
|
|
]
|
2024-07-24 11:07:57 +02:00
|
|
|
```
|
2024-07-25 13:03:10 +02:00
|
|
|
SAMPLES
|
|
|
|
-------
|
|
|
|
/justificatif/1/create;[{""date_debut"": ""2023-10-27T08:00"",""date_fin"": ""2023-10-27T10:00"",""etat"": ""attente""}]
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
"""
|
2023-10-27 16:05:40 +02:00
|
|
|
|
|
|
|
# Récupération de l'étudiant
|
2023-07-27 14:58:57 +02:00
|
|
|
etud: Identite = tools.get_etud(etudid, nip, ine)
|
|
|
|
|
|
|
|
if etud is None:
|
|
|
|
return json_error(
|
|
|
|
404,
|
|
|
|
message="étudiant inconnu",
|
|
|
|
)
|
2024-01-18 00:27:17 +01:00
|
|
|
set_sco_dept(etud.departement.acronym)
|
2023-04-17 15:35:42 +02:00
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Récupération des justificatifs à créer
|
2023-04-17 15:35:42 +02:00
|
|
|
create_list: list[object] = request.get_json(force=True)
|
|
|
|
|
|
|
|
if not isinstance(create_list, list):
|
|
|
|
return json_error(404, "Le contenu envoyé n'est pas une liste")
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
errors: list[dict] = []
|
|
|
|
success: list[dict] = []
|
|
|
|
|
|
|
|
# énumération des justificatifs
|
2023-04-17 15:35:42 +02:00
|
|
|
for i, data in enumerate(create_list):
|
2023-10-11 14:45:06 +02:00
|
|
|
code, obj, justi = _create_one(data, etud)
|
2023-10-27 16:05:40 +02:00
|
|
|
code: int
|
|
|
|
obj: str | dict
|
|
|
|
justi: Justificatif | None
|
2023-04-17 15:35:42 +02:00
|
|
|
if code == 404:
|
2023-07-27 18:00:40 +02:00
|
|
|
errors.append({"indice": i, "message": obj})
|
2023-04-17 15:35:42 +02:00
|
|
|
else:
|
2023-07-27 18:00:40 +02:00
|
|
|
success.append({"indice": i, "message": obj})
|
2024-02-29 14:20:39 +01:00
|
|
|
justi.justifier_assiduites()
|
2023-06-30 15:34:50 +02:00
|
|
|
scass.simple_invalidate_cache(data, etud.id)
|
2023-07-31 16:15:59 +02:00
|
|
|
|
2023-05-17 21:16:23 +02:00
|
|
|
return {"errors": errors, "success": success}
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
|
2023-10-11 14:45:06 +02:00
|
|
|
def _create_one(
|
2023-04-17 15:35:42 +02:00
|
|
|
data: dict,
|
|
|
|
etud: Identite,
|
2023-10-27 16:05:40 +02:00
|
|
|
) -> tuple[int, object, Justificatif]:
|
2023-04-17 15:35:42 +02:00
|
|
|
errors: list[str] = []
|
|
|
|
|
|
|
|
# -- vérifications de l'objet json --
|
|
|
|
# cas 1 : ETAT
|
2023-10-27 16:05:40 +02:00
|
|
|
etat: str = data.get("etat", None)
|
2023-04-17 15:35:42 +02:00
|
|
|
if etat is None:
|
|
|
|
errors.append("param 'etat': manquant")
|
|
|
|
elif not scu.EtatJustificatif.contains(etat):
|
|
|
|
errors.append("param 'etat': invalide")
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
etat: scu.EtatJustificatif = scu.EtatJustificatif.get(etat)
|
2024-06-26 10:32:15 +02:00
|
|
|
if etat != scu.EtatJustificatif.ATTENTE and not current_user.has_permission(
|
|
|
|
Permission.JustifValidate
|
|
|
|
):
|
|
|
|
errors.append("param 'etat': non autorisé (Permission.JustifValidate)")
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
# cas 2 : date_debut
|
2023-10-27 16:05:40 +02:00
|
|
|
date_debut: str = data.get("date_debut", None)
|
2023-04-17 15:35:42 +02:00
|
|
|
if date_debut is None:
|
|
|
|
errors.append("param 'date_debut': manquant")
|
2023-10-27 16:05:40 +02:00
|
|
|
deb: datetime = scu.is_iso_formated(date_debut, convert=True)
|
2023-04-17 15:35:42 +02:00
|
|
|
if deb is None:
|
|
|
|
errors.append("param 'date_debut': format invalide")
|
|
|
|
|
|
|
|
# cas 3 : date_fin
|
2023-10-27 16:05:40 +02:00
|
|
|
date_fin: str = data.get("date_fin", None)
|
2023-04-17 15:35:42 +02:00
|
|
|
if date_fin is None:
|
|
|
|
errors.append("param 'date_fin': manquant")
|
2023-10-27 16:05:40 +02:00
|
|
|
fin: datetime = scu.is_iso_formated(date_fin, convert=True)
|
2023-04-17 15:35:42 +02:00
|
|
|
if fin is None:
|
|
|
|
errors.append("param 'date_fin': format invalide")
|
|
|
|
|
|
|
|
# cas 4 : raison
|
|
|
|
|
|
|
|
raison: str = data.get("raison", None)
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
external_data: dict = data.get("external_data")
|
2023-07-31 09:41:32 +02:00
|
|
|
if external_data is not None:
|
|
|
|
if not isinstance(external_data, dict):
|
|
|
|
errors.append("param 'external_data' : n'est pas un objet JSON")
|
|
|
|
|
2023-04-17 15:35:42 +02:00
|
|
|
if errors:
|
|
|
|
err: str = ", ".join(errors)
|
2023-07-30 16:34:05 +02:00
|
|
|
return (404, err, None)
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
# TOUT EST OK
|
|
|
|
|
|
|
|
try:
|
2023-10-27 16:05:40 +02:00
|
|
|
# On essaye de créer le justificatif
|
2023-08-14 01:08:04 +02:00
|
|
|
nouv_justificatif: Query = Justificatif.create_justificatif(
|
2023-04-17 15:35:42 +02:00
|
|
|
date_debut=deb,
|
|
|
|
date_fin=fin,
|
|
|
|
etat=etat,
|
2023-12-22 15:25:58 +01:00
|
|
|
etudiant=etud,
|
2023-04-17 15:35:42 +02:00
|
|
|
raison=raison,
|
|
|
|
user_id=current_user.id,
|
2023-07-31 09:41:32 +02:00
|
|
|
external_data=external_data,
|
2023-04-17 15:35:42 +02:00
|
|
|
)
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Si tout s'est bien passé on ajoute l'assiduité à la session
|
|
|
|
# et on retourne un code 200 avec un objet possèdant le justif_id
|
|
|
|
# ainsi que les assiduités justifiées par le dit justificatif
|
|
|
|
|
|
|
|
# On renvoie aussi le justificatif créé pour pour le calcul total de fin
|
2023-04-17 15:35:42 +02:00
|
|
|
db.session.add(nouv_justificatif)
|
|
|
|
db.session.commit()
|
|
|
|
|
|
|
|
return (
|
|
|
|
200,
|
|
|
|
{
|
|
|
|
"justif_id": nouv_justificatif.id,
|
|
|
|
"couverture": scass.justifies(nouv_justificatif),
|
|
|
|
},
|
2023-07-30 16:34:05 +02:00
|
|
|
nouv_justificatif,
|
2023-04-17 15:35:42 +02:00
|
|
|
)
|
|
|
|
except ScoValueError as excp:
|
2023-10-27 16:05:40 +02:00
|
|
|
return (404, excp.args[0], None)
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
@bp.route("/justificatif/<int:justif_id>/edit", methods=["POST"])
|
|
|
|
@api_web_bp.route("/justificatif/<int:justif_id>/edit", methods=["POST"])
|
|
|
|
@login_required
|
|
|
|
@scodoc
|
2023-05-17 21:16:23 +02:00
|
|
|
@as_json
|
2023-09-29 21:17:31 +02:00
|
|
|
@permission_required(Permission.AbsChange)
|
2023-04-17 15:35:42 +02:00
|
|
|
def justif_edit(justif_id: int):
|
|
|
|
"""
|
2024-07-27 13:30:02 +02:00
|
|
|
Édition d'un justificatif à partir de son id.
|
2023-04-17 15:35:42 +02:00
|
|
|
|
2024-07-24 11:07:57 +02:00
|
|
|
DATA
|
|
|
|
----
|
|
|
|
```json
|
2023-04-17 15:35:42 +02:00
|
|
|
{
|
|
|
|
"etat"?: str,
|
|
|
|
"raison"?: str
|
|
|
|
"date_debut"?: str
|
|
|
|
"date_fin"?: str
|
|
|
|
}
|
2024-07-24 11:07:57 +02:00
|
|
|
```
|
2024-07-25 13:03:10 +02:00
|
|
|
|
|
|
|
SAMPLES
|
|
|
|
-------
|
|
|
|
/justificatif/1/edit;{""etat"":""valide""}
|
|
|
|
/justificatif/1/edit;{""raison"":""MEDIC""}
|
|
|
|
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
2023-10-27 16:05:40 +02:00
|
|
|
|
|
|
|
# Récupération du justificatif à modifier
|
2023-12-22 15:25:58 +01:00
|
|
|
justificatif_unique = Justificatif.get_justificatif(justif_id)
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
errors: list[str] = []
|
|
|
|
data = request.get_json(force=True)
|
2023-10-27 16:05:40 +02:00
|
|
|
|
|
|
|
# Récupération des assiduités (id) précédemment justifiée par le justificatif
|
2023-04-17 15:35:42 +02:00
|
|
|
avant_ids: list[int] = scass.justifies(justificatif_unique)
|
|
|
|
# Vérifications de data
|
|
|
|
|
|
|
|
# Cas 1 : Etat
|
|
|
|
if data.get("etat") is not None:
|
2023-10-27 16:05:40 +02:00
|
|
|
etat: scu.EtatJustificatif = scu.EtatJustificatif.get(data.get("etat"))
|
2023-04-17 15:35:42 +02:00
|
|
|
if etat is None:
|
|
|
|
errors.append("param 'etat': invalide")
|
|
|
|
else:
|
2024-06-26 10:32:15 +02:00
|
|
|
if current_user.has_permission(Permission.JustifValidate):
|
|
|
|
justificatif_unique.etat = etat
|
|
|
|
else:
|
|
|
|
errors.append("param 'etat': non autorisé (Permission.JustifValidate)")
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
# Cas 2 : raison
|
2023-10-27 16:05:40 +02:00
|
|
|
raison: str = data.get("raison", False)
|
2023-04-17 15:35:42 +02:00
|
|
|
if raison is not False:
|
|
|
|
justificatif_unique.raison = raison
|
|
|
|
|
|
|
|
deb, fin = None, None
|
|
|
|
|
|
|
|
# cas 3 : date_debut
|
2023-10-27 16:05:40 +02:00
|
|
|
date_debut: str = data.get("date_debut", False)
|
2023-04-17 15:35:42 +02:00
|
|
|
if date_debut is not False:
|
|
|
|
if date_debut is None:
|
|
|
|
errors.append("param 'date_debut': manquant")
|
2023-10-27 16:05:40 +02:00
|
|
|
deb: datetime = scu.is_iso_formated(date_debut.replace(" ", "+"), convert=True)
|
2023-04-17 15:35:42 +02:00
|
|
|
if deb is None:
|
|
|
|
errors.append("param 'date_debut': format invalide")
|
|
|
|
|
|
|
|
# cas 4 : date_fin
|
2023-10-27 16:05:40 +02:00
|
|
|
date_fin: str = data.get("date_fin", False)
|
2023-04-17 15:35:42 +02:00
|
|
|
if date_fin is not False:
|
|
|
|
if date_fin is None:
|
|
|
|
errors.append("param 'date_fin': manquant")
|
2023-10-27 16:05:40 +02:00
|
|
|
fin: datetime = scu.is_iso_formated(date_fin.replace(" ", "+"), convert=True)
|
2023-04-17 15:35:42 +02:00
|
|
|
if fin is None:
|
|
|
|
errors.append("param 'date_fin': format invalide")
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Récupération des dates précédentes si deb ou fin est None
|
2023-04-17 15:35:42 +02:00
|
|
|
deb = deb if deb is not None else justificatif_unique.date_debut
|
|
|
|
fin = fin if fin is not None else justificatif_unique.date_fin
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Mise à jour de l'external data
|
|
|
|
external_data: dict = data.get("external_data")
|
2023-07-31 09:41:32 +02:00
|
|
|
if external_data is not None:
|
|
|
|
if not isinstance(external_data, dict):
|
|
|
|
errors.append("param 'external_data' : n'est pas un objet JSON")
|
|
|
|
else:
|
|
|
|
justificatif_unique.external_data = external_data
|
|
|
|
|
2023-06-23 16:12:36 +02:00
|
|
|
if fin <= deb:
|
|
|
|
errors.append("param 'dates' : Date de début après date de fin")
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Mise à jour des dates du justificatif
|
2023-04-17 15:35:42 +02:00
|
|
|
justificatif_unique.date_debut = deb
|
|
|
|
justificatif_unique.date_fin = fin
|
|
|
|
|
|
|
|
if errors:
|
|
|
|
err: str = ", ".join(errors)
|
|
|
|
return json_error(404, err)
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Mise à jour du justificatif
|
2024-02-29 14:20:39 +01:00
|
|
|
justificatif_unique.dejustifier_assiduites()
|
2023-04-17 15:35:42 +02:00
|
|
|
db.session.add(justificatif_unique)
|
2024-02-28 11:33:23 +01:00
|
|
|
Scolog.logdb(
|
|
|
|
method="edit_justificatif",
|
|
|
|
etudid=justificatif_unique.etudiant.id,
|
|
|
|
msg=f"justificatif modif: {justificatif_unique}",
|
|
|
|
)
|
2024-07-08 23:13:45 +02:00
|
|
|
db.session.commit()
|
2024-02-28 11:33:23 +01:00
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Génération du dictionnaire de retour
|
|
|
|
# La couverture correspond
|
|
|
|
# - aux assiduités précédemment justifiées par le justificatif
|
|
|
|
# - aux assiduités qui sont justifiées par le justificatif modifié
|
2023-06-30 15:34:50 +02:00
|
|
|
retour = {
|
2023-05-17 21:16:23 +02:00
|
|
|
"couverture": {
|
|
|
|
"avant": avant_ids,
|
2024-02-29 14:20:39 +01:00
|
|
|
"apres": justificatif_unique.justifier_assiduites(),
|
2023-04-17 15:35:42 +02:00
|
|
|
}
|
2023-05-17 21:16:23 +02:00
|
|
|
}
|
2023-10-27 16:05:40 +02:00
|
|
|
# Invalide le cache
|
2023-06-30 15:34:50 +02:00
|
|
|
scass.simple_invalidate_cache(justificatif_unique.to_dict())
|
|
|
|
return retour
|
|
|
|
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
@bp.route("/justificatif/delete", methods=["POST"])
|
|
|
|
@api_web_bp.route("/justificatif/delete", methods=["POST"])
|
|
|
|
@login_required
|
|
|
|
@scodoc
|
2023-05-17 21:16:23 +02:00
|
|
|
@as_json
|
2023-09-29 21:17:31 +02:00
|
|
|
@permission_required(Permission.AbsChange)
|
2023-04-17 15:35:42 +02:00
|
|
|
def justif_delete():
|
|
|
|
"""
|
2024-07-27 13:30:02 +02:00
|
|
|
Suppression d'un justificatif à partir de son id.
|
2023-04-17 15:35:42 +02:00
|
|
|
|
2024-07-24 11:07:57 +02:00
|
|
|
DATA
|
|
|
|
----
|
|
|
|
```json
|
2023-04-17 15:35:42 +02:00
|
|
|
[
|
|
|
|
<justif_id:int>,
|
|
|
|
...
|
|
|
|
]
|
2024-07-24 11:07:57 +02:00
|
|
|
```
|
2024-07-25 13:03:10 +02:00
|
|
|
|
|
|
|
SAMPLES
|
|
|
|
-------
|
|
|
|
/justificatif/delete;[2, 2, 3]
|
|
|
|
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
2023-10-27 16:05:40 +02:00
|
|
|
|
|
|
|
# Récupération des justif_ids
|
2023-04-17 15:35:42 +02:00
|
|
|
justificatifs_list: list[int] = request.get_json(force=True)
|
|
|
|
if not isinstance(justificatifs_list, list):
|
|
|
|
return json_error(404, "Le contenu envoyé n'est pas une liste")
|
|
|
|
|
2023-07-27 18:00:40 +02:00
|
|
|
output = {"errors": [], "success": []}
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
for i, ass in enumerate(justificatifs_list):
|
2023-10-27 16:05:40 +02:00
|
|
|
code, msg = _delete_one(ass)
|
2023-04-17 15:35:42 +02:00
|
|
|
if code == 404:
|
2023-07-27 18:00:40 +02:00
|
|
|
output["errors"].append({"indice": i, "message": msg})
|
2023-04-17 15:35:42 +02:00
|
|
|
else:
|
2023-07-27 18:00:40 +02:00
|
|
|
output["success"].append({"indice": i, "message": "OK"})
|
2023-06-30 15:34:50 +02:00
|
|
|
|
2023-04-17 15:35:42 +02:00
|
|
|
db.session.commit()
|
2023-04-20 18:04:21 +02:00
|
|
|
|
2023-05-17 21:16:23 +02:00
|
|
|
return output
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
def _delete_one(justif_id: int) -> tuple[int, str]:
|
|
|
|
"""
|
|
|
|
_delete_one Supprime un justificatif
|
|
|
|
|
|
|
|
Args:
|
|
|
|
justif_id (int): l'identifiant du justificatif
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
tuple[int, str]: code, message
|
|
|
|
code : 200 si réussi, 404 sinon
|
|
|
|
message : OK si réussi, message d'erreur sinon
|
|
|
|
"""
|
|
|
|
# Récupération du justificatif à supprimer
|
2023-12-22 15:25:58 +01:00
|
|
|
try:
|
|
|
|
justificatif_unique = Justificatif.get_justificatif(justif_id)
|
|
|
|
except NotFound:
|
2023-04-17 15:35:42 +02:00
|
|
|
return (404, "Justificatif non existant")
|
2023-10-27 16:05:40 +02:00
|
|
|
# Récupération de l'archive du justificatif
|
2023-04-17 15:35:42 +02:00
|
|
|
archive_name: str = justificatif_unique.fichier
|
|
|
|
|
|
|
|
if archive_name is not None:
|
2023-10-27 16:05:40 +02:00
|
|
|
# Si elle existe : on essaye de la supprimer
|
2023-04-17 15:35:42 +02:00
|
|
|
archiver: JustificatifArchiver = JustificatifArchiver()
|
2023-07-04 15:04:58 +02:00
|
|
|
try:
|
2023-09-07 23:09:39 +02:00
|
|
|
archiver.delete_justificatif(justificatif_unique.etudiant, archive_name)
|
2023-07-04 15:04:58 +02:00
|
|
|
except ValueError:
|
|
|
|
pass
|
2023-07-30 18:59:06 +02:00
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# On invalide le cache
|
2023-06-30 15:34:50 +02:00
|
|
|
scass.simple_invalidate_cache(justificatif_unique.to_dict())
|
2024-02-29 14:20:39 +01:00
|
|
|
# On actualise les assiduités justifiées de l'étudiant concerné
|
|
|
|
justificatif_unique.dejustifier_assiduites()
|
2024-07-08 23:13:45 +02:00
|
|
|
Scolog.logdb(
|
|
|
|
method="justificatif/delete",
|
|
|
|
etudid=justificatif_unique.etudiant.id,
|
|
|
|
msg="suppression justificatif",
|
|
|
|
)
|
2023-10-27 16:05:40 +02:00
|
|
|
# On supprime le justificatif
|
|
|
|
db.session.delete(justificatif_unique)
|
2023-06-30 15:34:50 +02:00
|
|
|
|
2023-04-17 15:35:42 +02:00
|
|
|
return (200, "OK")
|
|
|
|
|
|
|
|
|
|
|
|
# Partie archivage
|
|
|
|
@bp.route("/justificatif/<int:justif_id>/import", methods=["POST"])
|
|
|
|
@api_web_bp.route("/justificatif/<int:justif_id>/import", methods=["POST"])
|
|
|
|
@scodoc
|
|
|
|
@login_required
|
2023-05-17 21:16:23 +02:00
|
|
|
@as_json
|
2023-09-29 21:17:31 +02:00
|
|
|
@permission_required(Permission.AbsChange)
|
2023-04-17 15:35:42 +02:00
|
|
|
def justif_import(justif_id: int = None):
|
|
|
|
"""
|
2024-07-27 13:30:02 +02:00
|
|
|
Importation d'un fichier (création d'archive).
|
2024-07-24 11:07:57 +02:00
|
|
|
|
|
|
|
> Procédure d'importation de fichier : [importer un justificatif](FichiersJustificatifs.md#importer-un-fichier)
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
2023-10-27 16:05:40 +02:00
|
|
|
|
|
|
|
# On vérifie qu'un fichier a bien été envoyé
|
2023-04-17 15:35:42 +02:00
|
|
|
if len(request.files) == 0:
|
|
|
|
return json_error(404, "Il n'y a pas de fichier joint")
|
|
|
|
file = list(request.files.values())[0]
|
|
|
|
if file.filename == "":
|
|
|
|
return json_error(404, "Il n'y a pas de fichier joint")
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# On récupère le justificatif auquel on va importer le fichier
|
2023-12-22 15:25:58 +01:00
|
|
|
justificatif_unique = Justificatif.get_justificatif(justif_id)
|
2023-04-17 15:35:42 +02:00
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Récupération de l'archive si elle existe
|
2023-04-17 15:35:42 +02:00
|
|
|
archive_name: str = justificatif_unique.fichier
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Utilisation de l'archiver de justificatifs
|
2023-04-17 15:35:42 +02:00
|
|
|
archiver: JustificatifArchiver = JustificatifArchiver()
|
|
|
|
try:
|
2023-10-27 16:05:40 +02:00
|
|
|
# On essaye de sauvegarder le fichier
|
2023-04-17 15:35:42 +02:00
|
|
|
fname: str
|
|
|
|
archive_name, fname = archiver.save_justificatif(
|
2023-09-07 23:09:39 +02:00
|
|
|
justificatif_unique.etudiant,
|
2023-04-17 15:35:42 +02:00
|
|
|
filename=file.filename,
|
|
|
|
data=file.stream.read(),
|
|
|
|
archive_name=archive_name,
|
2023-07-04 15:04:58 +02:00
|
|
|
user_id=current_user.id,
|
2023-04-17 15:35:42 +02:00
|
|
|
)
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# On actualise l'archive du justificatif
|
2023-04-17 15:35:42 +02:00
|
|
|
justificatif_unique.fichier = archive_name
|
|
|
|
|
|
|
|
db.session.add(justificatif_unique)
|
|
|
|
db.session.commit()
|
|
|
|
|
2023-05-17 21:16:23 +02:00
|
|
|
return {"filename": fname}
|
2023-12-12 03:05:31 +01:00
|
|
|
except ScoValueError as exc:
|
2023-10-27 16:05:40 +02:00
|
|
|
# Si cela ne fonctionne pas on renvoie une erreur
|
2023-12-12 03:05:31 +01:00
|
|
|
return json_error(404, exc.args[0])
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
|
2023-11-24 18:07:30 +01:00
|
|
|
@bp.route("/justificatif/<int:justif_id>/export/<filename>", methods=["GET", "POST"])
|
2023-12-11 15:24:55 +01:00
|
|
|
@api_web_bp.route(
|
|
|
|
"/justificatif/<int:justif_id>/export/<filename>", methods=["GET", "POST"]
|
|
|
|
)
|
2023-04-17 15:35:42 +02:00
|
|
|
@scodoc
|
|
|
|
@login_required
|
2023-12-16 22:53:02 +01:00
|
|
|
@permission_required(Permission.ScoView)
|
2023-12-11 15:24:55 +01:00
|
|
|
def justif_export(justif_id: int | None = None, filename: str | None = None):
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
2023-12-16 22:53:02 +01:00
|
|
|
Retourne un fichier d'une archive d'un justificatif.
|
2024-07-27 13:30:02 +02:00
|
|
|
|
|
|
|
La permission est `ScoView` + (`AbsJustifView` ou être l'auteur du justificatif).
|
2024-07-24 11:07:57 +02:00
|
|
|
|
|
|
|
> Procédure de téléchargement de fichier : [télécharger un justificatif](FichiersJustificatifs.md#télécharger-un-fichier)
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
2023-10-27 16:05:40 +02:00
|
|
|
# On récupère le justificatif concerné
|
2023-12-22 15:25:58 +01:00
|
|
|
justificatif_unique = Justificatif.get_justificatif(justif_id)
|
2023-04-17 15:35:42 +02:00
|
|
|
|
2023-12-16 22:53:02 +01:00
|
|
|
# Vérification des permissions
|
|
|
|
if not (
|
|
|
|
current_user.has_permission(Permission.AbsJustifView)
|
|
|
|
or justificatif_unique.user_id == current_user.id
|
|
|
|
):
|
2024-08-06 09:23:53 +02:00
|
|
|
return json_error(403, "non autorisé à voir ce fichier")
|
2023-12-16 22:53:02 +01:00
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# On récupère l'archive concernée
|
2023-04-17 15:35:42 +02:00
|
|
|
archive_name: str = justificatif_unique.fichier
|
|
|
|
if archive_name is None:
|
2023-10-27 16:05:40 +02:00
|
|
|
# On retourne une erreur si le justificatif n'a pas de fichiers
|
2023-04-17 15:35:42 +02:00
|
|
|
return json_error(404, "le justificatif ne possède pas de fichier")
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# On récupère le fichier et le renvoie en une réponse déjà formée
|
2023-04-17 15:35:42 +02:00
|
|
|
archiver: JustificatifArchiver = JustificatifArchiver()
|
|
|
|
try:
|
|
|
|
return archiver.get_justificatif_file(
|
2023-09-07 23:09:39 +02:00
|
|
|
archive_name, justificatif_unique.etudiant, filename
|
2023-04-17 15:35:42 +02:00
|
|
|
)
|
|
|
|
except ScoValueError as err:
|
2023-10-27 16:05:40 +02:00
|
|
|
# On retourne une erreur json si jamais il y a un problème
|
2023-04-17 15:35:42 +02:00
|
|
|
return json_error(404, err.args[0])
|
|
|
|
|
|
|
|
|
|
|
|
@bp.route("/justificatif/<int:justif_id>/remove", methods=["POST"])
|
|
|
|
@api_web_bp.route("/justificatif/<int:justif_id>/remove", methods=["POST"])
|
|
|
|
@scodoc
|
|
|
|
@login_required
|
2023-05-17 21:16:23 +02:00
|
|
|
@as_json
|
2023-09-29 21:17:31 +02:00
|
|
|
@permission_required(Permission.AbsChange)
|
2023-04-17 15:35:42 +02:00
|
|
|
def justif_remove(justif_id: int = None):
|
|
|
|
"""
|
2024-07-27 13:30:02 +02:00
|
|
|
Supression d'un fichier ou d'une archive.
|
2023-04-17 15:35:42 +02:00
|
|
|
|
2024-07-24 11:07:57 +02:00
|
|
|
> Procédure de suppression de fichier : [supprimer un justificatif](FichiersJustificatifs.md#supprimer-un-fichier)
|
|
|
|
|
|
|
|
DATA
|
|
|
|
----
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"remove": <"all"/"list">,
|
2023-04-17 15:35:42 +02:00
|
|
|
"filenames"?: [
|
|
|
|
<filename:str>,
|
|
|
|
...
|
|
|
|
]
|
|
|
|
}
|
2024-07-24 11:07:57 +02:00
|
|
|
```
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# On récupère le dictionnaire
|
2023-04-17 15:35:42 +02:00
|
|
|
data: dict = request.get_json(force=True)
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# On récupère le justificatif concerné
|
2023-12-22 15:25:58 +01:00
|
|
|
justificatif_unique = Justificatif.get_justificatif(justif_id)
|
2023-04-17 15:35:42 +02:00
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# On récupère l'archive
|
2023-04-17 15:35:42 +02:00
|
|
|
archive_name: str = justificatif_unique.fichier
|
|
|
|
if archive_name is None:
|
2023-10-27 16:05:40 +02:00
|
|
|
# On retourne une erreur si le justificatif n'a pas de fichiers
|
2023-04-17 15:35:42 +02:00
|
|
|
return json_error(404, "le justificatif ne possède pas de fichier")
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# On regarde le type de suppression (all ou list)
|
|
|
|
# Si all : on supprime tous les fichiers
|
|
|
|
# Si list : on supprime les fichiers dont le nom est dans la liste
|
2023-04-17 15:35:42 +02:00
|
|
|
remove: str = data.get("remove")
|
|
|
|
if remove is None or remove not in ("all", "list"):
|
|
|
|
return json_error(404, "param 'remove': Valeur invalide")
|
2023-10-27 16:05:40 +02:00
|
|
|
|
|
|
|
# On récupère l'archiver et l'étudiant
|
2023-04-17 15:35:42 +02:00
|
|
|
archiver: JustificatifArchiver = JustificatifArchiver()
|
2023-09-07 23:09:39 +02:00
|
|
|
etud = justificatif_unique.etudiant
|
2023-04-17 15:35:42 +02:00
|
|
|
try:
|
|
|
|
if remove == "all":
|
2023-10-27 16:05:40 +02:00
|
|
|
# Suppression de toute l'archive du justificatif
|
2023-09-07 23:09:39 +02:00
|
|
|
archiver.delete_justificatif(etud, archive_name=archive_name)
|
2023-04-17 15:35:42 +02:00
|
|
|
justificatif_unique.fichier = None
|
|
|
|
db.session.add(justificatif_unique)
|
|
|
|
db.session.commit()
|
|
|
|
|
|
|
|
else:
|
2023-10-27 16:05:40 +02:00
|
|
|
# Suppression des fichiers dont le nom se trouve dans la liste "filenames"
|
2023-04-17 15:35:42 +02:00
|
|
|
for fname in data.get("filenames", []):
|
|
|
|
archiver.delete_justificatif(
|
2023-09-07 23:09:39 +02:00
|
|
|
etud,
|
2023-04-17 15:35:42 +02:00
|
|
|
archive_name=archive_name,
|
|
|
|
filename=fname,
|
|
|
|
)
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Si il n'y a plus de fichiers dans l'archive, on la supprime
|
2023-09-07 23:09:39 +02:00
|
|
|
if len(archiver.list_justificatifs(archive_name, etud)) == 0:
|
|
|
|
archiver.delete_justificatif(etud, archive_name)
|
2023-04-17 15:35:42 +02:00
|
|
|
justificatif_unique.fichier = None
|
|
|
|
db.session.add(justificatif_unique)
|
|
|
|
db.session.commit()
|
|
|
|
|
|
|
|
except ScoValueError as err:
|
2023-10-27 16:05:40 +02:00
|
|
|
# On retourne une erreur json si jamais il y a eu un problème
|
2023-04-17 15:35:42 +02:00
|
|
|
return json_error(404, err.args[0])
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# On retourne une réponse "removed" si tout s'est bien passé
|
2023-05-17 21:16:23 +02:00
|
|
|
return {"response": "removed"}
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
@bp.route("/justificatif/<int:justif_id>/list", methods=["GET"])
|
|
|
|
@api_web_bp.route("/justificatif/<int:justif_id>/list", methods=["GET"])
|
|
|
|
@scodoc
|
|
|
|
@login_required
|
2023-05-17 21:16:23 +02:00
|
|
|
@as_json
|
2023-07-04 15:04:58 +02:00
|
|
|
@permission_required(Permission.ScoView)
|
2023-04-17 15:35:42 +02:00
|
|
|
def justif_list(justif_id: int = None):
|
|
|
|
"""
|
2024-07-27 13:30:02 +02:00
|
|
|
Liste les fichiers du justificatif.
|
2024-07-25 13:03:10 +02:00
|
|
|
|
|
|
|
SAMPLES
|
|
|
|
-------
|
|
|
|
/justificatif/1/list;
|
|
|
|
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Récupération du justificatif concerné
|
2023-12-22 15:25:58 +01:00
|
|
|
justificatif_unique = Justificatif.get_justificatif(justif_id)
|
2023-04-17 15:35:42 +02:00
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Récupération de l'archive avec l'archiver
|
2023-04-17 15:35:42 +02:00
|
|
|
archive_name: str = justificatif_unique.fichier
|
|
|
|
filenames: list[str] = []
|
|
|
|
archiver: JustificatifArchiver = JustificatifArchiver()
|
|
|
|
if archive_name is not None:
|
|
|
|
filenames = archiver.list_justificatifs(
|
2023-09-07 23:09:39 +02:00
|
|
|
archive_name, justificatif_unique.etudiant
|
2023-04-17 15:35:42 +02:00
|
|
|
)
|
2023-10-27 16:05:40 +02:00
|
|
|
# Préparation du retour
|
|
|
|
# - total : le nombre total de fichier du justificatif
|
|
|
|
# - filenames : le nom des fichiers visible par l'utilisateur
|
2023-07-04 15:04:58 +02:00
|
|
|
retour = {"total": len(filenames), "filenames": []}
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# Pour chaque nom de fichier on vérifie
|
|
|
|
# - Si l'utilisateur qui a importé le fichier est le même que
|
|
|
|
# l'utilisateur qui a demandé la liste des fichiers
|
|
|
|
# - Ou si l'utilisateur qui a demandé la liste possède la permission AbsJustifView
|
|
|
|
# Si c'est le cas alors on ajoute à la liste des fichiers visibles
|
2023-09-07 23:09:39 +02:00
|
|
|
for filename in filenames:
|
|
|
|
if int(filename[1]) == current_user.id or current_user.has_permission(
|
2023-09-29 21:17:31 +02:00
|
|
|
Permission.AbsJustifView
|
2023-07-04 15:04:58 +02:00
|
|
|
):
|
2023-09-07 23:09:39 +02:00
|
|
|
retour["filenames"].append(filename[0])
|
2023-10-27 16:05:40 +02:00
|
|
|
# On renvoie le total et la liste des fichiers visibles
|
2023-07-04 15:04:58 +02:00
|
|
|
return retour
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
# Partie justification
|
|
|
|
@bp.route("/justificatif/<int:justif_id>/justifies", methods=["GET"])
|
|
|
|
@api_web_bp.route("/justificatif/<int:justif_id>/justifies", methods=["GET"])
|
|
|
|
@scodoc
|
|
|
|
@login_required
|
2023-05-17 21:16:23 +02:00
|
|
|
@as_json
|
2023-09-29 21:17:31 +02:00
|
|
|
@permission_required(Permission.AbsChange)
|
2023-04-17 15:35:42 +02:00
|
|
|
def justif_justifies(justif_id: int = None):
|
|
|
|
"""
|
2024-07-27 13:30:02 +02:00
|
|
|
Liste `assiduite_id` justifiées par le justificatif.
|
2024-07-25 13:03:10 +02:00
|
|
|
|
|
|
|
SAMPLES
|
|
|
|
-------
|
|
|
|
/justificatif/1/justifies;
|
|
|
|
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# On récupère le justificatif concerné
|
2023-12-22 15:25:58 +01:00
|
|
|
justificatif_unique = Justificatif.get_justificatif(justif_id)
|
2023-04-17 15:35:42 +02:00
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# On récupère la liste des assiduités justifiées par le justificatif
|
2023-04-17 15:35:42 +02:00
|
|
|
assiduites_list: list[int] = scass.justifies(justificatif_unique)
|
2023-10-27 16:05:40 +02:00
|
|
|
# On la renvoie
|
2023-05-17 21:16:23 +02:00
|
|
|
return assiduites_list
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
# -- Utils --
|
|
|
|
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
def _filter_manager(requested, justificatifs_query: Query):
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
|
|
|
Retourne les justificatifs entrés filtrés en fonction de la request
|
2023-12-22 15:25:58 +01:00
|
|
|
et du département courant s'il y en a un
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
|
|
|
# cas 1 : etat justificatif
|
2023-10-27 16:05:40 +02:00
|
|
|
etat: str = requested.args.get("etat")
|
2023-04-17 15:35:42 +02:00
|
|
|
if etat is not None:
|
2023-10-27 16:05:40 +02:00
|
|
|
justificatifs_query: Query = scass.filter_justificatifs_by_etat(
|
2023-04-17 15:35:42 +02:00
|
|
|
justificatifs_query, etat
|
|
|
|
)
|
|
|
|
|
|
|
|
# cas 2 : date de début
|
2023-10-27 16:05:40 +02:00
|
|
|
deb: str = requested.args.get("date_debut", "").replace(" ", "+")
|
2023-04-17 15:35:42 +02:00
|
|
|
deb: datetime = scu.is_iso_formated(deb, True)
|
|
|
|
|
|
|
|
# cas 3 : date de fin
|
2023-10-27 16:05:40 +02:00
|
|
|
fin: str = requested.args.get("date_fin", "").replace(" ", "+")
|
|
|
|
fin: datetime = scu.is_iso_formated(fin, True)
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
if (deb, fin) != (None, None):
|
2023-08-14 01:08:04 +02:00
|
|
|
justificatifs_query: Query = scass.filter_by_date(
|
2023-04-17 15:35:42 +02:00
|
|
|
justificatifs_query, Justificatif, deb, fin
|
|
|
|
)
|
2023-10-27 16:05:40 +02:00
|
|
|
# cas 4 : user_id
|
2023-04-17 15:35:42 +02:00
|
|
|
user_id = requested.args.get("user_id", False)
|
|
|
|
if user_id is not False:
|
2023-08-14 01:08:04 +02:00
|
|
|
justificatifs_query: Query = scass.filter_by_user_id(
|
2023-08-09 09:57:47 +02:00
|
|
|
justificatifs_query, user_id
|
|
|
|
)
|
|
|
|
|
|
|
|
# cas 5 : formsemestre_id
|
|
|
|
formsemestre_id = requested.args.get("formsemestre_id")
|
|
|
|
|
2023-09-13 15:19:21 +02:00
|
|
|
if formsemestre_id not in [None, "", -1]:
|
2023-08-09 09:57:47 +02:00
|
|
|
formsemestre: FormSemestre = None
|
2023-09-13 15:19:21 +02:00
|
|
|
try:
|
|
|
|
formsemestre_id = int(formsemestre_id)
|
2023-12-22 15:25:58 +01:00
|
|
|
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
2023-09-13 15:19:21 +02:00
|
|
|
justificatifs_query = scass.filter_by_formsemestre(
|
|
|
|
justificatifs_query, Justificatif, formsemestre
|
|
|
|
)
|
|
|
|
except ValueError:
|
|
|
|
formsemestre = None
|
2023-04-17 15:35:42 +02:00
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# cas 6 : order (retourne les justificatifs par ordre décroissant de date_debut)
|
2023-09-11 08:31:09 +02:00
|
|
|
order = requested.args.get("order", None)
|
|
|
|
if order is not None:
|
|
|
|
justificatifs_query: Query = justificatifs_query.order_by(
|
|
|
|
Justificatif.date_debut.desc()
|
|
|
|
)
|
2023-10-27 16:05:40 +02:00
|
|
|
# cas 7 : courant (retourne uniquement les justificatifs de l'année scolaire courante)
|
2023-09-12 09:37:03 +02:00
|
|
|
courant = requested.args.get("courant", None)
|
|
|
|
if courant is not None:
|
|
|
|
annee: int = scu.annee_scolaire()
|
|
|
|
|
|
|
|
justificatifs_query: Query = justificatifs_query.filter(
|
2023-12-29 13:57:44 +01:00
|
|
|
Justificatif.date_debut >= scu.date_debut_annee_scolaire(annee),
|
|
|
|
Justificatif.date_fin <= scu.date_fin_annee_scolaire(annee),
|
2023-09-12 09:37:03 +02:00
|
|
|
)
|
|
|
|
|
2023-10-27 16:05:40 +02:00
|
|
|
# cas 8 : group_id filtre les justificatifs d'un groupe d'étudiant
|
2023-09-13 15:19:21 +02:00
|
|
|
group_id = requested.args.get("group_id", None)
|
|
|
|
if group_id is not None:
|
|
|
|
try:
|
|
|
|
group_id = int(group_id)
|
|
|
|
etudids: list[int] = [etu["etudid"] for etu in get_group_members(group_id)]
|
|
|
|
justificatifs_query = justificatifs_query.filter(
|
|
|
|
Justificatif.etudid.in_(etudids)
|
|
|
|
)
|
|
|
|
except ValueError:
|
|
|
|
group_id = None
|
|
|
|
|
2023-12-22 15:25:58 +01:00
|
|
|
# Département
|
|
|
|
if g.scodoc_dept:
|
|
|
|
justificatifs_query = justificatifs_query.join(Identite).filter_by(
|
|
|
|
dept_id=g.scodoc_dept_id
|
|
|
|
)
|
|
|
|
|
2023-04-17 15:35:42 +02:00
|
|
|
return justificatifs_query
|