diff --git a/app/scodoc/sco_assiduites.py b/app/scodoc/sco_assiduites.py
index 1bedcdb5..97f7f2de 100644
--- a/app/scodoc/sco_assiduites.py
+++ b/app/scodoc/sco_assiduites.py
@@ -427,7 +427,7 @@ def create_absence(
db.session.commit()
if est_just:
justi = Justificatif.create_justificatif(
- etud=etud,
+ etudiant=etud,
date_debut=date_debut,
date_fin=date_fin,
etat=scu.EtatJustificatif.VALIDE,
diff --git a/app/tables/liste_assiduites.py b/app/tables/liste_assiduites.py
index e39e9813..b9d031b1 100644
--- a/app/tables/liste_assiduites.py
+++ b/app/tables/liste_assiduites.py
@@ -277,8 +277,10 @@ class RowAssiJusti(tb.Row):
self.add_cell(
"entry_date",
"Saisie le",
- self.ligne["entry_date"].strftime("%d/%m/%y à %H:%M"),
- data={"order": self.ligne["entry_date"]},
+ self.ligne["entry_date"].strftime("%d/%m/%y à %H:%M")
+ if self.ligne["entry_date"]
+ else "?",
+ data={"order": self.ligne["entry_date"] or ""},
raw_content=self.ligne["entry_date"],
classes=["small-font"],
column_classes={"entry_date"},
@@ -387,13 +389,20 @@ class RowAssiJusti(tb.Row):
html.append(f'ℹ️')
# Modifier
- url = url_for(
- "assiduites.tableau_assiduite_actions",
- type=self.ligne["type"],
- action="modifier",
- obj_id=self.ligne["obj_id"],
- scodoc_dept=g.scodoc_dept,
- )
+ if self.ligne["type"] == "justificatif":
+ url = url_for(
+ "assiduites.edit_justificatif_etud",
+ justif_id=self.ligne["obj_id"],
+ scodoc_dept=g.scodoc_dept,
+ )
+ else:
+ url = url_for(
+ "assiduites.tableau_assiduite_actions",
+ type=self.ligne["type"],
+ action="modifier",
+ obj_id=self.ligne["obj_id"],
+ scodoc_dept=g.scodoc_dept,
+ )
html.append(f'📝')
# Supprimer
diff --git a/app/templates/assiduites/pages/ajout_assiduite_etud.j2 b/app/templates/assiduites/pages/ajout_assiduite_etud.j2
index 711ae5f2..5d5e5d5d 100644
--- a/app/templates/assiduites/pages/ajout_assiduite_etud.j2
+++ b/app/templates/assiduites/pages/ajout_assiduite_etud.j2
@@ -90,9 +90,9 @@ div.submit > input {
{# Raison #}
-
{{ form.assi_raison.label }}
- {{ form.assi_raison() }}
- {{ render_field_errors(form, 'assi_raison') }}
+
{{ form.raison.label }}
+ {{ form.raison() }}
+ {{ render_field_errors(form, 'raison') }}
{# Date dépot #}
{{ form.entry_date.label }} : {{ form.entry_date }}
diff --git a/app/templates/assiduites/pages/ajout_assiduites.j2 b/app/templates/assiduites/pages/ajout_assiduites.j2
index ca65d032..9326d930 100644
--- a/app/templates/assiduites/pages/ajout_assiduites.j2
+++ b/app/templates/assiduites/pages/ajout_assiduites.j2
@@ -52,8 +52,8 @@
@@ -135,7 +135,7 @@
const { deb, fin } = getDates()
const etat = field.querySelector('#assi_etat').value;
- const raison = field.querySelector('#assi_raison').value;
+ const raison = field.querySelector('#raison').value;
const module = field.querySelector("#ajout_assiduite_module_impl").value;
return {
@@ -168,7 +168,7 @@
field.querySelector('#assi_date_debut').value = "";
field.querySelector('#assi_date_fin').value = "";
field.querySelector('#assi_etat').value = "attente";
- field.querySelector('#assi_raison').value = "";
+ field.querySelector('#raison').value = "";
}
diff --git a/app/templates/assiduites/pages/ajout_justificatif_etud.j2 b/app/templates/assiduites/pages/ajout_justificatif_etud.j2
index 4d28e628..bd4abe92 100644
--- a/app/templates/assiduites/pages/ajout_justificatif_etud.j2
+++ b/app/templates/assiduites/pages/ajout_justificatif_etud.j2
@@ -1,3 +1,5 @@
+{# Formulaire ajout ou modification de justificatif
+Si justif, edit #}
{% extends "sco_page.j2" %}
{% import 'wtf.j2' as wtf %}
@@ -61,11 +63,27 @@ div.submit > input {
{# Raison #}
-
{{ form.assi_raison.label }}
- {{ form.assi_raison() }}
- {{ render_field_errors(form, 'assi_raison') }}
+
{{ form.raison.label }}
+ {{ form.raison() }}
+ {{ render_field_errors(form, 'raison') }}
- {# Fichier(s) justificatif(s) #}
+ {# Liste des fichiers existants #}
+ {% if justif and nb_files > 0 %}
+
+
{{nb_files}} fichiers justificatifs déposés
+ {% if filenames|length < nb_files %}
+ , dont {{filenames|length}} vous sont accessibles
+ {% endif %}
+
+ {% for filename in filenames %}
+ - {{scu.icontag("delete_img", alt="supprimer", title="Supprimer")|safe}}
+ {{filename}}
+ {% endfor %}
+
+
+ {% endif %}
+ {# Ajout fichier(s) justificatif(s) #}
{{ form.fichiers.label }}
{{ form.fichiers() }}
@@ -83,10 +101,11 @@ div.submit > input {
+ {% if tableau %}
-
+ {% endif %}
{% endblock app_content %}
@@ -108,4 +127,54 @@ $('.timepicker').timepicker({
scrollbar: false
});
+
{% endblock scripts %}
diff --git a/app/views/assiduites.py b/app/views/assiduites.py
index ee32f327..b7bc1ad9 100644
--- a/app/views/assiduites.py
+++ b/app/views/assiduites.py
@@ -400,7 +400,7 @@ def _get_dates_from_assi_form(
dt_entry_date = (
datetime.datetime.strptime(form.entry_date.data, "%d/%m/%Y")
if form.entry_date.data
- else None
+ else datetime.datetime.now() # local tz
)
except ValueError:
dt_entry_date = None
@@ -464,7 +464,7 @@ def _record_assiduite_etud(
dt_debut_tz_server,
dt_fin_tz_server,
scu.EtatAssiduite.get(form.assi_etat.data),
- description=form.assi_raison.data,
+ description=form.raison.data,
entry_date=dt_entry_date_tz_server,
external_data=external_data,
moduleimpl=moduleimpl,
@@ -596,6 +596,64 @@ def bilan_etud():
).build()
+@bp.route("/edit_justificatif_etud/
", methods=["GET", "POST"])
+@scodoc
+@permission_required(Permission.AbsChange)
+def edit_justificatif_etud(justif_id: int):
+ """
+ Edition d'un justificatif
+ Args:
+ justif_id (int): l'identifiant du justificatif
+
+ Returns:
+ str: l'html généré
+ """
+ justif = Justificatif.get_justificatif(justif_id)
+ form = AjoutJustificatifEtudForm(obj=justif)
+ # Set the default value for the etat field
+ if request.method == "GET":
+ form.date_debut.data = justif.date_debut.strftime("%d/%m/%Y")
+ form.date_fin.data = justif.date_fin.strftime("%d/%m/%Y")
+ if form.date_fin.data == form.date_debut.data:
+ # un seul jour: pas de date de fin, indique les heures
+ form.date_fin.data = ""
+ form.heure_debut.data = justif.date_debut.strftime("%H:%M")
+ form.heure_fin.data = justif.date_fin.strftime("%H:%M")
+ form.entry_date.data = (
+ justif.entry_date.strftime("%d/%m/%Y") if justif.entry_date else ""
+ )
+ form.etat.data = str(justif.etat)
+
+ redirect_url = url_for(
+ "assiduites.liste_assiduites_etud",
+ scodoc_dept=g.scodoc_dept,
+ etudid=justif.etudiant.id,
+ )
+ if form.validate_on_submit():
+ if _record_justificatif_etud(justif.etudiant, form, justif):
+ return redirect(redirect_url)
+
+ # Fichiers
+ filenames, nb_files = justif.get_fichiers()
+
+ return render_template(
+ "assiduites/pages/ajout_justificatif_etud.j2",
+ assi_limit_annee=sco_preferences.get_preference(
+ "assi_limit_annee",
+ dept_id=g.scodoc_dept_id,
+ ),
+ etud=justif.etudiant,
+ filenames=filenames,
+ form=form,
+ justif=justif,
+ nb_files=nb_files,
+ page_title="Modification justificatif",
+ redirect_url=redirect_url,
+ sco=ScoData(justif.etudiant),
+ scu=scu,
+ )
+
+
@bp.route(
"/ajout_justificatif_etud", methods=["GET", "POST"]
) # was AjoutJustificatifEtud
@@ -603,7 +661,7 @@ def bilan_etud():
@permission_required(Permission.AbsChange)
def ajout_justificatif_etud():
"""
- ajout_justificatif_etud : Affichage et création/modification des justificatifs de l'étudiant
+ ajout_justificatif_etud : Affichage et création des justificatifs de l'étudiant
Args:
etudid (int): l'identifiant de l'étudiant
@@ -654,8 +712,7 @@ def ajout_justificatif_etud():
def _record_justificatif_etud(
- etud: Identite,
- form: AjoutJustificatifEtudForm,
+ etud: Identite, form: AjoutJustificatifEtudForm, justif: Justificatif | None = None
) -> bool:
"""Enregistre les données du formulaire de saisie justificatif (et ses fichiers).
Returns ok if successfully recorded, else put error info in the form.
@@ -663,6 +720,7 @@ def _record_justificatif_etud(
form.assi_etat.data : 'absent'
form.date_debut.data : '05/12/2023'
form.heure_debut.data : '09:06' (heure locale du serveur)
+ Si justif, modifie le justif existant, sinon en crée un nouveau
"""
(
ok,
@@ -672,30 +730,53 @@ def _record_justificatif_etud(
) = _get_dates_from_assi_form(form)
if not ok:
+ log("_record_justificatif_etud: dates invalides")
+ form.set_error("Erreur: dates invalides")
return False
- etat = scu.EtatJustificatif.get(form.etat.data)
+ if not form.etat.data:
+ log("_record_justificatif_etud: etat invalide")
+ form.set_error("Erreur: état invalide")
+ return False
+ etat = int(form.etat.data)
+ if not scu.EtatJustificatif.is_valid_etat(etat):
+ log(f"_record_justificatif_etud: etat invalide ({etat})")
+ form.set_error("Erreur: état invalide")
+ return False
+
try:
- just = Justificatif.create_justificatif(
- etud,
- dt_debut_tz_server,
- dt_fin_tz_server,
- etat=etat,
- raison=form.assi_raison.data,
- entry_date=dt_entry_date_tz_server,
- user_id=current_user.id,
- )
- db.session.add(just)
- if not _upload_justificatif_files(just, form):
+ message = ""
+ if justif:
+ form.date_debut.data = dt_debut_tz_server
+ form.date_fin.data = dt_fin_tz_server
+ form.entry_date.data = dt_entry_date_tz_server
+ if justif.edit_from_form(form):
+ message = "Justificatif modifié"
+ else:
+ message = "Pas de modification"
+ else:
+ justif = Justificatif.create_justificatif(
+ etud,
+ dt_debut_tz_server,
+ dt_fin_tz_server,
+ etat=etat,
+ raison=form.raison.data,
+ entry_date=dt_entry_date_tz_server,
+ user_id=current_user.id,
+ )
+ message = "Justificatif créé"
+ db.session.add(justif)
+ if not _upload_justificatif_files(justif, form):
flash("Erreur enregistrement fichiers")
log("problem in _upload_justificatif_files, rolling back")
db.session.rollback()
return False
db.session.commit()
- compute_assiduites_justified(etud.id, [just])
- scass.simple_invalidate_cache(just.to_dict(), etud.id)
- flash("Justificatif enregistré")
+ compute_assiduites_justified(etud.id, [justif])
+ scass.simple_invalidate_cache(justif.to_dict(), etud.id)
+ flash(message)
return True
except ScoValueError as exc:
+ log(f"_record_justificatif_etud: erreur {exc.args[0]}")
db.session.rollback()
form.set_error(f"Erreur: {exc.args[0]}")
return False
@@ -1474,10 +1555,10 @@ def _action_modifier_assiduite(assi: Assiduite):
def _action_modifier_justificatif(justi: Justificatif):
+ "Modifie le justificatif avec les valeurs dans le form"
form = request.form
# Gestion des Dates
-
date_debut: datetime = scu.is_iso_formated(form["date_debut"], True)
date_fin: datetime = scu.is_iso_formated(form["date_fin"], True)
if date_debut is None or date_fin is None or date_fin < date_debut:
@@ -1556,40 +1637,30 @@ def _preparer_objet(
_preparer_objet("justificatif", justi, sans_gros_objet=True)
)
- else:
+ else: # objet == "justificatif"
+ justif: Justificatif = objet
objet_prepare["etat"] = (
- scu.EtatJustificatif(objet.etat).version_lisible().capitalize()
+ scu.EtatJustificatif(justif.etat).version_lisible().capitalize()
)
- objet_prepare["real_etat"] = scu.EtatJustificatif(objet.etat).name.lower()
- objet_prepare["raison"] = "" if objet.raison is None else objet.raison
+ objet_prepare["real_etat"] = scu.EtatJustificatif(justif.etat).name.lower()
+ objet_prepare["raison"] = "" if justif.raison is None else justif.raison
objet_prepare["raison"] = objet_prepare["raison"].strip()
objet_prepare["justification"] = {"assiduites": [], "fichiers": {}}
if not sans_gros_objet:
- assiduites: list[int] = scass.justifies(objet)
+ assiduites: list[int] = scass.justifies(justif)
for assi_id in assiduites:
assi: Assiduite = Assiduite.query.get(assi_id)
objet_prepare["justification"]["assiduites"].append(
_preparer_objet("assiduite", assi, sans_gros_objet=True)
)
- # Récupération de l'archive avec l'archiver
- archive_name: str = objet.fichier
- filenames: list[str] = []
- archiver: JustificatifArchiver = JustificatifArchiver()
- if archive_name is not None:
- filenames = archiver.list_justificatifs(archive_name, objet.etudiant)
+ # fichiers justificatifs archivés:
+ filenames, nb_files = justif.get_fichiers()
objet_prepare["justification"]["fichiers"] = {
- "total": len(filenames),
- "filenames": [],
+ "total": nb_files,
+ "filenames": filenames,
}
- for filename in filenames:
- if int(filename[1]) == current_user.id or current_user.has_permission(
- Permission.AbsJustifView
- ):
- objet_prepare["justification"]["fichiers"]["filenames"].append(
- filename[0]
- )
objet_prepare["date_fin"] = objet.date_fin.strftime("%d/%m/%y à %H:%M")
objet_prepare["real_date_fin"] = objet.date_fin.isoformat()
@@ -1600,7 +1671,7 @@ def _preparer_objet(
objet_prepare["etud_nom"] = objet.etudiant.nomprenom
- if objet.user_id != None:
+ if objet.user_id is not None:
user: User = User.query.get(objet.user_id)
objet_prepare["saisie_par"] = user.get_nomprenom()
else: