diff --git a/app/scodoc/VERSION.py b/app/scodoc/VERSION.py index 67d94d7baa..de4344f497 100644 --- a/app/scodoc/VERSION.py +++ b/app/scodoc/VERSION.py @@ -8,6 +8,7 @@ SCONAME = "ScoDoc" SCONEWS = """
OK, formation supprimée.
""" @@ -92,6 +92,31 @@ def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST return "\n".join(H) +def do_formation_delete(context, oid, REQUEST): + """delete a formation (and all its UE, matieres, modules) + XXX delete all ues, will break if there are validations ! USE WITH CARE ! + """ + F = sco_formations.formation_list(context, args={"formation_id": oid})[0] + if sco_formations.formation_has_locked_sems(context, oid): + raise ScoLockedFormError() + cnx = ndb.GetDBConnexion() + # delete all UE in this formation + ues = sco_edit_ue.do_ue_list(context, {"formation_id": oid}) + for ue in ues: + do_ue_delete(ue["ue_id"], REQUEST=REQUEST, force=True) + + sco_formations._formationEditor.delete(cnx, oid) + + # news + sco_news.add( + context, + REQUEST, + typ=NEWS_FORM, + object=oid, + text="Suppression de la formation %(acronyme)s" % F, + ) + + def formation_create(context, REQUEST=None): """Creation d'une formation""" return formation_edit(context, create=True, REQUEST=REQUEST) @@ -118,11 +143,11 @@ def formation_edit(context, formation_id=None, create=False, REQUEST=None): is_locked = False else: # edit an existing formation - F = context.formation_list(args={"formation_id": formation_id}) + F = sco_formations.formation_list(context, args={"formation_id": formation_id}) if not F: raise ScoValueError("formation inexistante !") initvalues = F[0] - is_locked = context.formation_has_locked_sems(formation_id) + is_locked = sco_formations.formation_has_locked_sems(context, formation_id) submitlabel = "Modifier les valeurs" H = [ html_sco_header.sco_header( @@ -212,7 +237,7 @@ def formation_edit(context, formation_id=None, create=False, REQUEST=None): "version": version, } ndb.quote_dict(args) - others = context.formation_list(args=args) + others = sco_formations.formation_list(context, args=args) if others and ((len(others) > 1) or others[0]["formation_id"] != formation_id): return ( "\n".join(H) @@ -237,7 +262,7 @@ def do_formation_create(context, args, REQUEST): a = args.copy() if a.has_key("formation_id"): del a["formation_id"] - F = context.formation_list(args=a) + F = sco_formations.formation_list(context, args=a) if len(F) > 0: log("do_formation_create: error: %d formations matching args=%s" % (len(F), a)) raise ScoValueError("Formation non unique (%s) !" % str(a)) @@ -263,7 +288,7 @@ def do_formation_edit(context, args): # On autorise la modif de la formation meme si elle est verrouillee # car cela ne change que du cosmetique, (sauf eventuellement le code formation ?) # mais si verrouillée on ne peut changer le type de parcours - if context.formation_has_locked_sems(args["formation_id"]): + if sco_formations.formation_has_locked_sems(context, args["formation_id"]): if args.has_key("type_parcours"): del args["type_parcours"] # On ne peut jamais supprimer le code formation: diff --git a/app/scodoc/sco_edit_matiere.py b/app/scodoc/sco_edit_matiere.py index d6567bc45a..39e53e9a81 100644 --- a/app/scodoc/sco_edit_matiere.py +++ b/app/scodoc/sco_edit_matiere.py @@ -32,13 +32,65 @@ import notesdb as ndb import sco_utils as scu from notes_log import log from TrivialFormulator import TrivialFormulator, TF, tf_error_message +import sco_edit_ue import sco_formsemestre +import sco_news from sco_exceptions import ScoValueError +_matiereEditor = ndb.EditableTable( + "notes_matieres", + "matiere_id", + ("matiere_id", "ue_id", "numero", "titre"), + sortkey="numero", + output_formators={"numero": ndb.int_null_is_zero}, +) + + +def do_matiere_list(context, *args, **kw): + "list matieres" + cnx = ndb.GetDBConnexion() + return _matiereEditor.list(cnx, *args, **kw) + + +def do_matiere_edit(context, *args, **kw): + "edit a matiere" + cnx = ndb.GetDBConnexion() + # check + mat = sco_edit_matiere.do_matiere_list( + context, {"matiere_id": args[0]["matiere_id"]} + )[0] + if sco_edit_matiere.matiere_is_locked(context, mat["matiere_id"]): + raise ScoLockedFormError() + # edit + _matiereEditor.edit(cnx, *args, **kw) + sco_core.inval_cache(context) # > modif matiere + + +def do_matiere_create(context, args, REQUEST): + "create a matiere" + cnx = ndb.GetDBConnexion() + # check + ue = sco_edit_ue.do_ue_list(context, {"ue_id": args["ue_id"]})[0] + # create matiere + r = _matiereEditor.create(cnx, args) + + # news + F = sco_formations.formation_list( + context, args={"formation_id": ue["formation_id"]} + )[0] + sco_news.add( + context, + REQUEST, + typ=NEWS_FORM, + object=ue["formation_id"], + text="Modification de la formation %(acronyme)s" % F, + ) + return r + def matiere_create(context, ue_id=None, REQUEST=None): """Creation d'une matiere""" - UE = context.do_ue_list(args={"ue_id": ue_id})[0] + UE = sco_edit_ue.do_ue_list(context, args={"ue_id": ue_id})[0] H = [ html_sco_header.sco_header( context, REQUEST, page_title="Création d'une matière" @@ -85,7 +137,7 @@ associé. return REQUEST.RESPONSE.redirect(dest_url) else: # check unicity - mats = context.do_matiere_list(args={"ue_id": ue_id, "titre": tf[2]["titre"]}) + mats = do_matiere_list(context, args={"ue_id": ue_id, "titre": tf[2]["titre"]}) if mats: return ( "\n".join(H) @@ -93,14 +145,46 @@ associé. + tf[1] + html_sco_header.sco_footer(context, REQUEST) ) - _ = context.do_matiere_create(tf[2], REQUEST) + _ = do_matiere_create(context, tf[2], REQUEST) return REQUEST.RESPONSE.redirect(dest_url) +def do_matiere_delete(context, oid, REQUEST): + "delete matiere and attached modules" + cnx = ndb.GetDBConnexion() + # check + mat = do_matiere_list(context, {"matiere_id": oid})[0] + ue = sco_edit_ue.do_ue_list(context, {"ue_id": mat["ue_id"]})[0] + locked = sco_edit_matiere.matiere_is_locked(context, mat["matiere_id"]) + if locked: + log("do_matiere_delete: mat=%s" % mat) + log("do_matiere_delete: ue=%s" % ue) + log("do_matiere_delete: locked sems: %s" % locked) + raise ScoLockedFormError() + log("do_matiere_delete: matiere_id=%s" % oid) + # delete all modules in this matiere + mods = sco_edit_module.do_module_list(context, {"matiere_id": oid}) + for mod in mods: + sco_edit_module.do_module_delete(context, mod["module_id"], REQUEST) + _matiereEditor.delete(cnx, oid) + + # news + F = sco_formations.formation_list( + context, args={"formation_id": ue["formation_id"]} + )[0] + sco_news.add( + context, + REQUEST, + typ=NEWS_FORM, + object=ue["formation_id"], + text="Modification de la formation %(acronyme)s" % F, + ) + + def matiere_delete(context, matiere_id=None, REQUEST=None): """Delete an UE""" - M = context.do_matiere_list(args={"matiere_id": matiere_id})[0] - UE = context.do_ue_list(args={"ue_id": M["ue_id"]})[0] + M = do_matiere_list(context, args={"matiere_id": matiere_id})[0] + UE = sco_edit_ue.do_ue_list(context, args={"ue_id": M["ue_id"]})[0] H = [ html_sco_header.sco_header( context, REQUEST, page_title="Suppression d'une matière" @@ -122,23 +206,25 @@ def matiere_delete(context, matiere_id=None, REQUEST=None): elif tf[0] == -1: return REQUEST.RESPONSE.redirect(dest_url) else: - context.do_matiere_delete(matiere_id, REQUEST) + do_matiere_delete(context, matiere_id, REQUEST) return REQUEST.RESPONSE.redirect(dest_url) def matiere_edit(context, matiere_id=None, REQUEST=None): """Edit matiere""" - F = context.do_matiere_list(args={"matiere_id": matiere_id}) + F = do_matiere_list(context, args={"matiere_id": matiere_id}) if not F: raise ScoValueError("Matière inexistante !") F = F[0] - U = context.do_ue_list(args={"ue_id": F["ue_id"]}) + U = sco_edit_ue.do_ue_list(context, args={"ue_id": F["ue_id"]}) if not F: raise ScoValueError("UE inexistante !") U = U[0] - Fo = context.formation_list(args={"formation_id": U["formation_id"]})[0] + Fo = sco_formations.formation_list( + context, args={"formation_id": U["formation_id"]} + )[0] - ues = context.do_ue_list(args={"formation_id": U["formation_id"]}) + ues = sco_edit_ue.do_ue_list(context, args={"formation_id": U["formation_id"]}) ue_names = ["%(acronyme)s (%(titre)s)" % u for u in ues] ue_ids = [u["ue_id"] for u in ues] H = [ @@ -195,8 +281,8 @@ associé. return REQUEST.RESPONSE.redirect(dest_url) else: # check unicity - mats = context.do_matiere_list( - args={"ue_id": tf[2]["ue_id"], "titre": tf[2]["titre"]} + mats = do_matiere_list( + context, args={"ue_id": tf[2]["ue_id"], "titre": tf[2]["titre"]} ) if len(mats) > 1 or (len(mats) == 1 and mats[0]["matiere_id"] != matiere_id): return ( @@ -215,7 +301,7 @@ associé. {"ue_id": tf[2]["ue_id"], "matiere_id": matiere_id}, ) - context.do_matiere_edit(tf[2]) + do_matiere_edit(context, tf[2]) return REQUEST.RESPONSE.redirect(dest_url) diff --git a/app/scodoc/sco_edit_module.py b/app/scodoc/sco_edit_module.py index 56f49fe854..b3f74afaa3 100644 --- a/app/scodoc/sco_edit_module.py +++ b/app/scodoc/sco_edit_module.py @@ -25,7 +25,7 @@ # ############################################################################## -"""Ajout/Modification/Supression UE +"""Ajout/Modification/Supression modules (portage from DTML) """ import notesdb as ndb @@ -55,14 +55,75 @@ Tous ces enseignants, plus le responsable du semestre, pourront saisir et modifier les notes de ce module. """ +_moduleEditor = ndb.EditableTable( + "notes_modules", + "module_id", + ( + "module_id", + "titre", + "code", + "abbrev", + "heures_cours", + "heures_td", + "heures_tp", + "coefficient", + "ue_id", + "matiere_id", + "formation_id", + "semestre_id", + "numero", + "code_apogee", + "module_type" + #'ects' + ), + sortkey="numero, code, titre", + output_formators={ + "heures_cours": ndb.float_null_is_zero, + "heures_td": ndb.float_null_is_zero, + "heures_tp": ndb.float_null_is_zero, + "numero": ndb.int_null_is_zero, + "coefficient": ndb.float_null_is_zero, + "module_type": ndb.int_null_is_zero + #'ects' : ndb.float_null_is_null + }, +) + + +def do_module_list(context, *args, **kw): + "list modules" + cnx = ndb.GetDBConnexion() + return _moduleEditor.list(cnx, *args, **kw) + + +def do_module_create(context, args, REQUEST): + "create a module" + # create + cnx = ndb.GetDBConnexion() + r = _moduleEditor.create(cnx, args) + + # news + F = sco_formations.formation_list( + context, args={"formation_id": args["formation_id"]} + )[0] + sco_news.add( + context, + REQUEST, + typ=NEWS_FORM, + object=args["formation_id"], + text="Modification de la formation %(acronyme)s" % F, + ) + return r + def module_create(context, matiere_id=None, REQUEST=None): """Creation d'un module""" if not matiere_id: raise ScoValueError("invalid matiere !") - M = context.do_matiere_list(args={"matiere_id": matiere_id})[0] - UE = context.do_ue_list(args={"ue_id": M["ue_id"]})[0] - Fo = context.formation_list(args={"formation_id": UE["formation_id"]})[0] + M = sco_edit_matiere.do_matiere_list(context, args={"matiere_id": matiere_id})[0] + UE = sco_edit_ue.do_ue_list(context, args={"ue_id": M["ue_id"]})[0] + Fo = sco_formations.formation_list( + context, args={"formation_id": UE["formation_id"]} + )[0] parcours = sco_codes_parcours.get_parcours_from_code(Fo["type_parcours"]) semestres_indices = range(1, parcours.NB_SEM + 1) H = [ @@ -72,7 +133,7 @@ def module_create(context, matiere_id=None, REQUEST=None): _MODULE_HELP, ] # cherche le numero adequat (pour placer le module en fin de liste) - Mods = context.do_module_list(args={"matiere_id": matiere_id}) + Mods = do_module_list(context, args={"matiere_id": matiere_id}) if Mods: default_num = max([m["numero"] for m in Mods]) + 10 else: @@ -172,17 +233,52 @@ def module_create(context, matiere_id=None, REQUEST=None): if tf[0] == 0: return "\n".join(H) + tf[1] + html_sco_header.sco_footer(context, REQUEST) else: - context.do_module_create(tf[2], REQUEST) + do_module_create(context, tf[2], REQUEST) return REQUEST.RESPONSE.redirect( scu.NotesURL() + "/ue_list?formation_id=" + UE["formation_id"] ) +def do_module_delete(context, oid, REQUEST): + "delete module" + mod = do_module_list(context, {"module_id": oid})[0] + if sco_edit_module.module_is_locked(context, mod["module_id"]): + raise ScoLockedFormError() + + # S'il y a des moduleimpls, on ne peut pas detruire le module ! + mods = sco_moduleimpl.do_moduleimpl_list(context, module_id=oid) + if mods: + err_page = scu.confirm_dialog( + context, + message="""%d étudiants ont validé l'UE %s (%s)
Si vous supprimez cette UE, ces validations vont être supprimées !
" + % (len(validations), ue["acronyme"], ue["titre"]), + dest_url="", + REQUEST=REQUEST, + target_variable="delete_validations", + cancel_url="ue_list?formation_id=%s" % ue["formation_id"], + parameters={"ue_id": ue_id, "dialog_confirmed": 1}, + ) + if delete_validations: + log("deleting all validations of UE %s" % ue_id) + ndb.SimpleQuery( + context, + "DELETE FROM scolar_formsemestre_validation WHERE ue_id=%(ue_id)s", + {"ue_id": ue_id}, + ) + + # delete all matiere in this UE + mats = sco_edit_matiere.do_matiere_list(context, {"ue_id": ue_id}) + for mat in mats: + sco_edit_matiere.do_matiere_delete(context, mat["matiere_id"], REQUEST) + # delete uecoef and events + ndb.SimpleQuery( + context, + "DELETE FROM notes_formsemestre_uecoef WHERE ue_id=%(ue_id)s", + {"ue_id": ue_id}, + ) + ndb.SimpleQuery( + context, "DELETE FROM scolar_events WHERE ue_id=%(ue_id)s", {"ue_id": ue_id} + ) + cnx = ndb.GetDBConnexion() + context._ueEditor.delete(cnx, ue_id) + # > UE delete + supr. validations associées etudiants (cas compliqué, mais rarement utilisé: acceptable de tout invalider ?): + sco_core.inval_cache(context) + # news + F = sco_formations.formation_list( + context, args={"formation_id": ue["formation_id"]} + )[0] + sco_news.add( + context, + REQUEST, + typ=NEWS_FORM, + object=ue["formation_id"], + text="Modification de la formation %(acronyme)s" % F, + ) + # + if not force: + return REQUEST.RESPONSE.redirect( + scu.NotesURL() + "/ue_list?formation_id=" + str(ue["formation_id"]) + ) + else: + return None + def ue_create(context, formation_id=None, REQUEST=None): """Creation d'une UE""" @@ -51,7 +180,7 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None): """Modification ou creation d'une UE""" create = int(create) if not create: - U = context.do_ue_list(args={"ue_id": ue_id}) + U = do_ue_list(context, args={"ue_id": ue_id}) if not U: raise ScoValueError("UE inexistante !") U = U[0] @@ -63,7 +192,7 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None): title = "Création d'une UE" initvalues = {} submitlabel = "Créer cette UE" - Fol = context.formation_list(args={"formation_id": formation_id}) + Fol = sco_formations.formation_list(context, args={"formation_id": formation_id}) if not Fol: raise ScoValueError( "Formation %s inexistante ! (si vous avez suivi un lien valide, merci de signaler le problème)" @@ -201,14 +330,14 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None): context, formation_id, int(tf[2]["semestre_id"] or 0) ) - ue_id = context.do_ue_create(tf[2], REQUEST) + ue_id = do_ue_create(context, tf[2], REQUEST) if parcours.UE_IS_MODULE or tf[2]["create_matiere"]: - matiere_id = context.do_matiere_create( + matiere_id = sco_edit_matiere.do_matiere_create(context, {"ue_id": ue_id, "titre": tf[2]["titre"], "numero": 1}, REQUEST ) if parcours.UE_IS_MODULE: # dans ce mode, crée un (unique) module dans l'UE: - _ = context.do_module_create( + _ = sco_edit_module.do_module_create(context, { "titre": tf[2]["titre"], "code": tf[2]["acronyme"], @@ -233,7 +362,7 @@ def _add_ue_semestre_id(context, ue_list): qui les place à la fin de la liste. """ for ue in ue_list: - Modlist = context.do_module_list(args={"ue_id": ue["ue_id"]}) + Modlist = sco_edit_module.do_module_list(context, args={"ue_id": ue["ue_id"]}) if Modlist: ue["semestre_id"] = Modlist[0]["semestre_id"] else: @@ -244,7 +373,7 @@ def next_ue_numero(context, formation_id, semestre_id=None): """Numero d'une nouvelle UE dans cette formation. Si le semestre est specifie, cherche les UE ayant des modules de ce semestre """ - ue_list = context.do_ue_list(args={"formation_id": formation_id}) + ue_list = do_ue_list(context, args={"formation_id": formation_id}) if not ue_list: return 0 if semestre_id is None: @@ -263,7 +392,7 @@ def ue_delete( context, ue_id=None, delete_validations=False, dialog_confirmed=False, REQUEST=None ): """Delete an UE""" - ue = context.do_ue_list(args={"ue_id": ue_id}) + ue = do_ue_list(context, args={"ue_id": ue_id}) if not ue: raise ScoValueError("UE inexistante !") ue = ue[0] @@ -278,8 +407,8 @@ def ue_delete( cancel_url="ue_list?formation_id=%s" % ue["formation_id"], ) - return context._do_ue_delete( - ue_id, delete_validations=delete_validations, REQUEST=REQUEST + return do_ue_delete( + context, ue_id, delete_validations=delete_validations, REQUEST=REQUEST ) @@ -289,14 +418,14 @@ def ue_list(context, formation_id=None, msg="", REQUEST=None): """ authuser = REQUEST.AUTHENTICATED_USER - F = context.formation_list(args={"formation_id": formation_id}) + F = sco_formations.formation_list(context, args={"formation_id": formation_id}) if not F: raise ScoValueError("invalid formation_id") F = F[0] parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"]) - locked = context.formation_has_locked_sems(formation_id) + locked = sco_formations.formation_has_locked_sems(context, formation_id) - ue_list = context.do_ue_list(args={"formation_id": formation_id}) + ue_list = do_ue_list(context, args={"formation_id": formation_id}) # tri par semestre et numero: _add_ue_semestre_id(context, ue_list) ue_list.sort(key=lambda u: (u["semestre_id"], u["numero"])) @@ -478,7 +607,7 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module H.append('[verrouillé]') if not parcours.UE_IS_MODULE: H.append('UE : %(acronyme)s
" % ue) # store min/max values used by JS client-side checks: H.append( @@ -880,7 +880,7 @@ def evaluation_create_form( else: min_note_max_str = "0" # - Mod = context.do_module_list(args={"module_id": M["module_id"]})[0] + Mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0] # help = """Le coefficient d'une évaluation n'est utilisé que pour pondérer les évaluations au sein d'un module. diff --git a/app/scodoc/sco_export_results.py b/app/scodoc/sco_export_results.py index ad8eb160e8..25f02ef4c2 100644 --- a/app/scodoc/sco_export_results.py +++ b/app/scodoc/sco_export_results.py @@ -62,7 +62,7 @@ def _build_results_table(context, start_date=None, end_date=None, types_parcours semlist = [dpv["formsemestre"] for dpv in dpv_by_sem.values() if dpv] semlist_parcours = [] for sem in semlist: - sem["formation"] = context.formation_list( + sem["formation"] = sco_formations.formation_list(context, args={"formation_id": sem["formation_id"]} )[0] sem["parcours"] = sco_codes_parcours.get_parcours_from_code( diff --git a/app/scodoc/sco_formations.py b/app/scodoc/sco_formations.py index c936ee0f9a..385e787eaf 100644 --- a/app/scodoc/sco_formations.py +++ b/app/scodoc/sco_formations.py @@ -61,14 +61,37 @@ _formationEditor = ndb.EditableTable( ) +def formation_list(context, formation_id=None, args={}): + """List formation(s) with given id, or matching args + (when args is given, formation_id is ignored). + """ + if not args: + if formation_id is None: + args = {} + else: + args = {"formation_id": formation_id} + cnx = ndb.GetDBConnexion() + r = _formationEditor.list(cnx, args=args) + # log('%d formations found' % len(r)) + return r + + +def formation_has_locked_sems(context, formation_id): + "True if there is a locked formsemestre in this formation" + sems = sco_formsemestre.do_formsemestre_list( + context, args={"formation_id": formation_id, "etat": "0"} + ) + return sems + + def formation_export( context, formation_id, export_ids=False, export_tags=True, format=None, REQUEST=None ): """Get a formation, with UE, matieres, modules in desired format """ - F = context.formation_list(args={"formation_id": formation_id})[0] - ues = context.do_ue_list({"formation_id": formation_id}) + F = formation_list(context, args={"formation_id": formation_id})[0] + ues = sco_edit_ue.do_ue_list(context, {"formation_id": formation_id}) F["ue"] = ues for ue in ues: ue_id = ue["ue_id"] @@ -77,14 +100,14 @@ def formation_export( del ue["formation_id"] if ue["ects"] is None: del ue["ects"] - mats = context.do_matiere_list({"ue_id": ue_id}) + mats = sco_edit_matiere.do_matiere_list(context, {"ue_id": ue_id}) ue["matiere"] = mats for mat in mats: matiere_id = mat["matiere_id"] if not export_ids: del mat["matiere_id"] del mat["ue_id"] - mods = context.do_module_list({"matiere_id": matiere_id}) + mods = sco_edit_module.do_module_list(context, {"matiere_id": matiere_id}) mat["module"] = mods for mod in mods: if export_tags: @@ -188,14 +211,14 @@ def formation_import_xml( del ue_info[1]["ue_id"] else: xml_ue_id = None - ue_id = context.do_ue_create(ue_info[1], REQUEST) + ue_id = sco_edit_ue.do_ue_create(context, ue_info[1], REQUEST) if xml_ue_id: ues_old2new[xml_ue_id] = ue_id # -- create matieres for mat_info in ue_info[2]: assert mat_info[0] == "matiere" mat_info[1]["ue_id"] = ue_id - mat_id = context.do_matiere_create(mat_info[1], REQUEST) + mat_id = sco_edit_matiere.do_matiere_create(context, mat_info[1], REQUEST) # -- create modules for mod_info in mat_info[2]: assert mod_info[0] == "module" @@ -207,7 +230,7 @@ def formation_import_xml( mod_info[1]["formation_id"] = formation_id mod_info[1]["matiere_id"] = mat_id mod_info[1]["ue_id"] = ue_id - mod_id = context.do_module_create(mod_info[1], REQUEST) + mod_id = sco_edit_module.do_module_create(context, mod_info[1], REQUEST) if xml_module_id: modules_old2new[xml_module_id] = mod_id if import_tags: @@ -223,7 +246,7 @@ def formation_list_table(context, formation_id=None, args={}, REQUEST=None): and listing associated semestres returns a table """ - formations = context.formation_list(formation_id=formation_id, args=args) + formations = formation_list(context, formation_id=formation_id, args=args) title = "Programmes pédagogiques" lockicon = scu.icontag( "lock32_img", title="Comporte des semestres verrouillés", border="0" @@ -269,7 +292,7 @@ def formation_list_table(context, formation_id=None, args={}, REQUEST=None): else: f["date_fin_dernier_sem"] = "" f["annee_dernier_sem"] = "" - locked = context.formation_has_locked_sems(f["formation_id"]) + locked = formation_has_locked_sems(context, f["formation_id"]) # if locked: but_locked = lockicon diff --git a/app/scodoc/sco_formsemestre_edit.py b/app/scodoc/sco_formsemestre_edit.py index 5ac3570708..4ea1be46e8 100644 --- a/app/scodoc/sco_formsemestre_edit.py +++ b/app/scodoc/sco_formsemestre_edit.py @@ -140,7 +140,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): allowed_user_names = login2display.values() + [""] # formation_id = REQUEST.form["formation_id"] - F = context.formation_list(args={"formation_id": formation_id}) + F = sco_formations.formation_list(context, args={"formation_id": formation_id}) if not F: raise ScoValueError("Formation inexistante !") F = F[0] @@ -193,11 +193,11 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): # on pourrait faire un simple module_list( ) # mais si on veut l'ordre du PPN (groupe par UE et matieres) il faut: mods = [] # liste de dicts - uelist = context.do_ue_list({"formation_id": formation_id}) + uelist = sco_edit_ue.do_ue_list(context, {"formation_id": formation_id}) for ue in uelist: - matlist = context.do_matiere_list({"ue_id": ue["ue_id"]}) + matlist = sco_edit_matiere.do_matiere_list(context, {"ue_id": ue["ue_id"]}) for mat in matlist: - modsmat = context.do_module_list({"matiere_id": mat["matiere_id"]}) + modsmat = sco_edit_module.do_module_list(context, {"matiere_id": mat["matiere_id"]}) # XXX debug checks for m in modsmat: if m["ue_id"] != ue["ue_id"]: @@ -747,7 +747,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): "responsable_id": tf[2][module_id], } moduleimpl_id = sco_moduleimpl.do_moduleimpl_create(context, modargs) - mod = context.do_module_list({"module_id": module_id})[0] + mod = sco_edit_module.do_module_list(context, {"module_id": module_id})[0] msg += ["création de %s (%s)" % (mod["code"], mod["titre"])] # INSCRIPTIONS DES ETUDIANTS log( @@ -798,7 +798,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): sco_moduleimpl.do_moduleimpl_edit( context, modargs, formsemestre_id=formsemestre_id ) - mod = context.do_module_list({"module_id": module_id})[0] + mod = sco_edit_module.do_module_list(context, {"module_id": module_id})[0] if msg: msg_html = ( @@ -834,7 +834,7 @@ def formsemestre_delete_moduleimpls(context, formsemestre_id, module_ids_to_del) moduleimpl_id = sco_moduleimpl.do_moduleimpl_list( context, formsemestre_id=formsemestre_id, module_id=module_id )[0]["moduleimpl_id"] - mod = context.do_module_list({"module_id": module_id})[0] + mod = sco_edit_module.do_module_list(context, {"module_id": module_id})[0] # Evaluations dans ce module ? evals = context.do_evaluation_list({"moduleimpl_id": moduleimpl_id}) if evals: @@ -1109,7 +1109,7 @@ def formsemestre_associate_new_version( if not dialog_confirmed: # dresse le liste des semestres de la meme formation et version sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - F = context.formation_list(args={"formation_id": sem["formation_id"]})[0] + F = sco_formations.formation_list(context, args={"formation_id": sem["formation_id"]})[0] othersems = sco_formsemestre.do_formsemestre_list( context, args={ @@ -1227,7 +1227,7 @@ def _reassociate_moduleimpls( def formsemestre_delete(context, formsemestre_id, REQUEST=None): """Delete a formsemestre (affiche avertissements)""" sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - F = context.formation_list(args={"formation_id": sem["formation_id"]})[0] + F = sco_formations.formation_list(context, args={"formation_id": sem["formation_id"]})[0] H = [ html_sco_header.html_sem_header( context, REQUEST, "Suppression du semestre", sem @@ -1672,7 +1672,7 @@ def get_formsemestre_session_id(context, sem, F, parcours): """ # sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - # F = context.formation_list( args={ 'formation_id' : sem['formation_id'] } )[0] + # F = sco_formations.formation_list(context, args={ 'formation_id' : sem['formation_id'] } )[0] # parcours = sco_codes_parcours.get_parcours_from_code(F['type_parcours']) ImputationDept = sco_preferences.get_preference( diff --git a/app/scodoc/sco_formsemestre_exterieurs.py b/app/scodoc/sco_formsemestre_exterieurs.py index 6794ac116c..aecbc04aea 100644 --- a/app/scodoc/sco_formsemestre_exterieurs.py +++ b/app/scodoc/sco_formsemestre_exterieurs.py @@ -49,7 +49,7 @@ def formsemestre_ext_create(context, etudid, sem_params, REQUEST=None): sem_params: dict nécessaire à la création du formsemestre """ # Check args - _formation = context.formation_list( + _formation = sco_formations.formation_list(context, args={"formation_id": sem_params["formation_id"]} )[0] if etudid: @@ -436,7 +436,7 @@ def _list_ue_with_coef_and_validations(context, sem, etudid): """ cnx = ndb.GetDBConnexion() formsemestre_id = sem["formsemestre_id"] - ue_list = context.do_ue_list({"formation_id": sem["formation_id"]}) + ue_list = sco_edit_ue.do_ue_list(context, {"formation_id": sem["formation_id"]}) for ue in ue_list: # add coefficient uecoef = sco_formsemestre.formsemestre_uecoef_list( diff --git a/app/scodoc/sco_formsemestre_status.py b/app/scodoc/sco_formsemestre_status.py index 1e3d8e02ac..8073a3f42b 100644 --- a/app/scodoc/sco_formsemestre_status.py +++ b/app/scodoc/sco_formsemestre_status.py @@ -140,7 +140,7 @@ def formsemestre_status_menubar(context, sem, REQUEST): else: change_lock_msg = "Déverrouiller" - F = context.formation_list(args={"formation_id": sem["formation_id"]})[0] + F = sco_formations.formation_list(context, args={"formation_id": sem["formation_id"]})[0] menuSemestre = [ { @@ -563,7 +563,7 @@ def fill_formsemestre(context, sem, REQUEST=None): ) else: sem["eyelink"] = "" - F = context.formation_list(args={"formation_id": sem["formation_id"]})[0] + F = sco_formations.formation_list(context, args={"formation_id": sem["formation_id"]})[0] sem["formation"] = F parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"]) if sem["semestre_id"] != -1: @@ -605,7 +605,7 @@ def formsemestre_description_table( use_ue_coefs = sco_preferences.get_preference( context, "use_ue_coefs", formsemestre_id ) - F = context.formation_list(args={"formation_id": sem["formation_id"]})[0] + F = sco_formations.formation_list(context, args={"formation_id": sem["formation_id"]})[0] parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"]) Mlist = sco_moduleimpl.do_moduleimpl_withmodule_list( context, formsemestre_id=formsemestre_id @@ -891,7 +891,7 @@ def html_expr_diagnostic(context, diagnostics): ) else: if diag["ue_id"] != last_id or diag["msg"] != last_msg: - ue = context.do_ue_list({"ue_id": diag["ue_id"]})[0] + ue = sco_edit_ue.do_ue_list(context, {"ue_id": diag["ue_id"]})[0] H.append( '
Aucun groupe sélectionné !
" M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0] - Mod = context.do_module_list(args={"module_id": M["module_id"]})[0] + Mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0] sem = sco_formsemestre.get_formsemestre(context, M["formsemestre_id"]) evalname = "%s-%s" % (Mod["code"], ndb.DateDMYtoISO(E["jour"])) if E["description"]: diff --git a/app/scodoc/sco_pvjury.py b/app/scodoc/sco_pvjury.py index 3bf6127f8c..47f98e352c 100644 --- a/app/scodoc/sco_pvjury.py +++ b/app/scodoc/sco_pvjury.py @@ -83,7 +83,7 @@ def _descr_decisions_ues(context, nt, etudid, decisions_ue, decision_sem): and sco_codes_parcours.code_semestre_validant(decision_sem["code"]) ) ): - ue = context.do_ue_list(args={"ue_id": ue_id})[0] + ue = sco_edit_ue.do_ue_list(context, args={"ue_id": ue_id})[0] uelist.append(ue) except: log("descr_decisions_ues: ue_id=%s decisions_ue=%s" % (ue_id, decisions_ue)) @@ -353,7 +353,7 @@ def dict_pvjury( "formsemestre": sem, "has_prev": has_prev, "semestre_non_terminal": semestre_non_terminal, - "formation": context.formation_list(args={"formation_id": sem["formation_id"]})[ + "formation": sco_formations.formation_list(context, args={"formation_id": sem["formation_id"]})[ 0 ], "decisions": L, @@ -720,7 +720,7 @@ def formsemestre_pvjury_pdf( def descrform_pvjury(context, sem): """Définition de formulaire pour PV jury PDF""" - F = context.formation_list(formation_id=sem["formation_id"])[0] + F = sco_formations.formation_list(context, formation_id=sem["formation_id"])[0] return [ ( "date_commission", diff --git a/app/scodoc/sco_recapcomplet.py b/app/scodoc/sco_recapcomplet.py index 73c516c3c9..4bddb19e87 100644 --- a/app/scodoc/sco_recapcomplet.py +++ b/app/scodoc/sco_recapcomplet.py @@ -66,7 +66,7 @@ def formsemestre_recapcomplet( trié par moyenne générale décroissante. """ sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - F = context.formation_list(args={"formation_id": sem["formation_id"]})[0] + F = sco_formations.formation_list(context, args={"formation_id": sem["formation_id"]})[0] parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"]) # traduit du DTML modejury = int(modejury) diff --git a/app/scodoc/sco_saisie_notes.py b/app/scodoc/sco_saisie_notes.py index 44cca39007..278e6e3331 100644 --- a/app/scodoc/sco_saisie_notes.py +++ b/app/scodoc/sco_saisie_notes.py @@ -280,7 +280,7 @@ def do_evaluation_upload_xls(context, REQUEST): M = sco_moduleimpl.do_moduleimpl_list( context, moduleimpl_id=E["moduleimpl_id"] )[0] - mod = context.do_module_list(args={"module_id": M["module_id"]})[0] + mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0] mod["moduleimpl_id"] = M["moduleimpl_id"] mod["url"] = "Notes/moduleimpl_status?moduleimpl_id=%(moduleimpl_id)s" % mod sco_news.add( @@ -371,7 +371,7 @@ def do_evaluation_set_missing( nb_changed, _, _ = _notes_add(context, authuser, evaluation_id, L, comment) # news M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0] - mod = context.do_module_list(args={"module_id": M["module_id"]})[0] + mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0] mod["moduleimpl_id"] = M["moduleimpl_id"] mod["url"] = "Notes/moduleimpl_status?moduleimpl_id=%(moduleimpl_id)s" % mod sco_news.add( @@ -447,7 +447,7 @@ def evaluation_suppress_alln(context, evaluation_id, REQUEST, dialog_confirmed=F ] # news M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0] - mod = context.do_module_list(args={"module_id": M["module_id"]})[0] + mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0] mod["moduleimpl_id"] = M["moduleimpl_id"] mod["url"] = "Notes/moduleimpl_status?moduleimpl_id=%(moduleimpl_id)s" % mod sco_news.add( @@ -785,7 +785,7 @@ def feuille_saisie_notes(context, evaluation_id, group_ids=[], REQUEST=None): E = evals[0] M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0] formsemestre_id = M["formsemestre_id"] - Mod = context.do_module_list(args={"module_id": M["module_id"]})[0] + Mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0] sem = sco_formsemestre.get_formsemestre(context, M["formsemestre_id"]) if E["jour"]: indication_date = DateDMYtoISO(E["jour"]) @@ -863,7 +863,7 @@ def has_existing_decision(context, M, E, etudid): return True dec_ues = nt.get_etud_decision_ues(etudid) if dec_ues: - mod = context.do_module_list({"module_id": M["module_id"]})[0] + mod = sco_edit_module.do_module_list(context, {"module_id": M["module_id"]})[0] ue_id = mod["ue_id"] if ue_id in dec_ues: return True # decision pour l'UE a laquelle appartient cette evaluation @@ -1249,7 +1249,7 @@ def save_note( ) E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0] - Mod = context.do_module_list(args={"module_id": M["module_id"]})[0] + Mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0] Mod["url"] = "Notes/moduleimpl_status?moduleimpl_id=%(moduleimpl_id)s" % M result = {"nbchanged": 0} # JSON # Check access: admin, respformation, or responsable_id diff --git a/app/scodoc/sco_tag_module.py b/app/scodoc/sco_tag_module.py index 074a85ad37..58c52dc1e0 100644 --- a/app/scodoc/sco_tag_module.py +++ b/app/scodoc/sco_tag_module.py @@ -248,7 +248,7 @@ def module_tag_set(context, module_id="", taglist=[], REQUEST=None): taglist = [t.strip() for t in taglist] log("module_tag_set: module_id=%s taglist=%s" % (module_id, taglist)) # Sanity check: - Mod = context.do_module_list(args={"module_id": module_id}) + Mod = sco_edit_module.do_module_list(context, args={"module_id": module_id}) if not Mod: raise ScoValueError("invalid module !") diff --git a/app/scodoc/sco_ue_external.py b/app/scodoc/sco_ue_external.py index faf8d066ee..9377e13701 100644 --- a/app/scodoc/sco_ue_external.py +++ b/app/scodoc/sco_ue_external.py @@ -91,7 +91,7 @@ def external_ue_create( numero = sco_edit_ue.next_ue_numero( context, formation_id, semestre_id=sem["semestre_id"] ) - ue_id = context.do_ue_create( + ue_id = sco_edit_ue.do_ue_create(context, { "formation_id": formation_id, "titre": titre, @@ -104,11 +104,11 @@ def external_ue_create( REQUEST, ) - matiere_id = context.do_matiere_create( + matiere_id = sco_edit_matiere.do_matiere_create(context, {"ue_id": ue_id, "titre": titre or acronyme, "numero": 1}, REQUEST ) - module_id = context.do_module_create( + module_id = sco_edit_module.do_module_create(context, { "titre": "UE extérieure", "code": acronyme, @@ -176,7 +176,7 @@ def external_ue_inscrit_et_note( def get_existing_external_ue(context, formation_id): "la liste de toutes les UE externes définies dans cette formation" - return context.do_ue_list(args={"formation_id": formation_id, "is_external": 1}) + return sco_edit_ue.do_ue_list(context, args={"formation_id": formation_id, "is_external": 1}) def get_external_moduleimpl_id(context, formsemestre_id, ue_id): @@ -235,7 +235,7 @@ def external_ue_create_form(context, formsemestre_id, etudid, REQUEST=None): """, ] html_footer = html_sco_header.sco_footer(context, REQUEST) - Fo = context.formation_list(args={"formation_id": sem["formation_id"]})[0] + Fo = sco_formations.formation_list(context, args={"formation_id": sem["formation_id"]})[0] parcours = sco_codes_parcours.get_parcours_from_code(Fo["type_parcours"]) ue_types = parcours.ALLOWED_UE_TYPES ue_types.sort() diff --git a/app/views/notes.py b/app/views/notes.py index fdc48636df..802b2fec20 100644 --- a/app/views/notes.py +++ b/app/views/notes.py @@ -407,33 +407,11 @@ sco_publish( Permission.ScoChangeFormation, ) - -@bp.route("/do_formation_delete") -@permission_required(Permission.ScoChangeFormation) -@scodoc7func(context) -def do_formation_delete(context, oid, REQUEST): - """delete a formation (and all its UE, matieres, modules) - XXX delete all ues, will break if there are validations ! USE WITH CARE ! - """ - F = context.formation_list(args={"formation_id": oid})[0] - if context.formation_has_locked_sems(oid): - raise ScoLockedFormError() - cnx = ndb.GetDBConnexion() - # delete all UE in this formation - ues = context.do_ue_list({"formation_id": oid}) - for ue in ues: - context._do_ue_delete(ue["ue_id"], REQUEST=REQUEST, force=True) - - _formationEditor.delete(cnx, oid) - - # news - sco_news.add( - context, - REQUEST, - typ=NEWS_FORM, - object=oid, - text="Suppression de la formation %(acronyme)s" % F, - ) +sco_publish( + "/do_formation_delete", + sco_edit_formation.do_formation_delete, + Permission.ScoChangeFormation, +) @bp.route("/formation_list") @@ -443,15 +421,7 @@ def formation_list(context, format=None, REQUEST=None, formation_id=None, args={ """List formation(s) with given id, or matching args (when args is given, formation_id is ignored). """ - # logCallStack() - if not args: - if formation_id is None: - args = {} - else: - args = {"formation_id": formation_id} - cnx = ndb.GetDBConnexion() - r = sco_formations._formationEditor.list(cnx, args=args) - # log('%d formations found' % len(r)) + r = sco_formation.formation_list(context, formation_id=formation_id, args=args) return scu.sendResult(REQUEST, r, name="formation", format=format) @@ -504,7 +474,9 @@ def formation_import_xml_form(context, REQUEST): elif tf[0] == -1: return REQUEST.RESPONSE.redirect(scu.NotesURL()) else: - formation_id, _, _ = context.formation_import_xml(tf[2]["xmlfile"], REQUEST) + formation_id, _, _ = sco_formations.formation_import_xml( + context, tf[2]["xmlfile"], REQUEST + ) return ( "\n".join(H) @@ -527,7 +499,7 @@ def formation_create_new_version(context, formation_id, redirect=True, REQUEST=N context, REQUEST, xml ) # news - F = context.formation_list(args={"formation_id": new_id})[0] + F = sco_formations.formation_list(context, args={"formation_id": new_id})[0] sco_news.add( context, REQUEST, @@ -544,382 +516,40 @@ def formation_create_new_version(context, formation_id, redirect=True, REQUEST=N # --- UE -_ueEditor = ndb.EditableTable( - "notes_ue", - "ue_id", - ( - "ue_id", - "formation_id", - "acronyme", - "numero", - "titre", - "type", - "ue_code", - "ects", - "is_external", - "code_apogee", - "coefficient", - ), - sortkey="numero", - input_formators={"type": ndb.int_null_is_zero}, - output_formators={ - "numero": ndb.int_null_is_zero, - "ects": ndb.float_null_is_null, - "coefficient": ndb.float_null_is_zero, - }, +sco_publish( + "/do_ue_create", + sco_edit_ue.do_ue_create, + Permission.ScoChangeFormation, ) - -@bp.route("/do_ue_create") -@permission_required(Permission.ScoChangeFormation) -@scodoc7func(context) -def do_ue_create(context, args, REQUEST): - "create an ue" - cnx = ndb.GetDBConnexion() - # check duplicates - ues = context.do_ue_list( - {"formation_id": args["formation_id"], "acronyme": args["acronyme"]} - ) - if ues: - raise ScoValueError('Acronyme d\'UE "%s" déjà utilisé !' % args["acronyme"]) - # create - r = context._ueEditor.create(cnx, args) - - # news - F = context.formation_list(args={"formation_id": args["formation_id"]})[0] - sco_news.add( - context, - REQUEST, - typ=NEWS_FORM, - object=args["formation_id"], - text="Modification de la formation %(acronyme)s" % F, - ) - return r - - -def _do_ue_delete(context, ue_id, delete_validations=False, REQUEST=None, force=False): - "delete UE and attached matieres (but not modules (it should ?))" - cnx = ndb.GetDBConnexion() - log("do_ue_delete: ue_id=%s, delete_validations=%s" % (ue_id, delete_validations)) - # check - ue = context.do_ue_list({"ue_id": ue_id}) - if not ue: - raise ScoValueError("UE inexistante !") - ue = ue[0] - if sco_edit_ue.ue_is_locked(context, ue["ue_id"]): - raise ScoLockedFormError() - # Il y a-t-il des etudiants ayant validé cette UE ? - # si oui, propose de supprimer les validations - validations = sco_parcours_dut.scolar_formsemestre_validation_list( - cnx, args={"ue_id": ue_id} - ) - if validations and not delete_validations and not force: - return scu.confirm_dialog( - context, - "%d étudiants ont validé l'UE %s (%s)
Si vous supprimez cette UE, ces validations vont être supprimées !
" - % (len(validations), ue["acronyme"], ue["titre"]), - dest_url="", - REQUEST=REQUEST, - target_variable="delete_validations", - cancel_url="ue_list?formation_id=%s" % ue["formation_id"], - parameters={"ue_id": ue_id, "dialog_confirmed": 1}, - ) - if delete_validations: - log("deleting all validations of UE %s" % ue_id) - ndb.SimpleQuery( - context, - "DELETE FROM scolar_formsemestre_validation WHERE ue_id=%(ue_id)s", - {"ue_id": ue_id}, - ) - - # delete all matiere in this UE - mats = context.do_matiere_list({"ue_id": ue_id}) - for mat in mats: - context.do_matiere_delete(mat["matiere_id"], REQUEST) - # delete uecoef and events - ndb.SimpleQuery( - context, - "DELETE FROM notes_formsemestre_uecoef WHERE ue_id=%(ue_id)s", - {"ue_id": ue_id}, - ) - ndb.SimpleQuery( - context, "DELETE FROM scolar_events WHERE ue_id=%(ue_id)s", {"ue_id": ue_id} - ) - cnx = ndb.GetDBConnexion() - context._ueEditor.delete(cnx, ue_id) - # > UE delete + supr. validations associées etudiants (cas compliqué, mais rarement utilisé: acceptable de tout invalider ?): - sco_core.inval_cache(context) - # news - F = context.formation_list(args={"formation_id": ue["formation_id"]})[0] - sco_news.add( - context, - REQUEST, - typ=NEWS_FORM, - object=ue["formation_id"], - text="Modification de la formation %(acronyme)s" % F, - ) - # - if not force: - return REQUEST.RESPONSE.redirect( - scu.NotesURL() + "/ue_list?formation_id=" + str(ue["formation_id"]) - ) - else: - return None - - -@bp.route("/do_ue_list") -@permission_required(Permission.ScoView) -@scodoc7func(context) -def do_ue_list(context, *args, **kw): - "list UEs" - cnx = ndb.GetDBConnexion() - return context._ueEditor.list(cnx, *args, **kw) +sco_publish( + "/do_ue_list", + sco_edit_ue.do_ue_list, + Permission.ScoView, +) # --- Matieres -_matiereEditor = ndb.EditableTable( - "notes_matieres", - "matiere_id", - ("matiere_id", "ue_id", "numero", "titre"), - sortkey="numero", - output_formators={"numero": ndb.int_null_is_zero}, +sco_publish( + "/do_matiere_create", + sco_edit_matiere.do_matiere_create, + Permission.ScoChangeFormation, +) +sco_publish( + "/do_matiere_delete", + sco_edit_matiere.do_matiere_delete, + Permission.ScoChangeFormation, ) - - -@bp.route("/do_matiere_create") -@permission_required(Permission.ScoChangeFormation) -@scodoc7func(context) -def do_matiere_create(context, args, REQUEST): - "create a matiere" - cnx = ndb.GetDBConnexion() - # check - ue = context.do_ue_list({"ue_id": args["ue_id"]})[0] - # create matiere - r = context._matiereEditor.create(cnx, args) - - # news - F = context.formation_list(args={"formation_id": ue["formation_id"]})[0] - sco_news.add( - context, - REQUEST, - typ=NEWS_FORM, - object=ue["formation_id"], - text="Modification de la formation %(acronyme)s" % F, - ) - return r - - -@bp.route("/do_matiere_delete") -@permission_required(Permission.ScoChangeFormation) -@scodoc7func(context) -def do_matiere_delete(context, oid, REQUEST): - "delete matiere and attached modules" - cnx = ndb.GetDBConnexion() - # check - mat = context.do_matiere_list({"matiere_id": oid})[0] - ue = context.do_ue_list({"ue_id": mat["ue_id"]})[0] - locked = sco_edit_matiere.matiere_is_locked(context, mat["matiere_id"]) - if locked: - log("do_matiere_delete: mat=%s" % mat) - log("do_matiere_delete: ue=%s" % ue) - log("do_matiere_delete: locked sems: %s" % locked) - raise ScoLockedFormError() - log("do_matiere_delete: matiere_id=%s" % oid) - # delete all modules in this matiere - mods = context.do_module_list({"matiere_id": oid}) - for mod in mods: - context.do_module_delete(mod["module_id"], REQUEST) - context._matiereEditor.delete(cnx, oid) - - # news - F = context.formation_list(args={"formation_id": ue["formation_id"]})[0] - sco_news.add( - context, - REQUEST, - typ=NEWS_FORM, - object=ue["formation_id"], - text="Modification de la formation %(acronyme)s" % F, - ) - - -@bp.route("/do_matiere_list") -@permission_required(Permission.ScoView) -@scodoc7func(context) -def do_matiere_list(context, *args, **kw): - "list matieres" - cnx = ndb.GetDBConnexion() - return context._matiereEditor.list(cnx, *args, **kw) - - -@bp.route("/do_matiere_edit") -@permission_required(Permission.ScoChangeFormation) -@scodoc7func(context) -def do_matiere_edit(context, *args, **kw): - "edit a matiere" - cnx = ndb.GetDBConnexion() - # check - mat = context.do_matiere_list({"matiere_id": args[0]["matiere_id"]})[0] - if sco_edit_matiere.matiere_is_locked(context, mat["matiere_id"]): - raise ScoLockedFormError() - # edit - context._matiereEditor.edit(cnx, *args, **kw) - sco_core.inval_cache(context) # > modif matiere - - -@bp.route("/do_matiere_formation_id") -@permission_required(Permission.ScoView) -@scodoc7func(context) -def do_matiere_formation_id(context, matiere_id): - "get formation_id from matiere" - cnx = ndb.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) - cursor.execute( - "select UE.formation_id from notes_matieres M, notes_ue UE where M.matiere_id = %(matiere_id)s and M.ue_id = UE.ue_id", - {"matiere_id": matiere_id}, - ) - res = cursor.fetchall() - return res[0][0] # --- Modules -_moduleEditor = ndb.EditableTable( - "notes_modules", - "module_id", - ( - "module_id", - "titre", - "code", - "abbrev", - "heures_cours", - "heures_td", - "heures_tp", - "coefficient", - "ue_id", - "matiere_id", - "formation_id", - "semestre_id", - "numero", - "code_apogee", - "module_type" - #'ects' - ), - sortkey="numero, code, titre", - output_formators={ - "heures_cours": ndb.float_null_is_zero, - "heures_td": ndb.float_null_is_zero, - "heures_tp": ndb.float_null_is_zero, - "numero": ndb.int_null_is_zero, - "coefficient": ndb.float_null_is_zero, - "module_type": ndb.int_null_is_zero - #'ects' : ndb.float_null_is_null - }, +sco_publish( + "/do_module_delete", + sco_edit_module.do_module_delete, + Permission.ScoChangeFormation, ) -@bp.route("/do_module_create") -@permission_required(Permission.ScoChangeFormation) -@scodoc7func(context) -def do_module_create(context, args, REQUEST): - "create a module" - # create - cnx = ndb.GetDBConnexion() - r = context._moduleEditor.create(cnx, args) - - # news - F = context.formation_list(args={"formation_id": args["formation_id"]})[0] - sco_news.add( - context, - REQUEST, - typ=NEWS_FORM, - object=args["formation_id"], - text="Modification de la formation %(acronyme)s" % F, - ) - return r - - -@bp.route("/do_module_delete") -@permission_required(Permission.ScoChangeFormation) -@scodoc7func(context) -def do_module_delete(context, oid, REQUEST): - "delete module" - mod = context.do_module_list({"module_id": oid})[0] - if sco_edit_module.module_is_locked(context, mod["module_id"]): - raise ScoLockedFormError() - - # S'il y a des moduleimpls, on ne peut pas detruire le module ! - mods = sco_moduleimpl.do_moduleimpl_list(context, module_id=oid) - if mods: - err_page = scu.confirm_dialog( - context, - message="""