forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -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)],
|
||||||
|
@ -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):
|
||||||
|
@ -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 = (
|
||||||
|
@ -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() }}
|
||||||
|
@ -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() }}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user