diff --git a/app/api/jury.py b/app/api/jury.py
index 28c0ae8bc3b79fd36d6b70fd3b903c0602168d0a..2800c77a99da18b0d4db3b2c0076c09191468aab 100644
--- a/app/api/jury.py
+++ b/app/api/jury.py
@@ -12,11 +12,20 @@ from flask_json import as_json
 from flask_login import login_required
 
 import app
-from app.api import api_bp as bp, api_web_bp
+from app import db, log
+from app.api import api_bp as bp, api_web_bp, tools
 from app.decorators import scodoc, permission_required
 from app.scodoc.sco_exceptions import ScoException
 from app.but import jury_but_results
-from app.models import FormSemestre
+from app.models import (
+    ApcValidationAnnee,
+    ApcValidationRCUE,
+    FormSemestre,
+    Identite,
+    ScolarAutorisationInscription,
+    ScolarFormSemestreValidation,
+)
+from app.scodoc import sco_cache
 from app.scodoc.sco_permissions import Permission
 
 
@@ -36,3 +45,134 @@ def decisions_jury(formsemestre_id: int):
         return rows
     else:
         raise ScoException("non implemente")
+
+
+@bp.route(
+    "/etudiant/<int:etudid>/jury/validation_ue/<int:validation_id>/delete",
+    methods=["POST"],
+)
+@api_web_bp.route(
+    "/etudiant/<int:etudid>/jury/validation_ue/<int:validation_id>/delete",
+    methods=["POST"],
+)
+@login_required
+@scodoc
+@permission_required(Permission.ScoEtudInscrit)
+@as_json
+def validation_ue_delete(etudid: int, validation_id: int):
+    "Efface cette validation"
+    return _validation_ue_delete(etudid, validation_id)
+
+
+@bp.route(
+    "/etudiant/<int:etudid>/jury/validation_formsemestre/<int:validation_id>/delete",
+    methods=["POST"],
+)
+@api_web_bp.route(
+    "/etudiant/<int:etudid>/jury/validation_formsemestre/<int:validation_id>/delete",
+    methods=["POST"],
+)
+@login_required
+@scodoc
+@permission_required(Permission.ScoEtudInscrit)
+@as_json
+def validation_formsemestre_delete(etudid: int, validation_id: int):
+    "Efface cette validation"
+    # c'est la même chose (formations classiques)
+    return _validation_ue_delete(etudid, validation_id)
+
+
+def _validation_ue_delete(etudid: int, validation_id: int):
+    "Efface cette validation (semestres classiques ou UEs)"
+    etud = tools.get_etud(etudid)
+    if etud is None:
+        return "étudiant inconnu", 404
+    validation = ScolarFormSemestreValidation.query.filter_by(
+        id=validation_id, etudid=etudid
+    ).first_or_404()
+    log(f"validation_ue_delete: etuid={etudid} {validation}")
+    db.session.delete(validation)
+    sco_cache.invalidate_formsemestre_etud(etud)
+    db.session.commit()
+    return "ok"
+
+
+@bp.route(
+    "/etudiant/<int:etudid>/jury/autorisation_inscription/<int:validation_id>/delete",
+    methods=["POST"],
+)
+@api_web_bp.route(
+    "/etudiant/<int:etudid>/jury/autorisation_inscription/<int:validation_id>/delete",
+    methods=["POST"],
+)
+@login_required
+@scodoc
+@permission_required(Permission.ScoEtudInscrit)
+@as_json
+def autorisation_inscription_delete(etudid: int, validation_id: int):
+    "Efface cette validation"
+    etud = tools.get_etud(etudid)
+    if etud is None:
+        return "étudiant inconnu", 404
+    validation = ScolarAutorisationInscription.query.filter_by(
+        id=validation_id, etudid=etudid
+    ).first_or_404()
+    log(f"autorisation_inscription_delete: etuid={etudid} {validation}")
+    db.session.delete(validation)
+    sco_cache.invalidate_formsemestre_etud(etud)
+    db.session.commit()
+    return "ok"
+
+
+@bp.route(
+    "/etudiant/<int:etudid>/jury/validation_rcue/<int:validation_id>/delete",
+    methods=["POST"],
+)
+@api_web_bp.route(
+    "/etudiant/<int:etudid>/jury/validation_rcue/<int:validation_id>/delete",
+    methods=["POST"],
+)
+@login_required
+@scodoc
+@permission_required(Permission.ScoEtudInscrit)
+@as_json
+def validation_rcue_delete(etudid: int, validation_id: int):
+    "Efface cette validation"
+    etud = tools.get_etud(etudid)
+    if etud is None:
+        return "étudiant inconnu", 404
+    validation = ApcValidationRCUE.query.filter_by(
+        id=validation_id, etudid=etudid
+    ).first_or_404()
+    log(f"validation_ue_delete: etuid={etudid} {validation}")
+    db.session.delete(validation)
+    sco_cache.invalidate_formsemestre_etud(etud)
+    db.session.commit()
+    return "ok"
+
+
+@bp.route(
+    "/etudiant/<int:etudid>/jury/validation_annee_but/<int:validation_id>/delete",
+    methods=["POST"],
+)
+@api_web_bp.route(
+    "/etudiant/<int:etudid>/jury/validation_annee_but/<int:validation_id>/delete",
+    methods=["POST"],
+)
+@login_required
+@scodoc
+@permission_required(Permission.ScoEtudInscrit)
+@as_json
+def validation_annee_but_delete(etudid: int, validation_id: int):
+    "Efface cette validation"
+    etud = tools.get_etud(etudid)
+    if etud is None:
+        return "étudiant inconnu", 404
+    validation = ApcValidationAnnee.query.filter_by(
+        id=validation_id, etudid=etudid
+    ).first_or_404()
+    log(f"validation_annee_but: etuid={etudid} {validation}")
+    db.session.delete(validation)
+    sco_cache.invalidate_formsemestre_etud(etud)
+    db.session.commit()
+    return "ok"
diff --git a/app/but/jury_edit_manual.py b/app/but/jury_edit_manual.py
new file mode 100644
index 0000000000000000000000000000000000000000..73e21ecf541e0047edd7bd6e5b41254826c44462
--- /dev/null
+++ b/app/but/jury_edit_manual.py
@@ -0,0 +1,66 @@
+##############################################################################
+# ScoDoc
+# Copyright (c) 1999 - 2023 Emmanuel Viennet.  All rights reserved.
+# See LICENSE
+##############################################################################
+
+"""Jury édition manuelle des décisions (correction d'erreurs, parcours hors normes)
+
+Non spécifique au BUT.
+"""
+
+import flask
+from flask import flash, render_template, url_for
+from flask import g, request
+
+from app import db
+
+from app.models import (
+    ApcValidationAnnee,
+    ApcValidationRCUE,
+    FormSemestre,
+    Identite,
+    UniteEns,
+    ScolarAutorisationInscription,
+    ScolarFormSemestreValidation,
+)
+from app.views import ScoData
+
+
+def jury_delete_manual(etud: Identite):
+    """Vue (réservée au chef de dept.)
+    présentant *toutes* les décisions de jury concernant cet étudiant
+    et permettant de les supprimer une à une.
+    """
+    sem_vals = ScolarFormSemestreValidation.query.filter_by(
+        etudid=etud.id, ue_id=None
+    ).order_by(ScolarFormSemestreValidation.event_date)
+    ue_vals = (
+        ScolarFormSemestreValidation.query.filter_by(etudid=etud.id)
+        .join(UniteEns)
+        .order_by(ScolarFormSemestreValidation.event_date, UniteEns.numero)
+    )
+    autorisations = ScolarAutorisationInscription.query.filter_by(
+        etudid=etud.id
+    ).order_by(
+        ScolarAutorisationInscription.semestre_id, ScolarAutorisationInscription.date
+    )
+    rcue_vals = (
+        ApcValidationRCUE.query.filter_by(etudid=etud.id)
+        .join(UniteEns, UniteEns.id == ApcValidationRCUE.ue1_id)
+        .order_by(UniteEns.semestre_idx, UniteEns.numero, ApcValidationRCUE.date)
+    )
+    annee_but_vals = ApcValidationAnnee.query.filter_by(etudid=etud.id).order_by(
+        ApcValidationAnnee.ordre, ApcValidationAnnee.date
+    )
+    return render_template(
+        "jury/jury_delete_manual.j2",
+        etud=etud,
+        sem_vals=sem_vals,
+        ue_vals=ue_vals,
+        autorisations=autorisations,
+        rcue_vals=rcue_vals,
+        annee_but_vals=annee_but_vals,
+        sco=ScoData(),
+        title=f"Toutes les décisions de jury enregistrées pour {etud.html_link_fiche()}",
+    )
diff --git a/app/models/etudiants.py b/app/models/etudiants.py
index 8a6047097ec66d98c089263112b0784d11b178d7..d67a8482814fcece7e092199fb5be51c8362036e 100644
--- a/app/models/etudiants.py
+++ b/app/models/etudiants.py
@@ -78,6 +78,12 @@ class Identite(db.Model):
             f"<Etud {self.id}/{self.departement.acronym} {self.nom!r} {self.prenom!r}>"
         )
 
+    def html_link_fiche(self) -> str:
+        "lien vers la fiche"
+        return f"""<a class="stdlink" href="{
+           url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=self.id)
+        }">{self.nomprenom}</a>"""
+
     @classmethod
     def from_request(cls, etudid=None, code_nip=None) -> "Identite":
         """Étudiant à partir de l'etudid ou du code_nip, soit
diff --git a/app/models/validations.py b/app/models/validations.py
index 9a938b6c5ab6759fea7eb21ecf4ed5988cd6b7e7..8a1a8dd0d4f0693d95c9f5a6376ac3b0ff0e2e06 100644
--- a/app/models/validations.py
+++ b/app/models/validations.py
@@ -76,12 +76,14 @@ class ScolarFormSemestreValidation(db.Model):
         d.pop("_sa_instance_state", None)
         return d
 
-    def html(self) -> str:
+    def html(self, detail=False) -> str:
         "Affichage html"
         if self.ue_id is not None:
-            return f"""Validation de l'UE {self.ue.acronyme}
-                (<b>{self.code}</b>
-                le {self.event_date.strftime("%d/%m/%Y")} à {self.event_date.strftime("%Hh%M")})
+            return f"""Validation de l'UE {self.ue.acronyme} de {self.ue.formation.acronyme}
+                {("émise par " + self.formsemestre.html_link_status()) 
+                    if self.formsemestre else ""}
+                :<b>{self.code}</b>
+                le {self.event_date.strftime("%d/%m/%Y")} à {self.event_date.strftime("%Hh%M")}
             """
         else:
             return f"""Validation du semestre S{
diff --git a/app/scodoc/sco_page_etud.py b/app/scodoc/sco_page_etud.py
index 9901dad365fab3ba8e992779a7ca469ecf5c2c14..4b1973768f9aa7129391e6ceb0e3e5a343b11345 100644
--- a/app/scodoc/sco_page_etud.py
+++ b/app/scodoc/sco_page_etud.py
@@ -312,7 +312,13 @@ def ficheEtud(etudid=None):
             ] = f"""<span class="link_bul_pdf"><a class="stdlink" href="{
                 url_for("notes.formsemestre_inscription_with_modules_form", 
                 scodoc_dept=g.scodoc_dept, etudid=etudid)
-                }">inscrire à un autre semestre</a></span>"""
+                }">inscrire à un autre semestre</a></span>
+                <span class="link_bul_pdf"><a class="stdlink" href="{
+                url_for("notes.jury_delete_manual", 
+                scodoc_dept=g.scodoc_dept, etudid=etudid)
+                }">éditer toutes décisions de jury</a></span>
+                """
+
         else:
             info["link_inscrire_ailleurs"] = ""
     else:
diff --git a/app/static/css/jury_delete_manual.css b/app/static/css/jury_delete_manual.css
new file mode 100644
index 0000000000000000000000000000000000000000..6580e089f38b1bad0ff634c120b4f443e4c58a01
--- /dev/null
+++ b/app/static/css/jury_delete_manual.css
@@ -0,0 +1,9 @@
+
+div.jury_decisions_list div {
+    font-size: 120%;
+    font-weight: bold;
+}
+
+div.jury_decisions_list form {
+    display: inline-block;
+}
\ No newline at end of file
diff --git a/app/templates/jury/erase_decisions_annee_formation.j2 b/app/templates/jury/erase_decisions_annee_formation.j2
index 5298437a5c816961380174651c7df8742cc74ed0..7d0353eb893247ddbd3b1333c04fc5e88d2a8957 100644
--- a/app/templates/jury/erase_decisions_annee_formation.j2
+++ b/app/templates/jury/erase_decisions_annee_formation.j2
@@ -3,7 +3,7 @@
 {% block app_content %}
 
 {% if not validations %}
-<p>Aucune validation de jury enregistrée pour <b>{{etud.nom_disp()}}</b> sur 
+<p>Aucune validation de jury enregistrée pour <b>{{etud.html_link_fiche()}}</b> sur 
 <b>l'année {{annee}}</b>
 de la formation <em>{{ formation.html() }}</em>
 </p>
@@ -13,7 +13,7 @@ de la formation <em>{{ formation.html() }}</em>
 </div>
 {% else %}
 
-<h2>Effacer les décisions de jury pour l'année {{annee}} de {{etud.nom_disp()}} ?</h2>
+<h2>Effacer les décisions de jury pour l'année {{annee}} de {{etud.html_link_fiche()}} ?</h2>
 
 <p class="help">Affectera toutes les décisions concernant l'année {{annee}} de la formation,
 quelle que soit leur origine.</p>
diff --git a/app/templates/jury/jury_delete_manual.j2 b/app/templates/jury/jury_delete_manual.j2
new file mode 100644
index 0000000000000000000000000000000000000000..ed7a9d2e8e05eb7e7c2a911aba9bdcea6a3152d0
--- /dev/null
+++ b/app/templates/jury/jury_delete_manual.j2
@@ -0,0 +1,134 @@
+{% extends 'base.j2' %}
+
+{% block styles %}
+    {{super()}}
+    <link href="{{scu.STATIC_DIR}}/css/jury_delete_manual.css" rel="stylesheet" type="text/css" />
+{% endblock %}
+
+{% block app_content %}
+
+
+<h2>Décisions de jury enregistrées pour {{etud.html_link_fiche()|safe}}</h2>
+
+<p class="help">
+Cette page liste toutes les décisions de jury connus de ScoDoc concernant cet étudiant
+et permet de les effacer une par une.
+</p>
+<p class="help">
+<b>Attention</b>, il vous appartient de vérifier la cohérence du résultat !
+En principe, <b>l'usage de cette page devrait rester exceptionnel</b>.
+Aucune annulation n'est ici possible (vous devrez re-saisir les décisions via les 
+pages de saisie de jury habituelles). 
+</p>
+{% if sem_vals.first() %}
+<div class="jury_decisions_list jury_decisions_sems">
+    <div>Décisions de semestres</div>
+    <ul>
+        {% for v in sem_vals %}
+            <li>{{v.html()|safe}}
+            <form><button data-v_id="{{v.id}}" data-type="validation_formsemestre">effacer</button></form>
+            </li>
+        {% endfor %}
+    </ul>
+</div>
+{% endif %}
+
+{% if ue_vals.first() %}
+<div class="jury_decisions_list jury_decisions_ues">
+    <div>Décisions d'UEs</div>
+    <ul>
+        {% for v in ue_vals %}
+            <li>{{v.html(detail=True)|safe}}
+            <form><button data-v_id="{{v.id}}" data-type="validation_ue">effacer</button></form>
+            </li>
+        {% endfor %}
+    </ul>
+</div>
+{% endif %}
+
+{% if rcue_vals.first() %}
+<div class="jury_decisions_list jury_decisions_rcues">
+    <div>Décisions de RCUE (niveaux de compétences)</div>
+    <ul>
+        {% for v in rcue_vals %}
+            <li>{{v.html()|safe}}
+            <form><button data-v_id="{{v.id}}" data-type="validation_rcue">effacer</button></form>
+            </li>
+        {% endfor %}
+    </ul>
+</div>
+{% endif %}
+
+{% if annee_but_vals.first() %}
+<div class="jury_decisions_list jury_decisions_annees_but">
+    <div>Décisions d'années BUT</div>
+    <ul>
+        {% for v in annee_but_vals %}
+            <li>{{v.html()|safe}}
+            <form><button data-v_id="{{v.id}}" data-type="validation_annee_but">effacer</button></form>
+            </li>
+        {% endfor %}
+    </ul>
+</div>
+{% endif %}
+
+{% if autorisations.first() %}
+<div class="jury_decisions_list jury_decisions_autorisation_inscription">
+    <div>Autorisations d'inscriptions (passages)</div>
+    <ul>
+        {% for v in autorisations %}
+            <li>{{v.html()|safe}}
+            <form><button data-v_id="{{v.id}}" data-type="autorisation_inscription">effacer</button></form>
+            </li>
+        {% endfor %}
+    </ul>
+</div>
+{% endif %}
+
+{% if not(
+    sem_vals.first() or sem_ues.first() or sem_rcues.first() 
+    or annee_but_vals.first() or autorisations.first()) 
+%}
+<div>
+    <p class="fontred">aucune décision enregistrée</p>
+</div>
+{% endif %}
+
+<div>
+    <a class="stdlink" href="{{etud.html_link_fiche()}}">retour à sa fiche</a>
+</div>
+
+{% endblock %}
+
+
+{% block scripts %}
+{{super()}}
+
+<script>
+document.addEventListener('DOMContentLoaded', () => {
+  const buttons = document.querySelectorAll('.jury_decisions_list button');
+  
+  buttons.forEach(button => {
+    button.addEventListener('click', (event) => {
+        // Handle button click event here
+        event.preventDefault();
+        const v_id = event.target.dataset.v_id;
+        const validation_type = event.target.dataset.type;
+        if (confirm("Supprimer cette validation ?")) {
+            fetch(`${SCO_URL}/../api/etudiant/{{etud.id}}/jury/${validation_type}/${v_id}/delete`,
+                {
+                    method: "POST",
+                }).then(response => {                    
+                    // Handle the response
+                    if (response.ok) {
+                        location.reload();
+                    } else {
+                        throw new Error('Request failed');
+                    }
+                });
+        }
+    });
+  });
+});
+</script>
+{% endblock %}
diff --git a/app/views/notes.py b/app/views/notes.py
index e29a93c918c14bc004013cbb15a2f5c28d25b09d..3a5e3bbe74a6bdb11fdab40c7c0e929ffbfe63b5 100644
--- a/app/views/notes.py
+++ b/app/views/notes.py
@@ -47,11 +47,12 @@ from app.but import jury_but, jury_but_validation_auto
 from app.but.forms import jury_but_forms
 from app.but import jury_but_pv
 from app.but import jury_but_view
+from app.but import jury_edit_manual
 
 from app.comp import jury, res_sem
 from app.comp.res_compat import NotesTableCompat
 from app.models import Formation, ScolarAutorisationInscription, ScolarNews, Scolog
-from app.models.but_refcomp import ApcNiveau, ApcParcours
+from app.models.but_refcomp import ApcNiveau
 from app.models.config import ScoDocSiteConfig
 from app.models.etudiants import Identite
 from app.models.formsemestre import FormSemestre
@@ -2940,6 +2941,18 @@ def erase_decisions_annee_formation(etudid: int, formation_id: int, annee: int):
     )
 
 
+@bp.route(
+    "/jury_delete_manual/<int:etudid>",
+    methods=["GET", "POST"],
+)
+@scodoc
+@permission_required(Permission.ScoEtudInscrit)
+def jury_delete_manual(etudid: int):
+    """Efface toute les décisions d'une année pour cet étudiant"""
+    etud: Identite = Identite.query.get_or_404(etudid)
+    return jury_edit_manual.jury_delete_manual(etud)
+
+
 sco_publish(
     "/formsemestre_lettres_individuelles",
     sco_pv_forms.formsemestre_lettres_individuelles,