diff --git a/app/api/justificatifs.py b/app/api/justificatifs.py
index e68b397ac31938de602f5ce1a0c76af7ed101eb3..f753fc0e0f5e9bb7fe04c136594d21ae400564e5 100644
--- a/app/api/justificatifs.py
+++ b/app/api/justificatifs.py
@@ -19,7 +19,13 @@ from app.api import api_bp as bp
 from app.api import api_web_bp
 from app.api import get_model_api_object, tools
 from app.decorators import permission_required, scodoc
-from app.models import Identite, Justificatif, Departement, FormSemestre
+from app.models import (
+    Identite,
+    Justificatif,
+    Departement,
+    FormSemestre,
+    FormSemestreInscription,
+)
 from app.models.assiduites import (
     compute_assiduites_justified,
 )
@@ -27,6 +33,7 @@ from app.scodoc.sco_archives_justificatifs import JustificatifArchiver
 from app.scodoc.sco_exceptions import ScoValueError
 from app.scodoc.sco_permissions import Permission
 from app.scodoc.sco_utils import json_error
+from app.scodoc.sco_groups import get_group_members
 
 
 # Partie Modèle
@@ -145,14 +152,40 @@ def justificatifs_dept(dept_id: int = None, with_query: bool = False):
 
     if with_query:
         justificatifs_query = _filter_manager(request, justificatifs_query)
+
     data_set: list[dict] = []
-    for just in justificatifs_query.all():
-        data = just.to_dict(format_api=True)
-        data_set.append(data)
+    for just in justificatifs_query:
+        data_set.append(_set_sems_and_groupe(just))
 
     return data_set
 
 
+def _set_sems_and_groupe(justi: Justificatif) -> dict:
+    from app.scodoc.sco_groups import get_etud_groups
+
+    data = justi.to_dict(format_api=True)
+
+    formsemestre: FormSemestre = (
+        FormSemestre.query.join(
+            FormSemestreInscription,
+            FormSemestre.id == FormSemestreInscription.formsemestre_id,
+        )
+        .filter(
+            justi.date_debut <= FormSemestre.date_fin,
+            justi.date_fin >= FormSemestre.date_debut,
+            FormSemestreInscription.etudid == justi.etudid,
+        )
+        .first()
+    )
+    if formsemestre:
+        data["formsemestre"] = {
+            "id": formsemestre.id,
+            "title": formsemestre.session_id(),
+        }
+
+    return data
+
+
 @bp.route(
     "/justificatifs/formsemestre/<int:formsemestre_id>", defaults={"with_query": False}
 )
@@ -732,13 +765,16 @@ def _filter_manager(requested, justificatifs_query):
     # cas 5 : formsemestre_id
     formsemestre_id = requested.args.get("formsemestre_id")
 
-    if formsemestre_id is not None:
+    if formsemestre_id not in [None, "", -1]:
         formsemestre: FormSemestre = None
-        formsemestre_id = int(formsemestre_id)
-        formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first()
-        justificatifs_query = scass.filter_by_formsemestre(
-            justificatifs_query, Justificatif, formsemestre
-        )
+        try:
+            formsemestre_id = int(formsemestre_id)
+            formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first()
+            justificatifs_query = scass.filter_by_formsemestre(
+                justificatifs_query, Justificatif, formsemestre
+            )
+        except ValueError:
+            formsemestre = None
 
     order = requested.args.get("order", None)
     if order is not None:
@@ -755,4 +791,15 @@ def _filter_manager(requested, justificatifs_query):
             Justificatif.date_fin <= scu.date_fin_anne_scolaire(annee),
         )
 
+    group_id = requested.args.get("group_id", None)
+    if group_id is not None:
+        try:
+            group_id = int(group_id)
+            etudids: list[int] = [etu["etudid"] for etu in get_group_members(group_id)]
+            justificatifs_query = justificatifs_query.filter(
+                Justificatif.etudid.in_(etudids)
+            )
+        except ValueError:
+            group_id = None
+
     return justificatifs_query
diff --git a/app/scodoc/sco_formsemestre_status.py b/app/scodoc/sco_formsemestre_status.py
index 7e67e4af8c999154c841ad40d6e4ecc8826aac00..c21e8774dc2d3088bccce12652383f623a297124 100755
--- a/app/scodoc/sco_formsemestre_status.py
+++ b/app/scodoc/sco_formsemestre_status.py
@@ -852,6 +852,11 @@ def _make_listes_sem(formsemestre: FormSemestre, with_absences=True):
                 }?group_ids=%(group_id)s&formsemestre_id={
                     formsemestre.formsemestre_id
                 }"><button>Saisie différée</button></a>
+                <a class="btn" href="{
+                    url_for("assiduites.bilan_dept", scodoc_dept=g.scodoc_dept) 
+                }?group_id=%(group_id)s&formsemestre_id={
+                    formsemestre.formsemestre_id
+                }"><button>Justificatifs en attente</button></a>
                 </td>
             """
         else:
diff --git a/app/scodoc/sco_groups_view.py b/app/scodoc/sco_groups_view.py
index 728ccb363552da0d92a6486aad7facb245ebebf9..0eefe05805ddceded46bfdd1b2fbb345e67298b1 100644
--- a/app/scodoc/sco_groups_view.py
+++ b/app/scodoc/sco_groups_view.py
@@ -900,7 +900,7 @@ def form_choix_jour_saisie_hebdo(groups_infos, moduleimpl_id=None):
             formsemestre_id=groups_infos.formsemestre_id,
             moduleimpl_id="" if moduleimpl_id is None else moduleimpl_id
             )
-    }';">Saisie du jour</button>
+    }';">Saisie du jour ({datetime.date.today().strftime('%d/%m/%Y')})</button>
     """
 
 
diff --git a/app/scodoc/sco_saisie_notes.py b/app/scodoc/sco_saisie_notes.py
index 058c53efb6e056c6d9dfd8c7ef67f4b1a20d3ed3..489165bd01e3a0b6c3671727d4009bb17396c11d 100644
--- a/app/scodoc/sco_saisie_notes.py
+++ b/app/scodoc/sco_saisie_notes.py
@@ -46,6 +46,7 @@ from app.models import (
     Module,
     ModuleImpl,
     ScolarNews,
+    Assiduite,
 )
 from app.models.etudiants import Identite
 
@@ -75,6 +76,8 @@ import app.scodoc.sco_utils as scu
 from app.scodoc.sco_utils import json_error
 from app.scodoc.sco_utils import ModuleType
 
+from flask_sqlalchemy.query import Query
+
 
 def convert_note_from_string(
     note: str,
@@ -1102,30 +1105,21 @@ def _get_sorted_etuds(evaluation: Evaluation, etudids: list, formsemestre_id: in
         # Groupes auxquels appartient cet étudiant:
         e["groups"] = sco_groups.get_etud_groups(etudid, formsemestre_id)
 
-        # Information sur absence (tenant compte de la demi-journée)
-        jour_iso = (
-            evaluation.date_debut.date().isoformat() if evaluation.date_debut else ""
-        )
-        warn_abs_lst = []
-        # XXX TODO-ASSIDUITE (issue #686)
-        if evaluation.is_matin():
-            nbabs = 0  # TODO-ASSIDUITE sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=True)
-            nbabsjust = 0  # TODO-ASSIDUITE sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=True)
-            if nbabs:
-                if nbabsjust:
-                    warn_abs_lst.append("absent justifié le matin !")
-                else:
-                    warn_abs_lst.append("absent le matin !")
-        if evaluation.is_apresmidi():
-            nbabs = 0  # TODO-ASSIDUITE sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=0)
-            nbabsjust = 0  # TODO-ASSIDUITE sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=0)
-            if nbabs:
-                if nbabsjust:
-                    warn_abs_lst.append("absent justifié l'après-midi !")
-                else:
-                    warn_abs_lst.append("absent l'après-midi !")
-
-        e["absinfo"] = '<span class="sn_abs">' + " ".join(warn_abs_lst) + "</span>  "
+        # Information sur absence
+        warn_abs_lst: str = ""
+        if evaluation.date_debut is not None and evaluation.date_fin is not None:
+            assiduites_etud: Query = etud.assiduites.filter(
+                Assiduite.etat == scu.EtatAssiduite.ABSENT,
+                Assiduite.date_debut <= evaluation.date_fin,
+                Assiduite.date_fin >= evaluation.date_debut,
+            )
+            premiere_assi: Assiduite = assiduites_etud.first()
+            if premiere_assi is not None:
+                warn_abs_lst: str = (
+                    f"absent {'justifié' if premiere_assi.est_just else ''}"
+                )
+
+        e["absinfo"] = '<span class="sn_abs">' + warn_abs_lst + "</span>  "
 
         # Note actuelle de l'étudiant:
         if etudid in notes_db:
diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py
index 7cbc3e0d200dbc55663b14a083fb8e2dab6c957a..f92ab38e38d877482212e24920bdbfc1d569125d 100644
--- a/app/scodoc/sco_utils.py
+++ b/app/scodoc/sco_utils.py
@@ -670,8 +670,8 @@ def AbsencesURL():
 
 def AssiduitesURL():
     """URL of Assiduités"""
-    return url_for("assiduites.index_html", scodoc_dept=g.scodoc_dept)[
-        : -len("/index_html")
+    return url_for("assiduites.bilan_dept", scodoc_dept=g.scodoc_dept)[
+        : -len("/BilanDept")
     ]
 
 
diff --git a/app/static/js/assiduites.js b/app/static/js/assiduites.js
index 019cb894a2849296d0a371bcc48c107e06a0ed30..dbfa3736e15eb76c0acc0f60124d00872f6e28d5 100644
--- a/app/static/js/assiduites.js
+++ b/app/static/js/assiduites.js
@@ -577,7 +577,7 @@ function updateDate() {
     return true;
   } else {
     const att = document.createTextNode(
-      "Le jour sélectionné n'est pas un jour travaillé."
+      `Le jour sélectionné (${formatDate(date)}) n'est pas un jour travaillé.`
     );
     openAlertModal("Erreur", att, "", "crimson");
     dateInput.value = dateInput.getAttribute("value");
diff --git a/app/templates/assiduites/pages/bilan_dept.j2 b/app/templates/assiduites/pages/bilan_dept.j2
index 2e8ca5be96e5e91c40be5c098d6db51660a5eb0f..3301c85f6d8f14e8fdd160a417dc24dd92f9a07e 100644
--- a/app/templates/assiduites/pages/bilan_dept.j2
+++ b/app/templates/assiduites/pages/bilan_dept.j2
@@ -6,6 +6,7 @@
 <section class="nonvalide">
     <!-- Tableaux des justificatifs à valider (attente / modifié ) -->
     <h4>Justificatifs en attente (ou modifiés)</h4>
+    <a class="icon filter" onclick="filterJusti(true)"></a>
     {% include "assiduites/widgets/tableau_justi.j2" %}
 </section>
 
@@ -34,14 +35,17 @@
         generate(defAnnee)
     }
 
+    let formsemestre_id = "{{formsemestre_id}}"
+    let group_id = "{{group_id}}"
+
     function getDeptJustificatifsFromPeriod(action) {
-        const path = getUrl() + `/api/justificatifs/dept/${dept_id}/query?date_debut=${bornes.deb}&date_fin=${bornes.fin}&etat=attente,modifie`
+        const formsemestre = formsemestre_id ? `&formsemestre_id=${formsemestre_id}` : ""
+        const group = group_id ? `&group_id=${group_id}` : ""
+        const path = getUrl() + `/api/justificatifs/dept/${dept_id}/query?date_debut=${bornes.deb}&date_fin=${bornes.fin}&etat=attente,modifie${formsemestre}${group}`
         async_get(
             path,
             (data, status) => {
-                console.log(data);
                 justificatifCallBack(data);
-
             },
             (data, status) => {
                 console.error(data, status)
@@ -88,6 +92,7 @@
 
         filterJustificatifs = {
             "columns": [
+                "formsemestre",
                 "etudid",
                 "entry_date",
                 "date_debut",
@@ -100,7 +105,7 @@
                 "etat": [
                     "attente",
                     "modifie"
-                ]
+                ],
             }
         }
         const select = document.querySelector('#annee');
diff --git a/app/templates/assiduites/pages/liste_assiduites.j2 b/app/templates/assiduites/pages/liste_assiduites.j2
index eb1f9ade3205da7406e5e6c3a105167f9aba21e9..aefc644bdf1129d3d9e106de2609b19e1b72482f 100644
--- a/app/templates/assiduites/pages/liste_assiduites.j2
+++ b/app/templates/assiduites/pages/liste_assiduites.j2
@@ -4,10 +4,10 @@
     <h2>Liste de l'assiduité et des justificatifs de <span class="rouge">{{sco.etud.nomprenom}}</span></h2>
     {% include "assiduites/widgets/tableau_base.j2" %}
     <h3>Assiduités :</h3>
-    <a class="icon filter" onclick="filter()"></a>
+    <a class="icon filter" onclick="filterAssi()"></a>
     {% include "assiduites/widgets/tableau_assi.j2" %}
     <h3>Justificatifs :</h3>
-    <a class="icon filter" onclick="filter(false)"></a>
+    <a class="icon filter" onclick="filterJusti()"></a>
     {% include "assiduites/widgets/tableau_justi.j2" %}
     <ul id="contextMenu" class="context-menu">
         <li id="detailOption">Detail</li>
diff --git a/app/templates/assiduites/widgets/tableau_assi.j2 b/app/templates/assiduites/widgets/tableau_assi.j2
index fd1ee7df7eea9aedcf0fdf0e97017e82a3024e3a..b6f5349b498287c52c320afd82e492c563a71ad8 100644
--- a/app/templates/assiduites/widgets/tableau_assi.j2
+++ b/app/templates/assiduites/widgets/tableau_assi.j2
@@ -261,4 +261,185 @@
             }
         );
     }
+
+    function filterAssi() {
+        let html = `
+                    <div class="filter-body">
+                        <h3>Affichage des colonnes:</h3>
+                        <div class="filter-head">
+                            <label>
+                                Date de saisie
+                                <input class="chk" type="checkbox" name="entry_date" id="entry_date">
+                            </label>
+                            <label>
+                                Date de Début
+                                <input class="chk" type="checkbox" name="date_debut" id="date_debut" checked>
+                            </label>
+                            <label>
+                                Date de Fin
+                                <input class="chk" type="checkbox" name="date_fin" id="date_fin" checked>
+                            </label>
+                            <label>
+                                Etat
+                                <input class="chk" type="checkbox" name="etat" id="etat" checked>
+                            </label>
+                            <label>
+                                Module
+                                <input class="chk" type="checkbox" name="moduleimpl_id" id="moduleimpl_id" checked>
+                            </label>
+                            <label>
+                                Justifiée
+                                <input class="chk" type="checkbox" name="est_just" id="est_just" checked>
+                            </label>
+                        </div>
+                        <hr>
+                        <h3>Filtrage des colonnes:</h3>
+                        <span class="filter-line">
+                            <span class="filter-title" for="entry_date">Date de saisie</span>
+                            <select name="entry_date_pref" id="entry_date_pref">
+                                <option value="-1">Avant</option>
+                                <option value="0">Égal</option>
+                                <option value="1">Après</option>
+                            </select>
+                            <input type="datetime-local" name="entry_date_time" id="entry_date_time">
+                        </span>
+                        <span class="filter-line">
+                            <span class="filter-title" for="date_debut">Date de début</span>
+                            <select name="date_debut_pref" id="date_debut_pref">
+                                <option value="-1">Avant</option>
+                                <option value="0">Égal</option>
+                                <option value="1">Après</option>
+                            </select>
+                            <input type="datetime-local" name="date_debut_time" id="date_debut_time">
+                        </span>
+                        <span class="filter-line">
+                            <span class="filter-title" for="date_fin">Date de fin</span>
+                            <select name="date_fin_pref" id="date_fin_pref">
+                                <option value="-1">Avant</option>
+                                <option value="0">Égal</option>
+                                <option value="1">Après</option>
+                            </select>
+                            <input type="datetime-local" name="date_fin_time" id="date_fin_time">
+                        </span>
+                        <span class="filter-line">
+                            <span class="filter-title" for="etat">Etat</span>
+                            <input checked type="checkbox" name="etat_present" id="etat_present" class="rbtn present" value="present">
+                            <input checked type="checkbox" name="etat_retard" id="etat_retard" class="rbtn retard" value="retard">
+                            <input checked type="checkbox" name="etat_absent" id="etat_absent" class="rbtn absent" value="absent">
+                        </span>
+                        <span class="filter-line">
+                            <span class="filter-title" for="moduleimpl_id">Module</span>
+                            <select id="moduleimpl_id">
+                                <option value="">Pas de filtre</option>
+                            </select>
+                        </span>
+                        <span class="filter-line">
+                            <span class="filter-title" for="est_just">Est Justifiée</span>
+                            <select id="est_just">
+                                <option value="">Pas de filtre</option>
+                                <option value="true">Oui</option>
+                                <option value="false">Non</option>
+                            </select>
+                        </span>
+                    </div>
+            `;
+        const span = document.createElement('span');
+        span.innerHTML = html
+        html = span.firstElementChild
+
+        const filterHead = html.querySelector('.filter-head');
+        filterHead.innerHTML = ""
+        let cols = ["entry_date", "date_debut", "date_fin", "etat", "moduleimpl_id", "est_just"];
+
+        cols.forEach((k) => {
+            const label = document.createElement('label')
+            label.classList.add('f-label')
+            const s = document.createElement('span');
+            s.textContent = columnTranslator(k);
+
+
+            const input = document.createElement('input');
+            input.classList.add('chk')
+            input.type = "checkbox"
+            input.name = k
+            input.id = k;
+            input.checked = filterAssiduites.columns.includes(k)
+
+            label.appendChild(s)
+            label.appendChild(input)
+            filterHead.appendChild(label)
+        })
+
+        const sl = html.querySelector('.filter-line #moduleimpl_id');
+        let opts = []
+        Object.keys(moduleimpls).forEach((k) => {
+            const opt = document.createElement('option');
+            opt.value = k == null ? "null" : k;
+            opt.textContent = moduleimpls[k];
+            opts.push(opt);
+        })
+
+        opts = opts.sort((a, b) => {
+            return a.value < b.value
+        })
+
+        sl.append(...opts);
+
+        // Mise à jour des filtres
+
+        Object.keys(filterAssiduites.filters).forEach((key) => {
+            const l = html.querySelector(`.filter-title[for="${key}"]`).parentElement;
+            if (key.indexOf('date') != -1) {
+                l.querySelector(`#${key}_pref`).value = filterAssiduites.filters[key].pref;
+                l.querySelector(`#${key}_time`).value = filterAssiduites.filters[key].time.format("YYYY-MM-DDTHH:mm");
+
+            } else if (key.indexOf('etat') != -1) {
+                l.querySelectorAll('input').forEach((e) => {
+                    e.checked = filterAssiduites.filters[key].includes(e.value)
+                })
+            } else if (key.indexOf("module") != -1) {
+                l.querySelector('#moduleimpl_id').value = filterAssiduites.filters[key];
+            } else if (key.indexOf("est_just") != -1) {
+                l.querySelector('#est_just').value = filterAssiduites.filters[key];
+            }
+        })
+
+        openPromptModal("Filtrage des assiduités", html, () => {
+
+            const columns = [...document.querySelectorAll('.chk')]
+                .map((el) => { if (el.checked) return el.id })
+                .filter((el) => el)
+
+            filterAssiduites.columns = columns
+            filterAssiduites.filters = {}
+            //reste des filtres
+
+            const lines = [...document.querySelectorAll('.filter-line')];
+
+            lines.forEach((l) => {
+                const key = l.querySelector('.filter-title').getAttribute('for');
+
+                if (key.indexOf('date') != -1) {
+                    const pref = l.querySelector(`#${key}_pref`).value;
+                    const time = l.querySelector(`#${key}_time`).value;
+                    if (l.querySelector(`#${key}_time`).value != "") {
+                        filterAssiduites.filters[key] = {
+                            pref: pref,
+                            time: new moment.tz(time, TIMEZONE)
+                        }
+                    }
+                } else if (key.indexOf('etat') != -1) {
+                    filterAssiduites.filters[key] = [...l.querySelectorAll("input:checked")].map((e) => e.value);
+                } else if (key.indexOf("module") != -1) {
+                    filterAssiduites.filters[key] = l.querySelector('#moduleimpl_id').value;
+                } else if (key.indexOf("est_just") != -1) {
+                    filterAssiduites.filters[key] = l.querySelector('#est_just').value;
+                }
+            })
+
+
+            getAllAssiduitesFromEtud(etudid, assiduiteCallBack)
+
+        }, () => { }, "#7059FF");
+    }
 </script>
\ No newline at end of file
diff --git a/app/templates/assiduites/widgets/tableau_base.j2 b/app/templates/assiduites/widgets/tableau_base.j2
index 2b468e6a4d9dc19264fe312bee542b38ec01ac82..e337ebedadc2bbabe3bc103aa2d2400d90398cf9 100644
--- a/app/templates/assiduites/widgets/tableau_base.j2
+++ b/app/templates/assiduites/widgets/tableau_base.j2
@@ -102,6 +102,10 @@
                     return f.obj_id.includes(obj_id)
                 }
 
+                if (k == "formsemestre") {
+                    return f.formsemestre === "" || (el.hasOwnProperty("formsemestre") && el.formsemestre.title.replaceAll('-', ' ').indexOf(f.formsemestre) != -1);
+                }
+
                 return true;
             })
 
@@ -286,343 +290,6 @@
 
     }
 
-    function filter(assi = true) {
-        if (assi) {
-            let html = `
-                    <div class="filter-body">
-                        <h3>Affichage des colonnes:</h3>
-                        <div class="filter-head">
-                            <label>
-                                Date de saisie
-                                <input class="chk" type="checkbox" name="entry_date" id="entry_date">
-                            </label>
-                            <label>
-                                Date de Début
-                                <input class="chk" type="checkbox" name="date_debut" id="date_debut" checked>
-                            </label>
-                            <label>
-                                Date de Fin
-                                <input class="chk" type="checkbox" name="date_fin" id="date_fin" checked>
-                            </label>
-                            <label>
-                                Etat
-                                <input class="chk" type="checkbox" name="etat" id="etat" checked>
-                            </label>
-                            <label>
-                                Module
-                                <input class="chk" type="checkbox" name="moduleimpl_id" id="moduleimpl_id" checked>
-                            </label>
-                            <label>
-                                Justifiée
-                                <input class="chk" type="checkbox" name="est_just" id="est_just" checked>
-                            </label>
-                        </div>
-                        <hr>
-                        <h3>Filtrage des colonnes:</h3>
-                        <span class="filter-line">
-                            <span class="filter-title" for="entry_date">Date de saisie</span>
-                            <select name="entry_date_pref" id="entry_date_pref">
-                                <option value="-1">Avant</option>
-                                <option value="0">Égal</option>
-                                <option value="1">Après</option>
-                            </select>
-                            <input type="datetime-local" name="entry_date_time" id="entry_date_time">
-                        </span>
-                        <span class="filter-line">
-                            <span class="filter-title" for="date_debut">Date de début</span>
-                            <select name="date_debut_pref" id="date_debut_pref">
-                                <option value="-1">Avant</option>
-                                <option value="0">Égal</option>
-                                <option value="1">Après</option>
-                            </select>
-                            <input type="datetime-local" name="date_debut_time" id="date_debut_time">
-                        </span>
-                        <span class="filter-line">
-                            <span class="filter-title" for="date_fin">Date de fin</span>
-                            <select name="date_fin_pref" id="date_fin_pref">
-                                <option value="-1">Avant</option>
-                                <option value="0">Égal</option>
-                                <option value="1">Après</option>
-                            </select>
-                            <input type="datetime-local" name="date_fin_time" id="date_fin_time">
-                        </span>
-                        <span class="filter-line">
-                            <span class="filter-title" for="etat">Etat</span>
-                            <input checked type="checkbox" name="etat_present" id="etat_present" class="rbtn present" value="present">
-                            <input checked type="checkbox" name="etat_retard" id="etat_retard" class="rbtn retard" value="retard">
-                            <input checked type="checkbox" name="etat_absent" id="etat_absent" class="rbtn absent" value="absent">
-                        </span>
-                        <span class="filter-line">
-                            <span class="filter-title" for="moduleimpl_id">Module</span>
-                            <select id="moduleimpl_id">
-                                <option value="">Pas de filtre</option>
-                            </select>
-                        </span>
-                        <span class="filter-line">
-                            <span class="filter-title" for="est_just">Est Justifiée</span>
-                            <select id="est_just">
-                                <option value="">Pas de filtre</option>
-                                <option value="true">Oui</option>
-                                <option value="false">Non</option>
-                            </select>
-                        </span>
-                    </div>
-            `;
-            const span = document.createElement('span');
-            span.innerHTML = html
-            html = span.firstElementChild
-
-            const filterHead = html.querySelector('.filter-head');
-            filterHead.innerHTML = ""
-            let cols = ["entry_date", "date_debut", "date_fin", "etat", "moduleimpl_id", "est_just"];
-
-            cols.forEach((k) => {
-                const label = document.createElement('label')
-                label.classList.add('f-label')
-                const s = document.createElement('span');
-                s.textContent = columnTranslator(k);
-
-
-                const input = document.createElement('input');
-                input.classList.add('chk')
-                input.type = "checkbox"
-                input.name = k
-                input.id = k;
-                input.checked = filterAssiduites.columns.includes(k)
-
-                label.appendChild(s)
-                label.appendChild(input)
-                filterHead.appendChild(label)
-            })
-
-            const sl = html.querySelector('.filter-line #moduleimpl_id');
-            let opts = []
-            Object.keys(moduleimpls).forEach((k) => {
-                const opt = document.createElement('option');
-                opt.value = k == null ? "null" : k;
-                opt.textContent = moduleimpls[k];
-                opts.push(opt);
-            })
-
-            opts = opts.sort((a, b) => {
-                return a.value < b.value
-            })
-
-            sl.append(...opts);
-
-            // Mise à jour des filtres
-
-            Object.keys(filterAssiduites.filters).forEach((key) => {
-                const l = html.querySelector(`.filter-title[for="${key}"]`).parentElement;
-                if (key.indexOf('date') != -1) {
-                    l.querySelector(`#${key}_pref`).value = filterAssiduites.filters[key].pref;
-                    l.querySelector(`#${key}_time`).value = filterAssiduites.filters[key].time.format("YYYY-MM-DDTHH:mm");
-
-                } else if (key.indexOf('etat') != -1) {
-                    l.querySelectorAll('input').forEach((e) => {
-                        e.checked = filterAssiduites.filters[key].includes(e.value)
-                    })
-                } else if (key.indexOf("module") != -1) {
-                    l.querySelector('#moduleimpl_id').value = filterAssiduites.filters[key];
-                } else if (key.indexOf("est_just") != -1) {
-                    l.querySelector('#est_just').value = filterAssiduites.filters[key];
-                }
-            })
-
-            openPromptModal("Filtrage des assiduités", html, () => {
-
-                const columns = [...document.querySelectorAll('.chk')]
-                    .map((el) => { if (el.checked) return el.id })
-                    .filter((el) => el)
-
-                filterAssiduites.columns = columns
-                filterAssiduites.filters = {}
-                //reste des filtres
-
-                const lines = [...document.querySelectorAll('.filter-line')];
-
-                lines.forEach((l) => {
-                    const key = l.querySelector('.filter-title').getAttribute('for');
-
-                    if (key.indexOf('date') != -1) {
-                        const pref = l.querySelector(`#${key}_pref`).value;
-                        const time = l.querySelector(`#${key}_time`).value;
-                        if (l.querySelector(`#${key}_time`).value != "") {
-                            filterAssiduites.filters[key] = {
-                                pref: pref,
-                                time: new moment.tz(time, TIMEZONE)
-                            }
-                        }
-                    } else if (key.indexOf('etat') != -1) {
-                        filterAssiduites.filters[key] = [...l.querySelectorAll("input:checked")].map((e) => e.value);
-                    } else if (key.indexOf("module") != -1) {
-                        filterAssiduites.filters[key] = l.querySelector('#moduleimpl_id').value;
-                    } else if (key.indexOf("est_just") != -1) {
-                        filterAssiduites.filters[key] = l.querySelector('#est_just').value;
-                    }
-                })
-
-
-                getAllAssiduitesFromEtud(etudid, assiduiteCallBack)
-
-            }, () => { }, "#7059FF");
-        } else {
-            let html = `
-                    <div class="filter-body">
-                        <h3>Affichage des colonnes:</h3>
-                        <div class="filter-head">
-                            <label>
-                                Date de saisie
-                                <input class="chk" type="checkbox" name="entry_date" id="entry_date">
-                            </label>
-                            <label>
-                                Date de Début
-                                <input class="chk" type="checkbox" name="date_debut" id="date_debut" checked>
-                            </label>
-                            <label>
-                                Date de Fin
-                                <input class="chk" type="checkbox" name="date_fin" id="date_fin" checked>
-                            </label>
-                            <label>
-                                Etat
-                                <input class="chk" type="checkbox" name="etat" id="etat" checked>
-                            </label>
-                            <label>
-                                Raison
-                                <input class="chk" type="checkbox" name="raison" id="raison" checked>
-                            </label>
-                            <label>
-                                Fichier
-                                <input class="chk" type="checkbox" name="fichier" id="fichier" checked>
-                            </label>
-                        </div>
-                        <hr>
-                        <h3>Filtrage des colonnes:</h3>
-                        <span class="filter-line">
-                            <span class="filter-title" for="entry_date">Date de saisie</span>
-                            <select name="entry_date_pref" id="entry_date_pref">
-                                <option value="-1">Avant</option>
-                                <option value="0">Égal</option>
-                                <option value="1">Après</option>
-                            </select>
-                            <input type="datetime-local" name="entry_date_time" id="entry_date_time">
-                        </span>
-                        <span class="filter-line">
-                            <span class="filter-title" for="date_debut">Date de début</span>
-                            <select name="date_debut_pref" id="date_debut_pref">
-                                <option value="-1">Avant</option>
-                                <option value="0">Égal</option>
-                                <option value="1">Après</option>
-                            </select>
-                            <input type="datetime-local" name="date_debut_time" id="date_debut_time">
-                        </span>
-                        <span class="filter-line">
-                            <span class="filter-title" for="date_fin">Date de fin</span>
-                            <select name="date_fin_pref" id="date_fin_pref">
-                                <option value="-1">Avant</option>
-                                <option value="0">Égal</option>
-                                <option value="1">Après</option>
-                            </select>
-                            <input type="datetime-local" name="date_fin_time" id="date_fin_time">
-                        </span>
-                        <span class="filter-line">
-                            <span class="filter-title" for="etat">Etat</span>
-                            <label>
-                                Valide
-                                <input checked type="checkbox" name="etat_valide" id="etat_valide" class="" value="valide">
-                            </label>
-                            <label>
-                                Non Valide
-                                <input checked type="checkbox" name="etat_valide" id="etat_valide" class="" value="non_valide">
-                            </label>
-                            <label>
-                                En Attente
-                                <input checked type="checkbox" name="etat_valide" id="etat_valide" class="" value="attente">
-                            </label>
-                            <label>
-                                Modifié
-                                <input checked type="checkbox" name="etat_valide" id="etat_valide" class="" value="modifie">
-                            </label>
-                        </span>
-                    </div>
-            `;
-            const span = document.createElement('span');
-            span.innerHTML = html
-            html = span.firstElementChild
-
-            const filterHead = html.querySelector('.filter-head');
-            filterHead.innerHTML = ""
-            let cols = ["entry_date", "date_debut", "date_fin", "etat", "raison", "fichier"];
-
-            cols.forEach((k) => {
-                const label = document.createElement('label')
-                label.classList.add('f-label')
-                const s = document.createElement('span');
-                s.textContent = columnTranslator(k);
-
-
-                const input = document.createElement('input');
-                input.classList.add('chk')
-                input.type = "checkbox"
-                input.name = k
-                input.id = k;
-                input.checked = filterJustificatifs.columns.includes(k)
-
-                label.appendChild(s)
-                label.appendChild(input)
-                filterHead.appendChild(label)
-            })
-
-            // Mise à jour des filtres
-
-            Object.keys(filterJustificatifs.filters).forEach((key) => {
-                const l = html.querySelector(`.filter-title[for="${key}"]`).parentElement;
-                if (key.indexOf('date') != -1) {
-                    l.querySelector(`#${key}_pref`).value = filterJustificatifs.filters[key].pref;
-                    l.querySelector(`#${key}_time`).value = filterJustificatifs.filters[key].time.format("YYYY-MM-DDTHH:mm");
-
-                } else if (key.indexOf('etat') != -1) {
-                    l.querySelectorAll('input').forEach((e) => {
-                        e.checked = filterJustificatifs.filters[key].includes(e.value)
-                    })
-                }
-            })
-
-            openPromptModal("Filtrage des Justificatifs", html, () => {
-
-                const columns = [...document.querySelectorAll('.chk')]
-                    .map((el) => { if (el.checked) return el.id })
-                    .filter((el) => el)
-
-                filterJustificatifs.columns = columns
-                filterJustificatifs.filters = {}
-                //reste des filtres
-
-                const lines = [...document.querySelectorAll('.filter-line')];
-
-                lines.forEach((l) => {
-                    const key = l.querySelector('.filter-title').getAttribute('for');
-
-                    if (key.indexOf('date') != -1) {
-                        const pref = l.querySelector(`#${key}_pref`).value;
-                        const time = l.querySelector(`#${key}_time`).value;
-                        if (l.querySelector(`#${key}_time`).value != "") {
-                            filterJustificatifs.filters[key] = {
-                                pref: pref,
-                                time: new moment.tz(time, TIMEZONE)
-                            }
-                        }
-                    } else if (key.indexOf('etat') != -1) {
-                        filterJustificatifs.filters[key] = [...l.querySelectorAll("input:checked")].map((e) => e.value);
-                    }
-                })
-
-
-                getAllJustificatifsFromEtud(etudid, justificatifCallBack)
-
-            }, () => { }, "#7059FF");
-        }
-    }
 
     function columnTranslator(colName) {
         switch (colName) {
@@ -644,6 +311,8 @@
                 return "Fichier";
             case "etudid":
                 return "Etudiant";
+            case "formsemestre":
+                return "Semestre";
         }
     }
 
diff --git a/app/templates/assiduites/widgets/tableau_justi.j2 b/app/templates/assiduites/widgets/tableau_justi.j2
index 4b3a50228986914c3e268598ddb0e99ae8805783..636f9ede514f2e9600909f9c23fc78bb998bf947 100644
--- a/app/templates/assiduites/widgets/tableau_justi.j2
+++ b/app/templates/assiduites/widgets/tableau_justi.j2
@@ -99,7 +99,13 @@
                 } else if (k.indexOf('etudid') != -1) {
                     const e = getEtudiant(justificatif.etudid);
 
-                    td.textContent = `${e.prenom.capitalize()} ${e.nom.toUpperCase()}`;
+                    td.innerHTML = `<a class="etudinfo" id="line-${justificatif.etudid}" href="BilanEtud?etudid=${justificatif.etudid}">${e.prenom.capitalize()} ${e.nom.toUpperCase()}</a>`;
+                } else if (k == "formsemestre") {
+                    if (justificatif.hasOwnProperty("formsemestre")) {
+                        td.textContent = justificatif.formsemestre.title.replaceAll('-', ' ');
+                    } else {
+                        td.textContent = `Pas de Semestre`;
+                    }
                 }
                 else {
                     if (justificatif[k] != null) {
@@ -458,7 +464,191 @@
         })
 
     }
+    function filterJusti(dept = false) {
+
+        let dept_html_head = `
+        <label>
+            Semestre
+            <input class="chk" type="checkbox" name="formsemestre" id="formsemestre" checked>
+        </label>
+        <label>
+            Etudiant
+            <input class="chk" type="checkbox" name="etudid" id="etudid" checked>
+        </label>
+        `
+
+        let dept_html_body = `
+        <span class="filter-line">
+            <span class="filter-title" for="formsemestre">Recherche dans les semestre</span>
+            <input type="text" name="formsemestre" id="formsemestre" placeholder="S1 2023" >
+        </span>
+        `
+
+        let html = `
+                    <div class="filter-body">
+                        <h3>Affichage des colonnes:</h3>
+                        <div class="filter-head">
+                            ${dept ? dept_html_head : ""}
+                            <label>
+                                Date de saisie
+                                <input class="chk" type="checkbox" name="entry_date" id="entry_date">
+                            </label>
+                            <label>
+                                Date de Début
+                                <input class="chk" type="checkbox" name="date_debut" id="date_debut" checked>
+                            </label>
+                            <label>
+                                Date de Fin
+                                <input class="chk" type="checkbox" name="date_fin" id="date_fin" checked>
+                            </label>
+                            <label>
+                                Etat
+                                <input class="chk" type="checkbox" name="etat" id="etat" checked>
+                            </label>
+                            <label>
+                                Raison
+                                <input class="chk" type="checkbox" name="raison" id="raison" checked>
+                            </label>
+                            <label>
+                                Fichier
+                                <input class="chk" type="checkbox" name="fichier" id="fichier" checked>
+                            </label>
+                        </div>
+                        <hr>
+                        <h3>Filtrage des colonnes:</h3>
+                        <span class="filter-line">
+                            <span class="filter-title" for="entry_date">Date de saisie</span>
+                            <select name="entry_date_pref" id="entry_date_pref">
+                                <option value="-1">Avant</option>
+                                <option value="0">Égal</option>
+                                <option value="1">Après</option>
+                            </select>
+                            <input type="datetime-local" name="entry_date_time" id="entry_date_time">
+                        </span>
+                        <span class="filter-line">
+                            <span class="filter-title" for="date_debut">Date de début</span>
+                            <select name="date_debut_pref" id="date_debut_pref">
+                                <option value="-1">Avant</option>
+                                <option value="0">Égal</option>
+                                <option value="1">Après</option>
+                            </select>
+                            <input type="datetime-local" name="date_debut_time" id="date_debut_time">
+                        </span>
+                        <span class="filter-line">
+                            <span class="filter-title" for="date_fin">Date de fin</span>
+                            <select name="date_fin_pref" id="date_fin_pref">
+                                <option value="-1">Avant</option>
+                                <option value="0">Égal</option>
+                                <option value="1">Après</option>
+                            </select>
+                            <input type="datetime-local" name="date_fin_time" id="date_fin_time">
+                        </span>
+                        <span class="filter-line">
+                            <span class="filter-title" for="etat">Etat</span>
+                            <label>
+                                Valide
+                                <input checked type="checkbox" name="etat_valide" id="etat_valide" class="" value="valide">
+                            </label>
+                            <label>
+                                Non Valide
+                                <input checked type="checkbox" name="etat_valide" id="etat_valide" class="" value="non_valide">
+                            </label>
+                            <label>
+                                En Attente
+                                <input checked type="checkbox" name="etat_valide" id="etat_valide" class="" value="attente">
+                            </label>
+                            <label>
+                                Modifié
+                                <input checked type="checkbox" name="etat_valide" id="etat_valide" class="" value="modifie">
+                            </label>
+                        </span>
+                        ${dept ? dept_html_body : ""}
+                    </div>
+            `;
+        const span = document.createElement('span');
+        span.innerHTML = html
+        html = span.firstElementChild
+
+        const filterHead = html.querySelector('.filter-head');
+        filterHead.innerHTML = ""
+        let cols = ["formsemestre", "etudid", "entry_date", "date_debut", "date_fin", "etat", "raison", "fichier"];
+
+        cols.forEach((k) => {
+            const label = document.createElement('label')
+            label.classList.add('f-label')
+            const s = document.createElement('span');
+            s.textContent = columnTranslator(k);
+
+
+            const input = document.createElement('input');
+            input.classList.add('chk')
+            input.type = "checkbox"
+            input.name = k
+            input.id = k;
+            input.checked = filterJustificatifs.columns.includes(k)
+
+            label.appendChild(s)
+            label.appendChild(input)
+            filterHead.appendChild(label)
+        })
+
+        // Mise à jour des filtres
+
+        Object.keys(filterJustificatifs.filters).forEach((key) => {
+            const l = html.querySelector(`.filter-title[for="${key}"]`).parentElement;
+            if (key.indexOf('date') != -1) {
+                l.querySelector(`#${key}_pref`).value = filterJustificatifs.filters[key].pref;
+                l.querySelector(`#${key}_time`).value = filterJustificatifs.filters[key].time.format("YYYY-MM-DDTHH:mm");
+
+            } else if (key.indexOf('etat') != -1) {
+                l.querySelectorAll('input').forEach((e) => {
+                    e.checked = filterJustificatifs.filters[key].includes(e.value)
+                })
+            } else if (key == "formsemestre") {
+                l.querySelector('#formsemestre').value = filterJustificatifs.filters["formsemestre"];
+            }
+        })
+
+        openPromptModal("Filtrage des Justificatifs", html, () => {
 
+            const columns = [...document.querySelectorAll('.chk')]
+                .map((el) => { if (el.checked) return el.id })
+                .filter((el) => el)
+
+            filterJustificatifs.columns = columns
+            filterJustificatifs.filters = {}
+            //reste des filtres
+
+            const lines = [...document.querySelectorAll('.filter-line')];
+
+            lines.forEach((l) => {
+                const key = l.querySelector('.filter-title').getAttribute('for');
+
+                if (key.indexOf('date') != -1) {
+                    const pref = l.querySelector(`#${key}_pref`).value;
+                    const time = l.querySelector(`#${key}_time`).value;
+                    if (l.querySelector(`#${key}_time`).value != "") {
+                        filterJustificatifs.filters[key] = {
+                            pref: pref,
+                            time: new moment.tz(time, TIMEZONE)
+                        }
+                    }
+                } else if (key.indexOf('etat') != -1) {
+                    filterJustificatifs.filters[key] = [...l.querySelectorAll("input:checked")].map((e) => e.value);
+                } else if (key == "formsemestre") {
+                    filterJustificatifs.filters["formsemestre"] = l.querySelector('#formsemestre').value;
+                }
+            })
+
+
+            if (dept) {
+                loadAll();
+            } else {
+                getAllJustificatifsFromEtud(etudid, justificatifCallBack)
+            }
+
+        }, () => { }, "#7059FF");
+    }
 </script>
 <style>
     .fich-file {
diff --git a/app/templates/sidebar.j2 b/app/templates/sidebar.j2
index 762b73be18927746e5e4d5454a1f0ed39e260cad..560cacfc2d72d49a18153f4056fff8717bfe9df2 100755
--- a/app/templates/sidebar.j2
+++ b/app/templates/sidebar.j2
@@ -26,7 +26,7 @@
     <a href="{{url_for('notes.index_html', scodoc_dept=g.scodoc_dept)}}" class="sidebar">Programmes</a> <br>
 
     {% if current_user.has_permission(sco.Permission.ScoAbsChange)%}
-    <a href="{{url_for('assiduites.index_html', scodoc_dept=g.scodoc_dept)}}" class="sidebar">Assiduités</a> <br>
+    <a href="{{url_for('assiduites.bilan_dept', scodoc_dept=g.scodoc_dept)}}" class="sidebar">Assiduités</a> <br>
     {% endif %}
     {% if current_user.has_permission(sco.Permission.ScoUsersAdmin)
     or current_user.has_permission(sco.Permission.ScoUsersView)
@@ -86,8 +86,7 @@
         <div class="sidebar-bottom"><a href="{{ url_for( 'scodoc.about', 
         scodoc_dept=g.scodoc_dept ) }}" class="sidebar">À propos</a>
             <br />
-            <a href="{{ scu.SCO_USER_MANUAL }}" 
-                target="_blank" rel="noopener" class="sidebar">Aide</a>
+            <a href="{{ scu.SCO_USER_MANUAL }}" target="_blank" rel="noopener" class="sidebar">Aide</a>
         </div>
     </div>
     <div class="logo-logo">
diff --git a/app/views/assiduites.py b/app/views/assiduites.py
index a2e5a3b1d7e02cb6d0b4bac90133c711171e7a3a..145e28a18e588fe1bd2c2364c3bb75ee7eedb73e 100644
--- a/app/views/assiduites.py
+++ b/app/views/assiduites.py
@@ -134,10 +134,10 @@ class HTMLBuilder:
 
 
 @bp.route("/")
-@bp.route("/index_html")
+@bp.route("/BilanDept")
 @scodoc
 @permission_required(Permission.ScoAbsChange)
-def index_html():
+def bilan_dept():
     """Gestionnaire assiduités, page principale"""
     H = [
         html_sco_header.sco_header(
@@ -180,17 +180,29 @@ def index_html():
         reverse=True,
     )
 
+    annee = scu.annee_scolaire()
+
     annees_str: str = "["
     for ann in annees:
         annees_str += f"{ann},"
     annees_str += "]"
 
+    formsemestre_id = request.args.get("formsemestre_id", "")
+    if formsemestre_id:
+        try:
+            formsemestre: FormSemestre = FormSemestre.get_formsemestre(formsemestre_id)
+            annee = formsemestre.annee_scolaire()
+        except AttributeError:
+            formsemestre_id = ""
+
     H.append(
         render_template(
             "assiduites/pages/bilan_dept.j2",
             dept_id=g.scodoc_dept_id,
-            annee=scu.annee_scolaire(),
+            annee=annee,
             annees=annees_str,
+            formsemestre_id=formsemestre_id,
+            group_id=request.args.get("group_id", ""),
         ),
     )
     H.append(html_sco_header.sco_footer())
@@ -565,10 +577,14 @@ def signal_assiduites_group():
 
     real_date = scu.is_iso_formated(date, True).date()
 
-    if real_date < formsemestre.date_debut:
-        date = formsemestre.date_debut.isoformat()
-    elif real_date > formsemestre.date_fin:
-        date = formsemestre.date_fin.isoformat()
+    if real_date < formsemestre.date_debut or real_date > formsemestre.date_fin:
+        real_str = real_date.strftime("%d/%m/%Y")
+        form_deb = formsemestre.date_debut.strftime("%d/%m/%Y")
+        form_fin = formsemestre.date_fin.strftime("%d/%m/%Y")
+        raise ScoValueError(
+            f"Impossible de saisir les assiduités pour le {real_str}"
+            + f" : Jour en dehors du semestre ( {form_deb} → {form_fin}) "
+        )
 
     # --- Restriction en fonction du moduleimpl_id ---
     if moduleimpl_id: