From 0037bf9f3a6e4e3a6829d08bb5a19cc121641444 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Thu, 14 Dec 2023 20:50:27 +0100 Subject: [PATCH] =?UTF-8?q?Am=C3=A9liore=20formulaire=20ajout=5Fassiduite?= =?UTF-8?q?=5Fetud?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/forms/assiduite/ajout_assiduite_etud.py | 14 +++- app/models/assiduites.py | 9 ++- app/models/moduleimpls.py | 6 +- .../assiduites/pages/ajout_assiduite_etud.j2 | 6 +- .../pages/ajout_justificatif_etud.j2 | 6 ++ app/views/assiduites.py | 75 ++++++++++--------- sco_version.py | 2 +- 7 files changed, 71 insertions(+), 47 deletions(-) diff --git a/app/forms/assiduite/ajout_assiduite_etud.py b/app/forms/assiduite/ajout_assiduite_etud.py index 2c83f0f5c..26a14ed6b 100644 --- a/app/forms/assiduite/ajout_assiduite_etud.py +++ b/app/forms/assiduite/ajout_assiduite_etud.py @@ -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)], diff --git a/app/models/assiduites.py b/app/models/assiduites.py index 2c116d49a..4cd5318b5 100644 --- a/app/models/assiduites.py +++ b/app/models/assiduites.py @@ -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): diff --git a/app/models/moduleimpls.py b/app/models/moduleimpls.py index 7b9c35968..00966033e 100644 --- a/app/models/moduleimpls.py +++ b/app/models/moduleimpls.py @@ -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 = ( diff --git a/app/templates/assiduites/pages/ajout_assiduite_etud.j2 b/app/templates/assiduites/pages/ajout_assiduite_etud.j2 index 850a0d7ec..711ae5f26 100644 --- a/app/templates/assiduites/pages/ajout_assiduite_etud.j2 +++ b/app/templates/assiduites/pages/ajout_assiduite_etud.j2 @@ -53,11 +53,11 @@ div.submit > input {

Signaler une absence, retard ou présence pour {{etud.html_link_fiche()|safe}}

- {% if form.error_message %} + {% for err_msg in form.error_messages %}
- {{ form.error_message }} + {{ err_msg }}
- {% endif %} + {% endfor %}
{{ form.hidden_tag() }} diff --git a/app/templates/assiduites/pages/ajout_justificatif_etud.j2 b/app/templates/assiduites/pages/ajout_justificatif_etud.j2 index 647f5c178..007ded7ca 100644 --- a/app/templates/assiduites/pages/ajout_justificatif_etud.j2 +++ b/app/templates/assiduites/pages/ajout_justificatif_etud.j2 @@ -28,6 +28,12 @@ div.submit > input {
+ {% for err_msg in form.error_messages %} +
+ {{ err_msg }} +
+ {% endfor %} +
{{ form.hidden_tag() }} diff --git a/app/views/assiduites.py b/app/views/assiduites.py index a62c7c0ea..9b9858f87 100644 --- a/app/views/assiduites.py +++ b/app/views/assiduites.py @@ -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 diff --git a/sco_version.py b/sco_version.py index ce9fa1ee6..5c3eb33ed 100644 --- a/sco_version.py +++ b/sco_version.py @@ -1,7 +1,7 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "9.6.69" +SCOVERSION = "9.6.70" SCONAME = "ScoDoc"