Corrige et modernise associations formsemestres/programmes

This commit is contained in:
Emmanuel Viennet 2023-03-22 21:39:55 +01:00
parent b7a7bf1edc
commit 01308561d3
4 changed files with 60 additions and 47 deletions

View File

@ -928,7 +928,7 @@ du programme" (menu "Semestre") si vous avez un semestre en cours);
H.append( H.append(
f""" f"""
<li><a class="stdlink" href="{ <li><a class="stdlink" href="{
url_for('notes.formsemestre_associate_new_version', url_for('notes.formsemestre_associate_new_version',
scodoc_dept=g.scodoc_dept, formation_id=formation_id scodoc_dept=g.scodoc_dept, formation_id=formation_id
) )
}">Créer une nouvelle version de la formation</a> (copie non verrouillée) }">Créer une nouvelle version de la formation</a> (copie non verrouillée)

View File

@ -36,21 +36,18 @@ from app.models import (
ModuleImpl, ModuleImpl,
Evaluation, Evaluation,
EvaluationUEPoids, EvaluationUEPoids,
ScolarEvent,
ScolarFormSemestreValidation,
UniteEns, UniteEns,
) )
from app.models.formations import Formation from app.models.formations import Formation
from app.models.formsemestre import FormSemestre from app.models.formsemestre import FormSemestre
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.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc import sco_etud
from app.scodoc import sco_formations 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( 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. """Formulaire nouvelle version formation et association d'un ou plusieurs formsemestre.
formation_id: la formation à dupliquer 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) if formsemestre_id else None
formsemestre_id = int(formsemestre_id)
formation: Formation = Formation.query.get_or_404(formation_id) 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": if request.method == "GET":
# dresse la liste des semestres non verrouillés de la même formation # dresse la liste des semestres non verrouillés de la même formation
other_formsemestres: list[FormSemestre] = formation.formsemestres.filter_by( other_formsemestres: list[FormSemestre] = formation.formsemestres.filter_by(
@ -90,7 +86,7 @@ def formsemestre_associate_new_version(
f"""<div><input type="checkbox" name="other_formsemestre_ids:list" f"""<div><input type="checkbox" name="other_formsemestre_ids:list"
value="{other_formsemestre.id}" {checked} {disabled} value="{other_formsemestre.id}" {checked} {disabled}
><a class="stdlink" href="{ ><a class="stdlink" href="{
url_for("notes.formsemestre_status", url_for("notes.formsemestre_status",
scodoc_dept=g.scodoc_dept, formsemestre_id=other_formsemestre.id) scodoc_dept=g.scodoc_dept, formsemestre_id=other_formsemestre.id)
}">{other_formsemestre.titre_mois()}</a></input></div>""" }">{other_formsemestre.titre_mois()}</a></input></div>"""
) )
@ -132,6 +128,9 @@ def formsemestre_associate_new_version(
{ "".join(H) } { "".join(H) }
<p>Les données (étudiants, notes...) de ces semestres seront inchangées.</p> <p>Les données (étudiants, notes...) de ces semestres seront inchangées.</p>
</div> </div>
"""
+ (
f"""
<div class="othersemlist"> <div class="othersemlist">
Vous pouvez aussi essayer d'<a class="stdlink" href="{url_for( Vous pouvez aussi essayer d'<a class="stdlink" href="{url_for(
"notes.formsemestre_change_formation", "notes.formsemestre_change_formation",
@ -139,7 +138,10 @@ def formsemestre_associate_new_version(
)} )}
">associer ce semestre à une autre formation identique</a>. ">associer ce semestre à une autre formation identique</a>.
</div> </div>
""", """
if formsemestre_id is not None
else ""
),
OK="Créer une nouvelle version et y associer ces semestres", OK="Créer une nouvelle version et y associer ces semestres",
dest_url="", dest_url="",
cancel_url=cancel_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}") 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] formsemestres = [FormSemestre.query.get_or_404(i) for i in formsemestre_ids]
if not all( if not all(
[formsemestre.formation_id == formation_id for formsemestre in formsemestres] [formsemestre.formation_id == formation_id for formsemestre in formsemestres]
): ):
raise ScoValueError("les semestres ne sont pas tous de la même formation !") raise ScoValueError("les semestres ne sont pas tous de la même formation !")
cnx = ndb.GetDBConnexion()
# New formation: # New formation:
( (
formation_id, formation_id,
@ -217,49 +218,51 @@ def do_formsemestres_associate_new_version(
log(f"{mod} -> {new_mod}") log(f"{mod} -> {new_mod}")
# re-associate # re-associate
for formsemestre_id in formsemestre_ids: for formsemestre_id in formsemestre_ids:
sem = sco_formsemestre.get_formsemestre(formsemestre_id) formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
sem["formation_id"] = formation_id formsemestre.formation_id = formation_id
sco_formsemestre.do_formsemestre_edit(sem, cnx=cnx, html_quote=False) db.session.add(formsemestre)
_reassociate_moduleimpls(cnx, formsemestre_id, ues_old2new, modules_old2new) _reassociate_moduleimpls(formsemestre, ues_old2new, modules_old2new)
cnx.commit() db.session.commit()
return formation_id 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 """Associe les moduleimpls d'un semestre existant à un autre programme
et met à jour les décisions de jury (validations d'UE). et met à jour les décisions de jury (validations d'UE).
""" """
# re-associate moduleimpls to new modules: # re-associate moduleimpls to new modules:
modimpls = sco_moduleimpl.moduleimpl_list(formsemestre_id=formsemestre_id) for modimpl in formsemestre.modimpls:
for mod in modimpls: modimpl.module_id = modules_old2new[modimpl.module_id]
mod["module_id"] = modules_old2new[mod["module_id"]] db.session.add(modimpl)
sco_moduleimpl.do_moduleimpl_edit(mod, formsemestre_id=formsemestre_id)
# Update poids des évaluations # Update poids des évaluations
# les poids associent les évaluations aux UE (qui ont changé d'id) # les poids associent les évaluations aux UE (qui ont changé d'id)
for poids in EvaluationUEPoids.query.filter( for poids in EvaluationUEPoids.query.filter(
EvaluationUEPoids.evaluation_id == Evaluation.id, EvaluationUEPoids.evaluation_id == Evaluation.id,
Evaluation.moduleimpl_id == ModuleImpl.id, Evaluation.moduleimpl_id == ModuleImpl.id,
ModuleImpl.formsemestre_id == formsemestre_id, ModuleImpl.formsemestre_id == formsemestre.id,
): ):
poids.ue_id = ues_old2new[poids.ue_id] poids.ue_id = ues_old2new[poids.ue_id]
db.session.add(poids) db.session.add(poids)
db.session.commit()
# update decisions: # update decisions:
events = sco_etud.scolar_events_list(cnx, args={"formsemestre_id": formsemestre_id}) for event in ScolarEvent.query.filter_by(formsemestre_id=formsemestre.id):
for e in events: if event.ue_id is not None:
if e["ue_id"]: event.ue_id = ues_old2new[event.ue_id]
e["ue_id"] = ues_old2new[e["ue_id"]] db.session.add(event)
sco_etud.scolar_events_edit(cnx, e)
validations = sco_cursus_dut.scolar_formsemestre_validation_list( for validation in ScolarFormSemestreValidation.query.filter_by(
cnx, args={"formsemestre_id": formsemestre_id} formsemestre_id=formsemestre.id
) ):
for e in validations: if validation.ue_id is not None:
if e["ue_id"]: validation.ue_id = ues_old2new[validation.ue_id]
e["ue_id"] = ues_old2new[e["ue_id"]] db.session.add(validation)
# log('e=%s' % e )
sco_cursus_dut.scolar_formsemestre_validation_edit(cnx, e) db.session.commit()
def formations_are_equals( def formations_are_equals(
@ -294,7 +297,8 @@ def formsemestre_change_formation(formsemestre: FormSemestre, new_formation: For
log( log(
f"formsemestre_change_formation: formsemestre {formsemestre} to formation {new_formation}" 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: for modimpl in formsemestre.modimpls:
old_module: Module = modimpl.module old_module: Module = modimpl.module
new_module: Module = ( new_module: Module = (
@ -311,7 +315,19 @@ def formsemestre_change_formation(formsemestre: FormSemestre, new_formation: For
raise ValueError( raise ValueError(
f"formsemestre_change_formation: erreur sur module {old_module}" f"formsemestre_change_formation: erreur sur module {old_module}"
) )
modimpl.module = new_module modules_old2new[old_module.id] = new_module.id
db.session.add(modimpl)
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 formsemestre.formation = new_formation
db.session.add(formsemestre)
_reassociate_moduleimpls(formsemestre, ues_old2new, modules_old2new)
db.session.commit() db.session.commit()

View File

@ -24,7 +24,7 @@ et que l'on a oublié d'y rattacher un semestre.
</div> </div>
</div> </div>
{% else %} {% else %}
<div>Aucune formation ne peut se substituer à celle de ce semestre.</div> <div class="fontred">Aucune formation ne peut se substituer à celle de ce semestre.</div>
{% endif %} {% endif %}
</div> </div>
{% endblock %} {% endblock %}

View File

@ -29,11 +29,8 @@ Vues "modernes" des formsemestre
Emmanuel Viennet, 2023 Emmanuel Viennet, 2023
""" """
import flask from flask import flash, redirect, render_template, url_for
from flask import abort, flash, redirect, render_template, url_for
from flask import g, request from flask import g, request
from flask_login import current_user
from wtforms.validators import ValidationError
from app.decorators import ( from app.decorators import (
scodoc, scodoc,