From d40d82aeb79518fcfa408f84a456cba3df96ad83 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Thu, 16 Dec 2021 16:27:35 +0100 Subject: [PATCH] =?UTF-8?q?Edition=20formation=20BUT:=20affiche=20UE=20de?= =?UTF-8?q?=20rattachement=20et=20force=20coh=C3=A9rence=20semestre=20modu?= =?UTF-8?q?le/UE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/formations.py | 39 ++++++++++++++++++++++++++++++-- app/models/modules.py | 1 + app/scodoc/sco_edit_formation.py | 15 ++++-------- app/scodoc/sco_edit_matiere.py | 3 ++- app/scodoc/sco_edit_module.py | 3 ++- app/scodoc/sco_edit_ue.py | 4 +++- app/scodoc/sco_formations.py | 10 ++++---- app/static/css/scodoc.css | 3 +++ app/templates/pn/form_mods.html | 8 ++++--- app/views/notes.py | 3 ++- app/views/pn_modules.py | 3 ++- 11 files changed, 65 insertions(+), 27 deletions(-) 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)