# -*- mode: python -*- # -*- coding: utf-8 -*- ############################################################################## # # Gestion scolarite IUT # # Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Emmanuel Viennet emmanuel.viennet@viennet.net # ############################################################################## """Ajout/Modification/Supression formations (portage from DTML) """ import notesdb as ndb import sco_utils as scu from notes_log import log from TrivialFormulator import TrivialFormulator, TF, tf_error_message import sco_codes_parcours import sco_formsemestre from sco_exceptions import ScoValueError import sco_formations def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST=None): """Delete a formation""" F = sco_formations.formation_list(context, args={"formation_id": formation_id}) if not F: raise ScoValueError("formation inexistante !") F = F[0] H = [ html_sco_header.sco_header( context, REQUEST, page_title="Suppression d'une formation" ), """
Impossible de supprimer cette formation, car les sessions suivantes l'utilisent:
Attention: la suppression d'une formation est irréversible et implique la supression de toutes les UE, matières et modules de la formation !
""" % F, REQUEST=REQUEST, OK="Supprimer cette formation", cancel_url=scu.NotesURL(), parameters={"formation_id": formation_id}, ) else: do_formation_delete(context, F["formation_id"], REQUEST) H.append( """OK, formation supprimée.
""" % scu.NotesURL() ) H.append(html_sco_header.sco_footer(context, 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) def formation_edit(context, formation_id=None, create=False, REQUEST=None): """Edit or create a formation""" if create: H = [ html_sco_header.sco_header( context, REQUEST, page_title="Création d'une formation" ), """Une "formation" décrit une filière, comme un DUT ou une Licence. La formation se subdivise en unités pédagogiques (UE, matières, modules). Elle peut se diviser en plusieurs semestres (ou sessions), qui seront mis en place séparément.
Le titre est le nom complet, parfois adapté pour mieux distinguer les modalités ou versions de programme pédagogique. Le titre_officiel est le nom complet du diplôme, qui apparaitra sur certains PV de jury de délivrance du diplôme.
""", ] submitlabel = "Créer cette formation" initvalues = {"type_parcours": sco_codes_parcours.DEFAULT_TYPE_PARCOURS} is_locked = False else: # edit an existing formation F = sco_formations.formation_list(context, args={"formation_id": formation_id}) if not F: raise ScoValueError("formation inexistante !") initvalues = F[0] is_locked = sco_formations.formation_has_locked_sems(context, formation_id) submitlabel = "Modifier les valeurs" H = [ html_sco_header.sco_header( context, REQUEST, page_title="Modification d'une formation" ), """Attention: Formation verrouillée, le type de parcours ne peut être modifié.
' ) tf = TrivialFormulator( REQUEST.URL0, REQUEST.form, ( ("formation_id", {"default": formation_id, "input_type": "hidden"}), ( "acronyme", { "size": 12, "explanation": "identifiant de la formation (par ex. DUT R&T)", "allow_null": False, }, ), ( "titre", { "size": 80, "explanation": "nom complet de la formation (ex: DUT Réseaux et Télécommunications", "allow_null": False, }, ), ( "titre_officiel", { "size": 80, "explanation": "nom officiel (pour les PV de jury)", "allow_null": False, }, ), ( "type_parcours", { "input_type": "menu", "title": "Type de parcours", "type": "int", "allowed_values": sco_codes_parcours.FORMATION_PARCOURS_TYPES, "labels": sco_codes_parcours.FORMATION_PARCOURS_DESCRS, "explanation": "détermine notamment le nombre de semestres et les règles de validation d'UE et de semestres (barres)", "readonly": is_locked, }, ), ( "formation_code", { "size": 12, "title": "Code formation", "explanation": "code interne. Toutes les formations partageant le même code sont compatibles (compensation de semestres, capitalisation d'UE). Laisser vide si vous ne savez pas, ou entrer le code d'une formation existante.", }, ), ( "code_specialite", { "size": 12, "title": "Code spécialité", "explanation": "optionel: code utilisé pour échanger avec d'autres logiciels et identifiant la filière ou spécialité (exemple: ASUR). N'est utilisé que s'il n'y a pas de numéro de semestre.", }, ), ), initvalues=initvalues, submitlabel=submitlabel, ) if tf[0] == 0: return "\n".join(H) + tf[1] + html_sco_header.sco_footer(context, REQUEST) elif tf[0] == -1: return REQUEST.RESPONSE.redirect(scu.NotesURL()) else: # check unicity : constraint UNIQUE(acronyme,titre,version) if create: version = 1 else: version = initvalues["version"] args = { "acronyme": tf[2]["acronyme"], "titre": tf[2]["titre"], "version": version, } ndb.quote_dict(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) + tf_error_message( "Valeurs incorrectes: il existe déjà une formation avec même titre, acronyme et version." ) + tf[1] + html_sco_header.sco_footer(context, REQUEST) ) # if create: formation_id = context.do_formation_create(tf[2], REQUEST) else: do_formation_edit(context, tf[2]) return REQUEST.RESPONSE.redirect("ue_list?formation_id=%s" % formation_id) def do_formation_create(context, args, REQUEST): "create a formation" cnx = ndb.GetDBConnexion() # check unique acronyme/titre/version a = args.copy() if a.has_key("formation_id"): del a["formation_id"] 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)) # Si pas de formation_code, l'enleve (default SQL) if args.has_key("formation_code") and not args["formation_code"]: del args["formation_code"] # r = sco_formations._formationEditor.create(cnx, args) sco_news.add( context, REQUEST, typ=NEWS_FORM, text="Création de la formation %(titre)s (%(acronyme)s)" % args, ) return r def do_formation_edit(context, args): "edit a formation" # log('do_formation_edit( args=%s )'%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 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: if args.has_key("formation_code") and not args["formation_code"]: del args["formation_code"] cnx = ndb.GetDBConnexion() sco_formations._formationEditor.edit(cnx, args) # Invalide les semestres utilisant cette formation: for sem in sco_formsemestre.do_formsemestre_list( context, args={"formation_id": args["formation_id"]} ): sco_core.inval_cache( context, formsemestre_id=sem["formsemestre_id"] ) # > formation modif.