diff --git a/app/scodoc/sco_page_etud.py b/app/scodoc/sco_page_etud.py
index 9e45d0ba770377a92b5cf2693b25c04fc69432fa..7839f7f75a46eb29912d82506b15a0f7ae5d918d 100644
--- a/app/scodoc/sco_page_etud.py
+++ b/app/scodoc/sco_page_etud.py
@@ -108,13 +108,15 @@ def _menu_scolarite(
         and authuser.has_permission(Permission.EtudInscrit)
         and not locked
     )
-    note_enabled = etat_inscription == scu.INSCRIT and (
-        etat_inscription != scu.DEMISSION
+    note_enabled = (
+        (etat_inscription == scu.INSCRIT)
+        and (not locked)
         and (
             authuser.has_permission(Permission.EditAllNotes)
             or (authuser.id in [resp.id for resp in formsemestre.responsables])
         )
     )
+
     items = [
         {
             "title": dem_title,
@@ -171,7 +173,7 @@ def _menu_scolarite(
             "enabled": authuser.has_permission(Permission.EtudInscrit),
         },
         {
-            "title": "Editer toutes les notes",
+            "title": "Éditer toutes les notes",
             "endpoint": "notes.form_saisie_notes_par_etu",
             "args": {"etu_id": etudid, "semestre_id": formsemestre.id},
             "enabled": note_enabled,
diff --git a/app/scodoc/sco_saisie_notes.py b/app/scodoc/sco_saisie_notes.py
index 0e65b1dca4c1bf90e65f5e68b3d069f52dbc3fd7..54933d7a526a4fc3299f4940713800509b9991fc 100644
--- a/app/scodoc/sco_saisie_notes.py
+++ b/app/scodoc/sco_saisie_notes.py
@@ -42,7 +42,6 @@ from app.comp.res_compat import NotesTableCompat
 from app.models import (
     Evaluation,
     FormSemestre,
-    Module,
     ModuleImpl,
     ScolarNews,
     Assiduite,
@@ -793,13 +792,8 @@ class DataModimpl:
             moduleimpl_id=modimpl.id,
         )
         self.link = (
-            f'<a class="stdlink" href="{href}">{self.module_code} {self.titre}</a>.'
+            f'<a class="stdlink" href="{href}">{self.module_code} {self.titre}</a>'
         )
-        # self.cursus = {}
-        formation_id = modimpl.formsemestre.formation_id
-        # for ins in etudiant.inscriptions():
-        #     if ins.formsemestre.formation_id == formation_id:
-        #         self.cursus[ins.formsemestre.id] = ins.formsemestre
 
     def add_eval(self, data_eval: DataSection):
         self.data_evals.append(data_eval)
@@ -814,11 +808,8 @@ class DataEval:
         self.evaluation_id = evaluation.id
         self.description = evaluation.description
         self.note_min, self.note_max = evaluation.get_bounds()
-        self.evaluation_type: EvaluationType = evaluation.evaluation_type
+        self.evaluation_type: int = evaluation.evaluation_type
         self.note = get_evaluation_etud_note(evaluation, etudid)
-        # self.data_debut = evaluation.date_debut
-        # self.date_fin = evaluation.date_fin
-        # self.ue_poids = evaluation.get_ue_poids_dict()
         self.note_value = (
             ""
             if self.note is None
@@ -840,8 +831,9 @@ class DataEval:
         """
 
     def forminput(self) -> str:
-        return f"""<input type="text" size="5" id="formnotes_note_{self.evaluation_id}" 
-        class="note" onkeypress="return enter_focus_next(this, event);" 
+        "Le champ html input"
+        return f"""<input type="text" size="5" id="formnotes_note_{self.evaluation_id}"
+        class="note" onkeypress="return enter_focus_next(this, event);"
         note_min="{self.note_min}" note_max="{self.note_max}" evaluation_id="{self.evaluation_id}"
         original-value="{self.note_value}" value="{self.note_value}" />"""
 
@@ -854,6 +846,7 @@ class DataEval:
         )
 
     def history(self):
+        "le span html avec le menu historique des saisies"
         return f"""<span id="formnotes_hist_{self.evaluation_id}">
         {get_note_history_menu(self.evaluation.id, self.etudid)}</span>"""
 
@@ -862,8 +855,9 @@ class DataForm:
     """
     Class qui décrit les données d'une page de saisie par étudiant:
     decision_jury: bool = indique si une décision de jury a été prise pour cet étudiant
-    data_sections: dict[ModuleTYpe, DataSection] = pour chaque section (ressource, SAE, Malus, Standard),
-                                                        la liste de ses modimpl concernés
+    data_sections: dict[ModuleTYpe, DataSection] =
+        pour chaque section (ressource, SAE, Malus, Standard),
+        la liste de ses modimpl concernés
     """
 
     def __init__(self, etudiant: Identite, semestre: FormSemestre, decision_jury: bool):
@@ -872,10 +866,8 @@ class DataForm:
         self.decision_jury = decision_jury
         self.data_sections = {}
 
-    def add_section(self, data_section: DataSection):
-        self.data_sections.append(data_section)
-
     def link_to_etudiant(self) -> str:
+        "Lien html vers le bulletin de l'étudiant"
         link: str = url_for(
             "notes.formsemestre_bulletinetud",
             scodoc_dept=g.scodoc_dept,
@@ -897,7 +889,7 @@ def get_data(semestre: FormSemestre, etudiant: Identite) -> DataForm:
         for module_type in ModuleType:
             data.data_sections[module_type] = DataSection(module_type)
     else:
-        for module_type in [ ModuleType.STANDARD, ModuleType.MALUS]:
+        for module_type in [ModuleType.STANDARD, ModuleType.MALUS]:
             data.data_sections[module_type] = DataSection(module_type)
     for modimpl in semestre.modimpls_sorted:
         module_type = modimpl.module.module_type
@@ -909,30 +901,33 @@ def get_data(semestre: FormSemestre, etudiant: Identite) -> DataForm:
     return data
 
 
-def saisie_notes_par_etu(semestre: FormSemestre, etudiant: Identite):
+def saisie_notes_par_etu(formsemestre: FormSemestre, etud: Identite):
+    "Formulaire de saisie de toutes les notes d'un semestre pour un étudiant"
     # Check access
     # (admin, respformation, and responsable_id)
-    locked = not semestre.etat
-    # readonly peut être uinutile si l accès à cette page n est pas autorisée au public
-    readonly = locked or not (
+    if not formsemestre.etat or not (
         current_user.has_permission(Permission.EditAllNotes)
-        or (current_user in semestre.responsables)
-    )
-    inscriptions = etudiant.formsemestre_inscriptions
-    inscription = None
-    for ins in inscriptions:
-        if ins.formsemestre_id == semestre.id:
-            inscription = ins
-    # assert ins is not None
-    if ins is None:
-        raise ScoValueError("Tentative d accès à une inscription inexistante")  # bug
-    if ins.etat != scu.INSCRIT:
-        raise ValueError(
-            "Etudiant démissionnaire ou défaillant"
-        )  # ne devrait pas être accessible. bug
-    "Formulaire de saisie de note centré sur l'étudiant"
-    data = get_data(semestre, etudiant)
-    if semestre.formation.is_apc():
+        or (current_user.id in [resp.id for resp in formsemestre.responsables])
+    ):
+        return render_template(
+            "sco_page.j2",
+            content=f"""
+            <h2>Modification des notes impossible pour {current_user.user_name}</h2>
+
+            <p>(vérifiez que le semestre n'est pas verrouillé et que vous
+               avez l'autorisation d'effectuer cette opération)</p>
+            <p>Retour à la fiche de {etud.html_link_fiche()}
+            </p>
+        """,
+            sco=ScoData(formsemestre=formsemestre, etud=etud),
+        )
+    inscription = formsemestre.etuds_inscriptions.get(etud.id)
+    if inscription is None:
+        raise ScoValueError("Étudiant non inscrit à ce semestre")
+    if inscription.etat != scu.INSCRIT:
+        raise ScoValueError("Étudiant démissionnaire ou défaillant")
+    data = get_data(formsemestre, etud)
+    if formsemestre.formation.is_apc():
         module_type_order = [
             ModuleType.RESSOURCE,
             ModuleType.SAE,
@@ -948,18 +943,15 @@ def saisie_notes_par_etu(semestre: FormSemestre, etudiant: Identite):
         "etud/saisie_notes_par_etu.j2",
         title="Saisie notes par étudiant",
         javascripts=["js/saisie_notes.js", "js/saisie_notes_par_etu.js"],
-        sco=ScoData(formsemestre=semestre),
+        sco=ScoData(formsemestre=formsemestre, etud=etud),
         data=data,
-        readonly=readonly,
         get_note_history_menu=get_note_history_menu,
         module_type_order=module_type_order,
     )
 
 
-# US 1030 - FIN
-
-
-def get_evaluation_etud_note(evaluation: Evaluation, etudid: int) -> float | str | None:
+def get_evaluation_etud_note(evaluation: Evaluation, etudid: int) -> NotesNotes | None:
+    "La note d'un étudiant à l'évaluation, None si pas de note"
     return NotesNotes.query.filter_by(
         evaluation_id=evaluation.id, etudid=etudid
     ).first()
diff --git a/app/templates/etud/saisie_notes_par_etu.j2 b/app/templates/etud/saisie_notes_par_etu.j2
index b0c6d6948cfb6bc228862096c462a73f1cfd2b04..df358c3b7d5df7c5fa573c5c8725de1e6225b868 100644
--- a/app/templates/etud/saisie_notes_par_etu.j2
+++ b/app/templates/etud/saisie_notes_par_etu.j2
@@ -8,6 +8,8 @@
         display:inline-grid;
         grid-template-columns: 40px 40px minmax(350px, 1fr) 70px minmax(200px, 1fr);
         align-items: baseline;
+        border: 1px solid black;
+        padding: 5px;
     }
     #formnotes .section {
         grid-column: 1 / span 5;
@@ -23,6 +25,37 @@
     }
     #formnotes .label {
         grid-column: 3;
+        display: flex;
+        align-items: center;
+        white-space: nowrap;
+    }
+
+    #formnotes .label:hover {
+        background-color: lightgray;
+    }
+    #formnotes .label a::before {
+        content: "•";
+    }
+    #formnotes .label a {
+        color: black;
+        flex-shrink: 0;
+        margin-right: 0.5em;
+    }
+    .dots {
+        flex-grow: 1;
+        border-bottom: 1px dotted #000; /* fallback look */
+        background-image: repeating-linear-gradient(to right, black 0 1px, transparent 1px 4px);
+        background-position: bottom;
+        background-repeat: repeat-x;
+        background-size: 4px 1px;
+        height: 1em;
+        margin-right: 0.5em;
+    }
+    #formnotes .commentaire {
+        grid-column: 3;
+        text-align: right;
+        white-space: nowrap;
+        margin-right: 0.5em;
     }
     #formnotes .input { grid-column: 4 }
     #formnotes .history { grid-column: 5;}
@@ -33,7 +66,6 @@
 
 {% block app_content %}
     <div id="saisie_notes_par_etu" class="table-container">
-        <span class="titre">{{title}}</span>
         <h3> Saisie des notes de l'étudiant : {{data.link_to_etudiant() | safe }} </h3>
         {% if data.decision_jury %}
         <div class="warning">
@@ -48,7 +80,7 @@
             <input type="hidden" id="formnotes_formsemestre_id" value="{{data.semestre.id}}" />
             {% if data.decision_jury %}
             {% endif %}
-            <div class="label">commentaire</div>
+            <div class="commentaire">commentaire :</div>
             <div class="long_input">
                 <input type="text" id="formnotes_comment" name="comment" class="input" size="44" onkeypress="return enter_focus_next(this, event);">
             </div>
@@ -60,6 +92,7 @@
                        {% for data_eval in data_modimpl.data_evals %}
                             <div class="label">
                                 {{ data_eval.titre() | safe }}
+                                <span class="dots"></span>
 {#                                <input type="hidden" id="date_debut_{{ data_eval.evaluation_id }}" value="{{ data_eval.date_debut }}">#}
 {#                                <input type="hidden" id="date_fin_{{ data_eval.evaluation_id }}" value="{{ data_eval.date_fin }}">#}
 {#                                    {% for ue in data_eval.ue_poids %}#}
@@ -95,7 +128,7 @@
         </form>
     </div>
     <div class="sco_help">
-        <p> 
+        <p>
             Les modifications sont enregistrées au fur et à mesure.
         </p>
         <h4> Codes spéciaux: </h4>
diff --git a/app/views/notes.py b/app/views/notes.py
index 7dfa03bd23ff942b820e08bf4a21d4231460cf6d..8f5929a270c991e4dc5a292e244886b80831d465 100644
--- a/app/views/notes.py
+++ b/app/views/notes.py
@@ -1816,20 +1816,14 @@ def form_saisie_notes(evaluation_id: int):
     return sco_saisie_notes.saisie_notes(evaluation, group_ids)
 
 
-# modification US 1030 - DEB
-
-
-@bp.route("/form_saisie_notes_par_etu/<int:semestre_id>/<int:etu_id>")
+@bp.route("/form_saisie_notes_par_etu/<int:formsemestre_id>/<int:etudid>")
 @scodoc
 @permission_required(Permission.EnsView)
-def form_saisie_notes_par_etu(etu_id: int, semestre_id: int):
+def form_saisie_notes_par_etu(etudid: int, formsemestre_id: int):
     "Formulaire de saisie des notes centré sur l'étudiant"
-    etudiant = Identite.get_etud(etu_id)
-    semestre = FormSemestre.get_formsemestre(semestre_id)
-    return sco_saisie_notes.saisie_notes_par_etu(semestre, etudiant)
-
-
-# modification US 1030 - FIN
+    formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
+    etud = Identite.get_etud(etudid)
+    return sco_saisie_notes.saisie_notes_par_etu(formsemestre, etud)
 
 
 @bp.route("/formsemestre_import_notes/<int:formsemestre_id>", methods=["GET", "POST"])