diff --git a/app/templates/assiduites/pages/signal_assiduites_hebdo.j2 b/app/templates/assiduites/pages/signal_assiduites_hebdo.j2
new file mode 100644
index 000000000..6bab7673a
--- /dev/null
+++ b/app/templates/assiduites/pages/signal_assiduites_hebdo.j2
@@ -0,0 +1,212 @@
+{% extends "sco_page.j2" %}
+
+{% block styles %}
+{{ super() }}
+
+
+
+
+{% endblock styles %}
+
+{% block scripts %}
+{{ super() }}
+
+
+
+{% include "sco_timepicker.j2" %}
+
+
+
+
+{% endblock scripts %}
+
+{% block title %}
+{{ title }}
+{% endblock title %}
+
+{% block app_content %}
+
+
Signalement hebdomadaire de l'assiduité {{ gr | safe }}
+
+
+
+
+
+
+
+
+
+
+
+{% include "assiduites/widgets/alert.j2" %}
+{% endblock app_content %}
\ No newline at end of file
diff --git a/app/views/assiduites.py b/app/views/assiduites.py
index f5ffe223f..4fb66a7fe 100644
--- a/app/views/assiduites.py
+++ b/app/views/assiduites.py
@@ -1987,6 +1987,107 @@ def traitement_justificatifs():
)
+@bp.route("signal_assiduites_hebdo")
+@scodoc
+@permission_required(Permission.AbsChange)
+def signal_assiduites_hebdo():
+ """
+ signal_assiduites_hebdo
+
+ paramètres obligatoires :
+ - formsemestre_id : id du formsemestre
+ - semaine : date semaine (iso 8601 -> 20XX-WXX)
+ - groups_id : id des groupes (séparés par des virgules -> 1,2,3)
+
+ paramètres optionnels :
+ - moduleimpl_id : id du moduleimpl (par défaut None)
+ """
+
+ # Récupération des paramètres
+ moduleimpl_id: int = request.args.get("moduleimpl_id", None)
+ semaine: str = request.args.get("semaine", None)
+ group_ids: list[int] = request.args.get("group_ids", None)
+ formsemestre_id: int = request.args.get("formsemestre_id", -1)
+
+ # Vérification des paramètres
+ if semaine is None or group_ids is None or formsemestre_id is None:
+ raise ScoValueError("Paramètres manquants", dest_url=request.referrer)
+
+ # Récupération du moduleimpl
+ moduleimpl: ModuleImpl | None = ModuleImpl.query.get(moduleimpl_id)
+ module_text: str = "Non spécifié"
+ if moduleimpl is not None:
+ module_text = f"{moduleimpl.code} {moduleimpl.titre}"
+ else:
+ if moduleimpl_id == "autre":
+ module_text = "Autre module (pas dans la liste)"
+ moduleimpl_id = None if moduleimpl_id != "autre" else moduleimpl_id
+
+ # Récupération du formsemestre
+ formsemestre: FormSemestre = FormSemestre.get_formsemestre(formsemestre_id)
+
+ # vérification semaine dans format iso 8601 et formsemestre
+ try:
+ lundi_semaine = datetime.datetime.strptime(semaine + "-1", "%G-W%V-%u")
+ if (
+ lundi_semaine.date() < formsemestre.date_debut
+ or lundi_semaine.date() > formsemestre.date_fin
+ ):
+ raise ScoValueError(
+ "Semaine en dehors du semestre", dest_url=request.referrer
+ )
+
+ except (ValueError, TypeError) as exc:
+ raise ScoValueError("Semaine invalide", dest_url=request.referrer) from exc
+ except ScoValueError as exc:
+ raise exc
+
+ etudiants: list[Identite] = []
+
+ # Vérification des groupes
+ if group_ids is None:
+ group_ids = []
+ else:
+ group_ids = group_ids.split(",")
+ map(str, group_ids)
+ groups_infos = sco_groups_view.DisplayedGroupsInfos(
+ group_ids, formsemestre_id=formsemestre.id, select_all_when_unspecified=True
+ )
+ if not groups_infos.members:
+ return (
+ html_sco_header.sco_header(page_title="Assiduité: saisie hébdomadaire")
+ + "Aucun étudiant !
"
+ + html_sco_header.sco_footer()
+ )
+
+ # Récupération des étudiants
+ etudiants.extend(
+ [Identite.get_etud(etudid=m["etudid"]) for m in groups_infos.members]
+ )
+ etudiants = list(sorted(etudiants, key=lambda etud: etud.sort_key))
+
+ if groups_infos.tous_les_etuds_du_sem:
+ gr_tit = "en"
+ else:
+ if len(groups_infos.group_ids) > 1:
+ grp = "des groupes"
+ else:
+ grp = "du groupe"
+ gr_tit = (
+ grp + ' ' + groups_infos.groups_titles + ""
+ )
+
+ return render_template(
+ "assiduites/pages/signal_assiduites_hebdo.j2",
+ gr=gr_tit,
+ module=module_text,
+ etudiants=etudiants,
+ moduleimpl_select=_module_selector(
+ formsemestre=formsemestre, moduleimpl_id=moduleimpl_id
+ ),
+ )
+
+
def generate_bul_list(etud: Identite, semestre: FormSemestre) -> str:
"""Génère la liste des assiduités d'un étudiant pour le bulletin mail"""