From e7081bb3670e72d0b1c845085a040a3a4f0cf723 Mon Sep 17 00:00:00 2001
From: Emmanuel Viennet <emmanuel.viennet@gmail.com>
Date: Thu, 7 Dec 2023 12:38:47 +0100
Subject: [PATCH] Assiduite: fixes

---
 app/models/assiduites.py | 33 ++++++++++++++++++++++++---------
 app/views/assiduites.py  | 15 ++++++---------
 2 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/app/models/assiduites.py b/app/models/assiduites.py
index 715abf311..3f683cf7e 100644
--- a/app/models/assiduites.py
+++ b/app/models/assiduites.py
@@ -10,6 +10,7 @@ from app.models import ModuleImpl, Module, Scolog, FormSemestre, FormSemestreIns
 from app.models.etudiants import Identite
 from app.auth.models import User
 from app.scodoc import sco_abs_notification
+from app.scodoc.sco_archives_justificatifs import JustificatifArchiver
 from app.scodoc.sco_exceptions import ScoValueError
 from app.scodoc.sco_utils import (
     EtatAssiduite,
@@ -209,6 +210,7 @@ class Assiduite(db.Model):
         return nouv_assiduite
 
     def set_moduleimpl(self, moduleimpl_id: int | str) -> bool:
+        """TODO"""
         moduleimpl: ModuleImpl = ModuleImpl.query.get(moduleimpl_id)
         if moduleimpl is not None:
             # Vérification de l'inscription de l'étudiant
@@ -236,13 +238,14 @@ class Assiduite(db.Model):
             if formsemestre:
                 force = is_assiduites_module_forced(formsemestre_id=formsemestre.id)
             else:
-                force = is_assiduites_module_forced(dept_id=etud.dept_id)
+                force = is_assiduites_module_forced(dept_id=self.etudiant.dept_id)
 
             if force:
                 raise ScoValueError("Module non renseigné")
         return True
 
-    def supprimer(self):
+    def supprime(self):
+        "Supprime l'assiduité. Log et commit."
         from app.scodoc import sco_assiduites as scass
 
         if g.scodoc_dept is None and self.etudiant.dept_id is not None:
@@ -262,9 +265,14 @@ class Assiduite(db.Model):
         scass.simple_invalidate_cache(obj_dict)
 
     def get_formsemestre(self) -> FormSemestre:
+        """Le formsemestre associé.
+        Attention: en cas d'inscription multiple prend arbitrairement l'un des semestres.
+        A utiliser avec précaution !
+        """
         return get_formsemestre_from_data(self.to_dict())
 
     def get_module(self, traduire: bool = False) -> int | str:
+        "TODO"
         if self.moduleimpl_id is not None:
             if traduire:
                 modimpl: ModuleImpl = ModuleImpl.query.get(self.moduleimpl_id)
@@ -412,7 +420,8 @@ class Justificatif(db.Model):
         )
         return nouv_justificatif
 
-    def supprimer(self):
+    def supprime(self):
+        "Supprime le justificatif. Log et commit."
         from app.scodoc import sco_assiduites as scass
 
         # Récupération de l'archive du justificatif
@@ -433,7 +442,7 @@ class Justificatif(db.Model):
         # Suppression de l'objet et LOG
         log(f"delete_justificatif: {self.etudiant.id} {self}")
         Scolog.logdb(
-            method=f"delete_justificatif",
+            method="delete_justificatif",
             etudid=self.etudiant.id,
             msg=f"Justificatif: {self}",
         )
@@ -541,7 +550,8 @@ def get_assiduites_justif(assiduite_id: int, long: bool) -> list[int | dict]:
             des identifiants des justificatifs
 
     Returns:
-        list[int | dict]: La liste des justificatifs (par défaut uniquement les identifiants, sinon les Dict si long est vrai)
+        list[int | dict]: La liste des justificatifs (par défaut uniquement
+            les identifiants, sinon les dict si long est vrai)
     """
     assi: Assiduite = Assiduite.query.get_or_404(assiduite_id)
     return get_justifs_from_date(assi.etudid, assi.date_debut, assi.date_fin, long)
@@ -571,7 +581,8 @@ def get_justifs_from_date(
             Defaults to False.
 
     Returns:
-        list[int | dict]: La liste des justificatifs (par défaut uniquement les identifiants, sinon les Dict si long est vrai)
+        list[int | dict]: La liste des justificatifs (par défaut uniquement
+                les identifiants, sinon les dict si long est vrai)
     """
     # On récupère les justificatifs d'un étudiant couvrant la période donnée
     justifs: Query = Justificatif.query.filter(
@@ -584,8 +595,11 @@ def get_justifs_from_date(
     if valid:
         justifs = justifs.filter(Justificatif.etat == EtatJustificatif.VALIDE)
 
-    # On renvoie la liste des id des justificatifs si long est Faux, sinon on renvoie les dicts des justificatifs
-    return [j.justif_id if not long else j.to_dict(True) for j in justifs]
+    # On renvoie la liste des id des justificatifs si long est Faux,
+    # sinon on renvoie les dicts des justificatifs
+    if long:
+        return [j.to_dict(True) for j in justifs]
+    return [j.justif_id for j in justifs]
 
 
 def get_formsemestre_from_data(data: dict[str, datetime | int]) -> FormSemestre:
@@ -593,7 +607,8 @@ def get_formsemestre_from_data(data: dict[str, datetime | int]) -> FormSemestre:
     get_formsemestre_from_data récupère un formsemestre en fonction des données passées
     Si l'étudiant est inscrit à plusieurs formsemestre, prend le premier.
     Args:
-        data (dict[str, datetime  |  int]): Une représentation simplifiée d'une assiduité ou d'un justificatif
+        data (dict[str, datetime  |  int]): Une représentation simplifiée d'une
+            assiduité ou d'un justificatif
 
             data = {
                 "etudid" : int,
diff --git a/app/views/assiduites.py b/app/views/assiduites.py
index 69834961c..3250ddd21 100644
--- a/app/views/assiduites.py
+++ b/app/views/assiduites.py
@@ -26,6 +26,7 @@
 
 import datetime
 import re
+from typing import Any
 
 from flask import g, request, render_template, flash
 from flask import abort, url_for, redirect, Response
@@ -88,7 +89,7 @@ class HTMLElement:
         self.children: list["HTMLElement"] = []
         self.self_close: bool = kattr.get("self_close", False)
         self.text_content: str = kattr.get("text_content", "")
-        self.key_attributes: dict[str, any] = kattr
+        self.key_attributes: dict[str, Any] = kattr
         self.attributes: list[str] = list(attr)
 
     def add(self, *child: "HTMLElement") -> None:
@@ -248,7 +249,7 @@ def bilan_dept():
     return "\n".join(H)
 
 
-@bp.route("/ajout_assiduite_etud", methods=["GEt", "POST"])
+@bp.route("/ajout_assiduite_etud", methods=["GET", "POST"])
 @scodoc
 @permission_required(Permission.AbsChange)
 def ajout_assiduite_etud():
@@ -270,9 +271,6 @@ def ajout_assiduite_etud():
     # Gestion évaluations (appel à la page depuis les évaluations)
     evaluation_id: int = request.args.get("evaluation_id")
     saisie_eval = evaluation_id is not None
-
-    date_deb: str = request.args.get("date_deb")
-    date_fin: str = request.args.get("date_fin")
     moduleimpl_id: int = request.args.get("moduleimpl_id", "")
 
     redirect_url: str = (
@@ -350,6 +348,7 @@ def _record_assiduite_etud(
     ok = True
     debut_jour = "00:00"
     fin_jour = "23:59:59"
+    date_fin = None
     # On commence par convertir individuellement tous les champs
     try:
         date_debut = datetime.datetime.strptime(form.date_debut.data, "%d/%m/%Y")
@@ -1275,7 +1274,7 @@ def tableau_assiduite_actions():
 
     # Suppression : attention, POST ou GET !
     if action == "supprimer":
-        objet.supprimer()
+        objet.supprime()
         flash(f"{objet_name} supprimé")
 
         return redirect(request.referrer)
@@ -1640,9 +1639,7 @@ def signal_evaluation_abs(etudid: int = None, evaluation_id: int = None):
                 "assiduites.ajout_assiduite_etud",
                 etudid=etudid,
                 evaluation_id=evaluation.id,
-                date_deb=evaluation.date_debut.strftime(
-                    "%Y-%m-%dT%H:%M:%S"
-                ),  # XXX TODO
+                date_deb=evaluation.date_debut.strftime("%Y-%m-%dT%H:%M:%S"),
                 date_fin=evaluation.date_fin.strftime("%Y-%m-%dT%H:%M:%S"),
                 moduleimpl_id=evaluation.moduleimpl.id,
                 saisie_eval="true",