BUT: modif semestre: modules de même semestre

This commit is contained in:
Emmanuel Viennet 2022-01-30 08:13:24 +01:00
parent 920aeb066f
commit d928a6be32

View File

@ -28,13 +28,16 @@
"""Form choix modules / responsables et creation formsemestre
"""
import flask
from flask import url_for, g, request
from flask import url_for, flash
from flask import g, request
from flask_login import current_user
from app import db
from app.auth.models import User
from app.models import APO_CODE_STR_LEN, SHORT_STR_LEN
from app.models import ModuleImpl, Evaluation, EvaluationUEPoids
from app.models import Module, ModuleImpl, Evaluation, EvaluationUEPoids
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.scodoc import sco_cache
@ -65,9 +68,9 @@ from app.scodoc import sco_preferences
from app.scodoc import sco_users
def _default_sem_title(F):
"""Default title for a semestre in formation F"""
return F["titre"]
def _default_sem_title(formation):
"""Default title for a semestre in formation"""
return formation.titre
def formsemestre_createwithmodules():
@ -140,6 +143,7 @@ def do_formsemestre_createwithmodules(edit=False):
if edit:
formsemestre_id = int(vals["formsemestre_id"])
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
if not current_user.has_permission(Permission.ScoImplement):
if not edit:
# il faut ScoImplement pour creer un semestre
@ -161,26 +165,25 @@ def do_formsemestre_createwithmodules(edit=False):
allowed_user_names = list(uid2display.values()) + [""]
#
formation_id = int(vals["formation_id"])
F = sco_formations.formation_list(args={"formation_id": formation_id})
if not F:
formation = Formation.query.get(formation_id)
if formation is None:
raise ScoValueError("Formation inexistante !")
F = F[0]
if not edit:
initvalues = {"titre": _default_sem_title(F)}
initvalues = {"titre": _default_sem_title(formation)}
semestre_id = int(vals["semestre_id"])
sem_module_ids = set()
module_ids_set = set()
else:
# setup form init values
initvalues = sem
semestre_id = initvalues["semestre_id"]
# add associated modules to tf-checked:
ams = sco_moduleimpl.moduleimpl_list(formsemestre_id=formsemestre_id)
sem_module_ids = set([x["module_id"] for x in ams])
initvalues["tf-checked"] = ["MI" + str(x["module_id"]) for x in ams]
for x in ams:
initvalues["MI" + str(x["module_id"])] = uid2display.get(
x["responsable_id"],
f"inconnu numéro {x['responsable_id']} resp. de {x['moduleimpl_id']} !",
module_ids_existing = [modimpl.module.id for modimpl in formsemestre.modimpls]
module_ids_set = set(module_ids_existing)
initvalues["tf-checked"] = ["MI" + str(x) for x in module_ids_existing]
for modimpl in formsemestre.modimpls:
initvalues[f"MI{modimpl.module.id}"] = uid2display.get(
modimpl.responsable_id,
f"inconnu numéro {modimpl.responsable_id} resp. de {modimpl.id} !",
)
initvalues["responsable_id"] = uid2display.get(
@ -192,15 +195,20 @@ def do_formsemestre_createwithmodules(edit=False):
)
# Liste des ID de semestres
if F["type_parcours"] is not None:
parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"])
if formation.type_parcours is not None:
parcours = sco_codes_parcours.get_parcours_from_code(formation.type_parcours)
NB_SEM = parcours.NB_SEM
else:
NB_SEM = 10 # fallback, max 10 semestres
if NB_SEM == 1:
semestre_id_list = [-1]
else:
if edit and formation.is_apc():
# en APC, ne permet pas de changer de semestre
semestre_id_list = [formsemestre.semestre_id]
else:
semestre_id_list = [-1] + list(range(1, NB_SEM + 1))
semestre_id_labels = []
for sid in semestre_id_list:
if sid == -1:
@ -319,7 +327,7 @@ def do_formsemestre_createwithmodules(edit=False):
"explanation": """n'indiquez pas les dates, ni le semestre, ni la modalité dans
le titre: ils seront automatiquement ajoutés <input type="button"
value="remettre titre par défaut" onClick="document.tf.titre.value='%s';"/>"""
% _default_sem_title(F),
% _default_sem_title(formation),
},
),
(
@ -340,6 +348,9 @@ def do_formsemestre_createwithmodules(edit=False):
"title": "Semestre dans la formation",
"allowed_values": semestre_id_list,
"labels": semestre_id_labels,
"explanation": "en BUT, on ne peut pas modifier le semestre après création"
if formation.is_apc()
else "",
},
),
)
@ -549,7 +560,12 @@ def do_formsemestre_createwithmodules(edit=False):
)
)
for mod in mods:
if mod["semestre_id"] == semestre_id:
if mod["semestre_id"] == semestre_id and (
(not edit) # creation => tous modules
or (not formation.is_apc()) # pas BUT, on peux mixer les semestres
or (semestre_id == formsemestre.semestre_id) # module du semestre
or (mod["module_id"] in module_ids_set) # module déjà présent
):
nbmod += 1
if edit:
select_name = "%s!group_id" % mod["module_id"]
@ -560,7 +576,7 @@ def do_formsemestre_createwithmodules(edit=False):
else:
return ""
if mod["module_id"] in sem_module_ids:
if mod["module_id"] in module_ids_set:
disabled = "disabled"
else:
disabled = ""
@ -684,12 +700,13 @@ def do_formsemestre_createwithmodules(edit=False):
msg = '<ul class="tf-msg"><li class="tf-msg">Code étape Apogée manquant</li></ul>'
if tf[0] == 0 or msg:
return (
'<p>Formation <a class="discretelink" href="ue_table?formation_id=%(formation_id)s"><em>%(titre)s</em> (%(acronyme)s), version %(version)s, code %(formation_code)s</a></p>'
% F
+ msg
+ str(tf[1])
)
return f"""<p>Formation <a class="discretelink" href="{
url_for("notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=formation_id)
}"><em>{formation.titre}</em> ({formation.acronyme}), version {formation.version}, code {formation.formation_code}</a>
</p>
{msg}
{tf[1]}
"""
elif tf[0] == -1:
return "<h4>annulation</h4>"
else:
@ -735,42 +752,58 @@ def do_formsemestre_createwithmodules(edit=False):
etape=tf[2]["etape_apo" + str(n)], vdi=tf[2]["vdi_apo" + str(n)]
)
)
# Modules sélectionnés:
# (retire le "MI" du début du nom de champs)
module_ids_checked = [int(x[2:]) for x in tf[2]["tf-checked"]]
if not edit:
# creation du semestre
if formation.is_apc():
_formsemestre_check_module_list(
module_ids_checked, tf[2]["semestre_id"]
)
# création du semestre
formsemestre_id = sco_formsemestre.do_formsemestre_create(tf[2])
# creation des modules
for module_id in tf[2]["tf-checked"]:
assert module_id[:2] == "MI"
# création des modules
for module_id in module_ids_checked:
modargs = {
"module_id": int(module_id[2:]),
"module_id": module_id,
"formsemestre_id": formsemestre_id,
"responsable_id": tf[2][module_id],
"responsable_id": tf[2][f"MI{module_id}"],
}
_ = sco_moduleimpl.do_moduleimpl_create(modargs)
flash("Nouveau semestre créé")
return flask.redirect(
"formsemestre_status?formsemestre_id=%s&head_message=Nouveau%%20semestre%%20créé"
% formsemestre_id
url_for(
"notes.formsemestre_status",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id,
)
)
else:
# modification du semestre:
# Modification du semestre:
# on doit creer les modules nouvellement selectionnés
# modifier ceux a modifier, et DETRUIRE ceux qui ne sont plus selectionnés.
# Note: la destruction echouera s'il y a des objets dependants
# (eg des evaluations définies)
# nouveaux modules
# (retire le "MI" du début du nom de champs)
checkedmods = [int(x[2:]) for x in tf[2]["tf-checked"]]
# modifier ceux à modifier, et DETRUIRE ceux qui ne sont plus selectionnés.
# Note: la destruction échouera s'il y a des objets dépendants
# (eg des évaluations définies)
module_ids_tocreate = [
x for x in module_ids_checked if not x in module_ids_existing
]
if formation.is_apc():
_formsemestre_check_module_list(
module_ids_tocreate, tf[2]["semestre_id"]
)
# modules existants à modifier
module_ids_toedit = [
x for x in module_ids_checked if x in module_ids_existing
]
# modules à détruire
module_ids_todelete = [
x for x in module_ids_existing if not x in module_ids_checked
]
#
sco_formsemestre.do_formsemestre_edit(tf[2])
ams = sco_moduleimpl.moduleimpl_list(formsemestre_id=formsemestre_id)
existingmods = [x["module_id"] for x in ams]
mods_tocreate = [x for x in checkedmods if not x in existingmods]
# modules a existants a modifier
mods_toedit = [x for x in checkedmods if x in existingmods]
# modules a detruire
mods_todelete = [x for x in existingmods if not x in checkedmods]
#
msg = []
for module_id in mods_tocreate:
for module_id in module_ids_tocreate:
modargs = {
"module_id": module_id,
"formsemestre_id": formsemestre_id,
@ -808,9 +841,11 @@ def do_formsemestre_createwithmodules(edit=False):
% (module_id, moduleimpl_id)
)
#
ok, diag = formsemestre_delete_moduleimpls(formsemestre_id, mods_todelete)
ok, diag = formsemestre_delete_moduleimpls(
formsemestre_id, module_ids_todelete
)
msg += diag
for module_id in mods_toedit:
for module_id in module_ids_toedit:
moduleimpl_id = sco_moduleimpl.moduleimpl_list(
formsemestre_id=formsemestre_id, module_id=module_id
)[0]["moduleimpl_id"]
@ -847,6 +882,22 @@ def do_formsemestre_createwithmodules(edit=False):
)
def _formsemestre_check_module_list(module_ids, semestre_idx):
"""En APC: Vérifie que tous les modules de la liste
sont dans le semestre indiqué.
Sinon, raise ScoValueError.
"""
# vérification de la cohérence / modules / semestre
mod_sems_idx = {
Module.query.get_or_404(module_id).ue.semestre_idx for module_id in module_ids
}
if mod_sems_idx and mod_sems_idx != {semestre_idx}:
raise ScoValueError(
"Les modules sélectionnés ne sont pas tous dans le semestre choisi !",
dest_url="javascript:history.back();",
)
def formsemestre_delete_moduleimpls(formsemestre_id, module_ids_to_del):
"""Delete moduleimpls
module_ids_to_del: list of module_id (warning: not moduleimpl)