diff --git a/app/models/formations.py b/app/models/formations.py
index 55de77f7a..3abbf3882 100644
--- a/app/models/formations.py
+++ b/app/models/formations.py
@@ -2,11 +2,12 @@
"""
from app import db
+from app.comp import df_cache
from app.models import SHORT_STR_LEN
from app.scodoc import notesdb as ndb
-from app.scodoc import sco_utils as scu
+from app.scodoc import sco_cache
from app.scodoc import sco_codes_parcours
-from app.comp import df_cache
+from app.scodoc import sco_utils as scu
class Formation(db.Model):
@@ -76,6 +77,10 @@ class Formation(db.Model):
df_cache.ModuleCoefsCache.set(key, modules_coefficients)
return modules_coefficients
+ def has_locked_sems(self):
+ "True if there is a locked formsemestre in this formation"
+ return len(self.formsemestres.filter_by(etat=False).all()) > 0
+
def invalidate_module_coefs(self, semestre_idx: int = None):
"""Invalide les coefficients de modules cachés.
Si semestre_idx est None, invalide tous les semestres,
@@ -86,6 +91,36 @@ class Formation(db.Model):
else:
keys = f"{self.id}.{semestre_idx}"
df_cache.ModuleCoefsCache.delete_many(keys | {f"{self.id}"})
+ sco_cache.invalidate_formsemestre()
+
+ def invalidate_cached_sems(self):
+ for sem in self.formsemestres:
+ sco_cache.invalidate_formsemestre(formsemestre_id=sem.id)
+
+ def force_semestre_modules_aux_ues(self) -> None:
+ """
+ Affecte à chaque module de cette formation le semestre de son UE de rattachement,
+ si elle en a une.
+ Devrait être appelé lorsqu'on change le type de formation vers le BUT, et aussi
+ lorsqu'on change le semestre d'une UE BUT.
+ Utile pour la migration des anciennes formations vers le BUT.
+ Invalide les caches coefs/poids.
+ """
+ if not self.is_apc():
+ return
+ change = False
+ for mod in self.modules:
+ if (
+ mod.ue.semestre_idx is not None
+ and mod.ue.semestre_idx > 0
+ and mod.semestre_id != mod.ue.semestre_idx
+ ):
+ mod.semestre_id = mod.ue.semestre_idx
+ db.session.add(mod)
+ change = True
+ db.session.commit()
+ if change:
+ self.invalidate_module_coefs()
class Matiere(db.Model):
diff --git a/app/models/modules.py b/app/models/modules.py
index d1affad02..00a6d4c9b 100644
--- a/app/models/modules.py
+++ b/app/models/modules.py
@@ -27,6 +27,7 @@ class Module(db.Model):
formation_id = db.Column(db.Integer, db.ForeignKey("notes_formations.id"))
matiere_id = db.Column(db.Integer, db.ForeignKey("notes_matieres.id"))
# pas un id mais le numéro du semestre: 1, 2, ...
+ # note: en APC, le semestre qui fait autorité est celui de l'UE
semestre_id = db.Column(db.Integer, nullable=False, default=1, server_default="1")
numero = db.Column(db.Integer) # ordre de présentation
# id de l'element pedagogique Apogee correspondant:
diff --git a/app/scodoc/sco_edit_formation.py b/app/scodoc/sco_edit_formation.py
index a609a8418..f53275843 100644
--- a/app/scodoc/sco_edit_formation.py
+++ b/app/scodoc/sco_edit_formation.py
@@ -33,6 +33,7 @@ from flask import g, url_for, request
from app import db
from app import log
+from app.models.formations import Formation
from app.models.modules import Module
import app.scodoc.notesdb as ndb
@@ -301,17 +302,9 @@ def do_formation_edit(args):
cnx = ndb.GetDBConnexion()
sco_formations._formationEditor.edit(cnx, args)
- invalidate_sems_in_formation(args["formation_id"])
-
-
-def invalidate_sems_in_formation(formation_id):
- "Invalide les semestres utilisant cette formation"
- for sem in sco_formsemestre.do_formsemestre_list(
- args={"formation_id": formation_id}
- ):
- sco_cache.invalidate_formsemestre(
- formsemestre_id=sem["formsemestre_id"]
- ) # > formation modif.
+ formation = Formation.query.get(args["formation_id"])
+ formation.invalidate_cached_sems()
+ formation.force_semestre_modules_aux_ues()
def objects_renumber(obj_list) -> None:
diff --git a/app/scodoc/sco_edit_matiere.py b/app/scodoc/sco_edit_matiere.py
index f07b9b588..8e957ab8b 100644
--- a/app/scodoc/sco_edit_matiere.py
+++ b/app/scodoc/sco_edit_matiere.py
@@ -34,6 +34,7 @@ from flask import g, url_for, request
import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu
from app import log
+from app.models import Formation
from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
from app.scodoc.sco_exceptions import ScoValueError, ScoLockedFormError
from app.scodoc import html_sco_header
@@ -66,7 +67,7 @@ def do_matiere_edit(*args, **kw):
# edit
_matiereEditor.edit(cnx, *args, **kw)
formation_id = sco_edit_ue.ue_list({"ue_id": mat["ue_id"]})[0]["formation_id"]
- sco_edit_formation.invalidate_sems_in_formation(formation_id)
+ Formation.query.get(formation_id).invalidate_cached_sems()
def do_matiere_create(args):
diff --git a/app/scodoc/sco_edit_module.py b/app/scodoc/sco_edit_module.py
index 5e804b324..24232164a 100644
--- a/app/scodoc/sco_edit_module.py
+++ b/app/scodoc/sco_edit_module.py
@@ -39,6 +39,7 @@ import app.scodoc.sco_utils as scu
from app.scodoc.sco_utils import ModuleType
from app import log
from app import models
+from app.models import Formation
from app.scodoc.TrivialFormulator import TrivialFormulator
from app.scodoc.sco_permissions import Permission
from app.scodoc.sco_exceptions import ScoValueError, ScoLockedFormError, ScoGenError
@@ -411,7 +412,7 @@ def do_module_edit(val):
# edit
cnx = ndb.GetDBConnexion()
_moduleEditor.edit(cnx, val)
- sco_edit_formation.invalidate_sems_in_formation(mod["formation_id"])
+ Formation.query.get(mod["formation_id"]).invalidate_cached_sems()
def check_module_code_unicity(code, field, formation_id, module_id=None):
diff --git a/app/scodoc/sco_edit_ue.py b/app/scodoc/sco_edit_ue.py
index 6e05fc4a9..cd5dcb7e3 100644
--- a/app/scodoc/sco_edit_ue.py
+++ b/app/scodoc/sco_edit_ue.py
@@ -1155,9 +1155,11 @@ def do_ue_edit(args, bypass_lock=False, dont_invalidate_cache=False):
cnx = ndb.GetDBConnexion()
_ueEditor.edit(cnx, args)
+ formation = Formation.query.get(ue["formation_id"])
if not dont_invalidate_cache:
# Invalide les semestres utilisant cette formation:
- sco_edit_formation.invalidate_sems_in_formation(ue["formation_id"])
+ formation.invalidate_cached_sems()
+ formation.force_semestre_modules_aux_ues()
# essai edition en ligne:
diff --git a/app/scodoc/sco_formations.py b/app/scodoc/sco_formations.py
index 81dede630..b2eaef981 100644
--- a/app/scodoc/sco_formations.py
+++ b/app/scodoc/sco_formations.py
@@ -86,12 +86,10 @@ def formation_list(formation_id=None, args={}):
return r
-def formation_has_locked_sems(formation_id):
- "True if there is a locked formsemestre in this formation"
- sems = sco_formsemestre.do_formsemestre_list(
- args={"formation_id": formation_id, "etat": False}
- )
- return sems
+def formation_has_locked_sems(formation_id): # XXX to remove
+ "backward compat: True if there is a locked formsemestre in this formation"
+ formation = Formation.query.get(formation_id)
+ return formation.has_locked_sems()
def formation_export(
diff --git a/app/static/css/scodoc.css b/app/static/css/scodoc.css
index ac0751281..4de392092 100644
--- a/app/static/css/scodoc.css
+++ b/app/static/css/scodoc.css
@@ -1619,6 +1619,9 @@ li.module_malus span.formation_module_tit {
text-decoration: underline;
}
+span.formation_module_ue {
+ background-color: #b7d2fa;
+}
span.notes_module_list_buts {
margin-right: 5px;
}
diff --git a/app/templates/pn/form_mods.html b/app/templates/pn/form_mods.html
index 045491f6e..90faee024 100644
--- a/app/templates/pn/form_mods.html
+++ b/app/templates/pn/form_mods.html
@@ -46,11 +46,13 @@
{% endif %}
+ ({{mod.ue.acronyme}}),
{{formation.get_parcours().SESSION_NAME}} {{mod.semestre_id}}
- ({{mod.heures_cours|default(" ",true)|safe}}/{{mod.heures_td|default(" ",true)|safe}}/{{mod.heures_tp|default(" ",true)|safe}},
-
- Apo:
diff --git a/app/views/notes.py b/app/views/notes.py
index 9a8797e61..8ec4702bb 100644
--- a/app/views/notes.py
+++ b/app/views/notes.py
@@ -402,7 +402,8 @@ def ue_set_internal(ue_id):
db.session.add(ue)
db.session.commit()
# Invalide les semestres de cette formation
- sco_edit_formation.invalidate_sems_in_formation(ue.formation_id)
+ ue.formation.invalidate_cached_sems()
+
return redirect(
url_for(
"notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=ue.formation_id
diff --git a/app/views/pn_modules.py b/app/views/pn_modules.py
index 0dc52d1bb..c3b18f355 100644
--- a/app/views/pn_modules.py
+++ b/app/views/pn_modules.py
@@ -144,7 +144,8 @@ def set_module_ue_coef():
return scu.json_error(f"UE not found ({ue_id})", 404)
module.set_ue_coef(ue, coef)
db.session.commit()
- sco_edit_formation.invalidate_sems_in_formation(module.formation_id)
+ module.formation.invalidate_cached_sems()
+
return scu.json_error("ok", success=True, status=201)