1
0
forked from ScoDoc/ScoDoc

corrections REV#Emm + samples API (WIP)

This commit is contained in:
iziram 2023-01-05 17:47:32 +01:00
parent 7adc7d824b
commit f3b1b8a3cb
8 changed files with 205 additions and 166 deletions

View File

@ -19,21 +19,22 @@ from app.scodoc.sco_permissions import Permission
from flask_login import login_required from flask_login import login_required
from app.models import Identite, Assiduite, FormSemestreInscription, FormSemestre from app.models import Identite, Assiduite, FormSemestre, ModuleImpl
from app.scodoc.sco_exceptions import ScoValueError
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
import app.scodoc.sco_assiduites as scass import app.scodoc.sco_assiduites as scass
@bp.route("/assiduite/<int:assiduiteid>") @bp.route("/assiduite/<int:assiduite_id>")
@api_web_bp.route("/assiduite/<int:assiduiteid>") @api_web_bp.route("/assiduite/<int:assiduite_id>")
@scodoc @scodoc
@permission_required(Permission.ScoView) @permission_required(Permission.ScoView)
def assiduite(assiduiteid: int = None): def assiduite(assiduite_id: int = None):
"""Retourne un objet assiduité à partir de son id """Retourne un objet assiduité à partir de son id
Exemple de résultat: Exemple de résultat:
{ {
"assiduiteid": 1, "assiduite_id": 1,
"etudid": 2, "etudid": 2,
"moduleimpl_id": 3, "moduleimpl_id": 3,
"date_debut": "2022-10-31T08:00+01:00", "date_debut": "2022-10-31T08:00+01:00",
@ -42,9 +43,11 @@ def assiduite(assiduiteid: int = None):
} }
""" """
assiduite = Assiduite.query.get(assiduiteid) query = Assiduite.query.filter_by(id=assiduite_id)
if assiduite is None: # if g.scodoc_dept:
return json_error(404, message="assiduité inexistante") # query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id)
assiduite = query.first_or_404()
data = assiduite.to_dict() data = assiduite.to_dict()
@ -346,13 +349,12 @@ def create_singular(
# cas 4 : moduleimpl_id # cas 4 : moduleimpl_id
moduleimpl_id = data.get("moduleimpl_id", None) moduleimpl_id = data.get("moduleimpl_id", False)
if moduleimpl_id is not None: moduleimpl: ModuleImpl = None
try:
moduleimpl_id: int = int(moduleimpl_id) if moduleimpl_id is not False:
if moduleimpl_id < 0: moduleimpl = ModuleImpl.query.filter_by(id=int(moduleimpl_id)).first()
raise Exception if moduleimpl is None:
except:
errors.append("param 'moduleimpl_id': invalide") errors.append("param 'moduleimpl_id': invalide")
if errors != []: if errors != []:
@ -360,25 +362,23 @@ def create_singular(
return (404, err) return (404, err)
# TOUT EST OK # TOUT EST OK
nouv_assiduite: Assiduite or int = Assiduite.create_assiduite(
try:
nouv_assiduite: Assiduite = Assiduite.create_assiduite(
date_debut=deb, date_debut=deb,
date_fin=fin, date_fin=fin,
etat=etat, etat=etat,
etud=etud, etud=etud,
module=moduleimpl_id, moduleimpl=moduleimpl,
) )
if type(nouv_assiduite) is Assiduite:
db.session.add(nouv_assiduite) db.session.add(nouv_assiduite)
db.session.commit() db.session.commit()
return (200, {"assiduiteid": nouv_assiduite.assiduiteid}) return (200, {"assiduite_id": nouv_assiduite.assiduite_id})
except ScoValueError as excp:
return ( return (
404, 404,
{ excp.args[0],
1: "La période sélectionnée est déjà couverte par une autre assiduite",
2: "L'étudiant ne participe pas au moduleimpl sélectionné",
}.get(nouv_assiduite),
) )
@ -417,7 +417,7 @@ def delete(batch: bool = False):
else: else:
code, msg = delete_singular( code, msg = delete_singular(
request.get_json(force=True).get("assiduiteid", -1), db request.get_json(force=True).get("assiduite_id", -1), db
) )
if code == 404: if code == 404:
return json_error(code, msg) return json_error(code, msg)
@ -434,13 +434,13 @@ def delete_singular(assiduite_id: int, db):
return (200, "OK") return (200, "OK")
@bp.route("/assiduite/<int:assiduiteid>/edit", methods=["POST"]) @bp.route("/assiduite/<int:assiduite_id>/edit", methods=["POST"])
@api_web_bp.route("/assiduite/<int:assiduiteid>/edit", methods=["POST"]) @api_web_bp.route("/assiduite/<int:assiduite_id>/edit", methods=["POST"])
@login_required @login_required
@scodoc @scodoc
@permission_required(Permission.ScoView) @permission_required(Permission.ScoView)
# @permission_required(Permission.ScoAssiduiteChange) # @permission_required(Permission.ScoAssiduiteChange)
def edit(assiduiteid: int): def 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":
@ -449,7 +449,7 @@ def edit(assiduiteid: int):
"moduleimpl_id": int "moduleimpl_id": int
} }
""" """
assiduite: Assiduite = Assiduite.query.filter_by(id=assiduiteid).first_or_404() assiduite: Assiduite = Assiduite.query.filter_by(id=assiduite_id).first_or_404()
errors: List[str] = [] errors: List[str] = []
data = request.get_json(force=True) data = request.get_json(force=True)
@ -465,18 +465,20 @@ def edit(assiduiteid: int):
# Cas 2 : Moduleimpl_id # Cas 2 : Moduleimpl_id
moduleimpl_id = data.get("moduleimpl_id", False) moduleimpl_id = data.get("moduleimpl_id", False)
moduleimpl: ModuleImpl = None
if moduleimpl_id is not False: if moduleimpl_id is not False:
try:
if moduleimpl_id is not None: if moduleimpl_id is not None:
moduleimpl_id: int = int(moduleimpl_id) moduleimpl = ModuleImpl.query.filter_by(id=int(moduleimpl_id)).first()
if moduleimpl_id < 0 or not Assiduite.verif_moduleimpl( if moduleimpl is None:
moduleimpl_id, assiduite.etudid errors.append("param 'moduleimpl_id': invalide")
else:
if not moduleimpl.est_inscrit(
Identite.query.filter_by(id=assiduite.etudid).first()
): ):
errors.append("param 'moduleimpl_id': etud non inscrit") errors.append("param 'moduleimpl_id': etud non inscrit")
else:
assiduite.moduleimpl_id = moduleimpl_id assiduite.moduleimpl_id = moduleimpl_id
except:
errors.append("param 'moduleimpl_id': invalide")
if errors != []: if errors != []:
err: str = ", ".join(errors) err: str = ", ".join(errors)

View File

@ -4,8 +4,8 @@
from app import db from app import db
from app.models import ModuleImpl, ModuleImplInscription from app.models import ModuleImpl, ModuleImplInscription
from app.models.etudiants import Identite from app.models.etudiants import Identite
from app.scodoc.sco_utils import EtatAssiduite, localize_datetime, verif_interval from app.scodoc.sco_utils import EtatAssiduite, localize_datetime, is_period_overlapping
from app.scodoc.sco_exceptions import ScoValueError
from datetime import datetime from datetime import datetime
@ -19,7 +19,7 @@ class Assiduite(db.Model):
__tablename__ = "assiduites" __tablename__ = "assiduites"
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
assiduiteid = db.synonym("id") assiduite_id = db.synonym("id")
date_debut = db.Column( date_debut = db.Column(
db.DateTime(timezone=True), server_default=db.func.now(), nullable=False db.DateTime(timezone=True), server_default=db.func.now(), nullable=False
@ -42,7 +42,7 @@ class Assiduite(db.Model):
def to_dict(self) -> dict: def to_dict(self) -> dict:
data = { data = {
"assiduiteid": self.assiduiteid, "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,
@ -58,13 +58,9 @@ class Assiduite(db.Model):
date_debut: datetime, date_debut: datetime,
date_fin: datetime, date_fin: datetime,
etat: EtatAssiduite, etat: EtatAssiduite,
module: int or None = None, moduleimpl: ModuleImpl = None,
) -> object or int: ) -> object or int:
"""Créer une nouvelle assiduité pour l'étudiant """Créer une nouvelle assiduité pour l'étudiant"""
Documentation des codes d'erreurs renvoyés:
1: Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)
2: l'ID du module_impl n'existe pas.
"""
# 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()
@ -73,26 +69,28 @@ class Assiduite(db.Model):
assiduites = [ assiduites = [
ass ass
for ass in assiduites for ass in assiduites
if verif_interval( if is_period_overlapping(
(date_debut, date_fin), (date_debut, date_fin),
(ass.date_debut, ass.date_fin), (ass.date_debut, ass.date_fin),
) )
] ]
if len(assiduites) != 0: if len(assiduites) != 0:
return 1 raise ScoValueError(
"Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)"
)
if module is not None: if moduleimpl is not None:
# Vérification de l'existance du module pour l'étudiant # Vérification de l'existence du module pour l'étudiant
if cls.verif_moduleimpl(module, etud): if moduleimpl.est_inscrit(etud):
nouv_assiduite = Assiduite( nouv_assiduite = Assiduite(
date_debut=date_debut, date_debut=date_debut,
date_fin=date_fin, date_fin=date_fin,
etat=etat, etat=etat,
etudiant=etud, etudiant=etud,
moduleimpl_id=module, moduleimpl_id=moduleimpl.id,
) )
else: else:
return 2 raise ScoValueError("L'étudiant n'est pas inscrit au moduleimpl")
else: else:
nouv_assiduite = Assiduite( nouv_assiduite = Assiduite(
date_debut=date_debut, date_debut=date_debut,
@ -103,30 +101,6 @@ class Assiduite(db.Model):
return nouv_assiduite return nouv_assiduite
@staticmethod
def verif_moduleimpl(moduleimpl_id: int, etud: Identite or int) -> bool:
"""
Vérifie si l'étudiant est bien inscrit au moduleimpl
Retourne Vrai si c'est le cas, faux sinon
"""
output = True
module: ModuleImpl = ModuleImpl.query.filter_by(
moduleimpl_id=moduleimpl_id
).first()
if module is None:
output = False
if output:
search_etudid: int = etud.id if type(etud) == Identite else etud
is_module: int = ModuleImplInscription.query.filter_by(
etudid=search_etudid, moduleimpl_id=moduleimpl_id
).count()
output = is_module > 0
return output
class Justificatif(db.Model): class Justificatif(db.Model):
""" """
@ -138,7 +112,7 @@ class Justificatif(db.Model):
__tablename__ = "justificatifs" __tablename__ = "justificatifs"
justifid = db.Column(db.Integer, primary_key=True) justif_id = db.Column(db.Integer, primary_key=True)
date_debut = db.Column( date_debut = db.Column(
db.DateTime(timezone=True), server_default=db.func.now(), nullable=False db.DateTime(timezone=True), server_default=db.func.now(), nullable=False
@ -158,11 +132,18 @@ class Justificatif(db.Model):
) )
raison = db.Column(db.Text()) raison = db.Column(db.Text())
fichier = db.Column(db.Integer())
"""
Les documents liés à l'étudiant sont dans
<archivedir>/docetuds/<dept_id>/<etudid>/<YYYY-MM-DD-HH-MM-SS>
d'après sco_archives.py
"""
fichier = db.Column(db.Date())
def to_dict(self) -> dict: def to_dict(self) -> dict:
data = { data = {
"justifid": self.assiduiteid, "justif_id": self.assiduite_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,

View File

@ -101,6 +101,22 @@ class ModuleImpl(db.Model):
d.pop("module", None) d.pop("module", None)
return d return d
def est_inscrit(self, etud: Identite) -> bool:
"""
Vérifie si l'étudiant est bien inscrit au moduleimpl
Retourne Vrai si c'est le cas, faux sinon
"""
is_module: int = (
ModuleImplInscription.query.filter_by(
etudid=etud.id, moduleimpl_id=self.id
).count()
> 0
)
return is_module
# Enseignants (chargés de TD ou TP) d'un moduleimpl # Enseignants (chargés de TD ou TP) d'un moduleimpl
notes_modules_enseignants = db.Table( notes_modules_enseignants = db.Table(

View File

@ -150,11 +150,11 @@ def is_iso_formated(date: str, convert=False) -> bool or datetime.datetime or No
def localize_datetime(date: datetime.datetime or str) -> datetime.datetime: def localize_datetime(date: datetime.datetime or str) -> datetime.datetime:
if type(date) == str: if isinstance(date, str):
date = is_iso_formated(date, convert=True) date = is_iso_formated(date, convert=True)
new_date: datetime.datetime = date new_date: datetime.datetime = date
if date.tzinfo == None: if date.tzinfo is None:
from app.models.assiduites import Assiduite from app.models.assiduites import Assiduite
first_assiduite = Assiduite.query.first() first_assiduite = Assiduite.query.first()
@ -167,27 +167,30 @@ def localize_datetime(date: datetime.datetime or str) -> datetime.datetime:
return new_date return new_date
def verif_interval( def is_period_overlapping(
periode: tuple[datetime.datetime], interval: tuple[datetime.datetime] periode: tuple[datetime.datetime, datetime.datetime],
interval: tuple[datetime.datetime, datetime.datetime],
) -> bool: ) -> bool:
""" """
Vérifie si une période est comprise dans un interval, chevauche l'interval ou comprend l'interval Vérifie si la période et l'interval s'intersectent
Retourne Vrai si c'est le cas, faux sinon Retourne Vrai si c'est le cas, faux sinon
""" """
p_deb, p_fin = periode p_deb, p_fin = periode
i_deb, i_fin = interval i_deb, i_fin = interval
i = intervalmap() # i = intervalmap()
p = intervalmap() # p = intervalmap()
i[:] = 0 # i[:] = 0
p[:] = 0 # p[:] = 0
i[i_deb:i_fin] = 1 # i[i_deb:i_fin] = 1
p[p_deb:p_fin] = 1 # p[p_deb:p_fin] = 1
res: int = sum((i[p_deb], i[p_fin], p[i_deb], p[i_fin])) # # TOTALK: Vérification des bornes de la période dans l'interval et inversement
# res: int = sum((i[p_deb], i[p_fin], p[i_deb], p[i_fin]))
return res > 0 # return res > 0
return p_deb <= i_fin and p_fin >= i_deb
# Types de modules # Types de modules

View File

@ -15,7 +15,7 @@ MODULE = 1
ASSIDUITES_FIELDS = { ASSIDUITES_FIELDS = {
"assiduiteid": int, "assiduite_id": int,
"etudid": int, "etudid": int,
"moduleimpl_id": int, "moduleimpl_id": int,
"date_debut": str, "date_debut": str,
@ -23,7 +23,7 @@ ASSIDUITES_FIELDS = {
"etat": str, "etat": str,
} }
CREATE_FIELD = {"assiduiteid": int} CREATE_FIELD = {"assiduite_id": int}
BATCH_FIELD = {"errors": dict, "success": dict} BATCH_FIELD = {"errors": dict, "success": dict}
COUNT_FIELDS = {"compte": int, "journee": int, "demi": int, "heure": float} COUNT_FIELDS = {"compte": int, "journee": int, "demi": int, "heure": float}
@ -86,7 +86,6 @@ def test_route_assiduite(api_headers):
check_failure_get( check_failure_get(
f"/assiduite/{FAUX}", f"/assiduite/{FAUX}",
api_headers, api_headers,
"assiduité inexistante",
) )
@ -195,12 +194,12 @@ def test_route_create(api_headers):
res = POST_JSON(f"/assiduite/{ETUDID}/create", data, api_headers) res = POST_JSON(f"/assiduite/{ETUDID}/create", data, api_headers)
check_fields(res, CREATE_FIELD) check_fields(res, CREATE_FIELD)
TO_REMOVE.append(res["assiduiteid"]) TO_REMOVE.append(res["assiduite_id"])
data2 = create_data("absent", "02", MODULE) data2 = create_data("absent", "02", MODULE)
res = POST_JSON(f"/assiduite/{ETUDID}/create", data2, api_headers) res = POST_JSON(f"/assiduite/{ETUDID}/create", data2, api_headers)
check_fields(res, CREATE_FIELD) check_fields(res, CREATE_FIELD)
TO_REMOVE.append(res["assiduiteid"]) TO_REMOVE.append(res["assiduite_id"])
# Mauvais fonctionnement # Mauvais fonctionnement
check_failure_post(f"/assiduite/{FAUX}/create", api_headers, data) check_failure_post(f"/assiduite/{FAUX}/create", api_headers, data)
@ -208,13 +207,13 @@ def test_route_create(api_headers):
f"/assiduite/{ETUDID}/create", f"/assiduite/{ETUDID}/create",
api_headers, api_headers,
data, data,
err="La période sélectionnée est déjà couverte par une autre assiduite", err="Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)",
) )
check_failure_post( check_failure_post(
f"/assiduite/{ETUDID}/create", f"/assiduite/{ETUDID}/create",
api_headers, api_headers,
create_data("absent", "03", FAUX), create_data("absent", "03", FAUX),
err="L'étudiant ne participe pas au moduleimpl sélectionné", err="param 'moduleimpl_id': invalide",
) )
# -== Avec batch ==- # -== Avec batch ==-
@ -233,7 +232,7 @@ def test_route_create(api_headers):
check_fields(res, BATCH_FIELD) check_fields(res, BATCH_FIELD)
for dat in res["success"]: for dat in res["success"]:
check_fields(res["success"][dat], CREATE_FIELD) check_fields(res["success"][dat], CREATE_FIELD)
TO_REMOVE.append(res["success"][dat]["assiduiteid"]) TO_REMOVE.append(res["success"][dat]["assiduite_id"])
# Mauvais Fonctionnement # Mauvais Fonctionnement
@ -252,9 +251,9 @@ def test_route_create(api_headers):
assert ( assert (
res["errors"]["0"] res["errors"]["0"]
== "La période sélectionnée est déjà couverte par une autre assiduite" == "Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)"
) )
assert res["errors"]["1"] == "L'étudiant ne participe pas au moduleimpl sélectionné" assert res["errors"]["1"] == "param 'moduleimpl_id': invalide"
assert res["errors"]["2"] == "param 'etat': invalide" assert res["errors"]["2"] == "param 'etat': invalide"
assert ( assert (
res["errors"]["3"] res["errors"]["3"]
@ -290,7 +289,7 @@ def test_route_delete(api_headers):
# -== Sans batch ==- # -== Sans batch ==-
# Bon fonctionnement # Bon fonctionnement
data = {"assiduiteid": TO_REMOVE[0]} data = {"assiduite_id": TO_REMOVE[0]}
res = POST_JSON(f"/assiduite/delete", data, api_headers) res = POST_JSON(f"/assiduite/delete", data, api_headers)
assert res == {"OK": True} assert res == {"OK": True}
@ -299,7 +298,7 @@ def test_route_delete(api_headers):
check_failure_post( check_failure_post(
f"/assiduite/delete", f"/assiduite/delete",
api_headers, api_headers,
{"assiduiteid": FAUX}, {"assiduite_id": FAUX},
err="Assiduite non existante", err="Assiduite non existante",
) )
# -== Avec batch ==- # -== Avec batch ==-

View File

@ -1,4 +1,24 @@
"entry_name";"url";"permission";"method";"content" "entry_name";"url";"permission";"method";"content"
"assiduite";"/assiduite/1";"ScoView";"GET";
"assiduites";"/assiduites/1";"ScoView";"GET";
"assiduites";"/assiduites/1/query?etat=retard";"ScoView";"GET";
"assiduites";"/assiduites/1/query?moduleimpl_id=1";"ScoView";"GET";
"assiduites_count";"/assiduites/1/count";"ScoView";"GET";
"assiduites_count";"/assiduites/1/count/query?etat=retard";"ScoView";"GET";
"assiduites_count";"/assiduites/1/count/query?etat=present,retard&metric=compte,heure";"ScoView";"GET";
"assiduites_formsemestre";"/assiduites/formsemestre/1";"ScoView";"GET";
"assiduites_formsemestre";"/assiduites/formsemestre/1/query?etat=retard";"ScoView";"GET";
"assiduites_formsemestre";"/assiduites/formsemestre/1/query?moduleimpl_id=1";"ScoView";"GET";
"assiduites_formsemestre_count";"/assiduites/formsemestre/1/count";"ScoView";"GET";
"assiduites_formsemestre_count";"/assiduites/formsemestre/1/count/query?etat=retard";"ScoView";"GET";
"assiduites_formsemestre_count";"/assiduites/formsemestre/1/count/query?etat=present,retard&metric=compte,heure";"ScoView";"GET";
"assiduite_create";"/assiduite/1/create";"ScoView";"POST";"{""date_debut"": ""2022-10-27T08:00"",""date_fin"": ""2022-10-27T10:00"",""etat"": ""absent""}"
"assiduite_create";"/assiduite/1/create/batch";"ScoView";"POST";"{""batch"":[{""date_debut"": ""2022-10-27T08:00"",""date_fin"": ""2022-10-27T10:00"",""etat"": ""absent""},{""date_debut"": ""2022-10-27T08:00"",""date_fin"": ""2022-10-27T10:00"",""etat"": ""retard""},{""date_debut"": ""2022-10-27T11:00"",""date_fin"": ""2022-10-27T13:00"",""etat"": ""present""}]}"
"assiduite_edit";"/assiduite/1/edit";"ScoView";"POST";"{""etat"":""absent""}"
"assiduite_edit";"/assiduite/1/edit";"ScoView";"POST";"{""moduleimpl_id"":2}"
"assiduite_edit";"/assiduite/1/edit";"ScoView";"POST";"{""etat"": ""retard"",""moduleimpl_id"":3}"
"assiduite_delete";"/assiduite/delete";"ScoView";"POST";"{""assiduite_id"": 1}"
"assiduite_delete";"/assiduite/delete/batch";"ScoView";"POST";"{""batch"":[2,2,3]}"
"departements";"/departements";"ScoView";"GET"; "departements";"/departements";"ScoView";"GET";
"departements-ids";"/departements_ids";"ScoView";"GET"; "departements-ids";"/departements_ids";"ScoView";"GET";
"departement";"/departement/TAPI";"ScoView";"GET"; "departement";"/departement/TAPI";"ScoView";"GET";

1 entry_name url permission method content
2 assiduite /assiduite/1 ScoView GET
3 assiduites /assiduites/1 ScoView GET
4 assiduites /assiduites/1/query?etat=retard ScoView GET
5 assiduites /assiduites/1/query?moduleimpl_id=1 ScoView GET
6 assiduites_count /assiduites/1/count ScoView GET
7 assiduites_count /assiduites/1/count/query?etat=retard ScoView GET
8 assiduites_count /assiduites/1/count/query?etat=present,retard&metric=compte,heure ScoView GET
9 assiduites_formsemestre /assiduites/formsemestre/1 ScoView GET
10 assiduites_formsemestre /assiduites/formsemestre/1/query?etat=retard ScoView GET
11 assiduites_formsemestre /assiduites/formsemestre/1/query?moduleimpl_id=1 ScoView GET
12 assiduites_formsemestre_count /assiduites/formsemestre/1/count ScoView GET
13 assiduites_formsemestre_count /assiduites/formsemestre/1/count/query?etat=retard ScoView GET
14 assiduites_formsemestre_count /assiduites/formsemestre/1/count/query?etat=present,retard&metric=compte,heure ScoView GET
15 assiduite_create /assiduite/1/create ScoView POST {"date_debut": "2022-10-27T08:00","date_fin": "2022-10-27T10:00","etat": "absent"}
16 assiduite_create /assiduite/1/create/batch ScoView POST {"batch":[{"date_debut": "2022-10-27T08:00","date_fin": "2022-10-27T10:00","etat": "absent"},{"date_debut": "2022-10-27T08:00","date_fin": "2022-10-27T10:00","etat": "retard"},{"date_debut": "2022-10-27T11:00","date_fin": "2022-10-27T13:00","etat": "present"}]}
17 assiduite_edit /assiduite/1/edit ScoView POST {"etat":"absent"}
18 assiduite_edit /assiduite/1/edit ScoView POST {"moduleimpl_id":2}
19 assiduite_edit /assiduite/1/edit ScoView POST {"etat": "retard","moduleimpl_id":3}
20 assiduite_delete /assiduite/delete ScoView POST {"assiduite_id": 1}
21 assiduite_delete /assiduite/delete/batch ScoView POST {"batch":[2,2,3]}
22 departements /departements ScoView GET
23 departements-ids /departements_ids ScoView GET
24 departement /departement/TAPI ScoView GET

View File

@ -14,7 +14,8 @@ 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 from app.models import Assiduite, Identite, FormSemestre, ModuleImpl
from app.scodoc.sco_exceptions import ScoValueError
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
@ -62,29 +63,33 @@ def test_general(test_client):
# Création des modulesimpls (4, 2 par semestre) # Création des modulesimpls (4, 2 par semestre)
moduleimpl_id_1_1 = G.create_moduleimpl( moduleimpl_1_1 = G.create_moduleimpl(
module_id=module_id_1, module_id=module_id_1,
formsemestre_id=formsemestre_id_1, formsemestre_id=formsemestre_id_1,
) )
moduleimpl_id_1_2 = G.create_moduleimpl( moduleimpl_1_2 = G.create_moduleimpl(
module_id=module_id_2, module_id=module_id_2,
formsemestre_id=formsemestre_id_1, formsemestre_id=formsemestre_id_1,
) )
moduleimpl_id_2_1 = G.create_moduleimpl( moduleimpl_2_1 = G.create_moduleimpl(
module_id=module_id_1, module_id=module_id_1,
formsemestre_id=formsemestre_id_2, formsemestre_id=formsemestre_id_2,
) )
moduleimpl_id_2_2 = G.create_moduleimpl( moduleimpl_2_2 = G.create_moduleimpl(
module_id=module_id_2, module_id=module_id_2,
formsemestre_id=formsemestre_id_2, formsemestre_id=formsemestre_id_2,
) )
moduleimpls = [ moduleimpls = [
moduleimpl_id_1_1, moduleimpl_1_1,
moduleimpl_id_1_2, moduleimpl_1_2,
moduleimpl_id_2_1, moduleimpl_2_1,
moduleimpl_id_2_2, moduleimpl_2_2,
]
moduleimpls = [
ModuleImpl.query.filter_by(id=mi_id).first() for mi_id in moduleimpls
] ]
# Création des étudiants (3) # Création des étudiants (3)
@ -100,7 +105,12 @@ def test_general(test_client):
assert None not in etuds, "Problème avec la conversion en Identite" assert None not in etuds, "Problème avec la conversion en Identite"
ajouter_assiduites(etuds, moduleimpls=moduleimpls) # Etudiant faux
etud_faux_dict = G.create_etud(code_nip=None, prenom="etudfaux")
etud_faux = Identite.query.filter_by(id=etud_faux_dict["id"]).first()
ajouter_assiduites(etuds, moduleimpls, etud_faux)
verifier_comptage_et_filtrage( verifier_comptage_et_filtrage(
etuds, moduleimpls, (formsemestre_1, formsemestre_2, formsemestre_3) etuds, moduleimpls, (formsemestre_1, formsemestre_2, formsemestre_3)
) )
@ -124,7 +134,7 @@ def editer_supprimer_assiduiter(etuds: list[Identite], moduleimpls: list[int]):
ass1.etat = scu.EtatAssiduite.RETARD ass1.etat = scu.EtatAssiduite.RETARD
db.session.add(ass1) db.session.add(ass1)
# Modification du moduleimpl # Modification du moduleimpl
ass2.moduleimpl_id = moduleimpls[0] ass2.moduleimpl_id = moduleimpls[0].id
db.session.add(ass2) db.session.add(ass2)
db.session.commit() db.session.commit()
@ -133,7 +143,7 @@ def editer_supprimer_assiduiter(etuds: list[Identite], moduleimpls: list[int]):
scass.filter_by_etat(etuds[0].assiduites, "retard").count() == 3 scass.filter_by_etat(etuds[0].assiduites, "retard").count() == 3
), "Edition d'assiduité mauvais" ), "Edition d'assiduité mauvais"
assert ( assert (
scass.filter_by_module_impl(etuds[1].assiduites, moduleimpls[0]).count() == 2 scass.filter_by_module_impl(etuds[1].assiduites, moduleimpls[0].id).count() == 2
), "Edition d'assiduité mauvais" ), "Edition d'assiduité mauvais"
# Supression d'une assiduité # Supression d'une assiduité
@ -144,7 +154,9 @@ def editer_supprimer_assiduiter(etuds: list[Identite], moduleimpls: list[int]):
assert etuds[2].assiduites.count() == 5, "Supression d'assiduité mauvais" assert etuds[2].assiduites.count() == 5, "Supression d'assiduité mauvais"
def ajouter_assiduites(etuds: list[Identite], moduleimpls: list[int]): def ajouter_assiduites(
etuds: list[Identite], moduleimpls: list[ModuleImpl], etud_faux: Identite
):
""" """
Première partie: Première partie:
- Ajoute 6 assiduités à chaque étudiant - Ajoute 6 assiduités à chaque étudiant
@ -160,43 +172,43 @@ def ajouter_assiduites(etuds: list[Identite], moduleimpls: list[int]):
"etat": scu.EtatAssiduite.PRESENT, "etat": scu.EtatAssiduite.PRESENT,
"deb": "2022-09-03T08:00+01:00", "deb": "2022-09-03T08:00+01:00",
"fin": "2022-09-03T10:00+01:00", "fin": "2022-09-03T10:00+01:00",
"moduleimpl_id": None, "moduleimpl": None,
}, },
{ {
"etat": scu.EtatAssiduite.PRESENT, "etat": scu.EtatAssiduite.PRESENT,
"deb": "2023-01-03T08:00+01:00", "deb": "2023-01-03T08:00+01:00",
"fin": "2023-01-03T10:00+01:00", "fin": "2023-01-03T10:00+01:00",
"moduleimpl_id": moduleimpls[2], "moduleimpl": moduleimpls[2],
}, },
{ {
"etat": scu.EtatAssiduite.ABSENT, "etat": scu.EtatAssiduite.ABSENT,
"deb": "2022-09-03T10:00:01+01:00", "deb": "2022-09-03T10:00:01+01:00",
"fin": "2022-09-03T11:00+01:00", "fin": "2022-09-03T11:00+01:00",
"moduleimpl_id": moduleimpls[0], "moduleimpl": moduleimpls[0],
}, },
{ {
"etat": scu.EtatAssiduite.ABSENT, "etat": scu.EtatAssiduite.ABSENT,
"deb": "2022-09-03T14:00:00+01:00", "deb": "2022-09-03T14:00:00+01:00",
"fin": "2022-09-03T15:00+01:00", "fin": "2022-09-03T15:00+01:00",
"moduleimpl_id": moduleimpls[1], "moduleimpl": moduleimpls[1],
}, },
{ {
"etat": scu.EtatAssiduite.RETARD, "etat": scu.EtatAssiduite.RETARD,
"deb": "2023-01-03T11:00:01+01:00", "deb": "2023-01-03T11:00:01+01:00",
"fin": "2023-01-03T12:00+01:00", "fin": "2023-01-03T12:00+01:00",
"moduleimpl_id": moduleimpls[3], "moduleimpl": moduleimpls[3],
}, },
{ {
"etat": scu.EtatAssiduite.RETARD, "etat": scu.EtatAssiduite.RETARD,
"deb": "2023-01-04T11:00:01+01:00", "deb": "2023-01-04T11:00:01+01:00",
"fin": "2023-01-04T12:00+01:00", "fin": "2023-01-04T12:00+01:00",
"moduleimpl_id": moduleimpls[3], "moduleimpl": moduleimpls[3],
}, },
] ]
assiduites = [ assiduites = [
Assiduite.create_assiduite( Assiduite.create_assiduite(
etud, ass["deb"], ass["fin"], ass["etat"], ass["moduleimpl_id"] etud, ass["deb"], ass["fin"], ass["etat"], ass["moduleimpl"]
) )
for ass in obj_assiduites for ass in obj_assiduites
] ]
@ -208,32 +220,36 @@ def ajouter_assiduites(etuds: list[Identite], moduleimpls: list[int]):
# Vérification de la gestion des erreurs # Vérification de la gestion des erreurs
test_assiduites = [ test_assiduite = {
{
"etat": scu.EtatAssiduite.RETARD, "etat": scu.EtatAssiduite.RETARD,
"deb": "2023-01-04T11:00:01+01:00", "deb": "2023-01-04T11:00:01+01:00",
"fin": "2023-01-04T12:00+01:00", "fin": "2023-01-04T12:00+01:00",
"moduleimpl_id": moduleimpls[3], "moduleimpl": moduleimpls[3],
}, }
{
"etat": scu.EtatAssiduite.RETARD,
"deb": "2023-01-05T11:00:01+01:00",
"fin": "2023-01-05T12:00+01:00",
"moduleimpl_id": 1000,
},
]
assiduites_crees = [ try:
Assiduite.create_assiduite( Assiduite.create_assiduite(
etuds[0], ass["deb"], ass["fin"], ass["etat"], ass["moduleimpl_id"] etuds[0],
test_assiduite["deb"],
test_assiduite["fin"],
test_assiduite["etat"],
test_assiduite["moduleimpl"],
) )
for ass in test_assiduites except ScoValueError as excp:
] assert (
excp.args[0]
assert [ass for ass in assiduites_crees if type(ass) != Assiduite] == [ == "Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)"
1, )
2, try:
], "La vérification des erreurs ne fonctionne pas" Assiduite.create_assiduite(
etud_faux,
test_assiduite["deb"],
test_assiduite["fin"],
test_assiduite["etat"],
test_assiduite["moduleimpl"],
)
except ScoValueError as excp:
assert excp.args[0] == "L'étudiant n'est pas inscrit au moduleimpl"
def verifier_comptage_et_filtrage( def verifier_comptage_et_filtrage(
@ -282,16 +298,16 @@ def verifier_comptage_et_filtrage(
# Module # Module
assert ( assert (
scass.filter_by_module_impl(etu3.assiduites, mod11).count() == 1 scass.filter_by_module_impl(etu3.assiduites, mod11.id).count() == 1
), "Filtrage par 'Moduleimpl' mauvais" ), "Filtrage par 'Moduleimpl' mauvais"
assert ( assert (
scass.filter_by_module_impl(etu3.assiduites, mod12).count() == 1 scass.filter_by_module_impl(etu3.assiduites, mod12.id).count() == 1
), "Filtrage par 'Moduleimpl' mauvais" ), "Filtrage par 'Moduleimpl' mauvais"
assert ( assert (
scass.filter_by_module_impl(etu3.assiduites, mod21).count() == 1 scass.filter_by_module_impl(etu3.assiduites, mod21.id).count() == 1
), "Filtrage par 'Moduleimpl' mauvais" ), "Filtrage par 'Moduleimpl' mauvais"
assert ( assert (
scass.filter_by_module_impl(etu3.assiduites, mod22).count() == 2 scass.filter_by_module_impl(etu3.assiduites, mod22.id).count() == 2
), "Filtrage par 'Moduleimpl' mauvais" ), "Filtrage par 'Moduleimpl' mauvais"
assert ( assert (
scass.filter_by_module_impl(etu3.assiduites, None).count() == 1 scass.filter_by_module_impl(etu3.assiduites, None).count() == 1

View File

@ -383,7 +383,7 @@ def ajouter_assiduites(formsemestre: FormSemestre):
""" """
Ajoute des assiduités semi-aléatoires à chaque étudiant du semestre Ajoute des assiduités semi-aléatoires à chaque étudiant du semestre
""" """
MODS = [moduleimpl.id for moduleimpl in formsemestre.modimpls] MODS = [moduleimpl for moduleimpl in formsemestre.modimpls]
MODS.append(None) MODS.append(None)
from app.scodoc.sco_utils import localize_datetime from app.scodoc.sco_utils import localize_datetime
@ -394,11 +394,13 @@ def ajouter_assiduites(formsemestre: FormSemestre):
for i in range(random.randint(1, 5)): for i in range(random.randint(1, 5)):
etat = random.randint(0, 2) etat = random.randint(0, 2)
module = random.choice(MODS) moduleimpl = random.choice(MODS)
deb_date = base_date + datetime.timedelta(days=i) deb_date = base_date + datetime.timedelta(days=i)
fin_date = deb_date + datetime.timedelta(hours=i) fin_date = deb_date + datetime.timedelta(hours=i)
code = Assiduite.create_assiduite(etud, deb_date, fin_date, etat, module) code = Assiduite.create_assiduite(
etud, deb_date, fin_date, etat, moduleimpl
)
assert isinstance( assert isinstance(
code, Assiduite code, Assiduite