Assiduites : révisions + corrections linter

This commit is contained in:
iziram 2023-01-31 16:23:49 +01:00
parent 3998b5a366
commit cf3258f5f9
8 changed files with 238 additions and 176 deletions

View File

@ -6,23 +6,20 @@
"""ScoDoc 9 API : Assiduités
"""
from datetime import datetime
from typing import List
from flask import g, jsonify, request
from app import db
from app.api import api_bp as bp, api_web_bp
from app.scodoc.sco_utils import json_error
from app.decorators import scodoc, permission_required
from app.scodoc.sco_permissions import Permission
from flask_login import login_required
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_assiduites as scass
import app.scodoc.sco_utils as scu
from app import db
from app.api import api_bp as bp
from app.api import api_web_bp
from app.decorators import permission_required, scodoc
from app.models import Assiduite, FormSemestre, Identite, ModuleImpl
from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc.sco_permissions import Permission
from app.scodoc.sco_utils import json_error
@bp.route("/assiduite/<int:assiduite_id>")
@ -47,10 +44,9 @@ def assiduite(assiduite_id: int = None):
query = Assiduite.query.filter_by(id=assiduite_id)
# if g.scodoc_dept:
# query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id)
assiduite_query = query.first_or_404()
assiduite = query.first_or_404()
data = assiduite.to_dict()
data = assiduite_query.to_dict()
return jsonify(change_etat(data))
@ -104,15 +100,15 @@ def count_assiduites(etudid: int = None, with_query: bool = False):
query = query.filter_by(dept_id=g.scodoc_dept_id)
etud: Identite = query.first_or_404(etudid)
filter: dict[str, object] = {}
filtered: dict[str, object] = {}
metric: str = "all"
if with_query:
metric, filter = count_manager(request)
metric, filtered = count_manager(request)
return jsonify(
scass.get_assiduites_stats(
assiduites=etud.assiduites, metric=metric, filter=filter
assiduites=etud.assiduites, metric=metric, filtered=filtered
)
)
@ -162,13 +158,13 @@ def assiduites(etudid: int = None, with_query: bool = False):
query = query.filter_by(dept_id=g.scodoc_dept_id)
etud: Identite = query.first_or_404(etudid)
assiduites = etud.assiduites
assiduites_query = etud.assiduites
if with_query:
assiduites = filter_manager(request, assiduites)
assiduites_query = filter_manager(request, assiduites_query)
data_set: List[dict] = []
for ass in assiduites.all():
for ass in assiduites_query.all():
data = ass.to_dict()
data_set.append(change_etat(data))
@ -200,17 +196,13 @@ def assiduites_formsemestre(formsemestre_id: int, with_query: bool = False):
if formsemestre is None:
return json_error(404, "le paramètre 'formsemestre_id' n'existe pas")
etuds = formsemestre.etuds.all()
etuds_id = [etud.id for etud in etuds]
assiduites = Assiduite.query.filter(Assiduite.etudid.in_(etuds_id))
assiduites = scass.filter_by_formsemstre(assiduites, formsemestre)
assiduites_query = scass.filter_by_formsemestre(Assiduite.query, formsemestre)
if with_query:
assiduites = filter_manager(request, assiduites)
assiduites_query = filter_manager(request, assiduites_query)
data_set: List[dict] = []
for ass in assiduites.all():
for ass in assiduites_query.all():
data = ass.to_dict()
data_set.append(change_etat(data))
@ -249,14 +241,14 @@ def count_assiduites_formsemestre(
etuds = formsemestre.etuds.all()
etuds_id = [etud.id for etud in etuds]
assiduites = Assiduite.query.filter(Assiduite.etudid.in_(etuds_id))
assiduites = scass.filter_by_formsemstre(assiduites, formsemestre)
assiduites_query = Assiduite.query.filter(Assiduite.etudid.in_(etuds_id))
assiduites_query = scass.filter_by_formsemestre(assiduites_query, formsemestre)
metric: str = "all"
filter: dict = {}
filtered: dict = {}
if with_query:
metric, filter = count_manager(request)
metric, filtered = count_manager(request)
return jsonify(scass.get_assiduites_stats(assiduites, metric, filter))
return jsonify(scass.get_assiduites_stats(assiduites_query, metric, filtered))
@bp.route("/assiduite/<int:etudid>/create", methods=["POST"])
@ -269,27 +261,37 @@ def create(etudid: int = None):
"""
Création d'une assiduité pour l'étudiant (etudid)
La requête doit avoir un content type "application/json":
{
"date_debut": str,
"date_fin": str,
"etat": str,
}
ou
{
"date_debut": str,
"date_fin": str,
"etat": str,
"moduleimpl_id": int,
}
[
{
"date_debut": str,
"date_fin": str,
"etat": str,
},
{
"date_debut": str,
"date_fin": str,
"etat": str,
"moduleimpl_id": int,
"desc":str,
}
...
]
TODO:
- vérifier si l'entrée est bien une liste
"""
etud: Identite = Identite.query.filter_by(id=etudid).first_or_404()
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")
errors: dict[int, str] = {}
success: dict[int, object] = {}
for i, data in enumerate(request.get_json(force=True)):
code, obj = create_singular(data, etud)
for i, data in enumerate(create_list):
code, obj = _create_singular(data, etud)
if code == 404:
errors[i] = obj
else:
@ -298,7 +300,7 @@ def create(etudid: int = None):
return jsonify({"errors": errors, "success": success})
def create_singular(
def _create_singular(
data: dict,
etud: Identite,
) -> tuple[int, object]:
@ -309,7 +311,7 @@ def create_singular(
etat = data.get("etat", None)
if etat is None:
errors.append("param 'etat': manquant")
elif etat not in scu.ETATS_ASSIDUITE.keys():
elif etat not in scu.ETATS_ASSIDUITE:
errors.append("param 'etat': invalide")
data = change_etat(data, False)
@ -329,7 +331,7 @@ def create_singular(
errors.append("param 'date_fin': manquant")
fin = scu.is_iso_formated(date_fin, convert=True)
if fin is None:
errors.append(f"param 'date_fin': format invalide")
errors.append("param 'date_fin': format invalide")
# cas 4 : moduleimpl_id
@ -343,9 +345,9 @@ def create_singular(
# cas 5 : desc
desc:str = data.get("desc", None)
desc: str = data.get("desc", None)
if errors != []:
if errors:
err: str = ", ".join(errors)
return (404, err)
@ -358,6 +360,7 @@ def create_singular(
etat=etat,
etud=etud,
moduleimpl=moduleimpl,
description=desc,
)
db.session.add(nouv_assiduite)
@ -379,12 +382,24 @@ def create_singular(
def delete():
"""
Suppression d'une assiduité à partir de son id
Forme des données envoyées :
[
<assiduite_id:int>,
...
]
"""
assiduites: list[int] = request.get_json(force=True)
assiduites_list: list[int] = request.get_json(force=True)
if not isinstance(assiduites_list, list):
return json_error(404, "Le contenu envoyé n'est pas une liste")
output = {"errors": {}, "success": {}}
for i, ass in enumerate(assiduites):
code, msg = delete_singular(ass, db)
for i, ass in enumerate(assiduites_list):
code, msg = _delete_singular(ass, db)
if code == 404:
output["errors"][f"{i}"] = msg
else:
@ -393,11 +408,11 @@ def delete():
return jsonify(output)
def delete_singular(assiduite_id: int, db):
assiduite: Assiduite = Assiduite.query.filter_by(id=assiduite_id).first()
if assiduite is None:
def _delete_singular(assiduite_id: int, database):
assiduite_unique: Assiduite = Assiduite.query.filter_by(id=assiduite_id).first()
if assiduite_unique is None:
return (404, "Assiduite non existante")
db.session.delete(assiduite)
database.session.delete(assiduite_unique)
return (200, "OK")
@ -412,11 +427,14 @@ def edit(assiduite_id: int):
Edition d'une assiduité à partir de son id
La requête doit avoir un content type "application/json":
{
"etat": str,
"moduleimpl_id": int
"etat"?: str,
"moduleimpl_id"?: int
"desc"?: str
}
"""
assiduite: Assiduite = Assiduite.query.filter_by(id=assiduite_id).first_or_404()
assiduite_unique: Assiduite = Assiduite.query.filter_by(
id=assiduite_id
).first_or_404()
errors: List[str] = []
data = request.get_json(force=True)
@ -428,7 +446,7 @@ def edit(assiduite_id: int):
if data.get("etat") is None:
errors.append("param 'etat': invalide")
else:
assiduite.etat = data.get("etat")
assiduite_unique.etat = data.get("etat")
# Cas 2 : Moduleimpl_id
moduleimpl_id = data.get("moduleimpl_id", False)
@ -441,18 +459,24 @@ def edit(assiduite_id: int):
errors.append("param 'moduleimpl_id': invalide")
else:
if not moduleimpl.est_inscrit(
Identite.query.filter_by(id=assiduite.etudid).first()
Identite.query.filter_by(id=assiduite_unique.etudid).first()
):
errors.append("param 'moduleimpl_id': etud non inscrit")
else:
assiduite.moduleimpl_id = moduleimpl_id
assiduite_unique.moduleimpl_id = moduleimpl_id
else:
assiduite.moduleimpl_id = moduleimpl_id
if errors != []:
assiduite_unique.moduleimpl_id = moduleimpl_id
# Cas 3 : desc
desc = data.get("desc", False)
if desc is not False:
assiduite_unique.desc = desc
if errors:
err: str = ", ".join(errors)
return json_error(404, err)
db.session.add(assiduite)
db.session.add(assiduite_unique)
db.session.commit()
return jsonify({"OK": True})
@ -467,104 +491,104 @@ def change_etat(data: dict, from_int: bool = True):
return data
def count_manager(request) -> tuple[str, dict]:
def count_manager(requested) -> tuple[str, dict]:
"""
Retourne la/les métriques à utiliser ainsi que le filtre donnés en query de la requête
"""
filter: dict = {}
filtered: dict = {}
# cas 1 : etat assiduite
etat = request.args.get("etat")
etat = requested.args.get("etat")
if etat is not None:
filter["etat"] = etat
filtered["etat"] = etat
# cas 2 : date de début
deb = request.args.get("date_debut")
deb = requested.args.get("date_debut")
deb: datetime = scu.is_iso_formated(deb, True)
if deb is not None:
filter["date_debut"] = deb
filtered["date_debut"] = deb
# cas 3 : date de fin
fin = request.args.get("date_fin")
fin = requested.args.get("date_fin")
fin = scu.is_iso_formated(fin, True)
if fin is not None:
filter["date_fin"] = fin
filtered["date_fin"] = fin
# cas 4 : moduleimpl_id
module = request.args.get("moduleimpl_id", False)
module = requested.args.get("moduleimpl_id", False)
try:
if module is False:
raise Exception
raise ValueError
if module != "":
module = int(module)
else:
module = None
except Exception:
except ValueError:
module = False
if module is not False:
filter["moduleimpl_id"] = module
filtered["moduleimpl_id"] = module
# cas 5 : formsemestre_id
formsemestre_id = request.args.get("formsemestre_id")
formsemestre_id = requested.args.get("formsemestre_id")
if formsemestre_id is not None:
formsemestre: FormSemestre = None
formsemestre_id = int(formsemestre_id)
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first()
filter["formsemestre"] = formsemestre
filtered["formsemestre"] = formsemestre
# cas 6 : type
metric = request.args.get("metric", "all")
metric = requested.args.get("metric", "all")
return (metric, filter)
return (metric, filtered)
def filter_manager(request, assiduites):
def filter_manager(requested, assiduites_query):
"""
Retourne les assiduites entrées filtrées en fonction de la request
"""
# cas 1 : etat assiduite
etat = request.args.get("etat")
etat = requested.args.get("etat")
if etat is not None:
assiduites = scass.filter_by_etat(assiduites, etat)
assiduites_query = scass.filter_by_etat(assiduites_query, etat)
# cas 2 : date de début
deb = request.args.get("date_debut")
deb = requested.args.get("date_debut")
deb: datetime = scu.is_iso_formated(deb, True)
if deb is not None:
assiduites = scass.filter_by_date(assiduites, deb, sup=True)
assiduites_query = scass.filter_by_date(assiduites_query, deb, sup=True)
# cas 3 : date de fin
fin = request.args.get("date_fin")
fin = requested.args.get("date_fin")
fin = scu.is_iso_formated(fin, True)
if fin is not None:
assiduites = scass.filter_by_date(assiduites, fin, sup=False)
assiduites_query = scass.filter_by_date(assiduites_query, fin, sup=False)
# cas 4 : moduleimpl_id
module = request.args.get("moduleimpl_id", False)
module = requested.args.get("moduleimpl_id", False)
try:
if module is False:
raise Exception
raise ValueError
if module != "":
module = int(module)
else:
module = None
except Exception:
except ValueError:
module = False
if module is not False:
assiduites = scass.filter_by_module_impl(assiduites, module)
assiduites_query = scass.filter_by_module_impl(assiduites_query, module)
# cas 5 : formsemestre_id
formsemestre_id = request.args.get("formsemestre_id")
formsemestre_id = requested.args.get("formsemestre_id")
if formsemestre_id is not None:
formsemestre: FormSemestre = None
formsemestre_id = int(formsemestre_id)
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first()
assiduites = scass.filter_by_formsemstre(assiduites, formsemestre)
assiduites_query = scass.filter_by_formsemestre(assiduites_query, formsemestre)
return assiduites
return assiduites_query

View File

@ -1,13 +1,14 @@
# -*- coding: UTF-8 -*
"""Gestion de l'assiduité (assiduités + justificatifs)
"""
from app import db
from app.models import ModuleImpl, ModuleImplInscription
from app.models.etudiants import Identite
from app.scodoc.sco_utils import EtatAssiduite, localize_datetime, is_period_overlapping
from app.scodoc.sco_exceptions import ScoValueError
from datetime import datetime
from app import db
from app.models import ModuleImpl
from app.models.etudiants import Identite
from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc.sco_utils import EtatAssiduite, is_period_overlapping, localize_datetime
class Assiduite(db.Model):
"""
@ -43,6 +44,8 @@ class Assiduite(db.Model):
desc = db.Column(db.Text)
entry_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
def to_dict(self) -> dict:
data = {
"assiduite_id": self.assiduite_id,
@ -52,6 +55,7 @@ class Assiduite(db.Model):
"date_fin": self.date_fin,
"etat": self.etat,
"desc": self.desc,
"entry_date": self.entry_date,
}
return data
@ -136,16 +140,14 @@ class Justificatif(db.Model):
)
etat = db.Column(
db.Integer,
nullable=False,
)
entry_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
raison = db.Column(db.Text())
"""
Les justificatifs sont enregistrés dans
<archivedir>/justificatifs/<dept_id>/<etudid>/<nom_fichier.extension>
d'après sco_archives.py#JustificatifArchiver
"""
# Archive_id -> sco_archives_justificatifs.py
fichier = db.Column(db.Text())
def to_dict(self) -> dict:
@ -157,5 +159,6 @@ class Justificatif(db.Model):
"etat": self.etat,
"raison": self.raison,
"fichier": self.fichier,
"entry_date": self.entry_date,
}
return data

View File

@ -65,6 +65,10 @@ class Identite(db.Model):
passive_deletes=True,
)
# Relations avec les assiduites et les justificatifs
assiduites = db.relationship("Assiduite", backref="etudiant", lazy="dynamic")
justificatifs = db.relationship("Justificatif", backref="etudiant", lazy="dynamic")
def __repr__(self):
return (
f"<Etud {self.id}/{self.departement.acronym} {self.nom!r} {self.prenom!r}>"

View File

@ -1,27 +1,29 @@
from app.models.etudiants import Identite
from app.models.formsemestre import FormSemestre
from app.models.assiduites import Assiduite
from datetime import date, datetime, time, timedelta
import app.scodoc.sco_utils as scu
from datetime import datetime, date, time, timedelta
from app.models.assiduites import Assiduite
from app.models.etudiants import Identite
from app.models.formsemestre import FormSemestre, FormSemestreInscription
# TOTALK: Réfléchir sur le fractionnement d'une assiduite prolongée
def get_assiduites_stats(
assiduites: Assiduite, metric: str = "all", filter: dict[str, object] = {}
assiduites: Assiduite, metric: str = "all", filtered: dict[str, object] = None
) -> Assiduite:
if filter != {}:
for key in filter:
if filtered is not None:
for key in filtered:
if key == "etat":
assiduites = filter_by_etat(assiduites, filter[key])
assiduites = filter_by_etat(assiduites, filtered[key])
elif key == "date_fin":
assiduites = filter_by_date(assiduites, filter[key], sup=False)
assiduites = filter_by_date(assiduites, filtered[key], sup=False)
elif key == "date_debut":
assiduites = filter_by_date(assiduites, filter[key], sup=True)
assiduites = filter_by_date(assiduites, filtered[key], sup=True)
elif key == "moduleimpl_id":
assiduites = filter_by_module_impl(assiduites, filter[key])
assiduites = filter_by_module_impl(assiduites, filtered[key])
elif key == "formsemestre":
assiduites = filter_by_formsemstre(assiduites, filter[key])
assiduites = filter_by_formsemestre(assiduites, filtered[key])
count: dict = get_count(assiduites)
@ -29,10 +31,10 @@ def get_assiduites_stats(
output: dict = {}
for key in count:
for key, val in count.items():
if key in metrics:
output[key] = count[key]
return output if output != {} else count
output[key] = val
return output if output else count
def get_count(assiduites: Assiduite) -> dict[str, int or float]:
@ -48,9 +50,11 @@ def get_count(assiduites: Assiduite) -> dict[str, int or float]:
current_day: date = None
current_time: str = None
MIDNIGHT: time = time(hour=0)
NOON: time = time(hour=12)
time_check = lambda d: (MIDNIGHT <= d.time() <= NOON)
midnight: time = time(hour=0)
noon: time = time(hour=12)
def time_check(dtime):
return midnight <= dtime.time() <= noon
for ass in all_assiduites:
delta: timedelta = ass.date_fin - ass.date_debut
@ -82,7 +86,7 @@ def filter_by_etat(assiduites: Assiduite, etat: str) -> Assiduite:
def filter_by_date(
assiduites: Assiduite, date: datetime, sup: bool = True
assiduites: Assiduite, date_: datetime, sup: bool = True
) -> Assiduite:
"""
Filtrage d'une collection d'assiduites en fonction d'une date
@ -91,15 +95,15 @@ def filter_by_date(
Sup == False -> les assiduites doivent finir avant 'date'
"""
if date.tzinfo is None:
if date_.tzinfo is None:
first_assiduite: Assiduite = assiduites.first()
if first_assiduite is not None:
date: datetime = date.replace(tzinfo=first_assiduite.date_debut.tzinfo)
date_: datetime = date_.replace(tzinfo=first_assiduite.date_debut.tzinfo)
if sup:
return assiduites.filter(Assiduite.date_debut >= date)
else:
return assiduites.filter(Assiduite.date_fin <= date)
return assiduites.filter(Assiduite.date_debut >= date_)
return assiduites.filter(Assiduite.date_fin <= date_)
def filter_by_module_impl(
@ -111,18 +115,24 @@ def filter_by_module_impl(
return assiduites.filter(Assiduite.moduleimpl_id == module_impl_id)
def filter_by_formsemstre(assiduites: Assiduite, formsemestre: FormSemestre):
def filter_by_formsemestre(assiduites_query: Assiduite, formsemestre: FormSemestre):
"""
Filtrage d'une collection d'assiduites en fonction d'un formsemestre
"""
if formsemestre is None:
return assiduites.filter(False)
return assiduites_query.filter(False)
assiduites = assiduites.filter(
Identite.query.filter_by(id=Assiduite.etudid).first()
in formsemestre.etuds.all()
assiduites_query = (
assiduites_query.join(Identite, Assiduite.etudid == Identite.id)
.join(
FormSemestreInscription,
Identite.id == FormSemestreInscription.etudid,
)
.filter(FormSemestreInscription.formsemestre_id == formsemestre.id)
)
assiduites = assiduites.filter(Assiduite.date_debut >= formsemestre.date_debut)
return assiduites.filter(Assiduite.date_fin <= formsemestre.date_fin)
assiduites_query = assiduites_query.filter(
Assiduite.date_debut >= formsemestre.date_debut
)
return assiduites_query.filter(Assiduite.date_fin <= formsemestre.date_fin)

View File

@ -1,8 +1,8 @@
"""Modèle Assiduites et Justificatifs
"""Modeles assiduites et justificatifs
Revision ID: 943eb2deb22e
Revises: 25e3ca6cc063
Create Date: 2023-01-30 14:08:47.214916
Revision ID: 961b2f2c595d
Revises: 5c7b208355df
Create Date: 2023-01-31 15:37:02.961533
"""
from alembic import op
@ -10,8 +10,8 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '943eb2deb22e'
down_revision = '25e3ca6cc063'
revision = '961b2f2c595d'
down_revision = '5c7b208355df'
branch_labels = None
depends_on = None
@ -23,7 +23,8 @@ def upgrade():
sa.Column('date_debut', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
sa.Column('date_fin', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
sa.Column('etudid', sa.Integer(), nullable=False),
sa.Column('etat', sa.Integer(), nullable=True),
sa.Column('etat', sa.Integer(), nullable=False),
sa.Column('entry_date', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True),
sa.Column('raison', sa.Text(), nullable=True),
sa.Column('fichier', sa.Text(), nullable=True),
sa.ForeignKeyConstraint(['etudid'], ['identite.id'], ondelete='CASCADE'),
@ -38,16 +39,27 @@ def upgrade():
sa.Column('etudid', sa.Integer(), nullable=False),
sa.Column('etat', sa.Integer(), nullable=False),
sa.Column('desc', sa.Text(), nullable=True),
sa.Column('entry_date', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True),
sa.ForeignKeyConstraint(['etudid'], ['identite.id'], ondelete='CASCADE'),
sa.ForeignKeyConstraint(['moduleimpl_id'], ['notes_moduleimpl.id'], ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_assiduites_etudid'), 'assiduites', ['etudid'], unique=False)
op.drop_constraint('dispenseUE_formsemestre_id_ue_id_etudid_key', 'dispenseUE', type_='unique')
op.drop_index('ix_dispenseUE_formsemestre_id', table_name='dispenseUE')
op.create_unique_constraint(None, 'dispenseUE', ['ue_id', 'etudid'])
op.drop_constraint('dispenseUE_formsemestre_id_fkey', 'dispenseUE', type_='foreignkey')
op.drop_column('dispenseUE', 'formsemestre_id')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('dispenseUE', sa.Column('formsemestre_id', sa.INTEGER(), autoincrement=False, nullable=True))
op.create_foreign_key('dispenseUE_formsemestre_id_fkey', 'dispenseUE', 'notes_formsemestre', ['formsemestre_id'], ['id'])
op.drop_constraint(None, 'dispenseUE', type_='unique')
op.create_index('ix_dispenseUE_formsemestre_id', 'dispenseUE', ['formsemestre_id'], unique=False)
op.create_unique_constraint('dispenseUE_formsemestre_id_ue_id_etudid_key', 'dispenseUE', ['formsemestre_id', 'ue_id', 'etudid'])
op.drop_index(op.f('ix_assiduites_etudid'), table_name='assiduites')
op.drop_table('assiduites')
op.drop_index(op.f('ix_justificatifs_etudid'), table_name='justificatifs')

View File

@ -5,9 +5,10 @@ Ecrit par HARTMANN Matthias
"""
from tests.api.setup_test_api import GET, POST_JSON, api_headers, APIError
from random import randint
from tests.api.setup_test_api import GET, POST_JSON, APIError, api_headers
ETUDID = 1
FAUX = 42069
FORMSEMESTREID = 1
@ -22,6 +23,7 @@ ASSIDUITES_FIELDS = {
"date_fin": str,
"etat": str,
"desc": str,
"entry_date": str,
}
CREATE_FIELD = {"assiduite_id": int}
@ -32,7 +34,9 @@ COUNT_FIELDS = {"compte": int, "journee": int, "demi": int, "heure": float}
TO_REMOVE = []
def check_fields(data, fields=ASSIDUITES_FIELDS):
def check_fields(data, fields: dict = None):
if fields is None:
fields = ASSIDUITES_FIELDS
assert set(data.keys()) == set(fields.keys())
for key in data:
if key in ("moduleimpl_id", "desc"):
@ -43,7 +47,7 @@ def check_fields(data, fields=ASSIDUITES_FIELDS):
def check_failure_get(path, headers, err=None):
try:
data = GET(path=path, headers=headers)
GET(path=path, headers=headers)
# ^ Renvoi un 404
except APIError as api_err:
if err is not None:
@ -297,13 +301,13 @@ def test_route_delete(api_headers):
# Bon fonctionnement
data = TO_REMOVE[0]
res = POST_JSON(f"/assiduite/delete", [data], api_headers)
res = POST_JSON("/assiduite/delete", [data], api_headers)
check_fields(res, BATCH_FIELD)
for dat in res["success"]:
assert res["success"][dat] == {"OK": True}
# Mauvais fonctionnement
res = POST_JSON(f"/assiduite/delete", [data], api_headers)
res = POST_JSON("/assiduite/delete", [data], api_headers)
check_fields(res, BATCH_FIELD)
assert len(res["errors"]) == 1
@ -313,7 +317,7 @@ def test_route_delete(api_headers):
data = TO_REMOVE[1:]
res = POST_JSON(f"/assiduite/delete", data, api_headers)
res = POST_JSON("/assiduite/delete", data, api_headers)
check_fields(res, BATCH_FIELD)
for dat in res["success"]:
assert res["success"][dat] == {"OK": True}
@ -326,7 +330,7 @@ def test_route_delete(api_headers):
FAUX + 2,
]
res = POST_JSON(f"/assiduite/delete", data2, api_headers)
res = POST_JSON("/assiduite/delete", data2, api_headers)
check_fields(res, BATCH_FIELD)
assert len(res["errors"]) == 3

View File

@ -59,6 +59,7 @@ def test_permissions(api_headers):
"role_name": "Ens",
"uid": 1,
"version": "long",
"assiduite_id": 1,
}
for rule in api_rules:
path = rule.build(args)[1]

View File

@ -20,37 +20,39 @@ import app.scodoc.sco_utils as scu
def test_general(test_client):
""" """
"""tests général du modèle assiduite"""
G = sco_fake_gen.ScoFake(verbose=False)
g_fake = sco_fake_gen.ScoFake(verbose=False)
# Création d'une formation (1)
formation_id = G.create_formation()
ue_id = G.create_ue(formation_id=formation_id, acronyme="T1", titre="UE TEST 1")
matiere_id = G.create_matiere(ue_id=ue_id, titre="test matière")
module_id_1 = G.create_module(
formation_id = g_fake.create_formation()
ue_id = g_fake.create_ue(
formation_id=formation_id, acronyme="T1", titre="UE TEST 1"
)
matiere_id = g_fake.create_matiere(ue_id=ue_id, titre="test matière")
module_id_1 = g_fake.create_module(
matiere_id=matiere_id, code="Mo1", coefficient=1.0, titre="test module"
)
module_id_2 = G.create_module(
module_id_2 = g_fake.create_module(
matiere_id=matiere_id, code="Mo2", coefficient=1.0, titre="test module2"
)
# Création semestre (2)
formsemestre_id_1 = G.create_formsemestre(
formsemestre_id_1 = g_fake.create_formsemestre(
formation_id=formation_id,
semestre_id=1,
date_debut="01/09/2022",
date_fin="31/12/2022",
)
formsemestre_id_2 = G.create_formsemestre(
formsemestre_id_2 = g_fake.create_formsemestre(
formation_id=formation_id,
semestre_id=2,
date_debut="01/01/2023",
date_fin="31/07/2023",
)
formsemestre_id_3 = G.create_formsemestre(
formsemestre_id_3 = g_fake.create_formsemestre(
formation_id=formation_id,
semestre_id=3,
date_debut="01/01/2024",
@ -63,20 +65,20 @@ def test_general(test_client):
# Création des modulesimpls (4, 2 par semestre)
moduleimpl_1_1 = G.create_moduleimpl(
moduleimpl_1_1 = g_fake.create_moduleimpl(
module_id=module_id_1,
formsemestre_id=formsemestre_id_1,
)
moduleimpl_1_2 = G.create_moduleimpl(
moduleimpl_1_2 = g_fake.create_moduleimpl(
module_id=module_id_2,
formsemestre_id=formsemestre_id_1,
)
moduleimpl_2_1 = G.create_moduleimpl(
moduleimpl_2_1 = g_fake.create_moduleimpl(
module_id=module_id_1,
formsemestre_id=formsemestre_id_2,
)
moduleimpl_2_2 = G.create_moduleimpl(
moduleimpl_2_2 = g_fake.create_moduleimpl(
module_id=module_id_2,
formsemestre_id=formsemestre_id_2,
)
@ -94,12 +96,14 @@ def test_general(test_client):
# Création des étudiants (3)
etuds_dict = [G.create_etud(code_nip=None, prenom=f"etud{i}") for i in range(3)]
etuds_dict = [
g_fake.create_etud(code_nip=None, prenom=f"etud{i}") for i in range(3)
]
etuds = []
for etud in etuds_dict:
G.inscrit_etudiant(formsemestre_id=formsemestre_id_1, etud=etud)
G.inscrit_etudiant(formsemestre_id=formsemestre_id_2, etud=etud)
g_fake.inscrit_etudiant(formsemestre_id=formsemestre_id_1, etud=etud)
g_fake.inscrit_etudiant(formsemestre_id=formsemestre_id_2, etud=etud)
etuds.append(Identite.query.filter_by(id=etud["id"]).first())
@ -107,7 +111,7 @@ def test_general(test_client):
# Etudiant faux
etud_faux_dict = G.create_etud(code_nip=None, prenom="etudfaux")
etud_faux_dict = g_fake.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)
@ -224,7 +228,7 @@ def ajouter_assiduites(
# Vérification de la création des assiduités
assert [
ass for ass in assiduites if type(ass) != Assiduite
ass for ass in assiduites if not isinstance(ass, Assiduite)
] == [], "La création des assiduités de base n'est pas OK"
# Vérification de la gestion des erreurs
@ -333,13 +337,13 @@ def verifier_comptage_et_filtrage(
FormSemestre.query.filter_by(id=fms["id"]).first() for fms in formsemestres
]
assert (
scass.filter_by_formsemstre(etu1.assiduites, formsemestres[0]).count() == 3
scass.filter_by_formsemestre(etu1.assiduites, formsemestres[0]).count() == 3
), "Filtrage 'Formsemestre' mauvais"
assert (
scass.filter_by_formsemstre(etu1.assiduites, formsemestres[1]).count() == 3
scass.filter_by_formsemestre(etu1.assiduites, formsemestres[1]).count() == 3
), "Filtrage 'Formsemestre' mauvais"
assert (
scass.filter_by_formsemstre(etu1.assiduites, formsemestres[2]).count() == 0
scass.filter_by_formsemestre(etu1.assiduites, formsemestres[2]).count() == 0
), "Filtrage 'Formsemestre' mauvais"
# Date début