Améliore formulaire ajout_assiduite_etud

This commit is contained in:
Emmanuel Viennet 2023-12-14 20:50:27 +01:00
parent ae2ee2deff
commit 0037bf9f3a
7 changed files with 71 additions and 47 deletions

View File

@ -47,7 +47,19 @@ class AjoutAssiOrJustForm(FlaskForm):
assiduité et justificatif
"""
error_message = "" # used to report our errors
def __init__(self, *args, **kwargs):
"Init form, adding a filed for our error messages"
super().__init__(*args, **kwargs)
self.ok = True
self.error_messages: list[str] = [] # used to report our errors
def set_error(self, err_msg, field=None):
"Set error message both in form and field"
self.ok = False
self.error_messages.append(err_msg)
if field:
field.errors.append(err_msg)
date_debut = StringField(
"Date de début",
validators=[validators.Length(max=10)],

View File

@ -148,6 +148,9 @@ class Assiduite(db.Model):
# Vérification de non duplication des périodes
assiduites: Query = etud.assiduites
if is_period_conflicting(date_debut, date_fin, assiduites, Assiduite):
log(
f"create_assiduite: period_conflicting etudid={etud.id} date_debut={date_debut} date_fin={date_fin}"
)
raise ScoValueError(
"Duplication: la période rentre en conflit avec une plage enregistrée"
)
@ -215,10 +218,10 @@ class Assiduite(db.Model):
# ci-dessous un fix temporaire en attendant explication de @iziram
try:
moduleimpl_id_int = int(moduleimpl_id)
except ValueError:
raise ScoValueError("invalid moduleimpl_id")
except ValueError as exc:
raise ScoValueError("invalid moduleimpl_id") from exc
# /fix
moduleimpl: ModuleImpl = ModuleImpl.query.get(moduleimpl_id)
moduleimpl: ModuleImpl = ModuleImpl.query.get(moduleimpl_id_int)
if moduleimpl is not None:
# Vérification de l'inscription de l'étudiant
if moduleimpl.est_inscrit(self.etudiant):

View File

@ -194,9 +194,9 @@ class ModuleImpl(db.Model):
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
Vérifie si l'étudiant est bien inscrit au moduleimpl (même si DEM ou DEF au semestre).
(lent, pas de cache: pour un accès rapide, utiliser nt.modimpl_inscr_df).
Retourne Vrai si inscrit au module, faux sinon.
"""
is_module: int = (

View File

@ -53,11 +53,11 @@ div.submit > input {
<div class="tab-content">
<h2>Signaler une absence, retard ou présence pour {{etud.html_link_fiche()|safe}}</h2>
{% if form.error_message %}
{% for err_msg in form.error_messages %}
<div class="wtf-error-messages">
{{ form.error_message }}
{{ err_msg }}
</div>
{% endif %}
{% endfor %}
<form id="ajout-assiduite-etud" method="post">
{{ form.hidden_tag() }}

View File

@ -28,6 +28,12 @@ div.submit > input {
<section class="justi-form page">
{% for err_msg in form.error_messages %}
<div class="wtf-error-messages">
{{ err_msg }}
</div>
{% endfor %}
<form id="ajout-justificatif-etud" method="post">
<fieldset>
{{ form.hidden_tag() }}

View File

@ -257,7 +257,7 @@ def bilan_dept():
@bp.route("/ajout_assiduite_etud", methods=["GET", "POST"])
@scodoc
@permission_required(Permission.AbsChange)
def ajout_assiduite_etud() -> str:
def ajout_assiduite_etud() -> str | Response:
"""
ajout_assiduite_etud Saisie d'une assiduité d'un étudiant
@ -270,13 +270,13 @@ def ajout_assiduite_etud() -> str:
Returns:
str: l'html généré
"""
etudid = request.args.get("etudid", -1)
etudid: int = request.args.get("etudid", -1)
etud = Identite.get_etud(etudid)
# Gestion évaluations (appel à la page depuis les évaluations)
evaluation_id: int = request.args.get("evaluation_id")
evaluation_id: int | None = request.args.get("evaluation_id")
saisie_eval = evaluation_id is not None
moduleimpl_id: int = request.args.get("moduleimpl_id", "")
moduleimpl_id: int | None = request.args.get("moduleimpl_id", "")
redirect_url: str = (
"#"
@ -340,13 +340,14 @@ def ajout_assiduite_etud() -> str:
def _get_dates_from_assi_form(
form: AjoutAssiOrJustForm,
) -> tuple[bool, datetime.datetime, datetime.datetime, datetime.datetime]:
) -> tuple[
bool, datetime.datetime | None, datetime.datetime | None, datetime.datetime | None
]:
"""Prend les dates et heures du form, les vérifie
puis converti en deux datetime, en timezone du serveur.
Ramène ok=True si ok.
Met des messages d'erreur dans le form.
"""
ok = True
debut_jour = "00:00"
fin_jour = "23:59:59"
date_fin = None
@ -355,8 +356,7 @@ def _get_dates_from_assi_form(
date_debut = datetime.datetime.strptime(form.date_debut.data, "%d/%m/%Y")
except ValueError:
date_debut = None
form.date_debut.errors.append("date début invalide")
ok = False
form.set_error("date début invalide", form.date_debut)
try:
date_fin = (
datetime.datetime.strptime(form.date_fin.data, "%d/%m/%Y")
@ -365,8 +365,7 @@ def _get_dates_from_assi_form(
)
except ValueError:
date_fin = None
form.date_fin.errors.append("date fin invalide")
ok = False
form.set_error("date fin invalide", form.date_fin)
if date_fin:
# ignore les heures si plusieurs jours
@ -378,38 +377,42 @@ def _get_dates_from_assi_form(
form.heure_debut.data or debut_jour
)
except ValueError:
form.heure_debut.errors.append("heure début invalide")
ok = False
form.set_error("heure début invalide", form.heure_debut)
if bool(form.heure_debut.data) != bool(form.heure_fin.data):
form.set_error(
"Les deux heures début et fin doivent être spécifiées, ou aucune"
)
try:
heure_fin = datetime.time.fromisoformat(form.heure_fin.data or fin_jour)
except ValueError:
form.heure_fin.errors.append("heure fin invalide")
ok = False
form.set_error("heure fin invalide", form.heure_fin)
if not form.ok:
return False, None, None, None
# Vérifie cohérence des dates/heures
dt_debut = (
datetime.datetime.combine(date_debut, heure_debut) if date_debut else None
)
dt_fin = (
datetime.datetime.combine(date_fin or date_debut, heure_fin)
if (date_fin or date_debut)
else None
)
if ok and dt_fin <= dt_debut:
form.errors["general_errors"] = ["Erreur: dates début/fin incohérentes"]
ok = False
dt_debut = datetime.datetime.combine(date_debut, heure_debut)
dt_fin = datetime.datetime.combine(date_fin or date_debut, heure_fin)
if dt_fin <= dt_debut:
form.set_error("dates début/fin incohérentes")
# La date de dépot (si vide, la date actuelle)
dt_entry_date = (
datetime.datetime.strptime(form.entry_date.data, "%d/%m/%Y")
if form.entry_date.data
else None
)
try:
dt_entry_date = (
datetime.datetime.strptime(form.entry_date.data, "%d/%m/%Y")
if form.entry_date.data
else None
)
except ValueError:
dt_entry_date = None
form.set_error("format de date de dépôt invalide", form.entry_date)
# Ajoute time zone serveur
dt_debut_tz_server = scu.TIME_ZONE.localize(dt_debut) if dt_debut else None
dt_fin_tz_server = scu.TIME_ZONE.localize(dt_fin) if dt_fin else None
dt_debut_tz_server = scu.TIME_ZONE.localize(dt_debut)
dt_fin_tz_server = scu.TIME_ZONE.localize(dt_fin)
dt_entry_date_tz_server = (
scu.TIME_ZONE.localize(dt_entry_date) if dt_entry_date else None
)
return ok, dt_debut_tz_server, dt_fin_tz_server, dt_entry_date_tz_server
return form.ok, dt_debut_tz_server, dt_fin_tz_server, dt_entry_date_tz_server
def _record_assiduite_etud(
@ -472,7 +475,7 @@ def _record_assiduite_etud(
db.session.commit()
return True
except ScoValueError as exc:
form.error_message = f"Erreur: {exc.args[0]}"
form.set_error(f"Erreur: {exc.args[0]}")
return False
@ -693,7 +696,7 @@ def _record_justificatif_etud(
return True
except ScoValueError as exc:
db.session.rollback()
form.error_message = f"Erreur: {exc.args[0]}"
form.set_error(f"Erreur: {exc.args[0]}")
return False
@ -725,7 +728,7 @@ def _upload_justificatif_files(
log(
f"_upload_justificatif_files: error on {file.filename} for etud {just.etudid}"
)
form.error_message = f"Erreur sur fichier justificatif: {exc.args[0]}"
form.set_error(f"Erreur sur fichier justificatif: {exc.args[0]}")
return False

View File

@ -1,7 +1,7 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
SCOVERSION = "9.6.69"
SCOVERSION = "9.6.70"
SCONAME = "ScoDoc"