Edition formation BUT: affiche UE de rattachement et force cohérence semestre module/UE

This commit is contained in:
Emmanuel Viennet 2021-12-16 16:27:35 +01:00
parent bf14f8ed34
commit d40d82aeb7
11 changed files with 65 additions and 27 deletions

View File

@ -2,11 +2,12 @@
""" """
from app import db from app import db
from app.comp import df_cache
from app.models import SHORT_STR_LEN from app.models import SHORT_STR_LEN
from app.scodoc import notesdb as ndb 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.scodoc import sco_codes_parcours
from app.comp import df_cache from app.scodoc import sco_utils as scu
class Formation(db.Model): class Formation(db.Model):
@ -76,6 +77,10 @@ class Formation(db.Model):
df_cache.ModuleCoefsCache.set(key, modules_coefficients) df_cache.ModuleCoefsCache.set(key, modules_coefficients)
return 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): def invalidate_module_coefs(self, semestre_idx: int = None):
"""Invalide les coefficients de modules cachés. """Invalide les coefficients de modules cachés.
Si semestre_idx est None, invalide tous les semestres, Si semestre_idx est None, invalide tous les semestres,
@ -86,6 +91,36 @@ class Formation(db.Model):
else: else:
keys = f"{self.id}.{semestre_idx}" keys = f"{self.id}.{semestre_idx}"
df_cache.ModuleCoefsCache.delete_many(keys | {f"{self.id}"}) 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): class Matiere(db.Model):

View File

@ -27,6 +27,7 @@ class Module(db.Model):
formation_id = db.Column(db.Integer, db.ForeignKey("notes_formations.id")) formation_id = db.Column(db.Integer, db.ForeignKey("notes_formations.id"))
matiere_id = db.Column(db.Integer, db.ForeignKey("notes_matieres.id")) matiere_id = db.Column(db.Integer, db.ForeignKey("notes_matieres.id"))
# pas un id mais le numéro du semestre: 1, 2, ... # 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") semestre_id = db.Column(db.Integer, nullable=False, default=1, server_default="1")
numero = db.Column(db.Integer) # ordre de présentation numero = db.Column(db.Integer) # ordre de présentation
# id de l'element pedagogique Apogee correspondant: # id de l'element pedagogique Apogee correspondant:

View File

@ -33,6 +33,7 @@ from flask import g, url_for, request
from app import db from app import db
from app import log from app import log
from app.models.formations import Formation
from app.models.modules import Module from app.models.modules import Module
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
@ -301,17 +302,9 @@ def do_formation_edit(args):
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()
sco_formations._formationEditor.edit(cnx, args) sco_formations._formationEditor.edit(cnx, args)
invalidate_sems_in_formation(args["formation_id"]) formation = Formation.query.get(args["formation_id"])
formation.invalidate_cached_sems()
formation.force_semestre_modules_aux_ues()
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.
def objects_renumber(obj_list) -> None: def objects_renumber(obj_list) -> None:

View File

@ -34,6 +34,7 @@ from flask import g, url_for, request
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app import log from app import log
from app.models import Formation
from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
from app.scodoc.sco_exceptions import ScoValueError, ScoLockedFormError from app.scodoc.sco_exceptions import ScoValueError, ScoLockedFormError
from app.scodoc import html_sco_header from app.scodoc import html_sco_header
@ -66,7 +67,7 @@ def do_matiere_edit(*args, **kw):
# edit # edit
_matiereEditor.edit(cnx, *args, **kw) _matiereEditor.edit(cnx, *args, **kw)
formation_id = sco_edit_ue.ue_list({"ue_id": mat["ue_id"]})[0]["formation_id"] 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): def do_matiere_create(args):

View File

@ -39,6 +39,7 @@ import app.scodoc.sco_utils as scu
from app.scodoc.sco_utils import ModuleType from app.scodoc.sco_utils import ModuleType
from app import log from app import log
from app import models from app import models
from app.models import Formation
from app.scodoc.TrivialFormulator import TrivialFormulator from app.scodoc.TrivialFormulator import TrivialFormulator
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
from app.scodoc.sco_exceptions import ScoValueError, ScoLockedFormError, ScoGenError from app.scodoc.sco_exceptions import ScoValueError, ScoLockedFormError, ScoGenError
@ -411,7 +412,7 @@ def do_module_edit(val):
# edit # edit
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()
_moduleEditor.edit(cnx, val) _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): def check_module_code_unicity(code, field, formation_id, module_id=None):

View File

@ -1155,9 +1155,11 @@ def do_ue_edit(args, bypass_lock=False, dont_invalidate_cache=False):
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()
_ueEditor.edit(cnx, args) _ueEditor.edit(cnx, args)
formation = Formation.query.get(ue["formation_id"])
if not dont_invalidate_cache: if not dont_invalidate_cache:
# Invalide les semestres utilisant cette formation: # 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: # essai edition en ligne:

View File

@ -86,12 +86,10 @@ def formation_list(formation_id=None, args={}):
return r return r
def formation_has_locked_sems(formation_id): def formation_has_locked_sems(formation_id): # XXX to remove
"True if there is a locked formsemestre in this formation" "backward compat: True if there is a locked formsemestre in this formation"
sems = sco_formsemestre.do_formsemestre_list( formation = Formation.query.get(formation_id)
args={"formation_id": formation_id, "etat": False} return formation.has_locked_sems()
)
return sems
def formation_export( def formation_export(

View File

@ -1619,6 +1619,9 @@ li.module_malus span.formation_module_tit {
text-decoration: underline; text-decoration: underline;
} }
span.formation_module_ue {
background-color: #b7d2fa;
}
span.notes_module_list_buts { span.notes_module_list_buts {
margin-right: 5px; margin-right: 5px;
} }

View File

@ -46,11 +46,13 @@
</a> </a>
{% endif %} {% endif %}
(<span class="formation_module_ue"><a title="UE de rattachement">{{mod.ue.acronyme}}</a></span>),
{{formation.get_parcours().SESSION_NAME}} {{mod.semestre_id}} {{formation.get_parcours().SESSION_NAME}} {{mod.semestre_id}}
({{mod.heures_cours|default("&nbsp;",true)|safe}}/{{mod.heures_td|default("&nbsp;",true)|safe}}/{{mod.heures_tp|default("&nbsp;",true)|safe}}, {% if mod.heures_cours or mod.heures_td or mod.heures_tp %}
({{mod.heures_cours|default("&nbsp;",true)|safe}}/{{mod.heures_td|default("&nbsp;",true)|safe}}/{{mod.heures_tp|default("&nbsp;",true)|safe}},
Apo:<span class="{% if editable %}span_apo_edit{% endif %}" {% else %}
({% endif %}Apo:<span class="{% if editable %}span_apo_edit{% endif %}"
data-url="edit_module_set_code_apogee" data-url="edit_module_set_code_apogee"
id="{{mod.id}}" id="{{mod.id}}"
data-placeholder="{{scu.APO_MISSING_CODE_STR}}"> data-placeholder="{{scu.APO_MISSING_CODE_STR}}">

View File

@ -402,7 +402,8 @@ def ue_set_internal(ue_id):
db.session.add(ue) db.session.add(ue)
db.session.commit() db.session.commit()
# Invalide les semestres de cette formation # Invalide les semestres de cette formation
sco_edit_formation.invalidate_sems_in_formation(ue.formation_id) ue.formation.invalidate_cached_sems()
return redirect( return redirect(
url_for( url_for(
"notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=ue.formation_id "notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=ue.formation_id

View File

@ -144,7 +144,8 @@ def set_module_ue_coef():
return scu.json_error(f"UE not found ({ue_id})", 404) return scu.json_error(f"UE not found ({ue_id})", 404)
module.set_ue_coef(ue, coef) module.set_ue_coef(ue, coef)
db.session.commit() 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) return scu.json_error("ok", success=True, status=201)