diff --git a/README.md b/README.md
index b1117729b7ee10352ccc8de0154be20691129f38..753fc3dc96610348906595a2616ee510f1c532cc 100644
--- a/README.md
+++ b/README.md
@@ -3,16 +3,12 @@
 
 (c) Emmanuel Viennet 1999 - 2021 (voir LICENCE.txt)
 
-VERSION EXPERIMENTALE - NE PAS DEPLOYER - TESTS EN COURS
-
 Installation: voir instructions à jour sur <https://scodoc.org/GuideInstallDebian11>
 
 Documentation utilisateur: <https://scodoc.org>
 
 ## Version ScoDoc 9
 
-N'utiliser que pour les développements et tests.
-
 La version ScoDoc 9 est basée sur Flask (au lieu de Zope) et sur 
 **python 3.9+**. 
 
@@ -22,13 +18,13 @@ Flask, SQLAlchemy, au lien de Python2/Zope dans les versions précédentes).
 
 
 
-### État actuel (27 août 21)
+### État actuel (26 sept 21)
 
- - Tests en cours, notamment système d'installation et de migration.
+ - 9.0 reproduit l'ensemble des fonctions de ScoDoc 7 (donc pas de BUT), sauf:
 
 **Fonctionnalités non intégrées:**
  
- - feuille "placement" (en cours)
+ - génération LaTeX des avis de poursuite d'études
 
  - ancien module "Entreprises" (obsolete)
 
diff --git a/app/models/departements.py b/app/models/departements.py
index c0a928e3678ff2d176a085eb68f35f83cbd5802c..32cb8637455860bc3fe699988727422072ee371f 100644
--- a/app/models/departements.py
+++ b/app/models/departements.py
@@ -44,3 +44,6 @@ class Departement(db.Model):
             "date_creation": self.date_creation,
         }
         return data
+
+    def __repr__(self):
+        return f"<{self.__class__.__name__}(id={self.id}, acronym='{self.acronym}')>"
diff --git a/app/models/formations.py b/app/models/formations.py
index 063bd624d4488ef7a39ddf971d7ad7b9dfac2954..5002ab08b45a00b81af6207db1541b98c31144de 100644
--- a/app/models/formations.py
+++ b/app/models/formations.py
@@ -30,8 +30,12 @@ class NotesFormation(db.Model):
     type_parcours = db.Column(db.Integer, default=0, server_default="0")
     code_specialite = db.Column(db.String(SHORT_STR_LEN))
 
+    ues = db.relationship("NotesUE", backref="formation", lazy="dynamic")
     formsemestres = db.relationship("FormSemestre", lazy="dynamic", backref="formation")
 
+    def __repr__(self):
+        return f"<{self.__class__.__name__}(id={self.id}, dept_id={self.dept_id}, acronyme='{self.acronyme}')>"
+
 
 class NotesUE(db.Model):
     """Unité d'Enseignement"""
@@ -61,6 +65,9 @@ class NotesUE(db.Model):
     # coef UE, utilise seulement si l'option use_ue_coefs est activée:
     coefficient = db.Column(db.Float)
 
+    def __repr__(self):
+        return f"<{self.__class__.__name__}(id={self.id}, formation_id={self.formation_id}, acronyme='{self.acronyme}')>"
+
 
 class NotesMatiere(db.Model):
     """Matières: regroupe les modules d'une UE
diff --git a/app/scodoc/sco_edit_ue.py b/app/scodoc/sco_edit_ue.py
index 6f51ee4d8483832b367543603b02893a974e9c4d..839e4c482beab6097b273a257cfc769ab1771a9b 100644
--- a/app/scodoc/sco_edit_ue.py
+++ b/app/scodoc/sco_edit_ue.py
@@ -32,6 +32,7 @@ import flask
 from flask import g, url_for, request
 from flask_login import current_user
 
+from app.models.formations import NotesUE
 import app.scodoc.notesdb as ndb
 import app.scodoc.sco_utils as scu
 from app import log
@@ -851,24 +852,26 @@ def ue_sharing_code(ue_code=None, ue_id=None, hide_ue_id=None):
         F = sco_formations.formation_list(args={"formation_id": ue["formation_id"]})[0]
         formation_code = F["formation_code"]
 
-    ue_list_all = do_ue_list(args={"ue_code": ue_code})
     if ue_id:
-        # retire les UE d'autres formations:
-        # log('checking ucode %s formation %s' % (ue_code, formation_code))
-        ue_list = []
-        for ue in ue_list_all:
-            F = sco_formations.formation_list(
-                args={"formation_id": ue["formation_id"]}
-            )[0]
-            if formation_code == F["formation_code"]:
-                ue_list.append(ue)
+        # UE du même code, code formation et departement
+        q_ues = (
+            NotesUE.query.filter_by(ue_code=ue_code)
+            .join(NotesUE.formation, aliased=True)
+            .filter_by(dept_id=F["dept_id"], formation_code=formation_code)
+        )
     else:
-        ue_list = ue_list_all
+        # Toutes les UE du departement avec ce code
+        q_ues = (
+            NotesUE.query.filter_by(ue_code=ue_code)
+            .join(NotesUE.formation, aliased=True)
+            .filter_by(dept_id=F["dept_id"])
+        )
 
     if hide_ue_id:  # enlève l'ue de depart
-        ue_list = [ue for ue in ue_list if ue["ue_id"] != hide_ue_id]
+        q_ues = q_ues.filter(NotesUE.id != hide_ue_id)
 
-    if not ue_list:
+    ues = q_ues.all()
+    if not ues:
         if ue_id:
             return """<span class="ue_share">Seule UE avec code %s</span>""" % ue_code
         else:
@@ -879,18 +882,13 @@ def ue_sharing_code(ue_code=None, ue_id=None, hide_ue_id=None):
     else:
         H.append('<span class="ue_share">UE avec le code %s:</span>' % ue_code)
     H.append("<ul>")
-    for ue in ue_list:
-        F = sco_formations.formation_list(args={"formation_id": ue["formation_id"]})[0]
+    for ue in ues:
         H.append(
-            '<li>%s (%s) dans <a class="stdlink" href="ue_list?formation_id=%s">%s (%s)</a>, version %s</li>'
-            % (
-                ue["acronyme"],
-                ue["titre"],
-                F["formation_id"],
-                F["acronyme"],
-                F["titre"],
-                F["version"],
-            )
+            f"""<li>{ue.acronyme} ({ue.titre}) dans <a class="stdlink" 
+            href="{url_for("notes.ue_list", scodoc_dept=g.scodoc_dept, formation_id=ue.formation.id)}"
+            >{ue.formation.acronyme} ({ue.formation.titre})</a>, version {ue.formation.version}
+            </li>
+            """
         )
     H.append("</ul>")
     return "\n".join(H)