diff --git a/app/models/__init__.py b/app/models/__init__.py
index 100b0a93..6f844602 100644
--- a/app/models/__init__.py
+++ b/app/models/__init__.py
@@ -48,13 +48,17 @@ from app.models.formsemestre import (
     FormsemestreCustomMenu,
     FormsemestreInscription,
     notes_formsemestre_responsables,
+    NotesSemSet,
+    notes_semset_formsemestre,
+)
+from app.models.moduleimpls import (
     ModuleImpl,
     notes_modules_enseignants,
     ModuleImplInscription,
+)
+from app.models.evaluations import (
     Evaluation,
     EvaluationUEPoids,
-    NotesSemSet,
-    notes_semset_formsemestre,
 )
 from app.models.but_pn import AppCrit
 from app.models.groups import Partition, GroupDescr, group_membership
diff --git a/app/models/evaluations.py b/app/models/evaluations.py
new file mode 100644
index 00000000..c5085ae6
--- /dev/null
+++ b/app/models/evaluations.py
@@ -0,0 +1,123 @@
+# -*- coding: UTF-8 -*
+
+"""ScoDoc models: evaluations
+"""
+from typing import Any
+
+from app import db
+from app.models import APO_CODE_STR_LEN
+from app.models import SHORT_STR_LEN
+from app.models import CODE_STR_LEN
+from app.models import UniteEns
+
+import app.scodoc.notesdb as ndb
+from app.scodoc import sco_evaluation_db
+
+
+class Evaluation(db.Model):
+    """Evaluation (contrôle, examen, ...)"""
+
+    __tablename__ = "notes_evaluation"
+
+    id = db.Column(db.Integer, primary_key=True)
+    evaluation_id = db.synonym("id")
+    moduleimpl_id = db.Column(
+        db.Integer, db.ForeignKey("notes_moduleimpl.id"), index=True
+    )
+    jour = db.Column(db.Date)
+    heure_debut = db.Column(db.Time)
+    heure_fin = db.Column(db.Time)
+    description = db.Column(db.Text)
+    note_max = db.Column(db.Float)
+    coefficient = db.Column(db.Float)
+    visibulletin = db.Column(
+        db.Boolean, nullable=False, default=True, server_default="true"
+    )
+    publish_incomplete = db.Column(
+        db.Boolean, nullable=False, default=False, server_default="false"
+    )
+    # type d'evaluation: 0 normale, 1 rattrapage, 2 "2eme session"
+    evaluation_type = db.Column(
+        db.Integer, nullable=False, default=0, server_default="0"
+    )
+    # ordre de presentation (par défaut, le plus petit numero
+    # est la plus ancienne eval):
+    numero = db.Column(db.Integer)
+    ues = db.relationship("UniteEns", secondary="evaluation_ue_poids", viewonly=True)
+
+    def to_dict(self):
+        e = dict(self.__dict__)
+        e.pop("_sa_instance_state", None)
+        # ScoDoc7 output_formators
+        e["jour"] = ndb.DateISOtoDMY(e["jour"])
+        e["numero"] = ndb.int_null_is_zero(e["numero"])
+        return sco_evaluation_db.evaluation_enrich_dict(e)
+
+    # def from_dict(self, data):
+    #     """Set evaluation attributes from given dict values."""
+    #     sco_evaluation_db._check_evaluation_args(data)
+    #     for field in [
+    #         "moduleimpl_id",
+    #         "jour",
+    #         "heure_debut",
+    #         "heure_fin",
+    #         "description",
+    #         "note_max",
+    #         "coefficient",
+    #         "visibulletin",
+    #         "publish_incomplete",
+    #         "evaluation_type",
+    #         "numero",
+    #     ]:
+    #         if field in data:
+    #             setattr(self, field, data[field] or None)
+
+    def set_ue_poids(self, ue, poids: float):
+        """Set poids évaluation vers cette UE"""
+        self.update_ue_poids_dict({ue.id: poids})
+
+    def set_ue_poids_dict(self, ue_poids_dict: dict):
+        """set poids vers les UE (remplace existants)
+        ue_poids_dict = { ue_id : poids }
+        """
+        L = []
+        for ue_id, poids in ue_poids_dict.items():
+            ue = UniteEns.query.get(ue_id)
+            L.append(EvaluationUEPoids(evaluation=self, ue=ue, poids=poids))
+        self.ue_poids = L
+
+    def update_ue_poids_dict(self, ue_poids_dict: dict):
+        """update poids vers UE (ajoute aux existants)"""
+        current = self.get_ue_poids_dict()
+        current.update(ue_poids_dict)
+        self.set_ue_poids_dict(current)
+
+    def get_ue_poids_dict(self):
+        """returns { ue_id : poids }"""
+        return {p.ue.id: p.poids for p in self.ue_poids}
+
+
+class EvaluationUEPoids(db.Model):
+    """Poids des évaluations (BUT)
+    association many to many
+    """
+
+    evaluation_id = db.Column(
+        db.Integer, db.ForeignKey("notes_evaluation.id"), primary_key=True
+    )
+    ue_id = db.Column(db.Integer, db.ForeignKey("notes_ue.id"), primary_key=True)
+    poids = db.Column(
+        db.Float,
+        nullable=False,
+    )
+    evaluation = db.relationship(
+        Evaluation,
+        backref=db.backref("ue_poids", cascade="all, delete-orphan"),
+    )
+    ue = db.relationship(
+        UniteEns,
+        backref=db.backref("evaluation_ue_poids", cascade="all, delete-orphan"),
+    )
+
+    def __repr__(self):
+        return f"<EvaluationUEPoids {self.evaluation} {self.ue} poids={self.poids}>"
diff --git a/app/models/formsemestre.py b/app/models/formsemestre.py
index f4eb8da3..1207d6bf 100644
--- a/app/models/formsemestre.py
+++ b/app/models/formsemestre.py
@@ -1,6 +1,6 @@
 # -*- coding: UTF-8 -*
 
-"""ScoDoc models
+"""ScoDoc models: formsemestre
 """
 from typing import Any
 
@@ -15,9 +15,7 @@ from app.scodoc import sco_evaluation_db
 
 
 class FormSemestre(db.Model):
-    """Mise en oeuvre d'un semestre de formation
-    was notes_formsemestre
-    """
+    """Mise en oeuvre d'un semestre de formation"""
 
     __tablename__ = "notes_formsemestre"
 
@@ -89,6 +87,9 @@ class FormSemestre(db.Model):
         if self.modalite is None:
             self.modalite = FormationModalite.DEFAULT_MODALITE
 
+    def get_ues(self):
+        "UE des modules de ce semestre"
+
 
 # Association id des utilisateurs responsables (aka directeurs des etudes) du semestre
 notes_formsemestre_responsables = db.Table(
@@ -240,167 +241,6 @@ class FormsemestreInscription(db.Model):
     etape = db.Column(db.String(APO_CODE_STR_LEN))
 
 
-class ModuleImpl(db.Model):
-    """Mise en oeuvre d'un module pour une annee/semestre"""
-
-    __tablename__ = "notes_moduleimpl"
-    __table_args__ = (db.UniqueConstraint("formsemestre_id", "module_id"),)
-
-    id = db.Column(db.Integer, primary_key=True)
-    moduleimpl_id = db.synonym("id")
-    module_id = db.Column(
-        db.Integer,
-        db.ForeignKey("notes_modules.id"),
-    )
-    formsemestre_id = db.Column(
-        db.Integer,
-        db.ForeignKey("notes_formsemestre.id"),
-        index=True,
-    )
-    responsable_id = db.Column("responsable_id", db.Integer, db.ForeignKey("user.id"))
-    # formule de calcul moyenne:
-    computation_expr = db.Column(db.Text())
-
-
-# Enseignants (chargés de TD ou TP) d'un moduleimpl
-notes_modules_enseignants = db.Table(
-    "notes_modules_enseignants",
-    db.Column(
-        "moduleimpl_id",
-        db.Integer,
-        db.ForeignKey("notes_moduleimpl.id"),
-    ),
-    db.Column("ens_id", db.Integer, db.ForeignKey("user.id")),
-    # ? db.UniqueConstraint("moduleimpl_id", "ens_id"),
-)
-# XXX il manque probablement une relation pour gérer cela
-
-
-class ModuleImplInscription(db.Model):
-    """Inscription à un module  (etudiants,moduleimpl)"""
-
-    __tablename__ = "notes_moduleimpl_inscription"
-    __table_args__ = (db.UniqueConstraint("moduleimpl_id", "etudid"),)
-
-    id = db.Column(db.Integer, primary_key=True)
-    moduleimpl_inscription_id = db.synonym("id")
-    moduleimpl_id = db.Column(
-        db.Integer,
-        db.ForeignKey("notes_moduleimpl.id"),
-        index=True,
-    )
-    etudid = db.Column(db.Integer, db.ForeignKey("identite.id"), index=True)
-
-
-class Evaluation(db.Model):
-    """Evaluation (contrôle, examen, ...)"""
-
-    __tablename__ = "notes_evaluation"
-
-    id = db.Column(db.Integer, primary_key=True)
-    evaluation_id = db.synonym("id")
-    moduleimpl_id = db.Column(
-        db.Integer, db.ForeignKey("notes_moduleimpl.id"), index=True
-    )
-    jour = db.Column(db.Date)
-    heure_debut = db.Column(db.Time)
-    heure_fin = db.Column(db.Time)
-    description = db.Column(db.Text)
-    note_max = db.Column(db.Float)
-    coefficient = db.Column(db.Float)
-    visibulletin = db.Column(
-        db.Boolean, nullable=False, default=True, server_default="true"
-    )
-    publish_incomplete = db.Column(
-        db.Boolean, nullable=False, default=False, server_default="false"
-    )
-    # type d'evaluation: 0 normale, 1 rattrapage, 2 "2eme session"
-    evaluation_type = db.Column(
-        db.Integer, nullable=False, default=0, server_default="0"
-    )
-    # ordre de presentation (par défaut, le plus petit numero
-    # est la plus ancienne eval):
-    numero = db.Column(db.Integer)
-    ues = db.relationship("UniteEns", secondary="evaluation_ue_poids", viewonly=True)
-
-    def to_dict(self):
-        e = dict(self.__dict__)
-        e.pop("_sa_instance_state", None)
-        # ScoDoc7 output_formators
-        e["jour"] = ndb.DateISOtoDMY(e["jour"])
-        e["numero"] = ndb.int_null_is_zero(e["numero"])
-        return sco_evaluation_db.evaluation_enrich_dict(e)
-
-    # def from_dict(self, data):
-    #     """Set evaluation attributes from given dict values."""
-    #     sco_evaluation_db._check_evaluation_args(data)
-    #     for field in [
-    #         "moduleimpl_id",
-    #         "jour",
-    #         "heure_debut",
-    #         "heure_fin",
-    #         "description",
-    #         "note_max",
-    #         "coefficient",
-    #         "visibulletin",
-    #         "publish_incomplete",
-    #         "evaluation_type",
-    #         "numero",
-    #     ]:
-    #         if field in data:
-    #             setattr(self, field, data[field] or None)
-
-    def set_ue_poids(self, ue, poids: float):
-        """Set poids évaluation vers cette UE"""
-        self.update_ue_poids_dict({ue.id: poids})
-
-    def set_ue_poids_dict(self, ue_poids_dict: dict):
-        """set poids vers les UE (remplace existants)
-        ue_poids_dict = { ue_id : poids }
-        """
-        L = []
-        for ue_id, poids in ue_poids_dict.items():
-            ue = UniteEns.query.get(ue_id)
-            L.append(EvaluationUEPoids(evaluation=self, ue=ue, poids=poids))
-        self.ue_poids = L
-
-    def update_ue_poids_dict(self, ue_poids_dict: dict):
-        """update poids vers UE (ajoute aux existants)"""
-        current = self.get_ue_poids_dict()
-        current.update(ue_poids_dict)
-        self.set_ue_poids_dict(current)
-
-    def get_ue_poids_dict(self):
-        """returns { ue_id : poids }"""
-        return {p.ue.id: p.poids for p in self.ue_poids}
-
-
-class EvaluationUEPoids(db.Model):
-    """Poids des évaluations (BUT)
-    association many to many
-    """
-
-    evaluation_id = db.Column(
-        db.Integer, db.ForeignKey("notes_evaluation.id"), primary_key=True
-    )
-    ue_id = db.Column(db.Integer, db.ForeignKey("notes_ue.id"), primary_key=True)
-    poids = db.Column(
-        db.Float,
-        nullable=False,
-    )
-    evaluation = db.relationship(
-        Evaluation,
-        backref=db.backref("ue_poids", cascade="all, delete-orphan"),
-    )
-    ue = db.relationship(
-        UniteEns,
-        backref=db.backref("evaluation_ue_poids", cascade="all, delete-orphan"),
-    )
-
-    def __repr__(self):
-        return f"<EvaluationUEPoids {self.evaluation} {self.ue} poids={self.poids}>"
-
-
 class NotesSemSet(db.Model):
     """semsets: ensemble de formsemestres pour exports Apogée"""
 
diff --git a/app/models/moduleimpls.py b/app/models/moduleimpls.py
new file mode 100644
index 00000000..66568802
--- /dev/null
+++ b/app/models/moduleimpls.py
@@ -0,0 +1,66 @@
+# -*- coding: UTF-8 -*
+
+"""ScoDoc models: moduleimpls
+"""
+from typing import Any
+
+from app import db
+from app.models import APO_CODE_STR_LEN
+from app.models import SHORT_STR_LEN
+from app.models import CODE_STR_LEN
+from app.models import UniteEns
+
+import app.scodoc.notesdb as ndb
+from app.scodoc import sco_evaluation_db
+
+
+class ModuleImpl(db.Model):
+    """Mise en oeuvre d'un module pour une annee/semestre"""
+
+    __tablename__ = "notes_moduleimpl"
+    __table_args__ = (db.UniqueConstraint("formsemestre_id", "module_id"),)
+
+    id = db.Column(db.Integer, primary_key=True)
+    moduleimpl_id = db.synonym("id")
+    module_id = db.Column(
+        db.Integer,
+        db.ForeignKey("notes_modules.id"),
+    )
+    formsemestre_id = db.Column(
+        db.Integer,
+        db.ForeignKey("notes_formsemestre.id"),
+        index=True,
+    )
+    responsable_id = db.Column("responsable_id", db.Integer, db.ForeignKey("user.id"))
+    # formule de calcul moyenne:
+    computation_expr = db.Column(db.Text())
+
+
+# Enseignants (chargés de TD ou TP) d'un moduleimpl
+notes_modules_enseignants = db.Table(
+    "notes_modules_enseignants",
+    db.Column(
+        "moduleimpl_id",
+        db.Integer,
+        db.ForeignKey("notes_moduleimpl.id"),
+    ),
+    db.Column("ens_id", db.Integer, db.ForeignKey("user.id")),
+    # ? db.UniqueConstraint("moduleimpl_id", "ens_id"),
+)
+# XXX il manque probablement une relation pour gérer cela
+
+
+class ModuleImplInscription(db.Model):
+    """Inscription à un module  (etudiants,moduleimpl)"""
+
+    __tablename__ = "notes_moduleimpl_inscription"
+    __table_args__ = (db.UniqueConstraint("moduleimpl_id", "etudid"),)
+
+    id = db.Column(db.Integer, primary_key=True)
+    moduleimpl_inscription_id = db.synonym("id")
+    moduleimpl_id = db.Column(
+        db.Integer,
+        db.ForeignKey("notes_moduleimpl.id"),
+        index=True,
+    )
+    etudid = db.Column(db.Integer, db.ForeignKey("identite.id"), index=True)