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 """Form choix modules / responsables et creation formsemestre
""" """
import flask 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 flask_login import current_user
from app import db from app import db
from app.auth.models import User from app.auth.models import User
from app.models import APO_CODE_STR_LEN, SHORT_STR_LEN 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.notesdb as ndb
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app.scodoc import sco_cache from app.scodoc import sco_cache
@ -65,9 +68,9 @@ from app.scodoc import sco_preferences
from app.scodoc import sco_users from app.scodoc import sco_users
def _default_sem_title(F): def _default_sem_title(formation):
"""Default title for a semestre in formation F""" """Default title for a semestre in formation"""
return F["titre"] return formation.titre
def formsemestre_createwithmodules(): def formsemestre_createwithmodules():
@ -140,6 +143,7 @@ def do_formsemestre_createwithmodules(edit=False):
if edit: if edit:
formsemestre_id = int(vals["formsemestre_id"]) formsemestre_id = int(vals["formsemestre_id"])
sem = sco_formsemestre.get_formsemestre(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 current_user.has_permission(Permission.ScoImplement):
if not edit: if not edit:
# il faut ScoImplement pour creer un semestre # il faut ScoImplement pour creer un semestre
@ -161,26 +165,25 @@ def do_formsemestre_createwithmodules(edit=False):
allowed_user_names = list(uid2display.values()) + [""] allowed_user_names = list(uid2display.values()) + [""]
# #
formation_id = int(vals["formation_id"]) formation_id = int(vals["formation_id"])
F = sco_formations.formation_list(args={"formation_id": formation_id}) formation = Formation.query.get(formation_id)
if not F: if formation is None:
raise ScoValueError("Formation inexistante !") raise ScoValueError("Formation inexistante !")
F = F[0]
if not edit: if not edit:
initvalues = {"titre": _default_sem_title(F)} initvalues = {"titre": _default_sem_title(formation)}
semestre_id = int(vals["semestre_id"]) semestre_id = int(vals["semestre_id"])
sem_module_ids = set() module_ids_set = set()
else: else:
# setup form init values # setup form init values
initvalues = sem initvalues = sem
semestre_id = initvalues["semestre_id"] semestre_id = initvalues["semestre_id"]
# add associated modules to tf-checked: # add associated modules to tf-checked:
ams = sco_moduleimpl.moduleimpl_list(formsemestre_id=formsemestre_id) module_ids_existing = [modimpl.module.id for modimpl in formsemestre.modimpls]
sem_module_ids = set([x["module_id"] for x in ams]) module_ids_set = set(module_ids_existing)
initvalues["tf-checked"] = ["MI" + str(x["module_id"]) for x in ams] initvalues["tf-checked"] = ["MI" + str(x) for x in module_ids_existing]
for x in ams: for modimpl in formsemestre.modimpls:
initvalues["MI" + str(x["module_id"])] = uid2display.get( initvalues[f"MI{modimpl.module.id}"] = uid2display.get(
x["responsable_id"], modimpl.responsable_id,
f"inconnu numéro {x['responsable_id']} resp. de {x['moduleimpl_id']} !", f"inconnu numéro {modimpl.responsable_id} resp. de {modimpl.id} !",
) )
initvalues["responsable_id"] = uid2display.get( initvalues["responsable_id"] = uid2display.get(
@ -192,15 +195,20 @@ def do_formsemestre_createwithmodules(edit=False):
) )
# Liste des ID de semestres # Liste des ID de semestres
if F["type_parcours"] is not None: if formation.type_parcours is not None:
parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"]) parcours = sco_codes_parcours.get_parcours_from_code(formation.type_parcours)
NB_SEM = parcours.NB_SEM NB_SEM = parcours.NB_SEM
else: else:
NB_SEM = 10 # fallback, max 10 semestres NB_SEM = 10 # fallback, max 10 semestres
if NB_SEM == 1: if NB_SEM == 1:
semestre_id_list = [-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: else:
semestre_id_list = [-1] + list(range(1, NB_SEM + 1)) semestre_id_list = [-1] + list(range(1, NB_SEM + 1))
semestre_id_labels = [] semestre_id_labels = []
for sid in semestre_id_list: for sid in semestre_id_list:
if sid == -1: 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 "explanation": """n'indiquez pas les dates, ni le semestre, ni la modalité dans
le titre: ils seront automatiquement ajoutés <input type="button" le titre: ils seront automatiquement ajoutés <input type="button"
value="remettre titre par défaut" onClick="document.tf.titre.value='%s';"/>""" 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", "title": "Semestre dans la formation",
"allowed_values": semestre_id_list, "allowed_values": semestre_id_list,
"labels": semestre_id_labels, "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: 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 nbmod += 1
if edit: if edit:
select_name = "%s!group_id" % mod["module_id"] select_name = "%s!group_id" % mod["module_id"]
@ -560,7 +576,7 @@ def do_formsemestre_createwithmodules(edit=False):
else: else:
return "" return ""
if mod["module_id"] in sem_module_ids: if mod["module_id"] in module_ids_set:
disabled = "disabled" disabled = "disabled"
else: else:
disabled = "" 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>' msg = '<ul class="tf-msg"><li class="tf-msg">Code étape Apogée manquant</li></ul>'
if tf[0] == 0 or msg: if tf[0] == 0 or msg:
return ( return f"""<p>Formation <a class="discretelink" href="{
'<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>' url_for("notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=formation_id)
% F }"><em>{formation.titre}</em> ({formation.acronyme}), version {formation.version}, code {formation.formation_code}</a>
+ msg </p>
+ str(tf[1]) {msg}
) {tf[1]}
"""
elif tf[0] == -1: elif tf[0] == -1:
return "<h4>annulation</h4>" return "<h4>annulation</h4>"
else: 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)] 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: 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]) formsemestre_id = sco_formsemestre.do_formsemestre_create(tf[2])
# creation des modules # création des modules
for module_id in tf[2]["tf-checked"]: for module_id in module_ids_checked:
assert module_id[:2] == "MI"
modargs = { modargs = {
"module_id": int(module_id[2:]), "module_id": module_id,
"formsemestre_id": formsemestre_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) _ = sco_moduleimpl.do_moduleimpl_create(modargs)
flash("Nouveau semestre créé")
return flask.redirect( return flask.redirect(
"formsemestre_status?formsemestre_id=%s&head_message=Nouveau%%20semestre%%20créé" url_for(
% formsemestre_id "notes.formsemestre_status",
scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id,
)
) )
else: else:
# modification du semestre: # Modification du semestre:
# on doit creer les modules nouvellement selectionnés # on doit creer les modules nouvellement selectionnés
# modifier ceux a modifier, et DETRUIRE ceux qui ne sont plus selectionnés. # modifier ceux à modifier, et DETRUIRE ceux qui ne sont plus selectionnés.
# Note: la destruction echouera s'il y a des objets dependants # Note: la destruction échouera s'il y a des objets dépendants
# (eg des evaluations définies) # (eg des évaluations définies)
# nouveaux modules module_ids_tocreate = [
# (retire le "MI" du début du nom de champs) x for x in module_ids_checked if not x in module_ids_existing
checkedmods = [int(x[2:]) for x in tf[2]["tf-checked"]] ]
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]) 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 = [] msg = []
for module_id in mods_tocreate: for module_id in module_ids_tocreate:
modargs = { modargs = {
"module_id": module_id, "module_id": module_id,
"formsemestre_id": formsemestre_id, "formsemestre_id": formsemestre_id,
@ -808,9 +841,11 @@ def do_formsemestre_createwithmodules(edit=False):
% (module_id, moduleimpl_id) % (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 msg += diag
for module_id in mods_toedit: for module_id in module_ids_toedit:
moduleimpl_id = sco_moduleimpl.moduleimpl_list( moduleimpl_id = sco_moduleimpl.moduleimpl_list(
formsemestre_id=formsemestre_id, module_id=module_id formsemestre_id=formsemestre_id, module_id=module_id
)[0]["moduleimpl_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): def formsemestre_delete_moduleimpls(formsemestre_id, module_ids_to_del):
"""Delete moduleimpls """Delete moduleimpls
module_ids_to_del: list of module_id (warning: not moduleimpl) module_ids_to_del: list of module_id (warning: not moduleimpl)