DocScoDoc/app/scodoc/sco_moduleimpl.py

345 lines
12 KiB
Python

# -*- 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
#
##############################################################################
"""Fonctions sur les moduleimpl
"""
# codes anciens déplacés de ZEntreprise
import datetime
import sco_utils as scu
import notesdb as ndb
from notesdb import ScoDocCursor, EditableTable, DateISOtoDMY, DateDMYtoISO
from sco_permissions import ScoImplement
from sco_exceptions import ScoValueError, AccessDenied
from notes_log import log
import scolog
import sco_formsemestre
# --- 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"),
)
def do_moduleimpl_create(context, args):
"create a moduleimpl"
cnx = ndb.GetDBConnexion()
r = _moduleimplEditor.create(cnx, args)
sco_core.inval_cache(
context, formsemestre_id=args["formsemestre_id"]
) # > creation moduleimpl
return r
def do_moduleimpl_delete(context, oid, formsemestre_id=None):
"delete moduleimpl (desinscrit tous les etudiants)"
cnx = ndb.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
_moduleimplEditor.delete(cnx, oid)
sco_core.inval_cache(
context, formsemestre_id=formsemestre_id
) # > moduleimpl_delete
def do_moduleimpl_list(
context, moduleimpl_id=None, formsemestre_id=None, module_id=None, REQUEST=None
):
"list moduleimpls"
args = locals()
cnx = ndb.GetDBConnexion()
modimpls = _moduleimplEditor.list(cnx, args) # *args, **kw)
# Ajoute la liste des enseignants
for mo in modimpls:
mo["ens"] = do_ens_list(context, args={"moduleimpl_id": mo["moduleimpl_id"]})
return scu.return_text_if_published(modimpls, REQUEST)
def do_moduleimpl_edit(context, args, formsemestre_id=None, cnx=None):
"edit a moduleimpl"
if not cnx:
cnx = ndb.GetDBConnexion()
_moduleimplEditor.edit(cnx, args)
sco_core.inval_cache(context, formsemestre_id=formsemestre_id) # > modif moduleimpl
def do_moduleimpl_withmodule_list(
context, 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.
Attention: Cette fonction fait partie de l'API ScoDoc 7 et est publiée.
"""
args = locals()
del args["context"]
del args["REQUEST"]
modimpls = do_moduleimpl_list(context, **args)
for mo in modimpls:
mo["module"] = context.do_module_list(args={"module_id": mo["module_id"]})[0]
mo["ue"] = context.do_ue_list(args={"ue_id": mo["module"]["ue_id"]})[0]
mo["matiere"] = context.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)))
return scu.return_text_if_published(modimpls, REQUEST)
def do_moduleimpl_inscription_list(
context, moduleimpl_id=None, etudid=None, REQUEST=None
):
"list moduleimpl_inscriptions"
args = locals()
cnx = ndb.GetDBConnexion()
return scu.return_text_if_published(
_moduleimpl_inscriptionEditor.list(cnx, args), REQUEST
)
def do_moduleimpl_listeetuds(context, 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 = ndb.GetDBConnexion()
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
cursor.execute(req, {"moduleimpl_id": moduleimpl_id})
res = cursor.fetchall()
return [x[0] for x in res]
def do_moduleimpl_inscrit_tout_semestre(context, moduleimpl_id, formsemestre_id):
"inscrit tous les etudiants inscrit au semestre a ce module"
# UNUSED
cnx = ndb.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)
# --- Inscriptions aux modules
_moduleimpl_inscriptionEditor = EditableTable(
"notes_moduleimpl_inscription",
"moduleimpl_inscription_id",
("moduleimpl_inscription_id", "etudid", "moduleimpl_id"),
)
def do_moduleimpl_inscription_create(context, args, REQUEST=None, formsemestre_id=None):
"create a moduleimpl_inscription"
cnx = ndb.GetDBConnexion()
log("do_moduleimpl_inscription_create: " + str(args))
r = _moduleimpl_inscriptionEditor.create(cnx, args)
sco_core.inval_cache(
context, formsemestre_id=formsemestre_id
) # > moduleimpl_inscription
if REQUEST:
scolog.logdb(
REQUEST,
cnx,
method="moduleimpl_inscription",
etudid=args["etudid"],
msg="inscription module %s" % args["moduleimpl_id"],
commit=False,
)
return r
def do_moduleimpl_inscription_delete(context, oid, formsemestre_id=None):
"delete moduleimpl_inscription"
cnx = ndb.GetDBConnexion()
_moduleimpl_inscriptionEditor.delete(cnx, oid)
sco_core.inval_cache(
context, formsemestre_id=formsemestre_id
) # > moduleimpl_inscription
def do_moduleimpl_inscrit_etuds(
context, 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 = context.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 = ndb.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(
[
# hum ?
x["etudid"]
for x in do_moduleimpl_inscription_list(
context, moduleimpl_id=moduleimpl_id
)
]
)
for etudid in etudids:
# deja inscrit ?
if not etudid in inmod_set:
do_moduleimpl_inscription_create(
context,
{"moduleimpl_id": moduleimpl_id, "etudid": etudid},
REQUEST=REQUEST,
formsemestre_id=formsemestre_id,
)
sco_core.inval_cache(
context, formsemestre_id=formsemestre_id
) # > moduleimpl_inscrit_etuds
def do_ens_list(context, *args, **kw):
"liste les enseignants d'un moduleimpl (pas le responsable)"
cnx = ndb.GetDBConnexion()
ens = _modules_enseignantsEditor.list(cnx, *args, **kw)
return ens
def do_ens_edit(context, *args, **kw):
"edit ens"
cnx = ndb.GetDBConnexion()
_modules_enseignantsEditor.edit(cnx, *args, **kw)
def do_ens_create(context, args):
"create ens"
cnx = ndb.GetDBConnexion()
r = _modules_enseignantsEditor.create(cnx, args)
return r
def do_ens_delete(context, oid):
"delete ens"
cnx = ndb.GetDBConnexion()
r = _modules_enseignantsEditor.delete(cnx, oid)
return r
def can_change_module_resp(context, 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 = do_moduleimpl_withmodule_list(context, moduleimpl_id=moduleimpl_id)[0]
# -- check lock
sem = sco_formsemestre.get_formsemestre(context, 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(Permission.ScoImplement, context) and (
(uid not in sem["responsables"]) or (not sem["resp_can_change_ens"])
):
raise AccessDenied("Modification impossible pour %s" % uid)
return M, sem
def can_change_ens(context, REQUEST, moduleimpl_id, raise_exc=True):
"check if current user can modify ens list (raise exception if not)"
M = do_moduleimpl_withmodule_list(context, moduleimpl_id=moduleimpl_id)[0]
# -- check lock
sem = sco_formsemestre.get_formsemestre(context, 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(Permission.ScoImplement, context)
and (uid not in sem["responsables"])
):
if raise_exc:
raise AccessDenied("Modification impossible pour %s" % uid)
else:
return False
return M, sem