forked from ScoDoc/ScoDoc
Assiduité : edit_assiduite_etud : modification dates/heures assiduités (formulaires)
This commit is contained in:
parent
9801cf7936
commit
93bb9d598e
@ -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})
|
||||||
|
@ -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
|
||||||
|
@ -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 }} : {{ form.date_debut }}
|
||||||
|
à {{ form.heure_debut }}
|
||||||
|
{{ render_field_errors(form, 'date_debut') }}
|
||||||
|
{{ render_field_errors(form, 'heure_debut') }}
|
||||||
|
<br>
|
||||||
|
{{ form.date_fin.label }} : {{ form.date_fin }}
|
||||||
|
à {{ form.heure_fin }}
|
||||||
|
{{ render_field_errors(form, 'date_fin') }}
|
||||||
|
{{ render_field_errors(form, 'heure_fin') }}
|
||||||
|
<br>
|
||||||
|
{{ form.entry_date.label }} : {{ form.entry_date }} à {{ form.entry_time }}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
{# Menu module #}
|
{# Menu module #}
|
||||||
<div class="select-module">
|
<div class="select-module">
|
||||||
{{ form.modimpl.label }} :
|
{{ form.modimpl.label }} :
|
||||||
|
@ -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}",
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user