From ed0925419e400b760d1f09dbf1e571fc29eccf79 Mon Sep 17 00:00:00 2001 From: ilona Date: Thu, 24 Oct 2024 12:11:10 +0200 Subject: [PATCH] Modernisation code ModuleImpl. --- app/formations/edit_ue.py | 2 +- app/scodoc/sco_formsemestre_edit.py | 25 +++-- app/scodoc/sco_formsemestre_inscriptions.py | 23 +++-- app/scodoc/sco_groups_view.py | 9 +- app/scodoc/sco_moduleimpl.py | 107 -------------------- app/views/notes.py | 7 +- tests/unit/test_formations.py | 35 +++---- 7 files changed, 48 insertions(+), 160 deletions(-) diff --git a/app/formations/edit_ue.py b/app/formations/edit_ue.py index 483d9e1fa..c1d82361f 100644 --- a/app/formations/edit_ue.py +++ b/app/formations/edit_ue.py @@ -1121,7 +1121,7 @@ def _ue_table_ues( # Cas spécial: si l'UE externe a plus d'un module, c'est peut être une UE # qui a été déclarée externe par erreur (ou suite à un bug d'import/export xml) # Dans ce cas, propose de changer le type (même si verrouillée) - if len(sco_moduleimpl.moduleimpls_in_external_ue(ue.id)) > 1: + if ue.modules.count() > 1: H.append('') if has_perm_change: H.append( diff --git a/app/scodoc/sco_formsemestre_edit.py b/app/scodoc/sco_formsemestre_edit.py index 0060b9b03..48db1a13b 100644 --- a/app/scodoc/sco_formsemestre_edit.py +++ b/app/scodoc/sco_formsemestre_edit.py @@ -959,19 +959,15 @@ def do_formsemestre_createwithmodules(edit=False, formsemestre: FormSemestre = N modimpl.id}: aucun etudiant inscrit""" ) # - ok, diag = formsemestre_delete_moduleimpls(formsemestre.id, module_ids_todelete) + ok, diag = formsemestre_delete_moduleimpls(formsemestre, module_ids_todelete) msg += diag for module_id in module_ids_toedit: - moduleimpl_id = sco_moduleimpl.moduleimpl_list( - formsemestre_id=formsemestre.id, module_id=module_id - )[0]["moduleimpl_id"] - modargs = { - "moduleimpl_id": moduleimpl_id, - "module_id": module_id, - "formsemestre_id": formsemestre.id, - "responsable_id": tf[2]["MI" + str(module_id)], - } - sco_moduleimpl.do_moduleimpl_edit(modargs, formsemestre_id=formsemestre.id) + modimpl = formsemestre.modimpls.filter_by(module_id=module_id).first() + if not modimpl: + raise ScoValueError("Module introuvable ! Veuillez recharger la page.") + modimpl.responsable_id = tf[2]["MI" + str(module_id)] + db.session.add(modimpl) + db.session.commit() # --- Etapes _set_apo_etapes(formsemestre, tf[2], etapes) # --- id edt du groupe par défault @@ -983,6 +979,7 @@ def do_formsemestre_createwithmodules(edit=False, formsemestre: FormSemestre = N db.session.add(formsemestre) db.session.commit() + sco_cache.invalidate_formsemestre(formsemestre_id=formsemestre.id) # --- Crée ou met à jour les groupes de parcours BUT formsemestre.setup_parcours_groups() @@ -1109,7 +1106,9 @@ def _formsemestre_check_ue_bonus_unicity(module_ids): ) -def formsemestre_delete_moduleimpls(formsemestre_id, module_ids_to_del): +def formsemestre_delete_moduleimpls( + formsemestre: FormSemestre, module_ids_to_del: list[int] +) -> tuple[bool, list[str]]: """Delete moduleimpls module_ids_to_del: list of module_id (warning: not moduleimpl) Moduleimpls must have no associated evaluations. @@ -1121,7 +1120,7 @@ def formsemestre_delete_moduleimpls(formsemestre_id, module_ids_to_del): if module is None: continue # ignore invalid ids modimpls = ModuleImpl.query.filter_by( - formsemestre_id=formsemestre_id, module_id=module_id + formsemestre_id=formsemestre.id, module_id=module_id ) for modimpl in modimpls: nb_evals = modimpl.evaluations.count() diff --git a/app/scodoc/sco_formsemestre_inscriptions.py b/app/scodoc/sco_formsemestre_inscriptions.py index e8ce67ce1..33ffb4bdb 100644 --- a/app/scodoc/sco_formsemestre_inscriptions.py +++ b/app/scodoc/sco_formsemestre_inscriptions.py @@ -35,7 +35,13 @@ from flask import flash, url_for, g, render_template, request from app import db from app.comp import res_sem from app.comp.res_compat import NotesTableCompat -from app.models import Formation, FormSemestre, FormSemestreInscription, Scolog +from app.models import ( + Formation, + FormSemestre, + FormSemestreInscription, + ModuleImpl, + Scolog, +) from app.models.etudiants import Identite from app.models.groups import Partition, GroupDescr from app.models.scolar_event import ScolarEvent @@ -729,23 +735,22 @@ def do_moduleimpl_incription_options( # inscriptions for moduleimpl_id in a_inscrire: # verifie que ce module existe bien - mods = sco_moduleimpl.moduleimpl_list(moduleimpl_id=moduleimpl_id) - if len(mods) != 1: + modimpl = db.session.query(ModuleImpl).get(moduleimpl_id) + if modimpl is None: raise ScoValueError(f"inscription: invalid moduleimpl_id: {moduleimpl_id}") - mod = mods[0] + sco_moduleimpl.do_moduleimpl_inscription_create( {"moduleimpl_id": moduleimpl_id, "etudid": etudid}, - formsemestre_id=mod["formsemestre_id"], + formsemestre_id=modimpl.formsemestre_id, ) # desinscriptions for moduleimpl_id in a_desinscrire: # verifie que ce module existe bien - mods = sco_moduleimpl.moduleimpl_list(moduleimpl_id=moduleimpl_id) - if len(mods) != 1: + modimpl = db.session.query(ModuleImpl).get(moduleimpl_id) + if modimpl is None: raise ScoValueError( f"desinscription: invalid moduleimpl_id: {moduleimpl_id}" ) - mod = mods[0] inscr = sco_moduleimpl.do_moduleimpl_inscription_list( moduleimpl_id=moduleimpl_id, etudid=etudid ) @@ -755,7 +760,7 @@ def do_moduleimpl_incription_options( ) oid = inscr[0]["moduleimpl_inscription_id"] sco_moduleimpl.do_moduleimpl_inscription_delete( - oid, formsemestre_id=mod["formsemestre_id"] + oid, formsemestre_id=modimpl.formsemestre_id ) H = [ diff --git a/app/scodoc/sco_groups_view.py b/app/scodoc/sco_groups_view.py index 75f65e6ea..f38c4cf90 100644 --- a/app/scodoc/sco_groups_view.py +++ b/app/scodoc/sco_groups_view.py @@ -40,13 +40,12 @@ from flask import url_for, g, render_template, request from flask_login import current_user from app import db, log -from app.models import FormSemestre, Identite, ScolarEvent +from app.models import FormSemestre, Identite, ModuleImpl, ScolarEvent import app.scodoc.sco_utils as scu from app.scodoc import sco_assiduites as scass from app.scodoc import sco_excel from app.scodoc import sco_formsemestre from app.scodoc import sco_groups -from app.scodoc import sco_moduleimpl from app.scodoc import sco_cursus from app.scodoc import sco_portal_apogee from app.scodoc import sco_preferences @@ -364,10 +363,10 @@ class DisplayedGroupsInfos: "identifiant de groupe invalide (mettre à jour vos bookmarks ?)" ) from exc if not formsemestre_id and moduleimpl_id: - mods = sco_moduleimpl.moduleimpl_list(moduleimpl_id=moduleimpl_id) - if len(mods) != 1: + modimpl = db.session.get(ModuleImpl, moduleimpl_id) + if modimpl is None: raise ValueError("invalid moduleimpl_id") - formsemestre_id = mods[0]["formsemestre_id"] + formsemestre_id = modimpl.formsemestre_id if not group_ids: # appel sans groupe (eg page accueil) if not formsemestre_id: diff --git a/app/scodoc/sco_moduleimpl.py b/app/scodoc/sco_moduleimpl.py index 6891f8d66..0aeaf8982 100644 --- a/app/scodoc/sco_moduleimpl.py +++ b/app/scodoc/sco_moduleimpl.py @@ -35,81 +35,6 @@ from app.scodoc import sco_cache import app.scodoc.notesdb as ndb from app.scodoc.sco_exceptions import ScoValueError -# --- Gestion des "Implémentations de Modules" -# Un "moduleimpl" correspond a la mise en oeuvre d'un module -# dans une formation spécifique, à une date spécifique. -_moduleimplEditor = ndb.EditableTable( - "notes_moduleimpl", - "moduleimpl_id", - ( - "moduleimpl_id", - "module_id", - "formsemestre_id", - "responsable_id", - "computation_expr", - ), -) - - -def do_moduleimpl_delete(oid, formsemestre_id=None): - "delete moduleimpl (desinscrit tous les etudiants)" - cnx = ndb.GetDBConnexion() - # --- desinscription des etudiants - cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) - req = ( - "DELETE FROM notes_moduleimpl_inscription WHERE moduleimpl_id=%(moduleimpl_id)s" - ) - cursor.execute(req, {"moduleimpl_id": oid}) - # --- suppression des enseignants - cursor.execute( - "DELETE FROM notes_modules_enseignants WHERE moduleimpl_id=%(moduleimpl_id)s", - {"moduleimpl_id": oid}, - ) - # --- suppression des references dans les absences - cursor.execute( - "UPDATE absences SET moduleimpl_id=NULL WHERE moduleimpl_id=%(moduleimpl_id)s", - {"moduleimpl_id": oid}, - ) - # --- destruction du moduleimpl - _moduleimplEditor.delete(cnx, oid) - sco_cache.invalidate_formsemestre( - formsemestre_id=formsemestre_id - ) # > moduleimpl_delete - - -def moduleimpl_list( - moduleimpl_id=None, formsemestre_id=None, module_id=None -) -> list[dict]: - "list moduleimpls" - args = locals() - cnx = ndb.GetDBConnexion() - modimpls = _moduleimplEditor.list(cnx, args) - return modimpls - - -def do_moduleimpl_edit(args, formsemestre_id=None, cnx=None): - "edit a moduleimpl" - if not cnx: - cnx = ndb.GetDBConnexion() - _moduleimplEditor.edit(cnx, args) - - sco_cache.invalidate_formsemestre( - formsemestre_id=formsemestre_id - ) # > modif moduleimpl - - -def moduleimpls_in_external_ue(ue_id): - """List of modimpls in this ue""" - cursor = ndb.SimpleQuery( - """SELECT DISTINCT mi.* - FROM notes_ue u, notes_moduleimpl mi, notes_modules m - WHERE u.is_external is true - AND mi.module_id = m.id AND m.ue_id = %(ue_id)s - """, - {"ue_id": ue_id}, - ) - return cursor.dictfetchall() - def do_moduleimpl_inscription_list(moduleimpl_id=None, etudid=None): "list moduleimpl_inscriptions" @@ -118,38 +43,6 @@ def do_moduleimpl_inscription_list(moduleimpl_id=None, etudid=None): return _moduleimpl_inscriptionEditor.list(cnx, args) -def moduleimpl_listeetuds(moduleimpl_id): # XXX OBSOLETE - "retourne liste des etudids inscrits a ce module" - req = """SELECT DISTINCT Im.etudid - FROM notes_moduleimpl_inscription Im, - notes_formsemestre_inscription Isem, - notes_moduleimpl M - WHERE Isem.etudid = Im.etudid - and Im.moduleimpl_id = M.id - and M.id = %(moduleimpl_id)s - """ - cnx = ndb.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) - cursor.execute(req, {"moduleimpl_id": moduleimpl_id}) - res = cursor.fetchall() - return [x[0] for x in res] - - -def do_moduleimpl_inscrit_tout_semestre(moduleimpl_id, formsemestre_id): - "inscrit tous les etudiants inscrit au semestre a ce module" - # UNUSED - cnx = ndb.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) - req = """INSERT INTO notes_moduleimpl_inscription - (moduleimpl_id, etudid) - SELECT %(moduleimpl_id)s, I.etudid - FROM notes_formsemestre_inscription I - WHERE I.formsemestre_id=%(formsemestre_id)s - """ - args = {"moduleimpl_id": moduleimpl_id, "formsemestre_id": formsemestre_id} - cursor.execute(req, args) - - # --- Inscriptions aux modules _moduleimpl_inscriptionEditor = ndb.EditableTable( "notes_moduleimpl_inscription", diff --git a/app/views/notes.py b/app/views/notes.py index 03a4c5310..a01c3dde6 100644 --- a/app/views/notes.py +++ b/app/views/notes.py @@ -2588,23 +2588,20 @@ def check_sem_integrity(formsemestre_id, fix=False): Check that ue and module formations are consistents """ formsemestre = FormSemestre.get_formsemestre(formsemestre_id) - modimpls = sco_moduleimpl.moduleimpl_list(formsemestre_id=formsemestre_id) + modimpls = formsemestre.modimpls.all() bad_ue = [] bad_sem = [] formations_set = set() # les formations mentionnées dans les UE et modules for modimpl in modimpls: - mod = Module.get_instance(modimpl["module_id"]) + mod = modimpl.module formations_set.add(mod.formation_id) ue = mod.ue ue_dict = ue.to_dict() formations_set.add(ue_dict["formation_id"]) if ue_dict["formation_id"] != mod.formation_id: - modimpl["mod"] = mod.to_dict() - modimpl["ue"] = ue_dict bad_ue.append(modimpl) if formsemestre.formation_id != mod.formation_id: bad_sem.append(modimpl) - modimpl["mod"] = mod.to_dict() H = [ f"""

formation_id={formsemestre.formation_id}""", diff --git a/tests/unit/test_formations.py b/tests/unit/test_formations.py index d047a0708..5e193567a 100644 --- a/tests/unit/test_formations.py +++ b/tests/unit/test_formations.py @@ -31,7 +31,6 @@ # - create_moduleimpl # - formation_export # - formsemestre_list -# - moduleimpl_list # - do_module_impl_with_module_list # - do_formsemestre_delete # - Module.delete @@ -231,25 +230,18 @@ def test_formations(test_client): # --- Liste des modules - lim_sem1 = sco_moduleimpl.moduleimpl_list(formsemestre_id=sem1["formsemestre_id"]) - + lim_sem1 = ( + db.session.query(ModuleImpl) + .filter_by(formsemestre_id=sem1["formsemestre_id"]) + .all() + ) assert len(lim_sem1) == 2 - assert module_id in ( - lim_sem1[0]["module_id"], - lim_sem1[1]["module_id"], - ) - assert module_id2 in ( - lim_sem1[0]["module_id"], - lim_sem1[1]["module_id"], - ) - - lim_modid = sco_moduleimpl.moduleimpl_list(module_id=module_id) + assert module_id in (lim_sem1[0].module_id, lim_sem1[1].module_id) + assert module_id2 in (lim_sem1[0].module_id, lim_sem1[1].module_id) + lim_modid = db.session.query(ModuleImpl).filter_by(module_id=module_id).all() assert len(lim_modid) == 1 - lim_modimpl_id = sco_moduleimpl.moduleimpl_list(moduleimpl_id=moduleimpl_id) - assert lim_modid == lim_modimpl_id - # --- Suppression du module, matiere et ue test du semestre 2 # on doit d'abord supprimer le semestre: @@ -280,8 +272,11 @@ def test_formations(test_client): len(li_module2_after) == len(li_module2_before) - 2 ) # verification de la suppression - lim_sem2 = sco_moduleimpl.moduleimpl_list(formsemestre_id=sem2["formsemestre_id"]) - + lim_sem2 = ( + db.session.query(ModuleImpl) + .filter_by(formsemestre_id=sem2["formsemestre_id"]) + .all() + ) assert len(lim_sem2) == 0 # deuxieme vérification si le module s'est bien sup li_mat = Matiere.query.all() @@ -344,8 +339,8 @@ def test_import_formation(test_client, filename="formation-exemple-1.xml"): module_id=mod.id, formsemestre_id=formsemestre_ids[mod.semestre_id - 1], ) - mi = sco_moduleimpl.moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] - assert mi["module_id"] == mod.id + mi = db.session.query(ModuleImpl).get(moduleimpl_id) + assert mi.module_id == mod.id # --- Export formation en XML doc1 = formation_io.formation_export(formation_id, fmt="xml").get_data(as_text=True)