From 94238578ec359538130b95015543858e4679e55a Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sun, 17 Jan 2021 22:31:28 +0100 Subject: [PATCH] Refactoring. Tests ok but needs more testing ! --- ZNotes.py | 421 +++---------------------------- ZScolar.py | 90 +------ config/create_dept.sh | 1 + config/delete_dept.sh | 24 +- htmlutils.py | 58 ++++- notes_table.py | 7 +- sco_abs_views.py | 3 +- sco_bulletins.py | 17 +- sco_compute_moy.py | 42 ++- sco_cost_formation.py | 5 +- sco_evaluations.py | 32 ++- sco_formsemestre.py | 47 ++++ sco_formsemestre_custommenu.py | 2 +- sco_formsemestre_edit.py | 112 +++----- sco_formsemestre_exterieurs.py | 2 +- sco_formsemestre_inscriptions.py | 29 ++- sco_formsemestre_status.py | 137 ++++------ sco_formsemestre_validation.py | 4 +- sco_groups.py | 53 ++-- sco_groups_edit.py | 2 +- sco_groups_view.py | 5 +- sco_liste_notes.py | 11 +- sco_moduleimpl.py | 330 ++++++++++++++++++++++++ sco_moduleimpl_inscriptions.py | 57 ++--- sco_moduleimpl_status.py | 105 +++++--- sco_news.py | 15 +- sco_page_etud.py | 8 +- sco_permissions.py | 3 - sco_placement.py | 14 +- sco_saisie_notes.py | 154 +++++++---- sco_trombino.py | 6 +- sco_ue_external.py | 10 +- sco_undo_notes.py | 4 +- scolars.py | 54 ++-- scotests/sco_fake_gen.py | 7 +- scotests/test_bonusmalus.py | 6 +- 36 files changed, 969 insertions(+), 908 deletions(-) create mode 100644 sco_moduleimpl.py diff --git a/ZNotes.py b/ZNotes.py index 7530d7cd..9ba88174 100644 --- a/ZNotes.py +++ b/ZNotes.py @@ -52,6 +52,7 @@ import sco_formsemestre_edit import sco_formsemestre_status import sco_formsemestre_inscriptions import sco_formsemestre_custommenu +import sco_moduleimpl import sco_moduleimpl_status import sco_moduleimpl_inscriptions import sco_evaluations @@ -830,7 +831,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl raise ScoLockedFormError() # S'il y a des moduleimpls, on ne peut pas detruire le module ! - mods = self.do_moduleimpl_list(module_id=oid) + mods = sco_moduleimpl.do_moduleimpl_list(self, module_id=oid) if mods: err_page = self.confirmDialog( message="""

Destruction du module impossible car il est utilisé dans des semestres existants !

""", @@ -908,7 +909,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl def module_count_moduleimpls(self, module_id): "Number of moduleimpls using this module" - mods = self.do_moduleimpl_list(module_id=module_id) + mods = sco_moduleimpl.do_moduleimpl_list(self, module_id=module_id) return len(mods) security.declareProtected(ScoView, "module_is_locked") @@ -1198,158 +1199,12 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl else: return h - # --- Gestion des "Implémentations de Modules" - # Un "moduleimpl" correspond a la mise en oeuvre d'un module - # dans une formation spécifique, à une date spécifique. - _moduleimplEditor = EditableTable( - "notes_moduleimpl", - "moduleimpl_id", - ( - "moduleimpl_id", - "module_id", - "formsemestre_id", - "responsable_id", - "computation_expr", - ), - ) - - _modules_enseignantsEditor = EditableTable( - "notes_modules_enseignants", - "modules_enseignants_id", - ("modules_enseignants_id", "moduleimpl_id", "ens_id"), - ) - - security.declareProtected(ScoImplement, "do_moduleimpl_create") - - def do_moduleimpl_create(self, args): - "create a moduleimpl" - cnx = self.GetDBConnexion() - r = self._moduleimplEditor.create(cnx, args) - self._inval_cache( - formsemestre_id=args["formsemestre_id"] - ) # > creation moduleimpl - return r - - security.declareProtected(ScoImplement, "do_moduleimpl_delete") - - def do_moduleimpl_delete(self, oid, formsemestre_id=None): - "delete moduleimpl (desinscrit tous les etudiants)" - cnx = self.GetDBConnexion() - # --- desinscription des etudiants - cursor = cnx.cursor(cursor_factory=ScoDocCursor) - req = "DELETE FROM notes_moduleimpl_inscription WHERE moduleimpl_id=%(moduleimpl_id)s" - cursor.execute(req, {"moduleimpl_id": oid}) - # --- suppression des enseignants - cursor.execute( - "DELETE FROM notes_modules_enseignants WHERE moduleimpl_id=%(moduleimpl_id)s", - {"moduleimpl_id": oid}, - ) - # --- suppression des references dans les absences - cursor.execute( - "UPDATE absences SET moduleimpl_id=NULL WHERE moduleimpl_id=%(moduleimpl_id)s", - {"moduleimpl_id": oid}, - ) - # --- destruction du moduleimpl - self._moduleimplEditor.delete(cnx, oid) - self._inval_cache(formsemestre_id=formsemestre_id) # > moduleimpl_delete - - security.declareProtected(ScoView, "do_moduleimpl_list") - - def do_moduleimpl_list( - self, moduleimpl_id=None, formsemestre_id=None, module_id=None, REQUEST=None - ): - "list moduleimpls" - args = locals() - cnx = self.GetDBConnexion() - modimpls = self._moduleimplEditor.list(cnx, args) # *args, **kw) - # Ajoute la liste des enseignants - for mo in modimpls: - mo["ens"] = self.do_ens_list(args={"moduleimpl_id": mo["moduleimpl_id"]}) - return return_text_if_published(modimpls, REQUEST) - - security.declareProtected(ScoImplement, "do_moduleimpl_edit") - - def do_moduleimpl_edit(self, args, formsemestre_id=None, cnx=None): - "edit a moduleimpl" - if not cnx: - cnx = self.GetDBConnexion() - self._moduleimplEditor.edit(cnx, args) - - self._inval_cache(formsemestre_id=formsemestre_id) # > modif moduleimpl - - security.declareProtected(ScoView, "do_moduleimpl_withmodule_list") - - def do_moduleimpl_withmodule_list( - self, moduleimpl_id=None, formsemestre_id=None, module_id=None, REQUEST=None - ): - """Liste les moduleimpls et ajoute dans chacun le module correspondant - Tri la liste par semestre/UE/numero_matiere/numero_module - """ - args = locals() - del args["self"] - del args["REQUEST"] - modimpls = self.do_moduleimpl_list(**args) - for mo in modimpls: - mo["module"] = self.do_module_list(args={"module_id": mo["module_id"]})[0] - mo["ue"] = self.do_ue_list(args={"ue_id": mo["module"]["ue_id"]})[0] - mo["matiere"] = self.do_matiere_list( - args={"matiere_id": mo["module"]["matiere_id"]} - )[0] - - # tri par semestre/UE/numero_matiere/numero_module - - extr = lambda x: ( - x["ue"]["numero"], - x["ue"]["ue_id"], - x["matiere"]["numero"], - x["matiere"]["matiere_id"], - x["module"]["numero"], - x["module"]["code"], - ) - - modimpls.sort(lambda x, y: cmp(extr(x), extr(y))) - # log('after sort args=%s' % args) - # log( ',\n'.join( [ str(extr(m)) for m in modimpls ] )) - # log('after sort: Mlist=\n' + ',\n'.join( [ str(m) for m in modimpls ] ) + '\n') - return return_text_if_published(modimpls, REQUEST) - - security.declareProtected(ScoView, "do_ens_list") - - def do_ens_list(self, *args, **kw): - "liste les enseignants d'un moduleimpl (pas le responsable)" - cnx = self.GetDBConnexion() - ens = self._modules_enseignantsEditor.list(cnx, *args, **kw) - return ens - - security.declareProtected(ScoImplement, "do_ens_edit") - - def do_ens_edit(self, *args, **kw): - "edit ens" - cnx = self.GetDBConnexion() - self._modules_enseignantsEditor.edit(cnx, *args, **kw) - - security.declareProtected(ScoImplement, "do_ens_create") - - def do_ens_create(self, args): - "create ens" - cnx = self.GetDBConnexion() - r = self._modules_enseignantsEditor.create(cnx, args) - return r - - security.declareProtected(ScoImplement, "do_ens_delete") - - def do_ens_delete(self, oid): - "delete ens" - cnx = self.GetDBConnexion() - r = self._modules_enseignantsEditor.delete(cnx, oid) - return r - # --- dialogue modif enseignants/moduleimpl security.declareProtected(ScoView, "edit_enseignants_form") def edit_enseignants_form(self, REQUEST, moduleimpl_id): "modif liste enseignants/moduleimpl" - M, sem = self.can_change_ens(REQUEST, moduleimpl_id) + M, sem = sco_moduleimpl.can_change_ens(self, REQUEST, moduleimpl_id) # -- header = self.html_sem_header( REQUEST, @@ -1444,8 +1299,8 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl % ens_id ) else: - self.do_ens_create( - {"moduleimpl_id": moduleimpl_id, "ens_id": ens_id} + sco_moduleimpl.do_ens_create( + self, {"moduleimpl_id": moduleimpl_id, "ens_id": ens_id} ) return REQUEST.RESPONSE.redirect( "edit_enseignants_form?moduleimpl_id=%s" % moduleimpl_id @@ -1458,7 +1313,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl """Changement d'un enseignant responsable de module Accessible par Admin et dir des etud si flag resp_can_change_ens """ - M, sem = self.can_change_module_resp(REQUEST, moduleimpl_id) + M, sem = sco_moduleimpl.can_change_module_resp(self, REQUEST, moduleimpl_id) H = [ self.html_sem_header( REQUEST, @@ -1526,7 +1381,8 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl return REQUEST.RESPONSE.redirect( "moduleimpl_status?moduleimpl_id=" + moduleimpl_id ) - self.do_moduleimpl_edit( + sco_moduleimpl.do_moduleimpl_edit( + self, {"moduleimpl_id": moduleimpl_id, "responsable_id": responsable_id}, formsemestre_id=sem["formsemestre_id"], ) @@ -1563,7 +1419,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl """Edition formule calcul moyenne module Accessible par Admin, dir des etud et responsable module """ - M, sem = self.can_change_ens(REQUEST, moduleimpl_id) + M, sem = sco_moduleimpl.can_change_ens(self, REQUEST, moduleimpl_id) H = [ self.html_sem_header( REQUEST, @@ -1607,7 +1463,8 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl "moduleimpl_status?moduleimpl_id=" + moduleimpl_id ) else: - self.do_moduleimpl_edit( + sco_moduleimpl.do_moduleimpl_edit( + self, { "moduleimpl_id": moduleimpl_id, "computation_expr": tf[2]["computation_expr"], @@ -1627,11 +1484,13 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl def view_module_abs(self, REQUEST, moduleimpl_id, format="html"): """Visualisation des absences a un module""" - M = self.do_moduleimpl_withmodule_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_withmodule_list( + self, moduleimpl_id=moduleimpl_id + )[0] sem = sco_formsemestre.get_formsemestre(self, M["formsemestre_id"]) debut_sem = DateDMYtoISO(sem["date_debut"]) fin_sem = DateDMYtoISO(sem["date_fin"]) - list_insc = self.do_moduleimpl_listeetuds(moduleimpl_id) + list_insc = sco_moduleimpl.do_moduleimpl_listeetuds(self, moduleimpl_id) T = [] for etudid in list_insc: @@ -1770,7 +1629,9 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl """ sem = sco_formsemestre.get_formsemestre(self, formsemestre_id) # resp. de modules: - mods = self.do_moduleimpl_withmodule_list(formsemestre_id=formsemestre_id) + mods = sco_moduleimpl.do_moduleimpl_withmodule_list( + self, formsemestre_id=formsemestre_id + ) sem_ens = {} for mod in mods: if not mod["responsable_id"] in sem_ens: @@ -1846,7 +1707,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl def edit_enseignants_form_delete(self, REQUEST, moduleimpl_id, ens_id): "remove ens" - M, sem = self.can_change_ens(REQUEST, moduleimpl_id) + M, sem = sco_moduleimpl.can_change_ens(self, REQUEST, moduleimpl_id) # search ens_id ok = False for ens in M["ens"]: @@ -1855,59 +1716,11 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl break if not ok: raise ScoValueError("invalid ens_id (%s)" % ens_id) - self.do_ens_delete(ens["modules_enseignants_id"]) + sco_moduleimpl.do_ens_delete(self, ens["modules_enseignants_id"]) return REQUEST.RESPONSE.redirect( "edit_enseignants_form?moduleimpl_id=%s" % moduleimpl_id ) - security.declareProtected(ScoView, "can_change_ens") - - def can_change_ens(self, REQUEST, moduleimpl_id, raise_exc=True): - "check if current user can modify ens list (raise exception if not)" - M = self.do_moduleimpl_withmodule_list(moduleimpl_id=moduleimpl_id)[0] - # -- check lock - sem = sco_formsemestre.get_formsemestre(self, M["formsemestre_id"]) - if sem["etat"] != "1": - if raise_exc: - raise ScoValueError("Modification impossible: semestre verrouille") - else: - return False - # -- check access - authuser = REQUEST.AUTHENTICATED_USER - uid = str(authuser) - # admin, resp. module ou resp. semestre - if ( - uid != M["responsable_id"] - and not authuser.has_permission(ScoImplement, self) - and (uid not in sem["responsables"]) - ): - if raise_exc: - raise AccessDenied("Modification impossible pour %s" % uid) - else: - return False - return M, sem - - security.declareProtected(ScoView, "can_change_module_resp") - - def can_change_module_resp(self, REQUEST, moduleimpl_id): - """Check if current user can modify module resp. (raise exception if not). - = Admin, et dir des etud. (si option l'y autorise) - """ - M = self.do_moduleimpl_withmodule_list(moduleimpl_id=moduleimpl_id)[0] - # -- check lock - sem = sco_formsemestre.get_formsemestre(self, M["formsemestre_id"]) - if sem["etat"] != "1": - raise ScoValueError("Modification impossible: semestre verrouille") - # -- check access - authuser = REQUEST.AUTHENTICATED_USER - uid = str(authuser) - # admin ou resp. semestre avec flag resp_can_change_resp - if not authuser.has_permission(ScoImplement, self) and ( - (uid not in sem["responsables"]) or (not sem["resp_can_change_ens"]) - ): - raise AccessDenied("Modification impossible pour %s" % uid) - return M, sem - # --- Gestion des inscriptions aux modules _formsemestre_inscriptionEditor = EditableTable( "notes_formsemestre_inscription", @@ -2123,8 +1936,8 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl res = cursor.fetchall() moduleimpl_inscription_ids = [x[0] for x in res] for moduleimpl_inscription_id in moduleimpl_inscription_ids: - self.do_moduleimpl_inscription_delete( - moduleimpl_inscription_id, formsemestre_id=formsemestre_id + sco_moduleimpl.do_moduleimpl_inscription_delete( + self, moduleimpl_inscription_id, formsemestre_id=formsemestre_id ) # -- desincription du semestre self.do_formsemestre_inscription_delete( @@ -2155,123 +1968,6 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl commit=False, ) - # --- Inscriptions aux modules - _moduleimpl_inscriptionEditor = EditableTable( - "notes_moduleimpl_inscription", - "moduleimpl_inscription_id", - ("moduleimpl_inscription_id", "etudid", "moduleimpl_id"), - ) - - security.declareProtected(ScoEtudInscrit, "do_moduleimpl_inscription_create") - - def do_moduleimpl_inscription_create( - self, args, REQUEST=None, formsemestre_id=None - ): - "create a moduleimpl_inscription" - cnx = self.GetDBConnexion() - log("do_moduleimpl_inscription_create: " + str(args)) - r = self._moduleimpl_inscriptionEditor.create(cnx, args) - self._inval_cache(formsemestre_id=formsemestre_id) # > moduleimpl_inscription - if REQUEST: - logdb( - REQUEST, - cnx, - method="moduleimpl_inscription", - etudid=args["etudid"], - msg="inscription module %s" % args["moduleimpl_id"], - commit=False, - ) - return r - - security.declareProtected(ScoImplement, "do_moduleimpl_inscription_delete") - - def do_moduleimpl_inscription_delete(self, oid, formsemestre_id=None): - "delete moduleimpl_inscription" - cnx = self.GetDBConnexion() - self._moduleimpl_inscriptionEditor.delete(cnx, oid) - self._inval_cache(formsemestre_id=formsemestre_id) # > moduleimpl_inscription - - security.declareProtected(ScoView, "do_moduleimpl_inscription_list") - - def do_moduleimpl_inscription_list( - self, moduleimpl_id=None, etudid=None, REQUEST=None - ): - "list moduleimpl_inscriptions" - args = locals() - cnx = self.GetDBConnexion() - return return_text_if_published( - self._moduleimpl_inscriptionEditor.list(cnx, args), REQUEST - ) - - security.declareProtected(ScoView, "do_moduleimpl_listeetuds") - - def do_moduleimpl_listeetuds(self, moduleimpl_id): - "retourne liste des etudids inscrits a ce module" - req = "select distinct Im.etudid from notes_moduleimpl_inscription Im, notes_formsemestre_inscription Isem, notes_moduleimpl M where Isem.etudid=Im.etudid and Im.moduleimpl_id=M.moduleimpl_id and M.moduleimpl_id = %(moduleimpl_id)s" - cnx = self.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) - cursor.execute(req, {"moduleimpl_id": moduleimpl_id}) - res = cursor.fetchall() - return [x[0] for x in res] - - security.declareProtected(ScoEtudInscrit, "do_moduleimpl_inscrit_tout_semestre") - - def do_moduleimpl_inscrit_tout_semestre(self, moduleimpl_id, formsemestre_id): - "inscrit tous les etudiants inscrit au semestre a ce module" - cnx = self.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) - req = """INSERT INTO notes_moduleimpl_inscription - (moduleimpl_id, etudid) - SELECT %(moduleimpl_id)s, I.etudid - FROM notes_formsemestre_inscription I - WHERE I.formsemestre_id=%(formsemestre_id)s""" - args = {"moduleimpl_id": moduleimpl_id, "formsemestre_id": formsemestre_id} - cursor.execute(req, args) - - security.declareProtected(ScoEtudInscrit, "do_moduleimpl_inscrit_etuds") - - def do_moduleimpl_inscrit_etuds( - self, moduleimpl_id, formsemestre_id, etudids, reset=False, REQUEST=None - ): - """Inscrit les etudiants (liste d'etudids) a ce module. - Si reset, desinscrit tous les autres. - """ - # Verifie qu'ils sont tous bien inscrits au semestre - for etudid in etudids: - insem = self.do_formsemestre_inscription_list( - args={"formsemestre_id": formsemestre_id, "etudid": etudid} - ) - if not insem: - raise ScoValueError("%s n'est pas inscrit au semestre !" % etudid) - - # Desinscriptions - if reset: - cnx = self.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) - cursor.execute( - "delete from notes_moduleimpl_inscription where moduleimpl_id = %(moduleimpl_id)s", - {"moduleimpl_id": moduleimpl_id}, - ) - # Inscriptions au module: - inmod_set = set( - [ - x["etudid"] - for x in self.do_moduleimpl_inscription_list( - moduleimpl_id=moduleimpl_id - ) - ] - ) - for etudid in etudids: - # deja inscrit ? - if not etudid in inmod_set: - self.do_moduleimpl_inscription_create( - {"moduleimpl_id": moduleimpl_id, "etudid": etudid}, - REQUEST=REQUEST, - formsemestre_id=formsemestre_id, - ) - - self._inval_cache(formsemestre_id=formsemestre_id) # > moduleimpl_inscrit_etuds - security.declareProtected(ScoEtudInscrit, "etud_desinscrit_ue") def etud_desinscrit_ue(self, etudid, formsemestre_id, ue_id, REQUEST=None): @@ -2388,7 +2084,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl raise ValueError("no moduleimpl specified") # bug authuser = REQUEST.AUTHENTICATED_USER uid = str(authuser) - M = self.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_list(self, moduleimpl_id=moduleimpl_id)[0] sem = sco_formsemestre.get_formsemestre(self, M["formsemestre_id"]) if ( @@ -2464,7 +2160,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl r = self._evaluationEditor.create(cnx, args) # news - M = self.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_list(self, moduleimpl_id=moduleimpl_id)[0] mod = self.do_module_list(args={"module_id": M["module_id"]})[0] mod["moduleimpl_id"] = M["moduleimpl_id"] mod["url"] = "Notes/moduleimpl_status?moduleimpl_id=%(moduleimpl_id)s" % mod @@ -2507,7 +2203,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl jour = args.get("jour", None) args["jour"] = jour if jour: - M = self.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_list(self, moduleimpl_id=moduleimpl_id)[0] sem = sco_formsemestre.get_formsemestre(self, M["formsemestre_id"]) d, m, y = [int(x) for x in sem["date_debut"].split("/")] date_debut = datetime.date(y, m, d) @@ -2539,7 +2235,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl if not El: raise ValueError("Evalution inexistante ! (%s)" % evaluation_id) E = El[0] - M = self.do_moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0] + M = sco_moduleimpl.do_moduleimpl_list(self, moduleimpl_id=E["moduleimpl_id"])[0] Mod = self.do_module_list(args={"module_id": M["module_id"]})[0] tit = "Suppression de l'évaluation %(description)s (%(jour)s)" % E etat = sco_evaluations.do_evaluation_etat(self, evaluation_id) @@ -2662,7 +2358,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl def do_evaluation_list_in_formsemestre(self, formsemestre_id): "list evaluations in this formsemestre" cnx = self.GetDBConnexion() - mods = self.do_moduleimpl_list(formsemestre_id=formsemestre_id) + mods = sco_moduleimpl.do_moduleimpl_list(self, formsemestre_id=formsemestre_id) evals = [] for mod in mods: evals += self.do_evaluation_list( @@ -2685,7 +2381,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl cnx = self.GetDBConnexion() self._evaluationEditor.edit(cnx, args) # inval cache pour ce semestre - M = self.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_list(self, moduleimpl_id=moduleimpl_id)[0] self._inval_cache( formsemestre_id=M["formsemestre_id"] ) # > evaluation_edit (coef, ...) @@ -2761,42 +2457,6 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl security.declareProtected(ScoView, "evaluation_suppress_alln") evaluation_suppress_alln = sco_saisie_notes.evaluation_suppress_alln - security.declareProtected(ScoView, "can_edit_notes") - - def can_edit_notes(self, authuser, moduleimpl_id, allow_ens=True): - """True if authuser can enter or edit notes in this module. - If allow_ens, grant access to all ens in this module - - Si des décisions de jury ont déjà été saisies dans ce semestre, - seul le directeur des études peut saisir des notes (et il ne devrait pas). - """ - uid = str(authuser) - M = self.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] - sem = sco_formsemestre.get_formsemestre(self, M["formsemestre_id"]) - if sem["etat"] != "1": - return False # semestre verrouillé - - if sco_parcours_dut.formsemestre_has_decisions(self, sem["formsemestre_id"]): - # il y a des décisions de jury dans ce semestre ! - return ( - authuser.has_permission(ScoEditAllNotes, self) - or uid in sem["responsables"] - ) - else: - if ( - (not authuser.has_permission(ScoEditAllNotes, self)) - and uid != M["responsable_id"] - and uid not in sem["responsables"] - ): - # enseignant (chargé de TD) ? - if allow_ens: - for ens in M["ens"]: - if ens["ens_id"] == uid: - return True - return False - else: - return True - security.declareProtected(ScoEditAllNotes, "dummy_ScoEditAllNotes") def dummy_ScoEditAllNotes(self): @@ -3079,21 +2739,6 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl ) # > appreciation_add return REQUEST.RESPONSE.redirect(bull_url) - security.declareProtected(ScoView, "can_change_groups") - - def can_change_groups(self, REQUEST, formsemestre_id): - "Vrai si utilisateur peut changer les groupes dans ce semestre" - sem = sco_formsemestre.get_formsemestre(self, formsemestre_id) - if sem["etat"] != "1": - return False # semestre verrouillé - authuser = REQUEST.AUTHENTICATED_USER - if authuser.has_permission(ScoEtudChangeGroups, self): - return True # admin, chef dept - uid = str(authuser) - if uid in sem["responsables"]: - return True - return False - def _can_edit_pv(self, REQUEST, formsemestre_id): "Vrai si utilisateur peut editer un PV de jury de ce semestre" @@ -3505,7 +3150,9 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl """ sem = sco_formsemestre.get_formsemestre(self, formsemestre_id) - modimpls = self.do_moduleimpl_list(formsemestre_id=formsemestre_id) + modimpls = sco_moduleimpl.do_moduleimpl_list( + self, formsemestre_id=formsemestre_id + ) bad_ue = [] bad_sem = [] for modimpl in modimpls: @@ -3579,7 +3226,9 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl # de formations diag = [] - Mlist = self.do_moduleimpl_withmodule_list(formsemestre_id=formsemestre_id) + Mlist = sco_moduleimpl.do_moduleimpl_withmodule_list( + self, formsemestre_id=formsemestre_id + ) for mod in Mlist: if mod["module"]["ue_id"] != mod["matiere"]["ue_id"]: diag.append( diff --git a/ZScolar.py b/ZScolar.py index 8d430780..683fa7eb 100644 --- a/ZScolar.py +++ b/ZScolar.py @@ -277,8 +277,8 @@ UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo ") else: H.append('

Aucun groupe dans cette partition') - if self.Notes.can_change_groups(REQUEST, formsemestre_id): + if sco_groups.can_change_groups(self, REQUEST, formsemestre_id): H.append( ' (créer)' % partition["partition_id"] ) H.append("

") - if self.Notes.can_change_groups(REQUEST, formsemestre_id): + if sco_groups.can_change_groups(self, REQUEST, formsemestre_id): H.append( '

Ajouter une partition

' % formsemestre_id @@ -1161,88 +1161,6 @@ UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo Changement de groupe de %(nomprenom)s (semestre %(semtitre)s)

' - % etud - ] - header = self.sco_header( - REQUEST, page_title="Changement de groupe de %(nomprenom)s" % etud - ) - # Liste des groupes existants - raise NotImplementedError # XXX utiliser form_group_choice ou supprimer completement ? - # - H.append("""

""") - - H.append( - """ - -

-(attention, vérifier que les groupes sont compatibles, selon votre organisation) -

- - -

Créer un nouveau groupe: - - - - -

-

- - - - -
""" - % ( - etudid, - formsemestre_id, - sem["nomgroupetd"], - sem["nomgroupeta"], - sem["nomgroupetp"], - REQUEST.URL1, - ) - ) - - return header + "\n".join(H) + self.sco_footer(REQUEST) - # --- Gestion des groupes: security.declareProtected(ScoView, "affectGroups") affectGroups = sco_groups_edit.affectGroups diff --git a/config/create_dept.sh b/config/create_dept.sh index 0079cc6a..52775272 100755 --- a/config/create_dept.sh +++ b/config/create_dept.sh @@ -9,6 +9,7 @@ # E. Viennet, Juin 2008 # +set -euo pipefail source config.sh source utils.sh diff --git a/config/delete_dept.sh b/config/delete_dept.sh index 3f2f05f6..d5e2bce2 100755 --- a/config/delete_dept.sh +++ b/config/delete_dept.sh @@ -4,11 +4,11 @@ # ScoDoc: suppression d'un departement # # Ce script supprime la base de donnees ScoDoc d'un departement -# *** le departement doit au prealable avoir �t� supprime via l'interface web ! *** +# *** le departement doit au prealable avoir été supprime via l'interface web ! *** # # Ne fonctionne que pour les configurations "standards" (dbname=xxx) # -# Il doit �tre lanc� par l'utilisateur unix root dans le repertoire .../config +# Il doit être lancé par l'utilisateur unix root dans le repertoire .../config # ^^^^^^^^^^^^^^^^^^^^^ # E. Viennet, Sept 2008 # @@ -17,7 +17,7 @@ source config.sh source utils.sh -check_uid_root $0 +check_uid_root "$0" usage() { echo "$0 [-n DEPT]" echo "(default to interactive mode)" @@ -59,11 +59,16 @@ then scodocctl stop # suppression de la base postgres - db_name=$(cat "$cfg_pathname" | sed '/^dbname=*/!d; s///;q') - echo "suppression de la base postgres $db_name" - su -c "dropdb $db_name" "$POSTGRES_SUPERUSER" || terminate "ne peux supprimer base de donnees $db_name" + db_name=$(sed '/^dbname=*/!d; s///;q' < "$cfg_pathname") + if su -c "psql -lt" "$POSTGRES_SUPERUSER" | cut -d \| -f 1 | grep -wq SCORT + then + echo "Suppression de la base postgres $db_name ..." + su -c "dropdb $db_name" "$POSTGRES_SUPERUSER" || terminate "ne peux supprimer base de donnees $db_name" + else + echo "la base postgres $db_name n'existe pas." + fi # suppression du fichier de config - /bin/rm -f "$cfg_pathname" || terminate "ne peux supprimer $cfg_pathname" + /bin/rm -f "$cfg_pathname" || terminate "Ne peux supprimer $cfg_pathname" # relance ScoDoc if [ "$interactive" = 1 ] then @@ -76,6 +81,7 @@ then fi exit 0 else - echo 'Erreur: pas de configuration trouvee pour "'"$DEPT"'"' - exit 1 + echo 'Attention: pas de configuration trouvee pour "'"$DEPT"'"' + echo " => ne fait rien." + exit 0 fi diff --git a/htmlutils.py b/htmlutils.py index 70ff837c..f75d9ccf 100644 --- a/htmlutils.py +++ b/htmlutils.py @@ -28,6 +28,8 @@ """Various HTML generation functions """ +import listhistogram + def horizontal_bargraph(value, mark): """html drawing an horizontal bar and a mark @@ -42,9 +44,6 @@ def horizontal_bargraph(value, mark): return tmpl % {"value": int(value), "mark": int(mark)} -import listhistogram - - def histogram_notes(notes): "HTML code drawing histogram" if not notes: @@ -70,3 +69,56 @@ def histogram_notes(notes): ) D.append("") return "\n".join(D) + + +def make_menu(title, items, css_class="", base_url="", alone=False): + """HTML snippet to render a simple drop down menu. + items is a list of dicts: + { 'title' : + 'url' : + 'id' : + 'attr' : "" # optionnal html attributes + 'enabled' : # True by default + 'helpmsg' : + 'submenu' : [ list of sub-items ] + } + """ + + def gen_menu_items(items): + H.append("") + + H = [] + if alone: + H.append('
    ' % css_class) + H.append("""
  • %s""" % title) + gen_menu_items(items) + H.append("
  • ") + if alone: + H.append("
") + return "".join(H) diff --git a/notes_table.py b/notes_table.py index 82613e8a..bdb30300 100644 --- a/notes_table.py +++ b/notes_table.py @@ -41,7 +41,8 @@ from sco_parcours_dut import formsemestre_get_etud_capitalisation from sco_parcours_dut import list_formsemestre_utilisateurs_uecap import sco_parcours_dut import sco_formsemestre -from sco_formsemestre_edit import formsemestre_uecoef_list, formsemestre_uecoef_create +from sco_formsemestre import formsemestre_uecoef_list, formsemestre_uecoef_create +import sco_moduleimpl import sco_evaluations import sco_compute_moy from sco_formulas import NoteVector @@ -85,7 +86,9 @@ def get_sem_ues_modimpls(context, formsemestre_id, modimpls=None): (utilisé quand on ne peut pas construire nt et faire nt.get_ues()) """ if modimpls is None: - modimpls = context.do_moduleimpl_list(formsemestre_id=formsemestre_id) + modimpls = sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=formsemestre_id + ) uedict = {} for modimpl in modimpls: mod = context.do_module_list(args={"module_id": modimpl["module_id"]})[0] diff --git a/sco_abs_views.py b/sco_abs_views.py index a76e225a..aabab46f 100644 --- a/sco_abs_views.py +++ b/sco_abs_views.py @@ -42,6 +42,7 @@ from notes_log import log import sco_groups import sco_find_etud import sco_formsemestre +import sco_moduleimpl import sco_photos import sco_abs @@ -86,7 +87,7 @@ def doSignaleAbsence( J = "NON " M = "" if moduleimpl_id and moduleimpl_id != "NULL": - mod = context.Notes.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] + mod = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0] formsemestre_id = mod["formsemestre_id"] nt = context.Notes._getNotesCache().get_NotesTable( context.Notes, formsemestre_id diff --git a/sco_bulletins.py b/sco_bulletins.py index 1a8fe6d6..9d2a8139 100644 --- a/sco_bulletins.py +++ b/sco_bulletins.py @@ -28,13 +28,16 @@ """Génération des bulletins de notes """ -from email.MIMEMultipart import MIMEMultipart -from email.MIMEText import MIMEText -from email.MIMEBase import MIMEBase -from email.Header import Header -from email import Encoders +from email.MIMEMultipart import ( # pylint: disable=no-name-in-module,import-error + MIMEMultipart, +) +from email.MIMEText import MIMEText # pylint: disable=no-name-in-module,import-error +from email.MIMEBase import MIMEBase # pylint: disable=no-name-in-module,import-error +from email.Header import Header # pylint: disable=no-name-in-module,import-error +from email import Encoders # pylint: disable=no-name-in-module,import-error -import htmlutils, time +import time +import htmlutils from reportlab.lib.colors import Color from sco_utils import * @@ -1146,7 +1149,7 @@ def _formsemestre_bulletinetud_header_html( ] H.append("""
""") - H.append(sco_formsemestre_status.makeMenu("Autres opérations", menuBul, alone=True)) + H.append(htmlutils.make_menu("Autres opérations", menuBul, alone=True)) H.append("""
""") H.append( ' %s' diff --git a/sco_compute_moy.py b/sco_compute_moy.py index 108f764f..368506fc 100644 --- a/sco_compute_moy.py +++ b/sco_compute_moy.py @@ -29,14 +29,24 @@ """ import traceback +import pprint +from types import FloatType -from sco_utils import * -from notesdb import * +import sco_utils as scu +from sco_utils import ( + NOTES_ATTENTE, + NOTES_NEUTRALISE, + EVALUATION_NORMALE, + EVALUATION_RATTRAPAGE, +) +from sco_exceptions import ScoException +from notesdb import EditableTable, quote_html from notes_log import log, sendAlarm import sco_formsemestre +import sco_moduleimpl import sco_groups import sco_evaluations -from sco_formulas import * +import sco_formulas import sco_abs @@ -67,7 +77,9 @@ def formsemestre_expressions_use_abscounts(context, formsemestre_id): if expr and expr[0] != "#" and ab in expr: return True # 2- moyennes de modules - for mod in context.Notes.do_moduleimpl_list(formsemestre_id=formsemestre_id): + for mod in sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=formsemestre_id + ): if moduleimpl_has_expression(context, mod) and ab in mod["computation_expr"]: return True return False @@ -148,7 +160,7 @@ def compute_user_formula( try: formula = formula.replace("\n", "").replace("\r", "") # log('expression : %s\nvariables=%s\n' % (formula, variables)) # XXX debug - user_moy = eval_user_expression(context, formula, variables) + user_moy = sco_formulas.eval_user_expression(context, formula, variables) # log('user_moy=%s' % user_moy) if user_moy != "NA0" and user_moy != "NA": user_moy = float(user_moy) @@ -188,10 +200,10 @@ def do_moduleimpl_moyennes(context, nt, mod): """ diag_info = {} # message d'erreur formule moduleimpl_id = mod["moduleimpl_id"] - is_malus = mod["module"]["module_type"] == MODULE_MALUS + is_malus = mod["module"]["module_type"] == scu.MODULE_MALUS sem = sco_formsemestre.get_formsemestre(context, mod["formsemestre_id"]) - etudids = context.do_moduleimpl_listeetuds( - moduleimpl_id + etudids = sco_moduleimpl.do_moduleimpl_listeetuds( + context, moduleimpl_id ) # tous, y compris demissions # Inscrits au semestre (pour traiter les demissions): inssem_set = set( @@ -256,7 +268,7 @@ def do_moduleimpl_moyennes(context, nt, mod): ] # R = {} - formula = unescape_html(mod["computation_expr"]) + formula = scu.unescape_html(mod["computation_expr"]) formula_use_abs = "abs" in formula for etudid in insmod_set: # inscrits au semestre et au module @@ -353,12 +365,14 @@ def do_formsemestre_moyennes(context, nt, formsemestre_id): la liste des moduleimpls, la liste des evaluations valides, liste des moduleimpls avec notes en attente. """ - sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - inscr = context.do_formsemestre_inscription_list( - args={"formsemestre_id": formsemestre_id} + # sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) + # inscr = context.do_formsemestre_inscription_list( + # args={"formsemestre_id": formsemestre_id} + # ) + # etudids = [x["etudid"] for x in inscr] + modimpls = sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=formsemestre_id ) - etudids = [x["etudid"] for x in inscr] - modimpls = context.do_moduleimpl_list(formsemestre_id=formsemestre_id) # recupere les moyennes des etudiants de tous les modules D = {} valid_evals = [] diff --git a/sco_cost_formation.py b/sco_cost_formation.py index 2334740f..22693867 100644 --- a/sco_cost_formation.py +++ b/sco_cost_formation.py @@ -37,6 +37,7 @@ from gen_tables import GenTable import sco_excel, sco_pdf from sco_pdf import SU import sco_formsemestre +import sco_moduleimpl import sco_formsemestre_status @@ -60,7 +61,9 @@ def formsemestre_table_estim_cost( """ sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) sco_formsemestre_status.fill_formsemestre(context, sem, REQUEST=REQUEST) - Mlist = context.do_moduleimpl_withmodule_list(formsemestre_id=formsemestre_id) + Mlist = sco_moduleimpl.do_moduleimpl_withmodule_list( + context, formsemestre_id=formsemestre_id + ) T = [] for M in Mlist: Mod = M["module"] diff --git a/sco_evaluations.py b/sco_evaluations.py index e877b62c..5e5b17e4 100644 --- a/sco_evaluations.py +++ b/sco_evaluations.py @@ -41,9 +41,11 @@ from gen_tables import GenTable from TrivialFormulator import TrivialFormulator import sco_news import sco_formsemestre +import sco_moduleimpl import sco_groups import sco_abs import sco_evaluations +import sco_saisie_notes # -------------------------------------------------------------------- # @@ -101,7 +103,7 @@ def do_evaluation_delete(context, REQUEST, evaluation_id): context._evaluationEditor.delete(cnx, evaluation_id) # inval cache pour ce semestre - M = context.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0] context._inval_cache(formsemestre_id=M["formsemestre_id"]) # > eval delete # news mod = context.do_module_list(args={"module_id": M["module_id"]})[0] @@ -165,7 +167,7 @@ def do_evaluation_etat( last_modif = None # ---- Liste des groupes complets et incomplets E = context.do_evaluation_list(args={"evaluation_id": evaluation_id})[0] - M = context.do_moduleimpl_list(moduleimpl_id=E["moduleimpl_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] is_malus = Mod["module_type"] == scu.MODULE_MALUS # True si module de malus formsemestre_id = M["formsemestre_id"] @@ -182,7 +184,9 @@ def do_evaluation_etat( # (pour avoir l'etat et le groupe) et aussi les inscriptions # au module (pour gerer les modules optionnels correctement) insem = context.do_formsemestre_inscription_listinscrits(formsemestre_id) - insmod = context.do_moduleimpl_inscription_list(moduleimpl_id=E["moduleimpl_id"]) + insmod = sco_moduleimpl.do_moduleimpl_inscription_list( + context, moduleimpl_id=E["moduleimpl_id"] + ) insmodset = set([x["etudid"] for x in insmod]) # retire de insem ceux qui ne sont pas inscrits au module ins = [i for i in insem if i["etudid"] in insmodset] @@ -451,7 +455,9 @@ def formsemestre_evaluations_cal(context, formsemestre_id, REQUEST=None): if not e["jour"]: continue day = e["jour"].strftime("%Y-%m-%d") - mod = context.do_moduleimpl_withmodule_list(moduleimpl_id=e["moduleimpl_id"])[0] + mod = sco_moduleimpl.do_moduleimpl_withmodule_list( + context, moduleimpl_id=e["moduleimpl_id"] + )[0] txt = mod["module"]["code"] or mod["module"]["abbrev"] or "eval" if e["heure_debut"]: debut = e["heure_debut"].strftime("%Hh%M") @@ -524,10 +530,10 @@ def evaluation_date_first_completion(context, evaluation_id): # (pour avoir l'etat et le groupe) et aussi les inscriptions # au module (pour gerer les modules optionnels correctement) # E = context.do_evaluation_list(args={"evaluation_id": evaluation_id})[0] - # M = context.do_moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0] + # M = sco_moduleimpl.do_moduleimpl_list(context,moduleimpl_id=E["moduleimpl_id"])[0] # formsemestre_id = M["formsemestre_id"] # insem = context.do_formsemestre_inscription_listinscrits(formsemestre_id) - # insmod = context.do_moduleimpl_inscription_list(moduleimpl_id=E["moduleimpl_id"]) + # insmod = sco_moduleimpl.do_moduleimpl_inscription_list(context,moduleimpl_id=E["moduleimpl_id"]) # insmodset = set([x["etudid"] for x in insmod]) # retire de insem ceux qui ne sont pas inscrits au module # ins = [i for i in insem if i["etudid"] in insmodset] @@ -566,7 +572,9 @@ def formsemestre_evaluations_delai_correction( evals = nt.get_sem_evaluation_etat_list() T = [] for e in evals: - M = context.do_moduleimpl_list(moduleimpl_id=e["moduleimpl_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] if (e["evaluation_type"] != scu.EVALUATION_NORMALE) or ( Mod["module_type"] == scu.MODULE_MALUS @@ -732,14 +740,14 @@ def evaluation_describe(context, evaluation_id="", edit_in_place=True, REQUEST=N """ E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] moduleimpl_id = E["moduleimpl_id"] - M = context.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0] Mod = context.do_module_list(args={"module_id": M["module_id"]})[0] formsemestre_id = M["formsemestre_id"] u = context.Users.user_info(M["responsable_id"]) resp = u["prenomnom"] nomcomplet = u["nomcomplet"] - can_edit = context.can_edit_notes( - REQUEST.AUTHENTICATED_USER, moduleimpl_id, allow_ens=False + can_edit = sco_saisie_notes.can_edit_notes( + context, REQUEST.AUTHENTICATED_USER, moduleimpl_id, allow_ens=False ) link = ( @@ -810,7 +818,9 @@ def evaluation_create_form( the_eval = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] moduleimpl_id = the_eval["moduleimpl_id"] # - M = context.do_moduleimpl_withmodule_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_withmodule_list( + context, moduleimpl_id=moduleimpl_id + )[0] is_malus = M["module"]["module_type"] == scu.MODULE_MALUS # True si module de malus formsemestre_id = M["formsemestre_id"] min_note_max = scu.NOTES_PRECISION # le plus petit bareme possible diff --git a/sco_formsemestre.py b/sco_formsemestre.py index 55c88ece..6ad764e1 100644 --- a/sco_formsemestre.py +++ b/sco_formsemestre.py @@ -241,6 +241,53 @@ def write_formsemestre_responsables(context, sem): return _write_formsemestre_aux(context, sem, "responsables", "responsable_id") +# ---------------------- Coefs des UE + +_formsemestre_uecoef_editor = EditableTable( + "notes_formsemestre_uecoef", + "formsemestre_uecoef_id", + ("formsemestre_uecoef_id", "formsemestre_id", "ue_id", "coefficient"), +) + +formsemestre_uecoef_create = _formsemestre_uecoef_editor.create +formsemestre_uecoef_edit = _formsemestre_uecoef_editor.edit +formsemestre_uecoef_list = _formsemestre_uecoef_editor.list +formsemestre_uecoef_delete = _formsemestre_uecoef_editor.delete + + +def do_formsemestre_uecoef_edit_or_create(context, cnx, formsemestre_id, ue_id, coef): + "modify or create the coef" + coefs = formsemestre_uecoef_list( + cnx, args={"formsemestre_id": formsemestre_id, "ue_id": ue_id} + ) + if coefs: + formsemestre_uecoef_edit( + cnx, + args={ + "formsemestre_uecoef_id": coefs[0]["formsemestre_uecoef_id"], + "coefficient": coef, + }, + ) + else: + formsemestre_uecoef_create( + cnx, + args={ + "formsemestre_id": formsemestre_id, + "ue_id": ue_id, + "coefficient": coef, + }, + ) + + +def do_formsemestre_uecoef_delete(context, cnx, formsemestre_id, ue_id): + "delete coef for this (ue,sem)" + coefs = formsemestre_uecoef_list( + cnx, args={"formsemestre_id": formsemestre_id, "ue_id": ue_id} + ) + if coefs: + formsemestre_uecoef_delete(cnx, coefs[0]["formsemestre_uecoef_id"]) + + def read_formsemestre_etapes(context, formsemestre_id): """recupere liste des codes etapes associés à ce semestre :returns: liste d'instance de ApoEtapeVDI diff --git a/sco_formsemestre_custommenu.py b/sco_formsemestre_custommenu.py index 661856bf..5365aa5c 100644 --- a/sco_formsemestre_custommenu.py +++ b/sco_formsemestre_custommenu.py @@ -74,7 +74,7 @@ def formsemestre_custommenu_html(context, formsemestre_id, base_url=""): + formsemestre_id, } ) - return sco_formsemestre_status.makeMenu("Liens", menu) + return sco_formsemestre_status.htmlutils.make_menu("Liens", menu) def formsemestre_custommenu_edit(context, formsemestre_id, REQUEST=None): diff --git a/sco_formsemestre_edit.py b/sco_formsemestre_edit.py index b35b3649..7850202e 100644 --- a/sco_formsemestre_edit.py +++ b/sco_formsemestre_edit.py @@ -41,6 +41,7 @@ import sco_codes_parcours import sco_compute_moy import sco_modalites import sco_formsemestre +import sco_moduleimpl from sco_formsemestre import ApoEtapeVDI @@ -155,7 +156,9 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): # if REQUEST.form.get('tf-submitted',False) and not REQUEST.form.has_key('inscrire_etudslist'): # REQUEST.form['inscrire_etudslist'] = [] # add associated modules to tf-checked - ams = context.do_moduleimpl_list(formsemestre_id=formsemestre_id) + ams = sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=formsemestre_id + ) sem_module_ids = set([x["module_id"] for x in ams]) initvalues["tf-checked"] = [x["module_id"] for x in ams] for x in ams: @@ -706,7 +709,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): "formsemestre_id": formsemestre_id, "responsable_id": tf[2][module_id], } - mid = context.do_moduleimpl_create(modargs) + mid = sco_moduleimpl.do_moduleimpl_create(context, modargs) return REQUEST.RESPONSE.redirect( "formsemestre_status?formsemestre_id=%s&head_message=Nouveau%%20semestre%%20créé" % formsemestre_id @@ -720,7 +723,9 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): # nouveaux modules checkedmods = tf[2]["tf-checked"] sco_formsemestre.do_formsemestre_edit(context, tf[2]) - ams = context.do_moduleimpl_list(formsemestre_id=formsemestre_id) + ams = sco_moduleimpl.do_moduleimpl_list( + context, 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 @@ -735,7 +740,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): "formsemestre_id": formsemestre_id, "responsable_id": tf[2][module_id], } - moduleimpl_id = context.do_moduleimpl_create(modargs) + moduleimpl_id = sco_moduleimpl.do_moduleimpl_create(context, modargs) mod = context.do_module_list({"module_id": module_id})[0] msg += ["création de %s (%s)" % (mod["code"], mod["titre"])] # INSCRIPTIONS DES ETUDIANTS @@ -771,8 +776,8 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): ) msg += diag for module_id in mods_toedit: - moduleimpl_id = context.do_moduleimpl_list( - formsemestre_id=formsemestre_id, module_id=module_id + moduleimpl_id = sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=formsemestre_id, module_id=module_id )[0]["moduleimpl_id"] modargs = { "moduleimpl_id": moduleimpl_id, @@ -780,7 +785,9 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): "formsemestre_id": formsemestre_id, "responsable_id": tf[2][module_id], } - context.do_moduleimpl_edit(modargs, formsemestre_id=formsemestre_id) + sco_moduleimpl.do_moduleimpl_edit( + context, modargs, formsemestre_id=formsemestre_id + ) mod = context.do_module_list({"module_id": module_id})[0] if msg: @@ -814,8 +821,8 @@ def formsemestre_delete_moduleimpls(context, formsemestre_id, module_ids_to_del) msg = [] for module_id in module_ids_to_del: # get id - moduleimpl_id = context.do_moduleimpl_list( - formsemestre_id=formsemestre_id, module_id=module_id + 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] # Evaluations dans ce module ? @@ -828,7 +835,9 @@ def formsemestre_delete_moduleimpls(context, formsemestre_id, module_ids_to_del) ok = False else: msg += ["suppression de %s (%s)" % (mod["code"], mod["titre"])] - context.do_moduleimpl_delete(moduleimpl_id, formsemestre_id=formsemestre_id) + sco_moduleimpl.do_moduleimpl_delete( + context, moduleimpl_id, formsemestre_id=formsemestre_id + ) return ok, msg @@ -984,17 +993,21 @@ def do_formsemestre_clone( formsemestre_id = context.do_formsemestre_create(args, REQUEST) log("created formsemestre %s" % formsemestre_id) # 2- create moduleimpls - mods_orig = context.do_moduleimpl_list(formsemestre_id=orig_formsemestre_id) + mods_orig = sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=orig_formsemestre_id + ) for mod_orig in mods_orig: args = mod_orig.copy() args["formsemestre_id"] = formsemestre_id - mid = context.do_moduleimpl_create(args) + mid = sco_moduleimpl.do_moduleimpl_create(context, args) # copy notes_modules_enseignants - ens = context.do_ens_list(args={"moduleimpl_id": mod_orig["moduleimpl_id"]}) + ens = sco_moduleimpl.do_ens_list( + context, args={"moduleimpl_id": mod_orig["moduleimpl_id"]} + ) for e in ens: args = e.copy() args["moduleimpl_id"] = mid - context.do_ens_create(args) + sco_moduleimpl.do_ens_create(context, args) # optionally, copy evaluations if clone_evaluations: evals = context.do_evaluation_list( @@ -1007,11 +1020,13 @@ def do_formsemestre_clone( evaluation_id = context.do_evaluation_create(REQUEST=REQUEST, **args) # 3- copy uecoefs - objs = formsemestre_uecoef_list(cnx, args={"formsemestre_id": orig_formsemestre_id}) + objs = sco_formsemestre.formsemestre_uecoef_list( + cnx, args={"formsemestre_id": orig_formsemestre_id} + ) for obj in objs: args = obj.copy() args["formsemestre_id"] = formsemestre_id - c = formsemestre_uecoef_create(cnx, args) + c = sco_formsemestre.formsemestre_uecoef_create(cnx, args) # NB: don't copy notes_formsemestre_custommenu (usually specific) @@ -1177,7 +1192,9 @@ def _reassociate_moduleimpls( et met à jour les décisions de jury (validations d'UE). """ # re-associate moduleimpls to new modules: - modimpls = context.do_moduleimpl_list(formsemestre_id=formsemestre_id) + modimpls = sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=formsemestre_id + ) for mod in modimpls: mod["module_id"] = modules_old2new[mod["module_id"]] context.do_moduleimpl_edit(mod, formsemestre_id=formsemestre_id, cnx=cnx) @@ -1314,8 +1331,8 @@ def do_formsemestre_delete(context, formsemestre_id, REQUEST): ) context.get_evaluations_cache().inval_cache(key=e["evaluation_id"]) - context.do_moduleimpl_delete( - mod["moduleimpl_id"], formsemestre_id=formsemestre_id + sco_moduleimpl.do_moduleimpl_delete( + context, mod["moduleimpl_id"], formsemestre_id=formsemestre_id ) # --- Desinscription des etudiants cursor = cnx.cursor(cursor_factory=ScoDocCursor) @@ -1465,20 +1482,6 @@ def formsemestre_change_publication_bul( ) -# ---------------------- Coefs des UE - -_formsemestre_uecoef_editor = EditableTable( - "notes_formsemestre_uecoef", - "formsemestre_uecoef_id", - ("formsemestre_uecoef_id", "formsemestre_id", "ue_id", "coefficient"), -) - -formsemestre_uecoef_create = _formsemestre_uecoef_editor.create -formsemestre_uecoef_edit = _formsemestre_uecoef_editor.edit -formsemestre_uecoef_list = _formsemestre_uecoef_editor.list -formsemestre_uecoef_delete = _formsemestre_uecoef_editor.delete - - def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST=None): """Changement manuel des coefficients des UE capitalisées.""" context = context.Notes # si appele d'en haut, eg par exception ScoValueError @@ -1527,7 +1530,7 @@ def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST= initvalues = {"formsemestre_id": formsemestre_id} form = [("formsemestre_id", {"input_type": "hidden"})] for ue in ues: - coefs = formsemestre_uecoef_list( + coefs = sco_formsemestre.formsemestre_uecoef_list( cnx, args={"formsemestre_id": formsemestre_id, "ue_id": ue["ue_id"]} ) if coefs: @@ -1564,7 +1567,7 @@ def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST= msg = [] for ue in ues: val = tf[2]["ue_" + ue["ue_id"]] - coefs = formsemestre_uecoef_list( + coefs = sco_formsemestre.formsemestre_uecoef_list( cnx, args={"formsemestre_id": formsemestre_id, "ue_id": ue["ue_id"]} ) if val == "" or val == "auto": @@ -1594,11 +1597,13 @@ def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST= # apply modifications for ue in ue_modified: - do_formsemestre_uecoef_edit_or_create( + sco_formsemestre.do_formsemestre_uecoef_edit_or_create( context, cnx, formsemestre_id, ue["ue_id"], ue["coef"] ) for ue in ue_deleted: - do_formsemestre_uecoef_delete(context, cnx, formsemestre_id, ue["ue_id"]) + sco_formsemestre.do_formsemestre_uecoef_delete( + context, cnx, formsemestre_id, ue["ue_id"] + ) if ue_modified or ue_deleted: z = ["""

Modification effectuées

"""] @@ -1630,39 +1635,6 @@ def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST= ) -def do_formsemestre_uecoef_edit_or_create(context, cnx, formsemestre_id, ue_id, coef): - "modify or create the coef" - coefs = formsemestre_uecoef_list( - cnx, args={"formsemestre_id": formsemestre_id, "ue_id": ue_id} - ) - if coefs: - formsemestre_uecoef_edit( - cnx, - args={ - "formsemestre_uecoef_id": coefs[0]["formsemestre_uecoef_id"], - "coefficient": coef, - }, - ) - else: - formsemestre_uecoef_create( - cnx, - args={ - "formsemestre_id": formsemestre_id, - "ue_id": ue_id, - "coefficient": coef, - }, - ) - - -def do_formsemestre_uecoef_delete(context, cnx, formsemestre_id, ue_id): - "delete coef for this (ue,sem)" - coefs = formsemestre_uecoef_list( - cnx, args={"formsemestre_id": formsemestre_id, "ue_id": ue_id} - ) - if coefs: - formsemestre_uecoef_delete(cnx, coefs[0]["formsemestre_uecoef_id"]) - - # ----- identification externe des sessions (pour SOJA et autres logiciels) def get_formsemestre_session_id(context, sem, F, parcours): """Identifiant de session pour ce semestre diff --git a/sco_formsemestre_exterieurs.py b/sco_formsemestre_exterieurs.py index e90e4805..1240d5e1 100644 --- a/sco_formsemestre_exterieurs.py +++ b/sco_formsemestre_exterieurs.py @@ -436,7 +436,7 @@ def _list_ue_with_coef_and_validations(context, sem, etudid): ue_list = context.do_ue_list({"formation_id": sem["formation_id"]}) for ue in ue_list: # add coefficient - uecoef = sco_formsemestre_edit.formsemestre_uecoef_list( + uecoef = sco_formsemestre.formsemestre_uecoef_list( cnx, args={"formsemestre_id": formsemestre_id, "ue_id": ue["ue_id"]} ) if uecoef: diff --git a/sco_formsemestre_inscriptions.py b/sco_formsemestre_inscriptions.py index 602ad670..44f2d137 100644 --- a/sco_formsemestre_inscriptions.py +++ b/sco_formsemestre_inscriptions.py @@ -37,6 +37,7 @@ from TrivialFormulator import TrivialFormulator, TF # from notes_table import * import sco_find_etud import sco_formsemestre +import sco_moduleimpl import sco_groups @@ -75,10 +76,13 @@ def do_formsemestre_inscription_with_modules( gdone[group_id] = 1 # inscription a tous les modules de ce semestre - modimpls = context.do_moduleimpl_withmodule_list(formsemestre_id=formsemestre_id) + modimpls = sco_moduleimpl.do_moduleimpl_withmodule_list( + context, formsemestre_id=formsemestre_id + ) for mod in modimpls: if mod["ue"]["type"] != UE_SPORT: - context.do_moduleimpl_inscription_create( + sco_moduleimpl.do_moduleimpl_inscription_create( + context, {"moduleimpl_id": mod["moduleimpl_id"], "etudid": etudid}, REQUEST=REQUEST, formsemestre_id=formsemestre_id, @@ -278,8 +282,10 @@ def formsemestre_inscription_option(context, etudid, formsemestre_id, REQUEST=No ] # Cherche les moduleimpls et les inscriptions - mods = context.do_moduleimpl_withmodule_list(formsemestre_id=formsemestre_id) - inscr = context.do_moduleimpl_inscription_list(etudid=etudid) + mods = sco_moduleimpl.do_moduleimpl_withmodule_list( + context, formsemestre_id=formsemestre_id + ) + inscr = sco_moduleimpl.do_moduleimpl_inscription_list(context, etudid=etudid) # Formulaire modimpls_by_ue_ids = DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_id ] modimpls_by_ue_names = DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_name ] @@ -502,13 +508,14 @@ def do_moduleimpl_incription_options( # inscriptions for moduleimpl_id in a_inscrire: # verifie que ce module existe bien - mods = context.do_moduleimpl_list(moduleimpl_id=moduleimpl_id) + mods = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id) if len(mods) != 1: raise ScoValueError( "inscription: invalid moduleimpl_id: %s" % moduleimpl_id ) mod = mods[0] - context.do_moduleimpl_inscription_create( + sco_moduleimpl.do_moduleimpl_inscription_create( + context, {"moduleimpl_id": moduleimpl_id, "etudid": etudid}, REQUEST=REQUEST, formsemestre_id=mod["formsemestre_id"], @@ -516,14 +523,14 @@ def do_moduleimpl_incription_options( # desinscriptions for moduleimpl_id in a_desinscrire: # verifie que ce module existe bien - mods = context.do_moduleimpl_list(moduleimpl_id=moduleimpl_id) + mods = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id) if len(mods) != 1: raise ScoValueError( "desinscription: invalid moduleimpl_id: %s" % moduleimpl_id ) mod = mods[0] - inscr = context.do_moduleimpl_inscription_list( - moduleimpl_id=moduleimpl_id, etudid=etudid + inscr = sco_moduleimpl.do_moduleimpl_inscription_list( + context, moduleimpl_id=moduleimpl_id, etudid=etudid ) if not inscr: raise ScoValueError( @@ -531,8 +538,8 @@ def do_moduleimpl_incription_options( % (etudid, moduleimpl_id) ) oid = inscr[0]["moduleimpl_inscription_id"] - context.do_moduleimpl_inscription_delete( - oid, formsemestre_id=mod["formsemestre_id"] + sco_moduleimpl.do_moduleimpl_inscription_delete( + context, oid, formsemestre_id=mod["formsemestre_id"] ) if REQUEST: diff --git a/sco_formsemestre_status.py b/sco_formsemestre_status.py index b3132e6a..e71e4624 100644 --- a/sco_formsemestre_status.py +++ b/sco_formsemestre_status.py @@ -31,9 +31,18 @@ # Rewritten from ancient DTML code from mx.DateTime import DateTime as mxDateTime -from notesdb import * from notes_log import log -from sco_utils import * +import sco_utils as scu +from sco_permissions import ( + ScoImplement, + ScoChangeFormation, + ScoEtudInscrit, + ScoView, + ScoEtudChangeAdr, +) +from sco_exceptions import ScoValueError +import VERSION +import htmlutils from sco_formsemestre_custommenu import formsemestre_custommenu_html from gen_tables import GenTable import sco_archives @@ -41,64 +50,12 @@ import sco_groups import sco_evaluations import sco_formsemestre import sco_formsemestre_edit +import sco_moduleimpl import sco_compute_moy import sco_codes_parcours import sco_bulletins -def makeMenu(title, items, css_class="", base_url="", alone=False): - """HTML snippet to render a simple drop down menu. - items is a list of dicts: - { 'title' : - 'url' : - 'id' : - 'attr' : "" # optionnal html attributes - 'enabled' : # True by default - 'helpmsg' : - 'submenu' : [ list of sub-items ] - } - """ - - def gen_menu_items(items): - H.append("") - - H = [] - if alone: - H.append('
    ' % css_class) - H.append("""
  • %s""" % title) - gen_menu_items(items) - H.append("
  • ") - if alone: - H.append("
") - return "".join(H) - - # H = [ """