diff --git a/app/scodoc/sco_edit_ue.py b/app/scodoc/sco_edit_ue.py index 623753ddb..ab8658e79 100644 --- a/app/scodoc/sco_edit_ue.py +++ b/app/scodoc/sco_edit_ue.py @@ -928,7 +928,7 @@ du programme" (menu "Semestre") si vous avez un semestre en cours); H.append( f"""
  • Créer une nouvelle version de la formation (copie non verrouillée) diff --git a/app/scodoc/sco_formation_versions.py b/app/scodoc/sco_formation_versions.py index 73a229501..50d7c849a 100644 --- a/app/scodoc/sco_formation_versions.py +++ b/app/scodoc/sco_formation_versions.py @@ -36,21 +36,18 @@ from app.models import ( ModuleImpl, Evaluation, EvaluationUEPoids, + ScolarEvent, + ScolarFormSemestreValidation, UniteEns, ) from app.models.formations import Formation from app.models.formsemestre import FormSemestre -import app.scodoc.notesdb as ndb import app.scodoc.sco_utils as scu from app import log from app.scodoc.sco_exceptions import ScoValueError -from app.scodoc import sco_etud from app.scodoc import sco_formations -from app.scodoc import sco_formsemestre -from app.scodoc import sco_moduleimpl -from app.scodoc import sco_cursus_dut def formsemestre_associate_new_version( @@ -60,12 +57,11 @@ def formsemestre_associate_new_version( ): """Formulaire nouvelle version formation et association d'un ou plusieurs formsemestre. formation_id: la formation à dupliquer - formsemestre_id: optionnel, formsemestre de départ, qui sera associé à la noiuvelle version + formsemestre_id: optionnel, formsemestre de départ, qui sera associé à la nouvelle version """ - if formsemestre_id is not None: - formsemestre_id = int(formsemestre_id) + formsemestre_id = int(formsemestre_id) if formsemestre_id else None formation: Formation = Formation.query.get_or_404(formation_id) - other_formsemestre_ids = {int(x) for x in other_formsemestre_ids or []} + other_formsemestre_ids = {int(x) for x in (other_formsemestre_ids or [])} if request.method == "GET": # dresse la liste des semestres non verrouillés de la même formation other_formsemestres: list[FormSemestre] = formation.formsemestres.filter_by( @@ -90,7 +86,7 @@ def formsemestre_associate_new_version( f"""
    {other_formsemestre.titre_mois()}
    """ ) @@ -132,6 +128,9 @@ def formsemestre_associate_new_version( { "".join(H) }

    Les données (étudiants, notes...) de ces semestres seront inchangées.

    + """ + + ( + f"""
    Vous pouvez aussi essayer d'associer ce semestre à une autre formation identique.
    - """, + """ + if formsemestre_id is not None + else "" + ), OK="Créer une nouvelle version et y associer ces semestres", dest_url="", cancel_url=cancel_url, @@ -189,14 +191,13 @@ def do_formsemestres_associate_new_version( """ log(f"do_formsemestres_associate_new_version {formation_id} {formsemestre_ids}") - # Check: tous les semestre de la formation + # Check: tous les semestres de la formation formsemestres = [FormSemestre.query.get_or_404(i) for i in formsemestre_ids] if not all( [formsemestre.formation_id == formation_id for formsemestre in formsemestres] ): raise ScoValueError("les semestres ne sont pas tous de la même formation !") - cnx = ndb.GetDBConnexion() # New formation: ( formation_id, @@ -217,49 +218,51 @@ def do_formsemestres_associate_new_version( log(f"{mod} -> {new_mod}") # re-associate for formsemestre_id in formsemestre_ids: - sem = sco_formsemestre.get_formsemestre(formsemestre_id) - sem["formation_id"] = formation_id - sco_formsemestre.do_formsemestre_edit(sem, cnx=cnx, html_quote=False) - _reassociate_moduleimpls(cnx, formsemestre_id, ues_old2new, modules_old2new) + formsemestre = FormSemestre.get_formsemestre(formsemestre_id) + formsemestre.formation_id = formation_id + db.session.add(formsemestre) + _reassociate_moduleimpls(formsemestre, ues_old2new, modules_old2new) - cnx.commit() + db.session.commit() return formation_id -def _reassociate_moduleimpls(cnx, formsemestre_id, ues_old2new, modules_old2new): +def _reassociate_moduleimpls( + formsemestre: FormSemestre, + ues_old2new: dict[int, int], + modules_old2new: dict[int, int], +): """Associe les moduleimpls d'un semestre existant à un autre programme et met à jour les décisions de jury (validations d'UE). """ # re-associate moduleimpls to new modules: - modimpls = sco_moduleimpl.moduleimpl_list(formsemestre_id=formsemestre_id) - for mod in modimpls: - mod["module_id"] = modules_old2new[mod["module_id"]] - sco_moduleimpl.do_moduleimpl_edit(mod, formsemestre_id=formsemestre_id) + for modimpl in formsemestre.modimpls: + modimpl.module_id = modules_old2new[modimpl.module_id] + db.session.add(modimpl) # Update poids des évaluations # les poids associent les évaluations aux UE (qui ont changé d'id) for poids in EvaluationUEPoids.query.filter( EvaluationUEPoids.evaluation_id == Evaluation.id, Evaluation.moduleimpl_id == ModuleImpl.id, - ModuleImpl.formsemestre_id == formsemestre_id, + ModuleImpl.formsemestre_id == formsemestre.id, ): poids.ue_id = ues_old2new[poids.ue_id] db.session.add(poids) - db.session.commit() # update decisions: - events = sco_etud.scolar_events_list(cnx, args={"formsemestre_id": formsemestre_id}) - for e in events: - if e["ue_id"]: - e["ue_id"] = ues_old2new[e["ue_id"]] - sco_etud.scolar_events_edit(cnx, e) - validations = sco_cursus_dut.scolar_formsemestre_validation_list( - cnx, args={"formsemestre_id": formsemestre_id} - ) - for e in validations: - if e["ue_id"]: - e["ue_id"] = ues_old2new[e["ue_id"]] - # log('e=%s' % e ) - sco_cursus_dut.scolar_formsemestre_validation_edit(cnx, e) + for event in ScolarEvent.query.filter_by(formsemestre_id=formsemestre.id): + if event.ue_id is not None: + event.ue_id = ues_old2new[event.ue_id] + db.session.add(event) + + for validation in ScolarFormSemestreValidation.query.filter_by( + formsemestre_id=formsemestre.id + ): + if validation.ue_id is not None: + validation.ue_id = ues_old2new[validation.ue_id] + db.session.add(validation) + + db.session.commit() def formations_are_equals( @@ -294,7 +297,8 @@ def formsemestre_change_formation(formsemestre: FormSemestre, new_formation: For log( f"formsemestre_change_formation: formsemestre {formsemestre} to formation {new_formation}" ) - # Il faut ré-associer tous les modimpls + # Il faut ré-associer tous les modimpls et les UEs + modules_old2new = {} for modimpl in formsemestre.modimpls: old_module: Module = modimpl.module new_module: Module = ( @@ -311,7 +315,19 @@ def formsemestre_change_formation(formsemestre: FormSemestre, new_formation: For raise ValueError( f"formsemestre_change_formation: erreur sur module {old_module}" ) - modimpl.module = new_module - db.session.add(modimpl) + modules_old2new[old_module.id] = new_module.id + + ues_old2new = {} + for old_ue in formsemestre.formation.ues: + new_ue: UniteEns = UniteEns.query.filter_by( + formation_id=new_formation.id, acronyme=old_ue.acronyme, titre=old_ue.titre + ).first() + if new_ue is None: + raise ValueError(f"formsemestre_change_formation: erreur sur UE {old_ue}") + ues_old2new[old_ue.id] = new_ue.id + formsemestre.formation = new_formation + db.session.add(formsemestre) + _reassociate_moduleimpls(formsemestre, ues_old2new, modules_old2new) + db.session.commit() diff --git a/app/templates/formsemestre/change_formation.j2 b/app/templates/formsemestre/change_formation.j2 index 2fccdb272..0b3820cae 100644 --- a/app/templates/formsemestre/change_formation.j2 +++ b/app/templates/formsemestre/change_formation.j2 @@ -24,7 +24,7 @@ et que l'on a oublié d'y rattacher un semestre. {% else %} -
    Aucune formation ne peut se substituer à celle de ce semestre.
    +
    Aucune formation ne peut se substituer à celle de ce semestre.
    {% endif %} {% endblock %} \ No newline at end of file diff --git a/app/views/notes_formsemestre.py b/app/views/notes_formsemestre.py index 9adb88e1a..e445d8843 100644 --- a/app/views/notes_formsemestre.py +++ b/app/views/notes_formsemestre.py @@ -29,11 +29,8 @@ Vues "modernes" des formsemestre Emmanuel Viennet, 2023 """ -import flask -from flask import abort, flash, redirect, render_template, url_for +from flask import flash, redirect, render_template, url_for from flask import g, request -from flask_login import current_user -from wtforms.validators import ValidationError from app.decorators import ( scodoc,