Assiduité : edit_assiduite_etud : modification dates/heures assiduités (formulaires)

This commit is contained in:
Iziram 2024-06-04 16:01:05 +02:00
parent 9801cf7936
commit 93bb9d598e
4 changed files with 111 additions and 37 deletions

View File

@ -1,7 +1,14 @@
""" """ """ """
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import SelectField, RadioField, TextAreaField, validators, SubmitField from wtforms import (
StringField,
SelectField,
RadioField,
TextAreaField,
validators,
SubmitField,
)
from app.scodoc.sco_utils import EtatAssiduite from app.scodoc.sco_utils import EtatAssiduite
@ -53,6 +60,63 @@ class EditAssiForm(FlaskForm):
"maxlength": 500, "maxlength": 500,
}, },
) )
date_debut = StringField(
"Date de début",
validators=[validators.Length(max=10)],
render_kw={
"class": "datepicker",
"size": 10,
"id": "assi_date_debut",
},
)
heure_debut = StringField(
"Heure début",
default="",
validators=[validators.Length(max=5)],
render_kw={
"class": "timepicker",
"size": 5,
"id": "assi_heure_debut",
},
)
heure_fin = StringField(
"Heure fin",
default="",
validators=[validators.Length(max=5)],
render_kw={
"class": "timepicker",
"size": 5,
"id": "assi_heure_fin",
},
)
date_fin = StringField(
"Date de fin",
validators=[validators.Length(max=10)],
render_kw={
"class": "datepicker",
"size": 10,
"id": "assi_date_fin",
},
)
entry_date = StringField(
"Date de dépôt ou saisie",
validators=[validators.Length(max=10)],
render_kw={
"class": "datepicker",
"size": 10,
"id": "entry_date",
},
)
entry_time = StringField(
"Heure dépôt",
default="",
validators=[validators.Length(max=5)],
render_kw={
"class": "timepicker",
"size": 5,
"id": "assi_heure_fin",
},
)
submit = SubmitField("Enregistrer") submit = SubmitField("Enregistrer")
cancel = SubmitField("Annuler", render_kw={"formnovalidate": True}) cancel = SubmitField("Annuler", render_kw={"formnovalidate": True})

View File

@ -703,10 +703,14 @@ def is_period_conflicting(
date_fin: datetime, date_fin: datetime,
collection: Query, collection: Query,
collection_cls: Assiduite | Justificatif, collection_cls: Assiduite | Justificatif,
obj_id: int = -1,
) -> bool: ) -> bool:
""" """
Vérifie si une date n'entre pas en collision Vérifie si une date n'entre pas en collision
avec les justificatifs ou assiduites déjà présentes avec les justificatifs ou assiduites déjà présentes
On peut donner un objet_id pour exclure un objet de la vérification
(utile pour les modifications)
""" """
# On s'assure que les dates soient avec TimeZone # On s'assure que les dates soient avec TimeZone
@ -714,7 +718,9 @@ def is_period_conflicting(
date_fin = localize_datetime(date_fin) date_fin = localize_datetime(date_fin)
count: int = collection.filter( count: int = collection.filter(
collection_cls.date_debut < date_fin, collection_cls.date_fin > date_debut collection_cls.date_debut < date_fin,
collection_cls.date_fin > date_debut,
collection_cls.id != obj_id,
).count() ).count()
return count > 0 return count > 0

View File

@ -119,6 +119,21 @@
{{ form.assi_etat.label }} {{ form.assi_etat.label }}
{{ form.assi_etat() }} {{ form.assi_etat() }}
</div> </div>
<div class="dates-heures">
{{ form.date_debut.label }}&nbsp;: {{ form.date_debut }}
à {{ form.heure_debut }}
{{ render_field_errors(form, 'date_debut') }}
{{ render_field_errors(form, 'heure_debut') }}
<br>
{{ form.date_fin.label }}&nbsp;: {{ form.date_fin }}
à {{ form.heure_fin }}
{{ render_field_errors(form, 'date_fin') }}
{{ render_field_errors(form, 'heure_fin') }}
<br>
{{ form.entry_date.label }}&nbsp;: {{ form.entry_date }} à {{ form.entry_time }}
</div>
<br>
{# Menu module #} {# Menu module #}
<div class="select-module"> <div class="select-module">
{{ form.modimpl.label }}&nbsp;: {{ form.modimpl.label }}&nbsp;:

View File

@ -66,7 +66,7 @@ from app.models import (
from app.scodoc.codes_cursus import UE_STANDARD from app.scodoc.codes_cursus import UE_STANDARD
from app.auth.models import User from app.auth.models import User
from app.models.assiduites import get_assiduites_justif from app.models.assiduites import get_assiduites_justif, is_period_conflicting
from app.tables.list_etuds import RowEtud, TableEtud from app.tables.list_etuds import RowEtud, TableEtud
import app.tables.liste_assiduites as liste_assi import app.tables.liste_assiduites as liste_assi
@ -741,32 +741,6 @@ def ajout_justificatif_etud():
) )
def _verif_date_form_justif(
form: AjoutJustificatifEtudForm, deb: datetime.datetime, fin: datetime.datetime
) -> tuple[datetime.datetime, datetime.datetime]:
"""Gère les cas suivants :
- si on indique seulement une date de debut : journée 0h-23h59
- si on indique date de debut et heures : journée +heure deb/fin
(déjà géré par _get_dates_from_assi_form)
- Si on indique une date de début et de fin sans heures : Journées 0h-23h59
- Si on indique une date de début et de fin avec heures : On fait un objet avec
datedeb/heuredeb + datefin/heurefin (déjà géré par _get_dates_from_assi_form)
"""
cas: list[bool] = [
# cas 1
not form.date_fin.data and not form.heure_debut.data,
# cas 3
form.date_fin.data != "" and not form.heure_debut.data,
]
if any(cas):
deb = deb.replace(hour=0, minute=0)
fin = fin.replace(hour=23, minute=59)
return deb, fin
def _record_justificatif_etud( def _record_justificatif_etud(
etud: Identite, form: AjoutJustificatifEtudForm, justif: Justificatif | None = None etud: Identite, form: AjoutJustificatifEtudForm, justif: Justificatif | None = None
) -> bool: ) -> bool:
@ -2222,13 +2196,17 @@ def edit_assiduite_etud(assiduite_id: int):
description = form.description.data or "" description = form.description.data or ""
description = description.strip() description = description.strip()
moduleimpl_id = form.modimpl.data or -1 moduleimpl_id = form.modimpl.data if form.modimpl.data is not None else -1
if isinstance(moduleimpl_id, int): # Vérifications des dates / horaires
try:
ModuleImpl.get_moduleimpl(moduleimpl_id) ok, dt_deb, dt_fin, dt_entry = _get_dates_from_assi_form(
except ValueError: form, etud, from_justif=True, formsemestre=formsemestre
form.error_messages.append("Module invalide") )
moduleimpl_id = -1 if ok:
if is_period_conflicting(
dt_deb, dt_fin, etud.assiduites, Assiduite, assi.id
):
form.set_error("La période est en conflit avec une autre assiduité")
form.ok = False form.ok = False
if form.ok: if form.ok:
@ -2237,6 +2215,10 @@ def edit_assiduite_etud(assiduite_id: int):
if moduleimpl_id != -1: if moduleimpl_id != -1:
assi.set_moduleimpl(moduleimpl_id) assi.set_moduleimpl(moduleimpl_id)
assi.date_debut = dt_deb
assi.date_fin = dt_fin
assi.entry_date = dt_entry
db.session.add(assi) db.session.add(assi)
db.session.commit() db.session.commit()
@ -2251,12 +2233,19 @@ def edit_assiduite_etud(assiduite_id: int):
moduleimpl_id: int | str | None = assi.get_moduleimpl_id() or "" moduleimpl_id: int | str | None = assi.get_moduleimpl_id() or ""
form.modimpl.data = str(moduleimpl_id) form.modimpl.data = str(moduleimpl_id)
form.date_debut.data = assi.date_debut.strftime(scu.DATE_FMT)
form.heure_debut.data = assi.date_debut.strftime(scu.TIME_FMT)
form.date_fin.data = assi.date_fin.strftime(scu.DATE_FMT)
form.heure_fin.data = assi.date_fin.strftime(scu.TIME_FMT)
form.entry_date.data = assi.entry_date.strftime(scu.DATE_FMT)
form.entry_time.data = assi.entry_date.strftime(scu.TIME_FMT)
return render_template( return render_template(
"assiduites/pages/edit_assiduite_etud.j2", "assiduites/pages/edit_assiduite_etud.j2",
etud=etud, etud=etud,
sco=ScoData(etud, formsemestre=formsemestre), sco=ScoData(etud, formsemestre=formsemestre),
form=form, form=form,
readonly=readonly, readonly=True,
objet=_preparer_objet("assiduite", assi), objet=_preparer_objet("assiduite", assi),
title=f"Assiduité {etud.nom_short}", title=f"Assiduité {etud.nom_short}",
) )