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 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_debut = StringField(
"Date de début", "Date de début",
validators=[validators.Length(max=10)], validators=[validators.Length(max=10)],

View File

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

View File

@ -194,9 +194,9 @@ class ModuleImpl(db.Model):
def est_inscrit(self, etud: Identite) -> bool: def est_inscrit(self, etud: Identite) -> bool:
""" """
Vérifie si l'étudiant est bien inscrit au moduleimpl 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 c'est le cas, faux sinon Retourne Vrai si inscrit au module, faux sinon.
""" """
is_module: int = ( is_module: int = (

View File

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

View File

@ -28,6 +28,12 @@ div.submit > input {
<section class="justi-form page"> <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"> <form id="ajout-justificatif-etud" method="post">
<fieldset> <fieldset>
{{ form.hidden_tag() }} {{ form.hidden_tag() }}

View File

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

View File

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