diff --git a/app/api/__init__.py b/app/api/__init__.py
index 6c2e493ffb3d94980b06397b22b0821db83d049d..5acb090966a62b055f54c6583dc02a124ea239a8 100644
--- a/app/api/__init__.py
+++ b/app/api/__init__.py
@@ -122,6 +122,7 @@ from app.api import (
     justificatifs,
     logos,
     moduleimpl,
+    operations,
     partitions,
     semset,
     users,
diff --git a/app/api/operations.py b/app/api/operations.py
new file mode 100644
index 0000000000000000000000000000000000000000..51ba5c6189d79421ba41602d7faf1ef676907c9e
--- /dev/null
+++ b/app/api/operations.py
@@ -0,0 +1,100 @@
+##############################################################################
+# ScoDoc
+# Copyright (c) 1999 - 2024 Emmanuel Viennet.  All rights reserved.
+# See LICENSE
+##############################################################################
+
+"""
+  ScoDoc 9 API : liste opérations effectuées par un utilisateur
+
+  CATEGORY
+  --------
+  Operations
+"""
+
+from flask import url_for
+from flask_json import as_json
+from flask_login import login_required
+
+import app
+from app import db
+from app.api import api_bp as bp, api_web_bp
+from app.api import api_permission_required as permission_required
+from app.decorators import scodoc
+from app.models import NotesNotes
+from app.scodoc.sco_permissions import Permission
+from app.scodoc import sco_utils as scu
+
+MAX_QUERY_LENGTH = 10000
+
+
+@bp.route("/operations/user/<int:uid>/notes")
+@api_web_bp.route("/operations/user/<int:uid>/notes")
+@login_required
+@scodoc
+@permission_required(Permission.ScoView)
+@as_json
+def operations_user_notes(uid: int):
+    """Liste les opérations de saisie de notes effectuées par utilisateur.
+
+    QUERY
+    -----
+    start: indice de début de la liste
+    length: nombre d'éléments à retourner
+    draw: numéro de la requête (pour pagination, renvoyé tel quel)
+    order[dir]: desc ou asc
+    search[value]: chaîne à chercher (dans évaluation et étudiant)
+    PARAMS
+    -----
+    uid: l'id de l'utilisateur
+    """
+    start = int(app.request.args.get("start", 0))
+    length = min(int(app.request.args.get("length", 10)), MAX_QUERY_LENGTH)
+    order = app.request.args.get("order[dir]", "desc")
+    draw = int(app.request.args.get("draw", 1))
+    search = app.request.args.get("search[value]", "")
+    query = db.session.query(NotesNotes).filter(NotesNotes.uid == uid)
+    if order == "asc":
+        query = query.order_by(NotesNotes.date.asc())
+    else:
+        query = query.order_by(NotesNotes.date.desc())
+
+    # Pour l'efficacité, limite si pas de recherche en python
+    limited_query = query.offset(start).limit(length) if not search else query
+
+    data = []
+    for note in limited_query:
+        obj = {
+            "date": note.date.isoformat(),
+            "date_dmy": note.date.strftime(scu.DATEATIME_FMT),
+            "operation": "Saisie de note",
+            "value": scu.fmt_note(note.value),
+            "id": note.id,
+            "uid": note.uid,
+            "etudiant": note.etudiant.to_dict_short(),
+            "etudiant_link": note.etudiant.html_link_fiche(),
+            "evaluation": note.evaluation.to_dict_api(),
+            "evaluation_link": f"""<a href="{
+                url_for('notes.evaluation_listenotes',
+                        scodoc_dept=note.evaluation.moduleimpl.formsemestre.departement.acronym,
+                        evaluation_id=note.evaluation_id)
+                }">{note.evaluation.descr()}</a>""",
+        }
+        if search:
+            search = search.lower()
+            if (
+                search not in note.etudiant.nomprenom.lower()
+                and search not in note.evaluation.descr().lower()
+                and search not in obj["date_dmy"]
+            ):
+                continue  # skip
+
+        data.append(obj)
+
+    result = data[start : start + length] if search else data
+    return {
+        "draw": draw,
+        "recordsTotal": query.count(),  # unfiltered
+        "recordsFiltered": len(data) if search else query.count(),
+        "data": result,
+    }
diff --git a/app/models/etudiants.py b/app/models/etudiants.py
index 6ef71ff2f64112dabd81251e1b27d46cc2ca2b29..6574047ee4df7a862931f026b523f00b0e52148b 100644
--- a/app/models/etudiants.py
+++ b/app/models/etudiants.py
@@ -121,6 +121,12 @@ class Identite(models.ScoDocModel):
         cascade="all, delete-orphan",
         lazy="dynamic",
     )
+    notes = db.relationship(
+        "NotesNotes",
+        backref="etudiant",
+        cascade="all, delete-orphan",
+        lazy="dynamic",
+    )
     # Relations avec les assiduites et les justificatifs
     assiduites = db.relationship(
         "Assiduite", back_populates="etudiant", lazy="dynamic", cascade="all, delete"
diff --git a/app/models/evaluations.py b/app/models/evaluations.py
index 06db8075d228ac534884905f558833a5f0da4204..cf998a56a429633b4a54808cf34976bfefda326b 100644
--- a/app/models/evaluations.py
+++ b/app/models/evaluations.py
@@ -58,6 +58,12 @@ class Evaluation(models.ScoDocModel):
     # ordre de presentation (par défaut, le plus petit numero
     # est la plus ancienne eval):
     numero = db.Column(db.Integer, nullable=False, default=0)
+    notes = db.relationship(
+        "NotesNotes",
+        backref="evaluation",
+        cascade="all, delete-orphan",
+        lazy="dynamic",
+    )
     ues = db.relationship("UniteEns", secondary="evaluation_ue_poids", viewonly=True)
 
     _sco_dept_relations = ("ModuleImpl", "FormSemestre")  # accès au dept_id
@@ -380,6 +386,13 @@ class Evaluation(models.ScoDocModel):
         return f"""du {self.date_debut.strftime('%d/%m/%Y')} à {
             _h(self.date_debut)} au {self.date_fin.strftime('%d/%m/%Y')} à {_h(self.date_fin)}"""
 
+    def descr(self) -> str:
+        "Description de l'évaluation pour affichage (avec module et semestre)"
+        return f"""{self.description} {self.descr_date()} en {
+            self.moduleimpl.module.titre_str()} du {
+            self.moduleimpl.formsemestre.titre_formation(with_sem_idx=True)
+        }"""
+
     def heure_debut(self) -> str:
         """L'heure de début (sans la date), en ISO.
         Chaine vide si non renseignée."""
diff --git a/app/templates/user_board/user_board.j2 b/app/templates/user_board/user_board.j2
index 5f5dac7ab5e33576b2ae3d4bfe06285f6016a75d..2832f95180ac2c6afdbcf2cc9f32bb11b9ac0e29 100644
--- a/app/templates/user_board/user_board.j2
+++ b/app/templates/user_board/user_board.j2
@@ -1,8 +1,10 @@
 {# Tableau de bord utilisateur #}
 
 {% extends "base.j2" %}
-
-{% block app_content %}
+{% block styles %}
+{{super()}}
+<link type="text/css" rel="stylesheet" href="{{scu.STATIC_DIR}}/libjs/qtip/jquery.qtip-3.0.3.min.css" />
+<link rel="stylesheet" type="text/css" href="{{scu.STATIC_DIR}}/DataTables/datatables.min.css" />
 <style>
 .ub-formsemestres {
     display: flex;
@@ -60,7 +62,14 @@
   color: black;
   text-decoration: none;
 }
+
+div.scobox.saisies-notes {
+  background-color: rgb(243, 255, 255);
+}
 </style>
+{% endblock %}
+
+{% block app_content %}
 
 <div class="tab-content">
     <h2>{{user.get_nomcomplet()}}</h2>
@@ -105,6 +114,61 @@
         {% endfor %}
         </div>
     {% endfor %}
+
+
+    <div class="scobox saisies-notes">
+      <div class="scobox-title">
+        Dernières saisies de notes par {{user.get_prenomnom()}}
+      </div>
+      <table id="saisies-notes" class="display" style="width:100%">
+          <thead>
+              <tr>
+                  <th>Date</th>
+                  <th>Évaluation</th>
+                  <th>Étudiant</th>
+                  <th>Note</th>
+              </tr>
+          </thead>
+          <tbody>
+              <!-- Data will be loaded dynamically via JavaScript -->
+          </tbody>
+      </table>
 </div>
 
+
+</div>
+
+
+
 {% endblock app_content %}
+
+
+{% block scripts %}
+  {{ super() }}
+  <script src="{{scu.STATIC_DIR}}/js/etud_info.js"></script>
+  <script src="{{scu.STATIC_DIR}}/DataTables/datatables.min.js"></script>
+  <script>
+  $(document).ready(function() {
+    $('#saisies-notes').DataTable({
+        "processing": true,
+        "serverSide": true,
+        "ajax": {
+          "url": "{{ url_for('apiweb.operations_user_notes',
+            scodoc_dept=current_user.dept or g.scodoc_dept or fallback_dept.acronym,
+            uid=user.id) }}",
+          "type": "GET"
+        },
+        "columns": [
+          { "data": "date_dmy", "orderable": false },
+          { "data": "evaluation_link", "orderable": false },
+          { "data": "etudiant_link", "orderable": false },
+          { "data": "value", "orderable": false }
+        ],
+        "language": {
+            search: "Chercher (date, titre, étudiant) :", // Change the "Search:" label
+            lengthMenu: "Show _MENU_ records per page"
+        }
+    });
+  });
+  </script>
+{% endblock %}
diff --git a/app/views/user_board.py b/app/views/user_board.py
index fe3489e4106dcc19ca9b5c5e28fefc4a5133eb7e..30d51c3ea8dd6a54be69152806c27942c3eb7de6 100644
--- a/app/views/user_board.py
+++ b/app/views/user_board.py
@@ -14,6 +14,7 @@ from app.decorators import (
     permission_required,
 )
 from app.models import Departement, FormSemestre
+from app.scodoc.sco_exceptions import ScoValueError
 from app.scodoc.sco_permissions import Permission
 from app.scodoc import sco_preferences
 from app.views import scodoc_bp as bp
@@ -25,6 +26,9 @@ from app.views import ScoData
 @login_required
 def user_board(user_name: str):
     """Tableau de bord utilisateur: liens vers ses objets"""
+    fallback_dept = db.session.query(Departement).first()
+    if not fallback_dept:
+        raise ScoValueError("Aucun département existant")
     user = User.query.filter_by(user_name=user_name).first_or_404()
     (
         formsemestres_by_dept,
@@ -47,6 +51,7 @@ def user_board(user_name: str):
         "user_board/user_board.j2",
         depts=depts,
         dept_names=dept_names_sorted,
+        fallback_dept=fallback_dept,
         formsemestres_by_dept=formsemestres_by_dept,
         modimpls_by_formsemestre=modimpls_by_formsemestre,
         sco=ScoData(),
diff --git a/sco_version.py b/sco_version.py
index 83b81513ea7f6e5ebb69690c006a818455526d6b..2e58c9f14c108151ecee3cdec4a408db4ece747e 100644
--- a/sco_version.py
+++ b/sco_version.py
@@ -3,7 +3,7 @@
 
 "Infos sur version ScoDoc"
 
-SCOVERSION = "9.7.37"
+SCOVERSION = "9.7.38"
 
 SCONAME = "ScoDoc"