forked from ScoDoc/ScoDoc
simplification enum + fonction generic + revisions
This commit is contained in:
parent
547040bb93
commit
a7b856b1ec
@ -40,14 +40,7 @@ def assiduite(assiduite_id: int = None):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
query = Assiduite.query.filter_by(id=assiduite_id)
|
return scu.get_model_api_object(Assiduite, assiduite_id)
|
||||||
# if g.scodoc_dept:
|
|
||||||
# query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id)
|
|
||||||
assiduite_query = query.first_or_404()
|
|
||||||
|
|
||||||
data = assiduite_query.to_dict()
|
|
||||||
|
|
||||||
return jsonify(_change_etat(data))
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/assiduites/<int:etudid>/count", defaults={"with_query": False})
|
@bp.route("/assiduites/<int:etudid>/count", defaults={"with_query": False})
|
||||||
@ -164,8 +157,8 @@ def assiduites(etudid: int = None, with_query: bool = False):
|
|||||||
|
|
||||||
data_set: list[dict] = []
|
data_set: list[dict] = []
|
||||||
for ass in assiduites_query.all():
|
for ass in assiduites_query.all():
|
||||||
data = ass.to_dict()
|
data = ass.to_dict(format_api=True)
|
||||||
data_set.append(_change_etat(data))
|
data_set.append(data)
|
||||||
|
|
||||||
return jsonify(data_set)
|
return jsonify(data_set)
|
||||||
|
|
||||||
@ -202,8 +195,8 @@ def assiduites_formsemestre(formsemestre_id: int, with_query: bool = False):
|
|||||||
|
|
||||||
data_set: list[dict] = []
|
data_set: list[dict] = []
|
||||||
for ass in assiduites_query.all():
|
for ass in assiduites_query.all():
|
||||||
data = ass.to_dict()
|
data = ass.to_dict(format_api=True)
|
||||||
data_set.append(_change_etat(data))
|
data_set.append(data)
|
||||||
|
|
||||||
return jsonify(data_set)
|
return jsonify(data_set)
|
||||||
|
|
||||||
@ -307,11 +300,10 @@ def _create_singular(
|
|||||||
etat = data.get("etat", None)
|
etat = data.get("etat", None)
|
||||||
if etat is None:
|
if etat is None:
|
||||||
errors.append("param 'etat': manquant")
|
errors.append("param 'etat': manquant")
|
||||||
elif etat not in scu.ETATS_ASSIDUITE:
|
elif not scu.EtatAssiduite.contains(etat):
|
||||||
errors.append("param 'etat': invalide")
|
errors.append("param 'etat': invalide")
|
||||||
|
|
||||||
data = _change_etat(data, False)
|
etat = scu.EtatAssiduite.get(etat)
|
||||||
etat = data.get("etat", None)
|
|
||||||
|
|
||||||
# cas 2 : date_debut
|
# cas 2 : date_debut
|
||||||
date_debut = data.get("date_debut", None)
|
date_debut = data.get("date_debut", None)
|
||||||
@ -418,7 +410,7 @@ def _delete_singular(assiduite_id: int, database):
|
|||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
# @permission_required(Permission.ScoAssiduiteChange)
|
# @permission_required(Permission.ScoAssiduiteChange)
|
||||||
def assiduite_cedit(assiduite_id: int):
|
def assiduite_edit(assiduite_id: int):
|
||||||
"""
|
"""
|
||||||
Edition d'une assiduité à partir de son id
|
Edition d'une assiduité à partir de son id
|
||||||
La requête doit avoir un content type "application/json":
|
La requête doit avoir un content type "application/json":
|
||||||
@ -438,11 +430,11 @@ def assiduite_cedit(assiduite_id: int):
|
|||||||
|
|
||||||
# Cas 1 : Etat
|
# Cas 1 : Etat
|
||||||
if data.get("etat") is not None:
|
if data.get("etat") is not None:
|
||||||
data = _change_etat(data, False)
|
etat = scu.EtatAssiduite.get(data.get("etat"))
|
||||||
if data.get("etat") is None:
|
if etat is None:
|
||||||
errors.append("param 'etat': invalide")
|
errors.append("param 'etat': invalide")
|
||||||
else:
|
else:
|
||||||
assiduite_unique.etat = data.get("etat")
|
assiduite_unique.etat = etat
|
||||||
|
|
||||||
# Cas 2 : Moduleimpl_id
|
# Cas 2 : Moduleimpl_id
|
||||||
moduleimpl_id = data.get("moduleimpl_id", False)
|
moduleimpl_id = data.get("moduleimpl_id", False)
|
||||||
@ -478,13 +470,6 @@ def assiduite_cedit(assiduite_id: int):
|
|||||||
|
|
||||||
|
|
||||||
# -- Utils --
|
# -- Utils --
|
||||||
def _change_etat(data: dict, from_int: bool = True):
|
|
||||||
"""change dans un json la valeur du champs état"""
|
|
||||||
if from_int:
|
|
||||||
data["etat"] = scu.ETAT_ASSIDUITE_NAME.get(data["etat"])
|
|
||||||
else:
|
|
||||||
data["etat"] = scu.ETATS_ASSIDUITE.get(data["etat"])
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
def _count_manager(requested) -> tuple[str, dict]:
|
def _count_manager(requested) -> tuple[str, dict]:
|
||||||
|
@ -5,22 +5,22 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
"""ScoDoc 9 API : Assiduités
|
"""ScoDoc 9 API : Assiduités
|
||||||
"""
|
"""
|
||||||
import os
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
from flask import g, jsonify, request
|
||||||
|
from flask_login import login_required
|
||||||
|
|
||||||
import app.scodoc.sco_assiduites as scass
|
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.api import api_bp as bp
|
from app.api import api_bp as bp
|
||||||
from app.api import api_web_bp
|
from app.api import api_web_bp
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
|
||||||
from app.decorators import permission_required, scodoc
|
from app.decorators import permission_required, scodoc
|
||||||
from app.models import Identite, Justificatif
|
from app.models import Identite, Justificatif
|
||||||
|
from app.models.assiduites import is_period_conflicting
|
||||||
from app.scodoc.sco_archives_justificatifs import JustificatifArchiver
|
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_permissions import Permission
|
||||||
from flask import g, jsonify, request
|
|
||||||
from flask_login import login_required
|
|
||||||
from app.scodoc.sco_utils import json_error
|
from app.scodoc.sco_utils import json_error
|
||||||
|
|
||||||
|
|
||||||
@ -35,9 +35,8 @@ from app.scodoc.sco_utils import json_error
|
|||||||
# return jsonify("done")
|
# return jsonify("done")
|
||||||
|
|
||||||
# Partie Modèle
|
# Partie Modèle
|
||||||
# TODO: justificatif
|
|
||||||
@bp.route("/justificatif/<int:justif_id>")
|
@bp.route("/justificatif/<int:justif_id>")
|
||||||
@api_web_bp.route("/assiduite/<int:justif_id>")
|
@api_web_bp.route("/justificatif/<int:justif_id>")
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
def justificatif(justif_id: int = None):
|
def justificatif(justif_id: int = None):
|
||||||
@ -54,19 +53,12 @@ def justificatif(justif_id: int = None):
|
|||||||
"raison": "une raison",
|
"raison": "une raison",
|
||||||
"entry_date": "2022-10-31T08:00+01:00",
|
"entry_date": "2022-10-31T08:00+01:00",
|
||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
query = Justificatif.query.filter_by(id=justif_id)
|
return scu.get_model_api_object(Justificatif, justif_id)
|
||||||
if g.scodoc_dept:
|
|
||||||
query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id)
|
|
||||||
justificatif_unique = query.first_or_404()
|
|
||||||
|
|
||||||
data = justificatif_unique.to_dict()
|
|
||||||
|
|
||||||
return jsonify(_change_etat(data))
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: justificatifs[-query]
|
|
||||||
@bp.route("/justificatifs/<int:etudid>", defaults={"with_query": False})
|
@bp.route("/justificatifs/<int:etudid>", defaults={"with_query": False})
|
||||||
@bp.route("/justificatifs/<int:etudid>/query", defaults={"with_query": True})
|
@bp.route("/justificatifs/<int:etudid>/query", defaults={"with_query": True})
|
||||||
@api_web_bp.route("/justificatifs/<int:etudid>", defaults={"with_query": False})
|
@api_web_bp.route("/justificatifs/<int:etudid>", defaults={"with_query": False})
|
||||||
@ -110,13 +102,12 @@ def justificatifs(etudid: int = None, with_query: bool = False):
|
|||||||
|
|
||||||
data_set: list[dict] = []
|
data_set: list[dict] = []
|
||||||
for just in justificatifs_query.all():
|
for just in justificatifs_query.all():
|
||||||
data = just.to_dict()
|
data = just.to_dict(format_api=True)
|
||||||
data_set.append(_change_etat(data))
|
data_set.append(data)
|
||||||
|
|
||||||
return jsonify(data_set)
|
return jsonify(data_set)
|
||||||
|
|
||||||
|
|
||||||
# TODO: justificatif-create
|
|
||||||
@bp.route("/justificatif/<int:etudid>/create", methods=["POST"])
|
@bp.route("/justificatif/<int:etudid>/create", methods=["POST"])
|
||||||
@api_web_bp.route("/justificatif/<int:etudid>/create", methods=["POST"])
|
@api_web_bp.route("/justificatif/<int:etudid>/create", methods=["POST"])
|
||||||
@scodoc
|
@scodoc
|
||||||
@ -173,11 +164,10 @@ def _create_singular(
|
|||||||
etat = data.get("etat", None)
|
etat = data.get("etat", None)
|
||||||
if etat is None:
|
if etat is None:
|
||||||
errors.append("param 'etat': manquant")
|
errors.append("param 'etat': manquant")
|
||||||
elif etat not in scu.ETATS_JUSTIFICATIF:
|
elif not scu.EtatJustificatif.contains(etat):
|
||||||
errors.append("param 'etat': invalide")
|
errors.append("param 'etat': invalide")
|
||||||
|
|
||||||
data = _change_etat(data, False)
|
etat = scu.EtatJustificatif.get(etat)
|
||||||
etat = data.get("etat", None)
|
|
||||||
|
|
||||||
# cas 2 : date_debut
|
# cas 2 : date_debut
|
||||||
date_debut = data.get("date_debut", None)
|
date_debut = data.get("date_debut", None)
|
||||||
@ -224,7 +214,6 @@ def _create_singular(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# TODO: justificatif-edit
|
|
||||||
@bp.route("/justificatif/<int:justif_id>/edit", methods=["POST"])
|
@bp.route("/justificatif/<int:justif_id>/edit", methods=["POST"])
|
||||||
@api_web_bp.route("/justificatif/<int:justif_id>/edit", methods=["POST"])
|
@api_web_bp.route("/justificatif/<int:justif_id>/edit", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
@ -235,9 +224,12 @@ def justif_edit(justif_id: int):
|
|||||||
"""
|
"""
|
||||||
Edition d'un justificatif à partir de son id
|
Edition d'un justificatif à partir de son id
|
||||||
La requête doit avoir un content type "application/json":
|
La requête doit avoir un content type "application/json":
|
||||||
|
|
||||||
{
|
{
|
||||||
"etat"?: str,
|
"etat"?: str,
|
||||||
"raison"?: str
|
"raison"?: str
|
||||||
|
"date_debut"?: str
|
||||||
|
"date_fin"?: str
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
justificatif_unique: Justificatif = Justificatif.query.filter_by(
|
justificatif_unique: Justificatif = Justificatif.query.filter_by(
|
||||||
@ -250,17 +242,58 @@ def justif_edit(justif_id: int):
|
|||||||
|
|
||||||
# Cas 1 : Etat
|
# Cas 1 : Etat
|
||||||
if data.get("etat") is not None:
|
if data.get("etat") is not None:
|
||||||
data = _change_etat(data, False)
|
etat = scu.EtatJustificatif.get(data.get("etat"))
|
||||||
if data.get("etat") is None:
|
if etat is None:
|
||||||
errors.append("param 'etat': invalide")
|
errors.append("param 'etat': invalide")
|
||||||
else:
|
else:
|
||||||
justificatif_unique.etat = data.get("etat")
|
justificatif_unique.etat = etat
|
||||||
|
|
||||||
# Cas 2 : raison
|
# Cas 2 : raison
|
||||||
raison = data.get("raison", False)
|
raison = data.get("raison", False)
|
||||||
if raison is not False:
|
if raison is not False:
|
||||||
justificatif_unique.raison = raison
|
justificatif_unique.raison = raison
|
||||||
|
|
||||||
|
deb, fin = None, None
|
||||||
|
|
||||||
|
# cas 3 : date_debut
|
||||||
|
date_debut = data.get("date_debut", False)
|
||||||
|
if date_debut is not False:
|
||||||
|
if date_debut is None:
|
||||||
|
errors.append("param 'date_debut': manquant")
|
||||||
|
deb = scu.is_iso_formated(date_debut, convert=True)
|
||||||
|
if deb is None:
|
||||||
|
errors.append("param 'date_debut': format invalide")
|
||||||
|
|
||||||
|
if justificatif_unique.date_fin >= deb:
|
||||||
|
errors.append("param 'date_debut': date de début située après date de fin ")
|
||||||
|
|
||||||
|
# cas 4 : date_fin
|
||||||
|
date_fin = data.get("date_fin", False)
|
||||||
|
if date_fin is not False:
|
||||||
|
if date_fin is None:
|
||||||
|
errors.append("param 'date_fin': manquant")
|
||||||
|
fin = scu.is_iso_formated(date_fin, convert=True)
|
||||||
|
if fin is None:
|
||||||
|
errors.append("param 'date_fin': format invalide")
|
||||||
|
if justificatif_unique.date_debut <= fin:
|
||||||
|
errors.append("param 'date_fin': date de fin située avant date de début ")
|
||||||
|
|
||||||
|
# Vérification du conflit d'horaire
|
||||||
|
if (deb is not None) or (fin is not None):
|
||||||
|
deb = deb if deb is not None else justificatif_unique.date_debut
|
||||||
|
fin = fin if fin is not None else justificatif_unique.date_fin
|
||||||
|
|
||||||
|
justificatifs_list: list[Justificatif] = Justificatif.query.filter_by(
|
||||||
|
etuid=justificatif_unique.etudid
|
||||||
|
).all()
|
||||||
|
|
||||||
|
if is_period_conflicting(deb, fin, justificatifs_list):
|
||||||
|
errors.append(
|
||||||
|
"Modification de la plage horaire impossible: conflit avec les autres justificatifs"
|
||||||
|
)
|
||||||
|
justificatif_unique.date_debut = deb
|
||||||
|
justificatif_unique.date_fin = fin
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
err: str = ", ".join(errors)
|
err: str = ", ".join(errors)
|
||||||
return json_error(404, err)
|
return json_error(404, err)
|
||||||
@ -270,7 +303,6 @@ def justif_edit(justif_id: int):
|
|||||||
return jsonify({"OK": True})
|
return jsonify({"OK": True})
|
||||||
|
|
||||||
|
|
||||||
# TODO: justificatif-delete
|
|
||||||
@bp.route("/justificatif/delete", methods=["POST"])
|
@bp.route("/justificatif/delete", methods=["POST"])
|
||||||
@api_web_bp.route("/justificatif/delete", methods=["POST"])
|
@api_web_bp.route("/justificatif/delete", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
@ -312,12 +344,18 @@ def _delete_singular(justif_id: int, database):
|
|||||||
).first()
|
).first()
|
||||||
if justificatif_unique is None:
|
if justificatif_unique is None:
|
||||||
return (404, "Justificatif non existant")
|
return (404, "Justificatif non existant")
|
||||||
|
|
||||||
|
archive_name: str = justificatif_unique.fichier
|
||||||
|
|
||||||
|
if archive_name is not None:
|
||||||
|
archiver: JustificatifArchiver = JustificatifArchiver()
|
||||||
|
archiver.delete_justificatif(justificatif_unique.etudid, archive_name)
|
||||||
|
|
||||||
database.session.delete(justificatif_unique)
|
database.session.delete(justificatif_unique)
|
||||||
return (200, "OK")
|
return (200, "OK")
|
||||||
|
|
||||||
|
|
||||||
# Partie archivage
|
# Partie archivage
|
||||||
# TODO: justificatif-import
|
|
||||||
@bp.route("/justificatif/import/<int:justif_id>", methods=["POST"])
|
@bp.route("/justificatif/import/<int:justif_id>", methods=["POST"])
|
||||||
@api_web_bp.route("/justificatif/import/<int:justif_id>", methods=["POST"])
|
@api_web_bp.route("/justificatif/import/<int:justif_id>", methods=["POST"])
|
||||||
@scodoc
|
@scodoc
|
||||||
@ -362,7 +400,6 @@ def justif_import(justif_id: int = None):
|
|||||||
return json_error(404, err.args[1])
|
return json_error(404, err.args[1])
|
||||||
|
|
||||||
|
|
||||||
# TODO: justificatif-export
|
|
||||||
@bp.route("/justificatif/export/<int:justif_id>/<filename>", methods=["GET"])
|
@bp.route("/justificatif/export/<int:justif_id>/<filename>", methods=["GET"])
|
||||||
@api_web_bp.route("/justificatif/export/<int:justif_id>/<filename>", methods=["GET"])
|
@api_web_bp.route("/justificatif/export/<int:justif_id>/<filename>", methods=["GET"])
|
||||||
@scodoc
|
@scodoc
|
||||||
@ -394,7 +431,6 @@ def justif_export(justif_id: int = None, filename: str = None):
|
|||||||
return json_error(404, err.args[1])
|
return json_error(404, err.args[1])
|
||||||
|
|
||||||
|
|
||||||
# TODO: justificatif-remove
|
|
||||||
@bp.route("/justificatif/remove/<int:justif_id>", methods=["POST"])
|
@bp.route("/justificatif/remove/<int:justif_id>", methods=["POST"])
|
||||||
@api_web_bp.route("/justificatif/remove/<int:justif_id>", methods=["POST"])
|
@api_web_bp.route("/justificatif/remove/<int:justif_id>", methods=["POST"])
|
||||||
@scodoc
|
@scodoc
|
||||||
@ -404,7 +440,7 @@ def justif_export(justif_id: int = None, filename: str = None):
|
|||||||
def justif_remove(justif_id: int = None):
|
def justif_remove(justif_id: int = None):
|
||||||
"""
|
"""
|
||||||
Supression d'un fichier ou d'une archive
|
Supression d'un fichier ou d'une archive
|
||||||
|
# TOTALK: Doc, expliquer les noms coté server
|
||||||
{
|
{
|
||||||
"remove": <"all"/"list">
|
"remove": <"all"/"list">
|
||||||
|
|
||||||
@ -459,7 +495,6 @@ def justif_remove(justif_id: int = None):
|
|||||||
return jsonify({"response": "removed"})
|
return jsonify({"response": "removed"})
|
||||||
|
|
||||||
|
|
||||||
# TODO: justificatif-list
|
|
||||||
@bp.route("/justificatif/list/<int:justif_id>", methods=["GET"])
|
@bp.route("/justificatif/list/<int:justif_id>", methods=["GET"])
|
||||||
@api_web_bp.route("/justificatif/list/<int:justif_id>", methods=["GET"])
|
@api_web_bp.route("/justificatif/list/<int:justif_id>", methods=["GET"])
|
||||||
@scodoc
|
@scodoc
|
||||||
@ -492,16 +527,29 @@ def justif_list(justif_id: int = None):
|
|||||||
|
|
||||||
# Partie justification
|
# Partie justification
|
||||||
# TODO: justificatif-justified
|
# TODO: justificatif-justified
|
||||||
|
@bp.route("/justificatif/justified/<int:justif_id>", methods=["GET"])
|
||||||
|
@api_web_bp.route("/justificatif/justified/<int:justif_id>", methods=["GET"])
|
||||||
|
@scodoc
|
||||||
|
@login_required
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
# @permission_required(Permission.ScoAssiduiteChange)
|
||||||
|
def justif_justified(justif_id: int = None):
|
||||||
|
"""
|
||||||
|
Liste assiduite_id justifiées par le justificatif
|
||||||
|
"""
|
||||||
|
|
||||||
|
query = Justificatif.query.filter_by(id=justif_id)
|
||||||
|
if g.scodoc_dept:
|
||||||
|
query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id)
|
||||||
|
|
||||||
|
justificatif_unique: Justificatif = query.first_or_404()
|
||||||
|
|
||||||
|
assiduites_list: list[int] = scass.justifies(justificatif_unique)
|
||||||
|
|
||||||
|
return jsonify(assiduites_list)
|
||||||
|
|
||||||
|
|
||||||
# -- Utils --
|
# -- Utils --
|
||||||
def _change_etat(data: dict, from_int: bool = True):
|
|
||||||
"""change dans un json la valeur du champs état"""
|
|
||||||
if from_int:
|
|
||||||
data["etat"] = scu.ETAT_JUSTIFICATIF_NAME.get(data["etat"])
|
|
||||||
else:
|
|
||||||
data["etat"] = scu.ETATS_JUSTIFICATIF.get(data["etat"])
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
def _filter_manager(requested, justificatifs_query):
|
def _filter_manager(requested, justificatifs_query):
|
||||||
|
@ -51,14 +51,18 @@ class Assiduite(db.Model):
|
|||||||
|
|
||||||
entry_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
entry_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self, format_api=True) -> dict:
|
||||||
|
etat = self.etat
|
||||||
|
|
||||||
|
if format_api:
|
||||||
|
etat = EtatJustificatif.inverse().get(self.etat).name
|
||||||
data = {
|
data = {
|
||||||
"assiduite_id": self.assiduite_id,
|
"assiduite_id": self.assiduite_id,
|
||||||
"etudid": self.etudid,
|
"etudid": self.etudid,
|
||||||
"moduleimpl_id": self.moduleimpl_id,
|
"moduleimpl_id": self.moduleimpl_id,
|
||||||
"date_debut": self.date_debut,
|
"date_debut": self.date_debut,
|
||||||
"date_fin": self.date_fin,
|
"date_fin": self.date_fin,
|
||||||
"etat": self.etat,
|
"etat": etat,
|
||||||
"desc": self.desc,
|
"desc": self.desc,
|
||||||
"entry_date": self.entry_date,
|
"entry_date": self.entry_date,
|
||||||
}
|
}
|
||||||
@ -78,17 +82,8 @@ class Assiduite(db.Model):
|
|||||||
# Vérification de non duplication des périodes
|
# Vérification de non duplication des périodes
|
||||||
assiduites: list[Assiduite] = etud.assiduites.all()
|
assiduites: list[Assiduite] = etud.assiduites.all()
|
||||||
|
|
||||||
date_debut = localize_datetime(date_debut)
|
assiduites: list[Justificatif] = etud.assiduites.all()
|
||||||
date_fin = localize_datetime(date_fin)
|
if is_period_conflicting(date_debut, date_fin, assiduites) != 0:
|
||||||
assiduites = [
|
|
||||||
ass
|
|
||||||
for ass in assiduites
|
|
||||||
if is_period_overlapping(
|
|
||||||
(date_debut, date_fin),
|
|
||||||
(ass.date_debut, ass.date_fin),
|
|
||||||
)
|
|
||||||
]
|
|
||||||
if len(assiduites) != 0:
|
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
"Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)"
|
"Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)"
|
||||||
)
|
)
|
||||||
@ -156,13 +151,20 @@ class Justificatif(db.Model):
|
|||||||
# Archive_id -> sco_archives_justificatifs.py
|
# Archive_id -> sco_archives_justificatifs.py
|
||||||
fichier = db.Column(db.Text())
|
fichier = db.Column(db.Text())
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self, format_api: bool = False) -> dict:
|
||||||
|
"""transformation de l'objet en dictionnaire sérialisable"""
|
||||||
|
|
||||||
|
etat = self.etat
|
||||||
|
|
||||||
|
if format_api:
|
||||||
|
etat = EtatJustificatif.inverse().get(self.etat).name
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"justif_id": self.justif_id,
|
"justif_id": self.justif_id,
|
||||||
"etudid": self.etudid,
|
"etudid": self.etudid,
|
||||||
"date_debut": self.date_debut,
|
"date_debut": self.date_debut,
|
||||||
"date_fin": self.date_fin,
|
"date_fin": self.date_fin,
|
||||||
"etat": self.etat,
|
"etat": etat,
|
||||||
"raison": self.raison,
|
"raison": self.raison,
|
||||||
"fichier": self.fichier,
|
"fichier": self.fichier,
|
||||||
"entry_date": self.entry_date,
|
"entry_date": self.entry_date,
|
||||||
@ -181,23 +183,12 @@ class Justificatif(db.Model):
|
|||||||
"""Créer un nouveau justificatif pour l'étudiant"""
|
"""Créer un nouveau justificatif pour l'étudiant"""
|
||||||
# Vérification de non duplication des périodes
|
# Vérification de non duplication des périodes
|
||||||
justificatifs: list[Justificatif] = etud.justificatifs.all()
|
justificatifs: list[Justificatif] = etud.justificatifs.all()
|
||||||
|
if is_period_conflicting(date_debut, date_fin, justificatifs) != 0:
|
||||||
date_debut = localize_datetime(date_debut)
|
|
||||||
date_fin = localize_datetime(date_fin)
|
|
||||||
justificatifs = [
|
|
||||||
just
|
|
||||||
for just in justificatifs
|
|
||||||
if is_period_overlapping(
|
|
||||||
(date_debut, date_fin),
|
|
||||||
(just.date_debut, just.date_fin),
|
|
||||||
)
|
|
||||||
]
|
|
||||||
if len(justificatifs) != 0:
|
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
"Duplication des justificatifs (la période rentrée rentre en conflit avec un justificatif enregistré)"
|
"Duplication des justificatifs (la période rentrée rentre en conflit avec un justificatif enregistré)"
|
||||||
)
|
)
|
||||||
|
|
||||||
nouv_assiduite = Justificatif(
|
nouv_justificatif = Justificatif(
|
||||||
date_debut=date_debut,
|
date_debut=date_debut,
|
||||||
date_fin=date_fin,
|
date_fin=date_fin,
|
||||||
etat=etat,
|
etat=etat,
|
||||||
@ -205,4 +196,28 @@ class Justificatif(db.Model):
|
|||||||
raison=raison,
|
raison=raison,
|
||||||
)
|
)
|
||||||
|
|
||||||
return nouv_assiduite
|
return nouv_justificatif
|
||||||
|
|
||||||
|
|
||||||
|
def is_period_conflicting(
|
||||||
|
date_debut: datetime,
|
||||||
|
date_fin: datetime,
|
||||||
|
collection: list[Assiduite or Justificatif],
|
||||||
|
) -> bool:
|
||||||
|
"""
|
||||||
|
Vérifie si une date n'entre pas en collision
|
||||||
|
avec les justificatifs ou assiduites déjà présentes
|
||||||
|
"""
|
||||||
|
|
||||||
|
date_debut = localize_datetime(date_debut)
|
||||||
|
date_fin = localize_datetime(date_fin)
|
||||||
|
unified = [
|
||||||
|
uni
|
||||||
|
for uni in collection
|
||||||
|
if is_period_overlapping(
|
||||||
|
(date_debut, date_fin),
|
||||||
|
(uni.date_debut, uni.date_fin),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
return len(unified) != 0
|
||||||
|
@ -68,7 +68,7 @@ from app import log
|
|||||||
from app.but import jury_but_pv
|
from app.but import jury_but_pv
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import Departement, FormSemestre
|
from app.models import FormSemestre
|
||||||
from app.scodoc.TrivialFormulator import TrivialFormulator
|
from app.scodoc.TrivialFormulator import TrivialFormulator
|
||||||
from app.scodoc.sco_exceptions import (
|
from app.scodoc.sco_exceptions import (
|
||||||
AccessDenied,
|
AccessDenied,
|
||||||
@ -89,6 +89,11 @@ class BaseArchiver(object):
|
|||||||
self.archive_type = archive_type
|
self.archive_type = archive_type
|
||||||
self.initialized = False
|
self.initialized = False
|
||||||
self.root = None
|
self.root = None
|
||||||
|
self.dept_id = None
|
||||||
|
|
||||||
|
def set_dept_id(self, dept_id: int):
|
||||||
|
"set dept"
|
||||||
|
self.dept_id = dept_id
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
if self.initialized:
|
if self.initialized:
|
||||||
@ -110,6 +115,8 @@ class BaseArchiver(object):
|
|||||||
finally:
|
finally:
|
||||||
scu.GSL.release()
|
scu.GSL.release()
|
||||||
self.initialized = True
|
self.initialized = True
|
||||||
|
if self.dept_id is None:
|
||||||
|
self.dept_id = getattr(g, "scodoc_dept_id")
|
||||||
|
|
||||||
def get_obj_dir(self, oid: int):
|
def get_obj_dir(self, oid: int):
|
||||||
"""
|
"""
|
||||||
@ -117,8 +124,7 @@ class BaseArchiver(object):
|
|||||||
If directory does not yet exist, create it.
|
If directory does not yet exist, create it.
|
||||||
"""
|
"""
|
||||||
self.initialize()
|
self.initialize()
|
||||||
dept = Departement.query.filter_by(acronym=g.scodoc_dept).first()
|
dept_dir = os.path.join(self.root, str(self.dept_id))
|
||||||
dept_dir = os.path.join(self.root, str(dept.id))
|
|
||||||
try:
|
try:
|
||||||
scu.GSL.acquire()
|
scu.GSL.acquire()
|
||||||
if not os.path.isdir(dept_dir):
|
if not os.path.isdir(dept_dir):
|
||||||
@ -137,8 +143,7 @@ class BaseArchiver(object):
|
|||||||
:return: list of archive oids
|
:return: list of archive oids
|
||||||
"""
|
"""
|
||||||
self.initialize()
|
self.initialize()
|
||||||
dept = Departement.query.filter_by(acronym=g.scodoc_dept).first()
|
base = os.path.join(self.root, str(self.dept_id)) + os.path.sep
|
||||||
base = os.path.join(self.root, str(dept.id)) + os.path.sep
|
|
||||||
dirs = glob.glob(base + "*")
|
dirs = glob.glob(base + "*")
|
||||||
return [os.path.split(x)[1] for x in dirs]
|
return [os.path.split(x)[1] for x in dirs]
|
||||||
|
|
||||||
|
@ -19,9 +19,6 @@ class JustificatifArchiver(BaseArchiver):
|
|||||||
├── [_description.txt]
|
├── [_description.txt]
|
||||||
└── [<filename.ext>]
|
└── [<filename.ext>]
|
||||||
|
|
||||||
|
|
||||||
TODO:
|
|
||||||
- Faire fonction suppression fichier unique dans archive
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -38,6 +35,7 @@ class JustificatifArchiver(BaseArchiver):
|
|||||||
"""
|
"""
|
||||||
Ajoute un fichier dans une archive "justificatif" pour l'etudid donné
|
Ajoute un fichier dans une archive "justificatif" pour l'etudid donné
|
||||||
Retourne l'archive_name utilisé
|
Retourne l'archive_name utilisé
|
||||||
|
TODO: renvoie archive_name + filename
|
||||||
"""
|
"""
|
||||||
self._set_dept(etudid)
|
self._set_dept(etudid)
|
||||||
if archive_name is None:
|
if archive_name is None:
|
||||||
@ -104,9 +102,8 @@ class JustificatifArchiver(BaseArchiver):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _set_dept(self, etudid: int):
|
def _set_dept(self, etudid: int):
|
||||||
if g.scodoc_dept is None or g.scodoc_dept_id is None:
|
"""
|
||||||
|
Mets à jour le dept_id de l'archiver en fonction du département de l'étudiant
|
||||||
|
"""
|
||||||
etud: Identite = Identite.query.filter_by(id=etudid).first()
|
etud: Identite = Identite.query.filter_by(id=etudid).first()
|
||||||
dept: Departement = Departement.query.filter_by(id=etud.dept_id).first()
|
self.set_dept_id(etud.dept_id)
|
||||||
|
|
||||||
g.scodoc_dept = dept.acronym
|
|
||||||
g.scodoc_dept_id = dept.id
|
|
||||||
|
@ -85,7 +85,7 @@ def filter_assiduites_by_etat(assiduites: Assiduite, etat: str) -> Assiduite:
|
|||||||
Filtrage d'une collection d'assiduites en fonction de leur état
|
Filtrage d'une collection d'assiduites en fonction de leur état
|
||||||
"""
|
"""
|
||||||
etats: list[str] = list(etat.split(","))
|
etats: list[str] = list(etat.split(","))
|
||||||
etats = [scu.ETATS_ASSIDUITE.get(e, -1) for e in etats]
|
etats = [scu.EtatAssiduite.get(e, -1) for e in etats]
|
||||||
return assiduites.filter(Assiduite.etat.in_(etats))
|
return assiduites.filter(Assiduite.etat.in_(etats))
|
||||||
|
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ def filter_justificatifs_by_etat(
|
|||||||
Filtrage d'une collection de justificatifs en fonction de leur état
|
Filtrage d'une collection de justificatifs en fonction de leur état
|
||||||
"""
|
"""
|
||||||
etats: list[str] = list(etat.split(","))
|
etats: list[str] = list(etat.split(","))
|
||||||
etats = [scu.ETATS_JUSTIFICATIF.get(e, -1) for e in etats]
|
etats = [scu.EtatJustificatif.get(e, -1) for e in etats]
|
||||||
return justificatifs.filter(Justificatif.etat.in_(etats))
|
return justificatifs.filter(Justificatif.etat.in_(etats))
|
||||||
|
|
||||||
|
|
||||||
@ -172,3 +172,27 @@ def filter_by_formsemestre(assiduites_query: Assiduite, formsemestre: FormSemest
|
|||||||
Assiduite.date_debut >= formsemestre.date_debut
|
Assiduite.date_debut >= formsemestre.date_debut
|
||||||
)
|
)
|
||||||
return assiduites_query.filter(Assiduite.date_fin <= formsemestre.date_fin)
|
return assiduites_query.filter(Assiduite.date_fin <= formsemestre.date_fin)
|
||||||
|
|
||||||
|
|
||||||
|
def justifies(justi: Justificatif) -> list[int]:
|
||||||
|
"""
|
||||||
|
Retourne la liste des assiduite_id qui sont justifié par la justification
|
||||||
|
Une assiduité est justifiée si elle est STRICTEMENT comprise dans la plage du justificatif
|
||||||
|
et que l'état du justificatif est "validé"
|
||||||
|
"""
|
||||||
|
|
||||||
|
justified: list[int] = []
|
||||||
|
|
||||||
|
if justi.etat != scu.EtatJustificatif.VALIDE:
|
||||||
|
return justified
|
||||||
|
|
||||||
|
assiduites_query: Assiduite = (
|
||||||
|
Assiduite.query.join(Justificatif)
|
||||||
|
.filter_by(etudid=justi.etudid)
|
||||||
|
.filter(justi.date_debut >= Assiduite.date_debut)
|
||||||
|
.filter(justi.date_fin <= Assiduite.date_fin)
|
||||||
|
)
|
||||||
|
|
||||||
|
justified = [assi.id for assi in assiduites_query.all()]
|
||||||
|
|
||||||
|
return justified
|
||||||
|
@ -32,7 +32,7 @@ import base64
|
|||||||
import bisect
|
import bisect
|
||||||
import copy
|
import copy
|
||||||
import datetime
|
import datetime
|
||||||
from enum import IntEnum
|
from enum import IntEnum, Enum
|
||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
@ -50,17 +50,17 @@ from PIL import Image as PILImage
|
|||||||
import pydot
|
import pydot
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
import dateutil.parser as dtparser
|
||||||
import flask
|
import flask
|
||||||
from flask import g, request
|
from flask import g, request
|
||||||
from flask import flash, url_for, make_response, jsonify
|
from flask import flash, url_for, make_response, jsonify
|
||||||
from werkzeug.http import HTTP_STATUS_CODES
|
from werkzeug.http import HTTP_STATUS_CODES
|
||||||
|
|
||||||
from config import Config
|
from config import Config
|
||||||
from app import log
|
from app import log, db
|
||||||
from app.scodoc.sco_vdi import ApoEtapeVDI
|
from app.scodoc.sco_vdi import ApoEtapeVDI
|
||||||
from app.scodoc.sco_codes_parcours import NOTES_TOLERANCE, CODES_EXPL
|
from app.scodoc.sco_codes_parcours import NOTES_TOLERANCE, CODES_EXPL
|
||||||
from app.scodoc import sco_xml
|
from app.scodoc import sco_xml
|
||||||
from app.scodoc.intervals import intervalmap
|
|
||||||
|
|
||||||
import sco_version
|
import sco_version
|
||||||
|
|
||||||
@ -88,7 +88,43 @@ ETATS_INSCRIPTION = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class EtatAssiduite(IntEnum):
|
def get_model_api_object(model_cls: db.Model, model_id: int):
|
||||||
|
from app.models import Identite
|
||||||
|
|
||||||
|
query = model_cls.query.filter_by(id=model_id)
|
||||||
|
if g.scodoc_dept:
|
||||||
|
query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id)
|
||||||
|
unique: model_cls = query.first_or_404()
|
||||||
|
|
||||||
|
return jsonify(unique.to_dict(format_api=True))
|
||||||
|
|
||||||
|
|
||||||
|
class BiDirectionalEnum(Enum):
|
||||||
|
"""Permet la recherche inverse d'un enum
|
||||||
|
Condition : les clés et les valeurs doivent être uniques
|
||||||
|
les clés doivent être en MAJUSCULES
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def contains(cls, attr: str):
|
||||||
|
return attr.upper() in cls._member_names_
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get(cls, attr: str, default: any = None):
|
||||||
|
val = None
|
||||||
|
try:
|
||||||
|
val = cls[attr.upper()]
|
||||||
|
except (KeyError, AttributeError):
|
||||||
|
val = default
|
||||||
|
return val
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def inverse(cls):
|
||||||
|
"""Retourne un dictionnaire représentant la map inverse de l'Enum"""
|
||||||
|
return cls._value2member_map_
|
||||||
|
|
||||||
|
|
||||||
|
class EtatAssiduite(int, BiDirectionalEnum):
|
||||||
"""Code des états d'assiduité"""
|
"""Code des états d'assiduité"""
|
||||||
|
|
||||||
# Stockés en BD ne pas modifier
|
# Stockés en BD ne pas modifier
|
||||||
@ -110,7 +146,7 @@ ETATS_ASSIDUITE = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class EtatJustificatif(IntEnum):
|
class EtatJustificatif(int, BiDirectionalEnum):
|
||||||
"""Code des états des justificatifs"""
|
"""Code des états des justificatifs"""
|
||||||
|
|
||||||
# Stockés en BD ne pas modifier
|
# Stockés en BD ne pas modifier
|
||||||
@ -121,21 +157,6 @@ class EtatJustificatif(IntEnum):
|
|||||||
MODIFIE = 3
|
MODIFIE = 3
|
||||||
|
|
||||||
|
|
||||||
ETAT_JUSTIFICATIF_NAME = {
|
|
||||||
EtatJustificatif.VALIDE: "validé",
|
|
||||||
EtatJustificatif.NON_VALIDE: "non validé",
|
|
||||||
EtatJustificatif.ATTENTE: "en attente",
|
|
||||||
EtatJustificatif.MODIFIE: "modifié",
|
|
||||||
}
|
|
||||||
|
|
||||||
ETATS_JUSTIFICATIF = {
|
|
||||||
"validé": EtatJustificatif.VALIDE,
|
|
||||||
"non vaidé": EtatJustificatif.NON_VALIDE,
|
|
||||||
"en attente": EtatJustificatif.ATTENTE,
|
|
||||||
"modifié": EtatJustificatif.MODIFIE,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def is_iso_formated(date: str, convert=False) -> bool or datetime.datetime or None:
|
def is_iso_formated(date: str, convert=False) -> bool or datetime.datetime or None:
|
||||||
"""
|
"""
|
||||||
Vérifie si une date est au format iso
|
Vérifie si une date est au format iso
|
||||||
@ -147,7 +168,6 @@ def is_iso_formated(date: str, convert=False) -> bool or datetime.datetime or No
|
|||||||
|
|
||||||
Retourne None sinon
|
Retourne None sinon
|
||||||
"""
|
"""
|
||||||
import dateutil.parser as dtparser
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
date: datetime.datetime = dtparser.isoparse(date)
|
date: datetime.datetime = dtparser.isoparse(date)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
Test de l'api Assiduité
|
Test de l'api justificatif
|
||||||
|
|
||||||
Ecrit par HARTMANN Matthias
|
Ecrit par HARTMANN Matthias
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ def test_route_create(api_headers):
|
|||||||
# -== Unique ==-
|
# -== Unique ==-
|
||||||
|
|
||||||
# Bon fonctionnement
|
# Bon fonctionnement
|
||||||
data = create_data("validé", "01")
|
data = create_data("valide", "01")
|
||||||
|
|
||||||
res = POST_JSON(f"/justificatif/{ETUDID}/create", [data], api_headers)
|
res = POST_JSON(f"/justificatif/{ETUDID}/create", [data], api_headers)
|
||||||
check_fields(res, BATCH_FIELD)
|
check_fields(res, BATCH_FIELD)
|
||||||
@ -129,7 +129,7 @@ def test_route_create(api_headers):
|
|||||||
|
|
||||||
TO_REMOVE.append(res["success"]["0"]["justif_id"])
|
TO_REMOVE.append(res["success"]["0"]["justif_id"])
|
||||||
|
|
||||||
data2 = create_data("modifié", "02", "raison")
|
data2 = create_data("modifie", "02", "raison")
|
||||||
res = POST_JSON(f"/justificatif/{ETUDID}/create", [data2], api_headers)
|
res = POST_JSON(f"/justificatif/{ETUDID}/create", [data2], api_headers)
|
||||||
check_fields(res, BATCH_FIELD)
|
check_fields(res, BATCH_FIELD)
|
||||||
assert len(res["success"]) == 1
|
assert len(res["success"]) == 1
|
||||||
@ -160,7 +160,7 @@ def test_route_create(api_headers):
|
|||||||
|
|
||||||
# Bon Fonctionnement
|
# Bon Fonctionnement
|
||||||
|
|
||||||
etats = ["validé", "modifé", "non validé", "en attente"]
|
etats = ["valide", "modifie", "non_valide", "attente"]
|
||||||
data = [
|
data = [
|
||||||
create_data(etats[d % 4], 10 + d, "raison" if d % 2 else None)
|
create_data(etats[d % 4], 10 + d, "raison" if d % 2 else None)
|
||||||
for d in range(randint(3, 5))
|
for d in range(randint(3, 5))
|
||||||
@ -175,10 +175,10 @@ def test_route_create(api_headers):
|
|||||||
# Mauvais Fonctionnement
|
# Mauvais Fonctionnement
|
||||||
|
|
||||||
data2 = [
|
data2 = [
|
||||||
create_data("modifié", "01"),
|
create_data("modifie", "01"),
|
||||||
create_data(None, "25"),
|
create_data(None, "25"),
|
||||||
create_data("blabla", 26),
|
create_data("blabla", 26),
|
||||||
create_data("validé", 32),
|
create_data("valide", 32),
|
||||||
]
|
]
|
||||||
|
|
||||||
res = POST_JSON(f"/justificatif/{ETUDID}/create", data2, api_headers)
|
res = POST_JSON(f"/justificatif/{ETUDID}/create", data2, api_headers)
|
||||||
@ -201,7 +201,7 @@ def test_route_edit(api_headers):
|
|||||||
|
|
||||||
# Bon fonctionnement
|
# Bon fonctionnement
|
||||||
|
|
||||||
data = {"etat": "modifié", "raison": "test"}
|
data = {"etat": "modifie", "raison": "test"}
|
||||||
res = POST_JSON(f"/justificatif/{TO_REMOVE[0]}/edit", data, api_headers)
|
res = POST_JSON(f"/justificatif/{TO_REMOVE[0]}/edit", data, api_headers)
|
||||||
assert res == {"OK": True}
|
assert res == {"OK": True}
|
||||||
|
|
||||||
@ -305,12 +305,12 @@ def test_import_justificatif(api_headers):
|
|||||||
|
|
||||||
# Bon fonctionnement
|
# Bon fonctionnement
|
||||||
|
|
||||||
filename: str = "/opt/scodoc/tests/api/test_api_justificatif.txt"
|
filename: str = "tests/api/test_api_justificatif.txt"
|
||||||
resp: dict = send_file(1, filename, api_headers)
|
resp: dict = send_file(1, filename, api_headers)
|
||||||
assert "response" in resp
|
assert "response" in resp
|
||||||
assert resp["response"] == "imported"
|
assert resp["response"] == "imported"
|
||||||
|
|
||||||
filename: str = "/opt/scodoc/tests/api/test_api_justificatif2.txt"
|
filename: str = "tests/api/test_api_justificatif2.txt"
|
||||||
resp: dict = send_file(1, filename, api_headers)
|
resp: dict = send_file(1, filename, api_headers)
|
||||||
assert "response" in resp
|
assert "response" in resp
|
||||||
assert resp["response"] == "imported"
|
assert resp["response"] == "imported"
|
||||||
@ -372,3 +372,4 @@ def test_remove_justificatif(api_headers):
|
|||||||
|
|
||||||
check_failure_post("/justificatif/remove/2", api_headers, {})
|
check_failure_post("/justificatif/remove/2", api_headers, {})
|
||||||
check_failure_post(f"/justificatif/remove/{FAUX}", api_headers, {"remove": "all"})
|
check_failure_post(f"/justificatif/remove/{FAUX}", api_headers, {"remove": "all"})
|
||||||
|
check_failure_post("/justificatif/remove/1", api_headers, {"remove": "all"})
|
||||||
|
@ -14,7 +14,7 @@ from app import db
|
|||||||
|
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
import app.scodoc.sco_assiduites as scass
|
import app.scodoc.sco_assiduites as scass
|
||||||
from app.models import Assiduite, Identite, FormSemestre, ModuleImpl
|
from app.models import Assiduite, Justificatif, Identite, FormSemestre, ModuleImpl
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
|
|
||||||
@ -118,9 +118,61 @@ def test_general(test_client):
|
|||||||
verifier_comptage_et_filtrage(
|
verifier_comptage_et_filtrage(
|
||||||
etuds, moduleimpls, (formsemestre_1, formsemestre_2, formsemestre_3)
|
etuds, moduleimpls, (formsemestre_1, formsemestre_2, formsemestre_3)
|
||||||
)
|
)
|
||||||
|
|
||||||
editer_supprimer_assiduiter(etuds, moduleimpls)
|
editer_supprimer_assiduiter(etuds, moduleimpls)
|
||||||
|
|
||||||
|
|
||||||
|
def ajouter_justificatifs(etud, etud_faux):
|
||||||
|
|
||||||
|
obj_justificatifs = [
|
||||||
|
{
|
||||||
|
"etat": scu.EtatJustificatif.ATTENTE,
|
||||||
|
"deb": "2022-09-03T08:00+01:00",
|
||||||
|
"fin": "2022-09-03T10:00+01:00",
|
||||||
|
"raison": None,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"etat": scu.EtatJustificatif.VALIDE,
|
||||||
|
"deb": "2023-01-03T07:00+01:00",
|
||||||
|
"fin": "2023-01-03T11:00+01:00",
|
||||||
|
"raison": None,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"etat": scu.EtatJustificatif.VALIDE,
|
||||||
|
"deb": "2022-09-03T09:00:01+01:00",
|
||||||
|
"fin": "2022-09-03T12:00+01:00",
|
||||||
|
"raison": None,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"etat": scu.EtatJustificatif.NON_VALIDE,
|
||||||
|
"deb": "2022-09-03T14:00:00+01:00",
|
||||||
|
"fin": "2022-09-03T15:00+01:00",
|
||||||
|
"raison": "Description",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"etat": scu.EtatJustificatif.MODIFIE,
|
||||||
|
"deb": "2023-01-03T11:00:01+01:00",
|
||||||
|
"fin": "2023-01-03T12:00+01:00",
|
||||||
|
"raison": None,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
justificatifs = [
|
||||||
|
Justificatif.create_justificatif(
|
||||||
|
etud,
|
||||||
|
ass["deb"],
|
||||||
|
ass["fin"],
|
||||||
|
ass["etat"],
|
||||||
|
ass["raison"],
|
||||||
|
)
|
||||||
|
for ass in obj_justificatifs
|
||||||
|
]
|
||||||
|
# Vérification de la création des justificatifs
|
||||||
|
assert [
|
||||||
|
justi for justi in justificatifs if not isinstance(justi, Justificatif)
|
||||||
|
] == [], "La création des justificatifs de base n'est pas OK"
|
||||||
|
|
||||||
|
|
||||||
def editer_supprimer_assiduiter(etuds: list[Identite], moduleimpls: list[int]):
|
def editer_supprimer_assiduiter(etuds: list[Identite], moduleimpls: list[int]):
|
||||||
"""
|
"""
|
||||||
Troisième Partie:
|
Troisième Partie:
|
||||||
|
Loading…
Reference in New Issue
Block a user