From b2e6ef63b99959dfe873684c9fe3a216f39b0384 Mon Sep 17 00:00:00 2001 From: Iziram Date: Fri, 22 Mar 2024 15:41:39 +0100 Subject: [PATCH] =?UTF-8?q?Assiduit=C3=A9=20:=20traitement=20des=20justifi?= =?UTF-8?q?catifs=20closes=20#818?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/assiduites.py | 18 + app/scodoc/sco_formsemestre_status.py | 16 +- app/static/css/assiduites.css | 8 + app/static/js/assiduites.js | 16 + .../pages/signal_assiduites_diff.j2 | 26 +- .../pages/traitement_justificatifs.j2 | 405 ++++++++++++++++++ app/templates/assiduites/widgets/toast.j2 | 5 +- app/views/assiduites.py | 69 +++ 8 files changed, 534 insertions(+), 29 deletions(-) create mode 100644 app/templates/assiduites/pages/traitement_justificatifs.j2 diff --git a/app/models/assiduites.py b/app/models/assiduites.py index 745dfdbb6..2b8742874 100644 --- a/app/models/assiduites.py +++ b/app/models/assiduites.py @@ -660,6 +660,24 @@ class Justificatif(ScoDocModel): return assiduites_dejustifiees + def get_assiduites(self) -> Query: + """ + get_assiduites Récupère les assiduités qui sont concernées par le justificatif + (Concernée ≠ Justifiée, mais qui sont sur la même période) + Ne prends pas en compte les Présences + Returns: + Query: Les assiduités concernées + """ + + assiduites_query = Assiduite.query.filter( + Assiduite.etudid == self.etudid, + Assiduite.date_debut >= self.date_debut, + Assiduite.date_fin <= self.date_fin, + Assiduite.etat != EtatAssiduite.PRESENT, + ) + + return assiduites_query + def is_period_conflicting( date_debut: datetime, diff --git a/app/scodoc/sco_formsemestre_status.py b/app/scodoc/sco_formsemestre_status.py index f17669e7b..9f1581dc3 100755 --- a/app/scodoc/sco_formsemestre_status.py +++ b/app/scodoc/sco_formsemestre_status.py @@ -25,8 +25,7 @@ # ############################################################################## -"""Tableau de bord semestre -""" +"""Tableau de bord semestre""" import datetime @@ -1128,6 +1127,19 @@ def formsemestre_status(formsemestre_id=None, check_parcours=True): _make_listes_sem(formsemestre), "", ] + + # --- Lien Traitement Justificatifs: + + if current_user.has_permission(Permission.AbsJustifView): + H.append( + f"""

+ + Traitement des justificatifs d'absence +

""" + ) + # --- Lien mail enseignants: adrlist = list(mails_enseignants - {None, ""}) if adrlist: diff --git a/app/static/css/assiduites.css b/app/static/css/assiduites.css index d23a9ef4c..1cb99e386 100644 --- a/app/static/css/assiduites.css +++ b/app/static/css/assiduites.css @@ -756,4 +756,12 @@ tr.row-justificatif.non_valide td.assi-type { var(--color-justi-attente-stripe) 4px, var(--color-justi-attente) 4px, var(--color-justi-attente) 7px) !important; +} + +#gtrcontent .pdp { + display: none; +} + +#gtrcontent[data-pdp="true"] .pdp { + display: block; } \ No newline at end of file diff --git a/app/static/js/assiduites.js b/app/static/js/assiduites.js index 8054f3de3..afcc29854 100644 --- a/app/static/js/assiduites.js +++ b/app/static/js/assiduites.js @@ -908,3 +908,19 @@ function setupAssiduiteBubble(el, assiduite) { el.appendChild(bubble); } + +/** + * Permet d'afficher ou non les photos des étudiants + * @param {boolean} checked + */ +function afficherPDP(checked) { + if (checked) { + gtrcontent.setAttribute("data-pdp", "true"); + } else { + gtrcontent.removeAttribute("data-pdp"); + } + + // On sauvegarde le choix dans le localStorage + localStorage.setItem("scodoc-etud-pdp", `${checked}`); + pdp.checked = checked; +} diff --git a/app/templates/assiduites/pages/signal_assiduites_diff.j2 b/app/templates/assiduites/pages/signal_assiduites_diff.j2 index 120369fee..6847259e6 100644 --- a/app/templates/assiduites/pages/signal_assiduites_diff.j2 +++ b/app/templates/assiduites/pages/signal_assiduites_diff.j2 @@ -49,14 +49,6 @@ width: 10em; } - #gtrcontent .pdp { - display: none; - } - - #gtrcontent[data-pdp="true"] .pdp { - display: block; - } - #tableau-periode { display: flex; flex-direction: column; @@ -142,22 +134,6 @@ + + + + + +{% endblock %} + +{% block app_content %} + +

Traitement des justificatifs {{formsemestre.titre_num()}}

+ +
+ + + +
+ +
+
+
Etudiant
+
Abs
+
Plage
+
Description
+
Fichiers
+
Validation
+
+ + {% for ligne in lignes %} +
+
+ {{ligne.etud.nomprenom}} + {{ ligne.etud.nomprenom }} +
+
+ + NJ : {{ligne.etud.stats[0]}} + + + J : {{ligne.etud.stats[1]}} + +
+
+ {% if ligne.justif.date_debut.date() == ligne.justif.date_fin.date() %} + + {{ligne.justif.date_debut.strftime("%d/%m/%y")}} de {{ligne.justif.date_debut.strftime("%Hh%M")}} à + {{ligne.justif.date_fin.strftime("%Hh%M")}} + + {% else %} + + du {{ligne.justif.date_debut.strftime("%d/%m/%y")}} + + + au {{ligne.justif.date_fin.strftime("%d/%m/%y")}} + + {% endif %} + + {% if ligne.assiduites.__len__() == 0 %} +

Aucune assiduité concernée

+ {% else %} +
+ + Assiduités concernées + +
    + {% for assi in ligne.assiduites %} +
  • + {{scu.EtatAssiduite(assi.etat).version_lisible()}} + {% if assi.date_debut.date() == assi.date_fin.date() %} + du {{assi.date_debut.strftime("%d/%m/%y")}} de {{assi.date_debut.strftime("%Hh%M")}} à + {{assi.date_fin.strftime("%Hh%M")}} + {% else %} + du {{assi.date_debut.strftime("%d/%m/%y %Hh%M")}} au {{assi.date_fin.strftime("%d/%m/%y + %Hh%M")}} + {% endif %} +
  • + {% endfor %} +
+
+ {% endif %} + +
+
+

{{ligne.justif.raison}}

+ {% if ligne.etat == "modifie" %} +

le justificatif a été modifié

+ {% endif %} +
+
+ {% if ligne.fichiers.total == 0 %} +

Aucun fichier joint

+ {% else %} +
+ Fichiers joints +
    + {% for filename in ligne.fichiers.filenames %} +
  • + {{filename}} +
  • + {% endfor %} +
+
+ {% endif %} +
+
+ + + + + +
+ +
+ {% endfor %} +
+ +{% include "assiduites/widgets/toast.j2" %} + +{% endblock %} \ No newline at end of file diff --git a/app/templates/assiduites/widgets/toast.j2 b/app/templates/assiduites/widgets/toast.j2 index f7946f1bf..6081d227f 100644 --- a/app/templates/assiduites/widgets/toast.j2 +++ b/app/templates/assiduites/widgets/toast.j2 @@ -10,17 +10,18 @@ width: 20vw; display: flex; flex-direction: column; - flex-wrap: wrap; + align-items: end; transition: all 0.3s ease-in-out; pointer-events: none; z-index: 999; + overflow: hidden; } .toast { margin: 0.5vh 0; display: flex; - width: 100%; + width: fit-content; height: fit-content; justify-content: flex-start; align-items: center; diff --git a/app/views/assiduites.py b/app/views/assiduites.py index 08a5e2504..527d04043 100644 --- a/app/views/assiduites.py +++ b/app/views/assiduites.py @@ -2036,6 +2036,75 @@ def signale_evaluation_abs(etudid: int = None, evaluation_id: int = None): ) +@bp.route("traitement_justificatifs") +@scodoc +@permission_required(Permission.AbsJustifView) +def traitement_justificatifs(): + """Page de traitement des justificatifs + On traite les justificatifs par formsemestre + On peut Valider, Invalider ou mettre en ATT + """ + # Récupération du formsemestre + formsemestre_id: int = request.args.get("formsemestre_id", -1) + formsemestre: FormSemestre = FormSemestre.get_formsemestre(formsemestre_id) + + lignes: list[dict] = [] + + # Récupération des justificatifs + justificatifs_query: Query = scass.filter_by_formsemestre( + Justificatif.query, Justificatif, formsemestre + ) + justificatifs_query = justificatifs_query.filter( + Justificatif.etat.in_( + [scu.EtatJustificatif.ATTENTE, scu.EtatJustificatif.MODIFIE] + ) + ).order_by(Justificatif.date_debut) + + justif: Justificatif + for justif in justificatifs_query: + etud: Identite = justif.etudiant + assi_stats: tuple[int, int, int] = scass.get_assiduites_count( + etud.id, formsemestre.to_dict() + ) + etud_dict: dict = { + "id": etud.id, + "nom": etud.nom, + "prenom": etud.prenom, + "nomprenom": etud.nomprenom, + "stats": assi_stats, + "sort_key": etud.sort_key, + } + + assiduites_justifiees: list[Assiduite] = justif.get_assiduites().all() + + # fichiers justificatifs archivés: + filenames, nb_files = justif.get_fichiers() + fichiers = { + "total": nb_files, + "filenames": filenames, + } + + lignes.append( + { + "etud": etud_dict, + "justif": justif, + "assiduites": assiduites_justifiees, + "fichiers": fichiers, + "etat": scu.EtatJustificatif(justif.etat).name.lower(), + } + ) + + # Tri en fonction du nom des étudiants + lignes = sorted(lignes, key=lambda x: x["etud"]["sort_key"]) + + return render_template( + "assiduites/pages/traitement_justificatifs.j2", + formsemestre=formsemestre, + sco=ScoData(formsemestre=formsemestre), + lignes=lignes, + ) + + def generate_bul_list(etud: Identite, semestre: FormSemestre) -> str: """Génère la liste des assiduités d'un étudiant pour le bulletin mail"""