diff --git a/app/comp/res_common.py b/app/comp/res_common.py
index c456517905f89d92ad3436a952d33d9eb912ae44..afb7acd00ae4f8a2b75686b4176e6a75d80e90e1 100644
--- a/app/comp/res_common.py
+++ b/app/comp/res_common.py
@@ -494,7 +494,7 @@ class ResultatsSemestre(ResultatsCache):
             classes: str = "",
             idx: int = 100,
         ):
-            "Add a row to our table. classes is a list of css class names"
+            "Add a cell to our table. classes is a list of css class names"
             row[col_id] = content
             if classes:
                 row[f"_{col_id}_class"] = classes + f" c{idx}"
@@ -569,7 +569,8 @@ class ResultatsSemestre(ResultatsCache):
                 )
             # --- Moyenne d'UE
             nb_ues_validables, nb_ues_warning = 0, 0
-            for ue in ues_sans_bonus:
+            idx_ue_start = idx
+            for idx_ue, ue in enumerate(ues_sans_bonus):
                 ue_status = self.get_etud_ue_status(etudid, ue.id)
                 if ue_status is not None:
                     col_id = f"moy_ue_{ue.id}"
@@ -590,7 +591,7 @@ class ResultatsSemestre(ResultatsCache):
                         ue.acronyme,
                         fmt_note(val),
                         "col_ue" + note_class,
-                        idx,
+                        idx_ue * 10000 + idx_ue_start,
                     )
                     titles_bot[
                         f"_{col_id}_target_attrs"
@@ -611,7 +612,7 @@ class ResultatsSemestre(ResultatsCache):
                             f"Bonus {ue.acronyme}",
                             val_fmt_html if allow_html else val_fmt,
                             "col_ue_bonus",
-                            idx,
+                            idx_ue * 10000 + idx_ue_start + 1,
                         )
                         row[f"_bonus_ue_{ue.id}_xls"] = val_fmt
                     # Les moyennes des modules (ou ressources et SAÉs) dans cette UE
@@ -656,7 +657,11 @@ class ResultatsSemestre(ResultatsCache):
                             val_fmt_html,
                             # class col_res mod_ue_123
                             f"col_{modimpl.module.type_abbrv()} mod_ue_{ue.id}",
-                            idx,
+                            idx_ue * 10000
+                            + idx_ue_start
+                            + 1
+                            + (modimpl.module.module_type or 0) * 1000
+                            + (modimpl.module.numero or 0),
                         )
                         row[f"_{col_id}_xls"] = val_fmt
                         if modimpl.module.module_type == scu.ModuleType.MALUS:
diff --git a/app/models/formsemestre.py b/app/models/formsemestre.py
index 55e60cc06e5e898c61a4cde0ea8f1739e54e548b..3c457d9805974bac81cf4904b3a6e240a4bf4c94 100644
--- a/app/models/formsemestre.py
+++ b/app/models/formsemestre.py
@@ -157,6 +157,11 @@ class FormSemestre(db.Model):
     def __repr__(self):
         return f"<{self.__class__.__name__} {self.id} {self.titre_annee()}>"
 
+    def sort_key(self) -> tuple:
+        """clé pour tris par ordre alphabétique
+        (pour avoir le plus récent d'abord, sort avec reverse=True)"""
+        return (self.date_debut, self.semestre_id)
+
     def to_dict(self, convert_objects=False) -> dict:
         """dict (compatible ScoDoc7).
         If convert_objects, convert all attributes to native types
@@ -325,7 +330,7 @@ class FormSemestre(db.Model):
         if self.formation.is_apc():
             modimpls.sort(
                 key=lambda m: (
-                    m.module.module_type or 0,
+                    m.module.module_type or 0,  # ressources (2) avant SAEs (3)
                     m.module.numero or 0,
                     m.module.code or 0,
                 )
diff --git a/app/scodoc/sco_edit_ue.py b/app/scodoc/sco_edit_ue.py
index 4a9af68698078a8f67c3a6a3a942aa5e2e9e41e6..5d269875e42f335a4437288aaf7d0284ae7e82fb 100644
--- a/app/scodoc/sco_edit_ue.py
+++ b/app/scodoc/sco_edit_ue.py
@@ -39,6 +39,7 @@ from app.but import apc_edit_ue
 from app.models import APO_CODE_STR_LEN, SHORT_STR_LEN
 from app.models import (
     Formation,
+    FormSemestre,
     FormSemestreUEComputationExpr,
     FormSemestreUECoef,
     Matiere,
@@ -925,7 +926,7 @@ du programme" (menu "Semestre") si vous avez un semestre en cours);
         <li><a class="stdlink" href="{
             url_for('notes.module_table', scodoc_dept=g.scodoc_dept,
             formation_id=formation_id)
-            }">Liste détaillée des modules de la formation</a> (debug) 
+            }">Liste détaillée des modules de la formation</a> (debug)
         </li>
         </ul>
         </p>"""
@@ -936,19 +937,24 @@ du programme" (menu "Semestre") si vous avez un semestre en cours);
         <h3> <a name="sems">Semestres ou sessions de cette formation</a></h3>
         <p><ul>"""
         )
-        for sem in sco_formsemestre.do_formsemestre_list(
-            args={"formation_id": formation_id}
+        for formsemestre in sorted(
+            FormSemestre.query.filter_by(formation_id=formation_id).all(),
+            key=lambda s: s.sort_key(),
+            reverse=True,
         ):
             H.append(
-                '<li><a class="stdlink" href="formsemestre_status?formsemestre_id=%(formsemestre_id)s">%(titremois)s</a>'
-                % sem
+                f"""<li><a class="stdlink" href="{
+                    url_for("notes.formsemestre_status", scodoc_dept=g.scodoc_dept,
+                        formsemestre_id=formsemestre.id
+                    )}">{formsemestre.titre_mois()}</a>"""
             )
-            if not sem["etat"]:
+            if not formsemestre.etat:
                 H.append(" [verrouillé]")
             else:
                 H.append(
-                    ' <a class="stdlink" href="formsemestre_editwithmodules?formation_id=%(formation_id)s&formsemestre_id=%(formsemestre_id)s">Modifier</a>'
-                    % sem
+                    f""" &nbsp;<a class="stdlink" href="{url_for("notes.formsemestre_editwithmodules",
+                        scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre.id
+                        )}">Modifier</a>"""
                 )
             H.append("</li>")
         H.append("</ul>")
diff --git a/app/scodoc/sco_formsemestre_status.py b/app/scodoc/sco_formsemestre_status.py
index af37125fc4ab52d83a4244673ff2543f1d9ab0ab..11ba8c80ae46f10686c4b5fd94aba5c3231e3d33 100644
--- a/app/scodoc/sco_formsemestre_status.py
+++ b/app/scodoc/sco_formsemestre_status.py
@@ -179,7 +179,6 @@ def formsemestre_status_menubar(formsemestre: FormSemestre) -> str:
             "title": "Modifier le semestre",
             "endpoint": "notes.formsemestre_editwithmodules",
             "args": {
-                "formation_id": formation.id,
                 "formsemestre_id": formsemestre_id,
             },
             "enabled": can_modify_sem,
diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py
index c877db598ef11ff132866b4f11d1d5cebdae3e29..e57a5070336683a8722919945d3e4d7f4b358290 100644
--- a/app/scodoc/sco_utils.py
+++ b/app/scodoc/sco_utils.py
@@ -1155,6 +1155,8 @@ def gen_cell(key: str, row: dict, elt="td", with_col_class=False):
     if with_col_class:
         klass = key + " " + klass
     attrs = f'class="{klass}"' if klass else ""
+    if elt == "th":
+        attrs += ' scope="row"'
     data = row.get(f"_{key}_data")  # dict
     if data:
         for k in data:
diff --git a/app/views/notes.py b/app/views/notes.py
index fce8b95a06597854e089eca8f2c247668f18300e..415b6cc80656a9995aea0fdc83e1b802ccba226b 100644
--- a/app/views/notes.py
+++ b/app/views/notes.py
@@ -272,7 +272,8 @@ def formsemestre_bulletinetud(
     code_ine=None,
 ):
     format = format or "html"
-
+    if not isinstance(etudid, int):
+        raise ScoInvalidIdType("formsemestre_bulletinetud: etudid must be an integer !")
     if formsemestre_id is not None and not isinstance(formsemestre_id, int):
         raise ScoInvalidIdType(
             "formsemestre_bulletinetud: formsemestre_id must be an integer !"