diff --git a/app/api/formations.py b/app/api/formations.py index e618716b0..def1c12e7 100644 --- a/app/api/formations.py +++ b/app/api/formations.py @@ -21,6 +21,7 @@ from app import db, log from app.api import api_bp as bp, api_web_bp from app.api import api_permission_required as permission_required from app.decorators import scodoc +from app.formations import edit_module from app.models import APO_CODE_STR_LEN from app.scodoc.sco_utils import json_error from app.models import ( @@ -493,8 +494,7 @@ def formation_module_edit(module_id: int): query = query.join(Formation).filter_by(dept_id=g.scodoc_dept_id) module: Module = query.first_or_404() args = request.get_json(force=True) # may raise 400 Bad Request - module.from_dict(args) - db.session.commit() + edit_module.do_module_edit(args, module=module) db.session.refresh(module) log(f"API module_edit: module_id={module.id} args={args}") r = module.to_dict(convert_objects=True, with_parcours_ids=True) diff --git a/app/formations/edit_module.py b/app/formations/edit_module.py index 388552774..6fe09e8fc 100644 --- a/app/formations/edit_module.py +++ b/app/formations/edit_module.py @@ -33,7 +33,7 @@ from flask import flash, url_for, render_template from flask import g, request from flask_login import current_user -from app import db +from app import db, log from app import models from app.models import APO_CODE_STR_LEN from app.models import Formation, Matiere, Module, UniteEns @@ -98,14 +98,42 @@ def module_delete(module_id=None): return flask.redirect(dest_url) -def do_module_edit(vals: dict) -> None: - "edit a module" +def do_module_edit(vals: dict, module: Module | None = None) -> None: + """edit a module (donné par module ou vals["module_id"]). + Gère les changements d'UEs. + commit et inval cache. + """ # check - module = Module.get_instance(vals["module_id"]) + if module is None: + module: Module = Module.get_instance(vals["module_id"]) + # Changement d'UE ? + if ( + not module.is_locked() + and "ue_id" in vals + and vals["ue_id"] + and vals["ue_id"] != module.ue_id + ): + # Affecte le module à la première matière de l'UE destination + ue_dest = UniteEns.get_ue(vals["ue_id"]) + log(f"do_module_edit: changing UE of {module} to {ue_dest}") + mat_dest = ue_dest.matieres.first() + if not mat_dest: + log("do_module_edit: creating new Matiere in dest UE") + mat_dest = Matiere.create_from_dict( + { + "ue_id": ue_dest.id, + "titre": ue_dest.titre or "", + "numero": 1, + } + ) + db.session.add(mat_dest) + module.matiere = mat_dest + module.ue = ue_dest # edit modif = module.from_dict(vals) if modif: module.formation.invalidate_cached_sems() + db.session.commit() def module_create( @@ -735,9 +763,8 @@ def module_edit( tf[2]["app_critiques"], formation.referentiel_competence ) - # Check unicité code module dans la formation - # ??? TODO - # + # Le check unicité code module dans la formation + # est fait par Module.from_dict do_module_edit(tf[2]) # Modifie les parcours if form_parcours is not None and formation.referentiel_competence: diff --git a/app/models/formsemestre.py b/app/models/formsemestre.py index cfcc47567..b3f8da2ab 100644 --- a/app/models/formsemestre.py +++ b/app/models/formsemestre.py @@ -216,6 +216,7 @@ class FormSemestre(models.ScoDocModel): except (TypeError, ValueError): if accept_none: return None + log("get_formsemestre: formsemestre_id invalide") abort(404, "formsemestre_id invalide") dept_id = ( diff --git a/app/models/modules.py b/app/models/modules.py index 6adba8d50..5a8752a55 100644 --- a/app/models/modules.py +++ b/app/models/modules.py @@ -183,6 +183,7 @@ class Module(models.ScoDocModel): matiere = db.session.get(Matiere, new_matiere_id) if matiere is None or matiere.ue_id != self.ue_id: + log("Module.from_dict: invalid matiere") raise ScoValueError("invalid matiere") modified = super().from_dict( diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py index 84a3d77d9..2a56cacfd 100644 --- a/app/scodoc/sco_utils.py +++ b/app/scodoc/sco_utils.py @@ -1694,11 +1694,13 @@ def confirm_dialog( if add_headers: formsemestre = ( FormSemestre.get_formsemestre(parameters["formsemestre_id"]) - if "formsemestre_id" in parameters + if parameters.get("formsemestre_id") else None ) etud = ( - Identite.get_etud(parameters["etudid"]) if "etudid" in parameters else None + Identite.get_etud(parameters["etudid"]) + if parameters.get("etudid") + else None ) return render_template( template, diff --git a/tests/api/start_api_server.sh b/tests/api/start_api_server.sh index ac4a1ce0a..0fdd447fb 100755 --- a/tests/api/start_api_server.sh +++ b/tests/api/start_api_server.sh @@ -27,7 +27,7 @@ done source "$SCRIPT_DIR"/.env export FLASK_ENV=test_api -export FLASK_DEBUG=1 +export FLASK_DEBUG=1 tools/create_database.sh --drop SCODOC_TEST_API flask db upgrade flask sco-db-init --erase @@ -39,7 +39,7 @@ flask edit-role LecteurAPI -a ScoView flask user-role "$API_USER" -a LecteurAPI if [ -z "$PORT" ] -then +then flask run --host 0.0.0.0 else flask run --host 0.0.0.0 -p "$PORT" diff --git a/tests/api/test_api_formations.py b/tests/api/test_api_formations.py index 8192961bc..ec3a08883 100644 --- a/tests/api/test_api_formations.py +++ b/tests/api/test_api_formations.py @@ -388,14 +388,6 @@ def test_api_module_edit(api_admin_headers): assert module["heures_cours"] == 16 assert module["semestre_id"] == 1 assert module["abbrev"] == "ALLO" - # tente de changer l'UE: ne devrait rien faire: - ue_id = module["ue_id"] - module = POST( - f"/formation/module/{module_id}/edit", - {"ue_id": 666}, - api_admin_headers, - ) - assert module["ue_id"] == ue_id # tente de changer la formation: ne devrait rien faire: formation_id = module["formation_id"] module = POST(