forked from ScoDoc/ScoDoc
WIP suite de la migration
This commit is contained in:
parent
8f91d5292c
commit
6a4d6e5109
@ -1,838 +0,0 @@
|
||||
# -*- 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
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
"""Site ScoDoc pour plusieurs departements:
|
||||
gestion de l'installation et des creation de départements.
|
||||
|
||||
Chaque departement est géré par un ZScolar sous ZScoDoc.
|
||||
"""
|
||||
|
||||
import time
|
||||
import datetime
|
||||
import string
|
||||
import glob
|
||||
import re
|
||||
import inspect
|
||||
import urllib
|
||||
import urllib2
|
||||
import cgi
|
||||
import xml
|
||||
|
||||
from cStringIO import StringIO
|
||||
from zipfile import ZipFile
|
||||
import os.path
|
||||
import traceback
|
||||
|
||||
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
|
||||
|
||||
from app.scodoc.sco_zope import (
|
||||
ObjectManager,
|
||||
PropertyManager,
|
||||
RoleManager,
|
||||
Item,
|
||||
Persistent,
|
||||
Implicit,
|
||||
ClassSecurityInfo,
|
||||
DTMLFile,
|
||||
Globals,
|
||||
)
|
||||
|
||||
try:
|
||||
import Products.ZPsycopgDA.DA as ZopeDA
|
||||
except:
|
||||
import ZPsycopgDA.DA as ZopeDA # interp.py
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc import VERSION
|
||||
import mails
|
||||
from app.scodoc.notes_log import log
|
||||
from app.scodoc import sco_find_etud
|
||||
from app.scodoc import sco_users
|
||||
from app.scodoc.sco_permissions import (
|
||||
ScoView,
|
||||
ScoEnsView,
|
||||
ScoImplement,
|
||||
ScoChangeFormation,
|
||||
ScoObservateur,
|
||||
ScoEtudInscrit,
|
||||
ScoEtudChangeGroups,
|
||||
ScoEtudChangeAdr,
|
||||
ScoEtudSupprAnnotations,
|
||||
ScoEditAllEvals,
|
||||
ScoEditAllNotes,
|
||||
ScoEditFormationTags,
|
||||
ScoEditApo,
|
||||
ScoSuperAdmin,
|
||||
)
|
||||
from app.scodoc.sco_exceptions import (
|
||||
ScoValueError,
|
||||
ScoLockedFormError,
|
||||
ScoGenError,
|
||||
AccessDenied,
|
||||
)
|
||||
from app.scodoc import html_sco_header
|
||||
|
||||
|
||||
class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Implicit):
|
||||
|
||||
"ZScoDoc object"
|
||||
|
||||
meta_type = "ZScoDoc"
|
||||
security = ClassSecurityInfo()
|
||||
file_path = Globals.package_home(globals())
|
||||
|
||||
# This is the list of the methods associated to 'tabs' in the ZMI
|
||||
# Be aware that The first in the list is the one shown by default, so if
|
||||
# the 'View' tab is the first, you will never see your tabs by cliquing
|
||||
# on the object.
|
||||
manage_options = (
|
||||
({"label": "Contents", "action": "manage_main"},)
|
||||
+ PropertyManager.manage_options # add the 'Properties' tab
|
||||
+ ({"label": "View", "action": "index_html"},)
|
||||
+ Item.manage_options # add the 'Undo' & 'Owner' tab
|
||||
+ RoleManager.manage_options # add the 'Security' tab
|
||||
)
|
||||
|
||||
def __init__(self, id, title):
|
||||
"Initialise a new instance of ZScoDoc"
|
||||
self.id = id
|
||||
self.title = title
|
||||
self.manage_addProperty("admin_password_initialized", "0", "string")
|
||||
|
||||
security.declareProtected(ScoView, "ScoDocURL")
|
||||
|
||||
def ScoDocURL(self):
|
||||
"base URL for this instance (top level for ScoDoc site)"
|
||||
return self.absolute_url()
|
||||
|
||||
def _check_admin_perm(self, REQUEST):
|
||||
"""Check if user has permission to add/delete departements"""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
if authuser.has_role("manager") or authuser.has_permission(
|
||||
Permission.ScoSuperAdmin, self
|
||||
):
|
||||
return ""
|
||||
else:
|
||||
return """<h2>Vous n'avez pas le droit d'accéder à cette page</h2>"""
|
||||
|
||||
def _check_users_folder(self, REQUEST=None):
|
||||
"""Vérifie UserFolder et le crée s'il le faut"""
|
||||
try:
|
||||
_ = self.UsersDB
|
||||
return "<!-- uf ok -->"
|
||||
except:
|
||||
e = self._check_admin_perm(REQUEST)
|
||||
if not e: # admin permissions:
|
||||
self.create_users_cnx(REQUEST)
|
||||
self.create_users_folder(REQUEST)
|
||||
return '<div class="head_message">Création du connecteur utilisateurs réussie</div>'
|
||||
else:
|
||||
return """<div class="head_message">Installation non terminée: connectez vous avec les droits d'administrateur</div>"""
|
||||
|
||||
security.declareProtected("View", "create_users_folder")
|
||||
|
||||
def create_users_folder(self, REQUEST=None):
|
||||
"""Create Zope user folder"""
|
||||
e = self._check_admin_perm(REQUEST)
|
||||
if e:
|
||||
return e
|
||||
|
||||
if REQUEST is None:
|
||||
REQUEST = {}
|
||||
|
||||
REQUEST.form["pgauth_connection"] = "UsersDB"
|
||||
REQUEST.form["pgauth_table"] = "sco_users"
|
||||
REQUEST.form["pgauth_usernameColumn"] = "user_name"
|
||||
REQUEST.form["pgauth_passwordColumn"] = "passwd"
|
||||
REQUEST.form["pgauth_rolesColumn"] = "roles"
|
||||
|
||||
add_method = self.manage_addProduct["OFSP"].manage_addexUserFolder
|
||||
log("create_users_folder: in %s" % self.id)
|
||||
return add_method(
|
||||
authId="pgAuthSource",
|
||||
propId="nullPropSource",
|
||||
memberId="nullMemberSource",
|
||||
groupId="nullGroupSource",
|
||||
cryptoId="MD51",
|
||||
# doAuth='1', doProp='1', doMember='1', doGroup='1', allDone='1',
|
||||
cookie_mode=2,
|
||||
session_length=500,
|
||||
not_session_length=0,
|
||||
REQUEST=REQUEST,
|
||||
)
|
||||
|
||||
def _fix_users_folder(self):
|
||||
"""removes docLogin and docLogout dtml methods from exUserFolder, so that we use ours.
|
||||
(called each time be index_html, to fix old ScoDoc installations.)
|
||||
"""
|
||||
try:
|
||||
self.acl_users.manage_delObjects(ids=["docLogin", "docLogout"])
|
||||
except:
|
||||
pass
|
||||
# add missing getAuthFailedMessage (bug in exUserFolder ?)
|
||||
try:
|
||||
_ = self.getAuthFailedMessage
|
||||
except:
|
||||
log("adding getAuthFailedMessage to Zope install")
|
||||
parent = self.aq_parent
|
||||
from OFS.DTMLMethod import addDTMLMethod # pylint: disable=import-error
|
||||
|
||||
addDTMLMethod(parent, "getAuthFailedMessage", file="Identification")
|
||||
|
||||
security.declareProtected("View", "create_users_cnx")
|
||||
|
||||
def create_users_cnx(self, REQUEST=None):
|
||||
"""Create Zope connector to UsersDB
|
||||
|
||||
Note: la connexion est fixée (SCOUSERS) (base crée par l'installeur) !
|
||||
Les utilisateurs avancés pourront la changer ensuite.
|
||||
"""
|
||||
# ce connecteur zope - db est encore pour l'instant utilisé par exUserFolder.pgAuthSource
|
||||
# (en lecture seule en principe)
|
||||
oid = "UsersDB"
|
||||
log("create_users_cnx: in %s" % self.id)
|
||||
da = ZopeDA.Connection(
|
||||
oid,
|
||||
"Cnx bd utilisateurs",
|
||||
scu.SCO_DEFAULT_SQL_USERS_CNX,
|
||||
False,
|
||||
check=1,
|
||||
tilevel=2,
|
||||
encoding="LATIN1",
|
||||
)
|
||||
self._setObject(oid, da)
|
||||
|
||||
security.declareProtected("View", "change_admin_user")
|
||||
|
||||
def change_admin_user(self, password, REQUEST=None):
|
||||
"""Change password of admin user"""
|
||||
# note: controle sur le role et non pas sur une permission
|
||||
# (non definies au top level)
|
||||
if not REQUEST.AUTHENTICATED_USER.has_role("Manager"):
|
||||
log("user %s is not Manager" % REQUEST.AUTHENTICATED_USER)
|
||||
log("roles=%s" % REQUEST.AUTHENTICATED_USER.getRolesInContext(self))
|
||||
raise AccessDenied("vous n'avez pas le droit d'effectuer cette opération")
|
||||
log("trying to change admin password")
|
||||
# 1-- check strong password
|
||||
if not sco_users.is_valid_password(password):
|
||||
log("refusing weak password")
|
||||
return REQUEST.RESPONSE.redirect(
|
||||
"change_admin_user_form?message=Mot%20de%20passe%20trop%20simple,%20recommencez"
|
||||
)
|
||||
# 2-- change password for admin user
|
||||
username = "admin"
|
||||
acl_users = self.aq_parent.acl_users
|
||||
user = acl_users.getUser(username)
|
||||
r = acl_users._changeUser(
|
||||
username, password, password, user.roles, user.domains
|
||||
)
|
||||
if not r:
|
||||
# OK, set property to indicate we changed the password
|
||||
log("admin password changed successfully")
|
||||
self.manage_changeProperties(admin_password_initialized="1")
|
||||
return r or REQUEST.RESPONSE.redirect("index_html")
|
||||
|
||||
security.declareProtected("View", "change_admin_user_form")
|
||||
|
||||
def change_admin_user_form(self, message="", REQUEST=None):
|
||||
"""Form allowing to change the ScoDoc admin password"""
|
||||
# note: controle sur le role et non pas sur une permission
|
||||
# (non definies au top level)
|
||||
if not REQUEST.AUTHENTICATED_USER.has_role("Manager"):
|
||||
raise AccessDenied("vous n'avez pas le droit d'effectuer cette opération")
|
||||
H = [
|
||||
html_sco_header.scodoc_top_html_header(
|
||||
self, REQUEST, page_title="ScoDoc: changement mot de passe"
|
||||
)
|
||||
]
|
||||
if message:
|
||||
H.append('<div id="message">%s</div>' % message)
|
||||
H.append(
|
||||
"""<h2>Changement du mot de passe administrateur (utilisateur admin)</h2>
|
||||
<p>
|
||||
<form action="change_admin_user" method="post"><table>
|
||||
<tr><td>Nouveau mot de passe:</td><td><input type="password" size="14" name="password"/></td></tr>
|
||||
<tr><td>Confirmation: </td><td><input type="password" size="14" name="password2" /></td></tr>
|
||||
</table>
|
||||
<input type="submit" value="Changer">
|
||||
"""
|
||||
)
|
||||
H.append("""</body></html>""")
|
||||
return "\n".join(H)
|
||||
|
||||
security.declareProtected("View", "list_depts")
|
||||
|
||||
def list_depts(self, viewable=True, format=None, REQUEST=None):
|
||||
"""List departments
|
||||
If viewable, list only depts viewable the current user.
|
||||
"""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
viewable = int(viewable)
|
||||
return scu.sendResult(
|
||||
REQUEST,
|
||||
[
|
||||
d.id
|
||||
for d in self._list_depts()
|
||||
if (not viewable)
|
||||
or authuser.has_permission(Permission.ScoView, d.Scolarite)
|
||||
],
|
||||
name="depts",
|
||||
format=format,
|
||||
)
|
||||
|
||||
def _list_depts(self, REQUEST=None): # not published
|
||||
# List departments folders
|
||||
# (returns a list of Zope folders containing a ZScolar instance)
|
||||
folders = self.objectValues("Folder")
|
||||
# select folders with Scolarite object:
|
||||
r = []
|
||||
for folder in folders:
|
||||
try:
|
||||
_ = folder.Scolarite
|
||||
r.append(folder)
|
||||
except:
|
||||
pass
|
||||
return r
|
||||
|
||||
security.declareProtected("View", "create_dept")
|
||||
|
||||
def create_dept(self, REQUEST=None, DeptId="", pass2=False):
|
||||
"""Creation (ajout) d'un site departement
|
||||
(instance ZScolar + dossier la contenant)
|
||||
"""
|
||||
e = self._check_admin_perm(REQUEST)
|
||||
if e:
|
||||
return e
|
||||
|
||||
if not DeptId:
|
||||
raise ValueError("nom de departement invalide")
|
||||
if not pass2:
|
||||
# 1- Creation de repertoire Dept
|
||||
log("creating Zope folder " + DeptId)
|
||||
add_method = self.manage_addProduct["OFSP"].manage_addFolder
|
||||
add_method(DeptId, title="Site dept. " + DeptId)
|
||||
|
||||
DeptFolder = self[DeptId]
|
||||
|
||||
if not pass2:
|
||||
# 2- Creation du repertoire Fotos
|
||||
log("creating Zope folder %s/Fotos" % DeptId)
|
||||
add_method = DeptFolder.manage_addProduct["OFSP"].manage_addFolder
|
||||
add_method("Fotos", title="Photos identites " + DeptId)
|
||||
|
||||
# 3- Creation instance ScoDoc
|
||||
log("creating Zope ZScolar instance")
|
||||
add_method = DeptFolder.manage_addProduct["ScoDoc"].manage_addZScolarForm
|
||||
return add_method(DeptId, REQUEST=REQUEST)
|
||||
|
||||
security.declareProtected("View", "delete_dept")
|
||||
|
||||
def delete_dept(self, REQUEST=None, DeptId="", force=False):
|
||||
"""Supprime un departement (de Zope seulement, ne touche pas la BD)"""
|
||||
e = self._check_admin_perm(REQUEST)
|
||||
if e:
|
||||
return e
|
||||
|
||||
if not force and DeptId not in [x.id for x in self._list_depts()]:
|
||||
raise ValueError("nom de departement invalide")
|
||||
|
||||
self.manage_delObjects(ids=[DeptId])
|
||||
|
||||
return (
|
||||
"<p>Département "
|
||||
+ DeptId
|
||||
+ """ supprimé du serveur web (la base de données n'est pas affectée)!</p><p><a href="/ScoDoc">Continuer</a></p>"""
|
||||
)
|
||||
|
||||
security.declareProtected("View", "index_html")
|
||||
|
||||
def index_html(self, REQUEST=None, message=None):
|
||||
"""Top level page for ScoDoc"""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
deptList = self._list_depts()
|
||||
self._fix_users_folder() # fix our exUserFolder
|
||||
isAdmin = not self._check_admin_perm(REQUEST)
|
||||
try:
|
||||
admin_password_initialized = self.admin_password_initialized
|
||||
except:
|
||||
admin_password_initialized = "0"
|
||||
if isAdmin and admin_password_initialized != "1":
|
||||
return REQUEST.RESPONSE.redirect(
|
||||
"ScoDoc/change_admin_user_form?message=Le%20mot%20de%20passe%20administrateur%20doit%20etre%20change%20!"
|
||||
)
|
||||
|
||||
# Si l'URL indique que l'on est dans un folder, affiche page login du departement
|
||||
try:
|
||||
deptfoldername = REQUEST.URL0.split("ScoDoc")[1].split("/")[1]
|
||||
if deptfoldername in [x.id for x in self._list_depts()]:
|
||||
return self.index_dept(deptfoldername=deptfoldername, REQUEST=REQUEST)
|
||||
except:
|
||||
pass
|
||||
|
||||
H = [
|
||||
html_sco_header.scodoc_top_html_header(
|
||||
self, REQUEST, page_title="ScoDoc: bienvenue"
|
||||
),
|
||||
self._check_users_folder(REQUEST=REQUEST), # ensure setup is done
|
||||
]
|
||||
if message:
|
||||
H.append('<div id="message">%s</div>' % message)
|
||||
|
||||
if isAdmin and not message:
|
||||
H.append('<div id="message">Attention: connecté comme administrateur</div>')
|
||||
|
||||
H.append(
|
||||
"""
|
||||
<div class="maindiv">
|
||||
<h2>ScoDoc: gestion scolarité</h2>
|
||||
"""
|
||||
)
|
||||
if authuser.has_role("Authenticated"):
|
||||
H.append(
|
||||
"""<p>Bonjour <font color="red"><b>%s</b></font>.</p>""" % str(authuser)
|
||||
)
|
||||
H.append(
|
||||
"""<p>N'oubliez pas de vous <a href="acl_users/logout">déconnecter</a> après usage.</p>"""
|
||||
)
|
||||
else:
|
||||
H.append(
|
||||
"""<p>Ce site est <font color="red"><b>réservé au personnel autorisé</b></font></p>"""
|
||||
)
|
||||
H.append(self.authentication_form(destination="."))
|
||||
|
||||
if not deptList:
|
||||
H.append("<em>aucun département existant !</em>")
|
||||
# si pas de dept et pas admin, propose lien pour loger admin
|
||||
if not isAdmin:
|
||||
H.append(
|
||||
"""<p><a href="/force_admin_authentication">Identifiez vous comme administrateur</a> (au début: nom 'admin', mot de passe 'scodoc')</p>"""
|
||||
)
|
||||
else:
|
||||
H.append('<ul class="main">')
|
||||
if isAdmin:
|
||||
dest_folder = "/Scolarite"
|
||||
else:
|
||||
dest_folder = ""
|
||||
for deptFolder in self._list_depts():
|
||||
if authuser.has_permission(Permission.ScoView, deptFolder.Scolarite):
|
||||
link_cls = "link_accessible"
|
||||
else:
|
||||
link_cls = "link_unauthorized"
|
||||
# Essai de recuperer le nom du departement dans ses preferences
|
||||
try:
|
||||
DeptName = (
|
||||
deptFolder.Scolarite.get_preference("DeptName") or deptFolder.id
|
||||
)
|
||||
except:
|
||||
DeptName = deptFolder.id
|
||||
H.append(
|
||||
'<li><a class="stdlink %s" href="%s%s">Département %s</a>'
|
||||
% (link_cls, deptFolder.absolute_url(), dest_folder, DeptName)
|
||||
)
|
||||
# check if roles are initialized in this depts, and do it if necessary
|
||||
if deptFolder.Scolarite.roles_initialized == "0":
|
||||
if isAdmin:
|
||||
deptFolder.Scolarite._setup_initial_roles_and_permissions()
|
||||
else:
|
||||
H.append(" (non initialisé, connectez vous comme admin)")
|
||||
H.append("</li>")
|
||||
H.append("</ul>")
|
||||
# Recherche etudiant
|
||||
H.append(sco_find_etud.form_search_etud_in_accessible_depts(self, REQUEST))
|
||||
|
||||
if isAdmin:
|
||||
H.append('<p><a href="scodoc_admin">Administration de ScoDoc</a></p>')
|
||||
else:
|
||||
H.append(
|
||||
'<p><a href="%s/force_admin_authentication">Se connecter comme administrateur</a></p>'
|
||||
% REQUEST.BASE0
|
||||
)
|
||||
|
||||
# Lien expérimental temporaire:
|
||||
H.append(
|
||||
'<p><a href="/ScoDoc/static/mobile">Version mobile (expérimentale, à vos risques et périls)</a></p>'
|
||||
)
|
||||
|
||||
H.append(
|
||||
"""
|
||||
<div id="scodoc_attribution">
|
||||
<p><a href="%s">ScoDoc</a> est un logiciel libre de suivi de la scolarité des étudiants conçu par
|
||||
E. Viennet (Université Paris 13).</p>
|
||||
</div>
|
||||
</div>"""
|
||||
% (scu.SCO_WEBSITE,)
|
||||
)
|
||||
|
||||
H.append("""</body></html>""")
|
||||
return "\n".join(H)
|
||||
|
||||
def authentication_form(self, destination=""):
|
||||
"""html snippet for authentication"""
|
||||
return (
|
||||
"""<!-- authentication_form -->
|
||||
<form action="doLogin" method="post">
|
||||
<input type="hidden" name="destination" value="%s"/>
|
||||
<p>
|
||||
<table border="0" cellpadding="3">
|
||||
<tr>
|
||||
<td><b>Nom:</b></td>
|
||||
<td><input id="name" type="text" name="__ac_name" size="20"/></td>
|
||||
</tr><tr>
|
||||
<td><b>Mot de passe:</b></td>
|
||||
<td><input id="password" type="password" name="__ac_password" size="20"/></td>
|
||||
<td><input id="submit" name="submit" type="submit" value="OK"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
</form>"""
|
||||
% destination
|
||||
)
|
||||
|
||||
security.declareProtected("View", "index_dept")
|
||||
|
||||
def index_dept(self, deptfoldername="", REQUEST=None):
|
||||
"""Page d'accueil departement"""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
try:
|
||||
dept = getattr(self, deptfoldername)
|
||||
if authuser.has_permission(Permission.ScoView, dept):
|
||||
return REQUEST.RESPONSE.redirect("ScoDoc/%s/Scolarite" % deptfoldername)
|
||||
except:
|
||||
log(
|
||||
"*** problem in index_dept (%s) user=%s"
|
||||
% (deptfoldername, str(authuser))
|
||||
)
|
||||
|
||||
H = [
|
||||
html_sco_header.standard_html_header(),
|
||||
"""<div style="margin: 1em;">
|
||||
<h2>Scolarité du département %s</h2>"""
|
||||
% deptfoldername,
|
||||
"""<p>Ce site est
|
||||
<font color="#FF0000"><b>réservé au personnel du département</b></font>.
|
||||
</p>""",
|
||||
self.authentication_form(destination="Scolarite"),
|
||||
"""
|
||||
<p>Pour quitter, <a href="acl_users/logout">logout</a></p>
|
||||
<p><a href="%s">Retour à l'accueil</a></p>
|
||||
</div>
|
||||
"""
|
||||
% self.ScoDocURL(),
|
||||
html_sco_header.standard_html_footer(),
|
||||
]
|
||||
return "\n".join(H)
|
||||
|
||||
security.declareProtected("View", "doLogin")
|
||||
|
||||
def doLogin(self, REQUEST=None, destination=None):
|
||||
"redirect to destination after login"
|
||||
if destination:
|
||||
return REQUEST.RESPONSE.redirect(destination)
|
||||
|
||||
security.declareProtected("View", "docLogin")
|
||||
docLogin = DTMLFile("dtml/docLogin", globals())
|
||||
security.declareProtected("View", "docLogout")
|
||||
docLogout = DTMLFile("dtml/docLogout", globals())
|
||||
|
||||
security.declareProtected("View", "query_string_to_form_inputs")
|
||||
|
||||
def query_string_to_form_inputs(self, query_string=""):
|
||||
"""Return html snippet representing the query string as POST form hidden inputs.
|
||||
This is useful in conjonction with exUserfolder to correctly redirect the response
|
||||
after authentication.
|
||||
"""
|
||||
H = []
|
||||
for a in query_string.split("&"):
|
||||
if a:
|
||||
nv = a.split("=")
|
||||
if len(nv) == 2:
|
||||
name, value = nv
|
||||
H.append(
|
||||
'<input type="hidden" name="'
|
||||
+ name
|
||||
+ '" value="'
|
||||
+ value
|
||||
+ '"/>'
|
||||
)
|
||||
|
||||
return "<!-- query string -->\n" + "\n".join(H)
|
||||
|
||||
security.declareProtected("View", "standard_error_message")
|
||||
|
||||
def standard_error_message(
|
||||
self,
|
||||
error_value=None,
|
||||
error_message=None, # unused ?
|
||||
error_type=None,
|
||||
error_traceback=None,
|
||||
error_tb=None,
|
||||
**kv
|
||||
):
|
||||
"Recuperation des exceptions Zope"
|
||||
# neat (or should I say dirty ?) hack to get REQUEST
|
||||
# in fact, our caller (probably SimpleItem.py) has the REQUEST variable
|
||||
# that we'd like to use for our logs, but does not pass it as an argument.
|
||||
try:
|
||||
frame = inspect.currentframe()
|
||||
REQUEST = frame.f_back.f_locals["REQUEST"]
|
||||
except:
|
||||
REQUEST = {}
|
||||
|
||||
# Authentication uses exceptions, pass them up
|
||||
HTTP_X_FORWARDED_FOR = REQUEST.get("HTTP_X_FORWARDED_FOR", "")
|
||||
if error_type == "LoginRequired":
|
||||
log("LoginRequired from %s" % HTTP_X_FORWARDED_FOR)
|
||||
self.login_page = error_value
|
||||
return error_value
|
||||
elif error_type == "Unauthorized":
|
||||
log("Unauthorized from %s" % HTTP_X_FORWARDED_FOR)
|
||||
return self.acl_users.docLogin(self, REQUEST=REQUEST)
|
||||
|
||||
log("exception caught: %s" % error_type)
|
||||
log(traceback.format_exc())
|
||||
|
||||
params = {
|
||||
"error_type": error_type,
|
||||
"error_value": error_value,
|
||||
"error_tb": error_tb,
|
||||
"sco_exc_mail": scu.SCO_EXC_MAIL,
|
||||
"sco_dev_mail": scu.SCO_DEV_MAIL,
|
||||
}
|
||||
|
||||
if error_type == "ScoGenError":
|
||||
return "<p>" + str(error_value) + "</p>"
|
||||
elif error_type in ("ScoValueError", "FormatError"):
|
||||
# Not a bug, presents a gentle message to the user:
|
||||
H = [
|
||||
html_sco_header.standard_html_header(),
|
||||
"""<h2>Erreur !</h2><p>%s</p>""" % error_value,
|
||||
]
|
||||
if error_value.dest_url:
|
||||
H.append('<p><a href="%s">Continuer</a></p>' % error_value.dest_url)
|
||||
H.append(html_sco_header.standard_html_footer())
|
||||
return "\n".join(H)
|
||||
else: # Other exceptions, try carefully to build an error page...
|
||||
# log('exc A')
|
||||
H = []
|
||||
try:
|
||||
H.append(html_sco_header.standard_html_header())
|
||||
except:
|
||||
pass
|
||||
H.append(
|
||||
"""<table border="0" width="100%%"><tr valign="top">
|
||||
<td width="10%%" align="center"></td>
|
||||
<td width="90%%"><h2>Erreur !</h2>
|
||||
<p>Une erreur est survenue</p>
|
||||
<p>
|
||||
<strong>Error Type: %(error_type)s</strong><br>
|
||||
<strong>Error Value: %(error_value)s</strong><br>
|
||||
</p>
|
||||
<hr noshade>
|
||||
<p>L'URL est peut-etre incorrecte ?</p>
|
||||
|
||||
<p>Si l'erreur persiste, contactez Emmanuel Viennet:
|
||||
<a href="mailto:%(sco_dev_mail)s">%(sco_dev_mail)s</a>
|
||||
en copiant ce message d'erreur et le contenu du cadre bleu ci-dessous si possible.
|
||||
</p>
|
||||
</td></tr>
|
||||
</table> """
|
||||
% params
|
||||
)
|
||||
# display error traceback (? may open a security risk via xss attack ?)
|
||||
params["txt_html"] = self._report_request(REQUEST, fmt="html")
|
||||
H.append(
|
||||
"""<h4 class="scodoc">Zope Traceback (à envoyer par mail à <a href="mailto:%(sco_dev_mail)s">%(sco_dev_mail)s</a>)</h4><div style="background-color: rgb(153,153,204); border: 1px;">
|
||||
%(error_tb)s
|
||||
<p><b>Informations:</b><br/>
|
||||
%(txt_html)s
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p>Merci de votre patience !</p>
|
||||
"""
|
||||
% params
|
||||
)
|
||||
try:
|
||||
H.append(html_sco_header.standard_html_footer())
|
||||
except:
|
||||
log("no footer found for error page")
|
||||
pass
|
||||
|
||||
# --- Mail:
|
||||
params["error_traceback_txt"] = scu.scodoc_html2txt(error_tb)
|
||||
txt = (
|
||||
"""
|
||||
ErrorType: %(error_type)s
|
||||
|
||||
%(error_traceback_txt)s
|
||||
"""
|
||||
% params
|
||||
)
|
||||
|
||||
mails.send_debug_alert(context, txt, REQUEST=REQUEST)
|
||||
# ---
|
||||
log("done processing exception")
|
||||
# log( '\n page=\n' + '\n'.join(H) )
|
||||
return "\n".join(H)
|
||||
|
||||
security.declareProtected("View", "scodoc_admin")
|
||||
|
||||
def scodoc_admin(self, REQUEST=None):
|
||||
"""Page Operations d'administration"""
|
||||
e = self._check_admin_perm(REQUEST)
|
||||
if e:
|
||||
return e
|
||||
|
||||
H = [
|
||||
html_sco_header.scodoc_top_html_header(
|
||||
self, REQUEST, page_title="ScoDoc: bienvenue"
|
||||
),
|
||||
"""
|
||||
<h3>Administration ScoDoc</h3>
|
||||
|
||||
<p><a href="change_admin_user_form">changer le mot de passe super-administrateur</a></p>
|
||||
<p><a href="%s">retour à la page d'accueil</a></p>
|
||||
|
||||
<h4 class="scodoc">Création d'un département</h4>
|
||||
<p class="help_important">Le département doit avoir été créé au préalable sur le serveur en utilisant le script
|
||||
<tt>create_dept.sh</tt> (à lancer comme <tt>root</tt> dans le répertoire <tt>config</tt> de ScoDoc).
|
||||
</p>"""
|
||||
% self.absolute_url(),
|
||||
]
|
||||
|
||||
deptList = [x.id for x in self._list_depts()] # definis dans Zope
|
||||
deptIds = set(self._list_depts_ids()) # definis sur le filesystem
|
||||
existingDepts = set(deptList)
|
||||
addableDepts = deptIds - existingDepts
|
||||
|
||||
if not addableDepts:
|
||||
# aucun departement defini: aide utilisateur
|
||||
H.append("<p>Aucun département à ajouter !</p>")
|
||||
else:
|
||||
H.append("""<form action="create_dept"><select name="DeptId"/>""")
|
||||
for deptId in addableDepts:
|
||||
H.append("""<option value="%s">%s</option>""" % (deptId, deptId))
|
||||
H.append(
|
||||
"""</select>
|
||||
<input type="submit" value="Créer département">
|
||||
</form>"""
|
||||
)
|
||||
|
||||
if deptList:
|
||||
H.append(
|
||||
"""
|
||||
<h4 class="scodoc">Suppression d'un département</h4>
|
||||
<p>Ceci permet de supprimer le site web associé à un département, mais n'affecte pas la base de données
|
||||
(le site peut donc être recréé sans perte de données).
|
||||
</p>
|
||||
<form action="delete_dept">
|
||||
<select name="DeptId">
|
||||
"""
|
||||
)
|
||||
for deptFolder in self._list_depts():
|
||||
H.append(
|
||||
'<option value="%s">%s</option>' % (deptFolder.id, deptFolder.id)
|
||||
)
|
||||
H.append(
|
||||
"""</select>
|
||||
<input type="submit" value="Supprimer département">
|
||||
|
||||
</form>"""
|
||||
)
|
||||
|
||||
H.append("""</body></html>""")
|
||||
return "\n".join(H)
|
||||
|
||||
def _list_depts_ids(self):
|
||||
"""Liste de id de departements definis par create_dept.sh
|
||||
(fichiers depts/*.cfg)
|
||||
"""
|
||||
filenames = glob.glob(scu.SCODOC_VAR_DIR + "/config/depts/*.cfg")
|
||||
ids = [os.path.split(os.path.splitext(f)[0])[1] for f in filenames]
|
||||
return ids
|
||||
|
||||
security.declareProtected("View", "http_expiration_date")
|
||||
|
||||
def http_expiration_date(self):
|
||||
"http expiration date for cachable elements (css, ...)"
|
||||
d = datetime.timedelta(minutes=10)
|
||||
return (datetime.datetime.utcnow() + d).strftime("%a, %d %b %Y %H:%M:%S GMT")
|
||||
|
||||
security.declareProtected("View", "get_etud_dept")
|
||||
|
||||
def get_etud_dept(self, REQUEST=None):
|
||||
"""Returns the dept id (eg "GEII") of an etud (identified by etudid, INE or NIP in REQUEST).
|
||||
Warning: This function is inefficient and its result should be cached.
|
||||
"""
|
||||
depts = self._list_depts()
|
||||
depts_etud = [] # liste des depts où l'etud est defini
|
||||
for dept in depts:
|
||||
etuds = dept.Scolarite.getEtudInfo(REQUEST=REQUEST)
|
||||
if etuds:
|
||||
depts_etud.append((dept, etuds))
|
||||
if not depts_etud:
|
||||
return "" # not found
|
||||
elif len(depts_etud) == 1:
|
||||
return depts_etud[0][0].id
|
||||
# inscriptions dans plusieurs departements: cherche la plus recente
|
||||
last_dept = None
|
||||
last_date = None
|
||||
for (dept, etuds) in depts_etud:
|
||||
sco_etud.fill_etuds_info(self, etuds)
|
||||
etud = etuds[0]
|
||||
if etud["sems"]:
|
||||
if (not last_date) or (etud["sems"][0]["date_fin_iso"] > last_date):
|
||||
last_date = etud["sems"][0]["date_fin_iso"]
|
||||
last_dept = dept
|
||||
if not last_dept:
|
||||
# est present dans plusieurs semestres mais inscrit dans aucun
|
||||
return depts_etud[0][0]
|
||||
return last_dept.id
|
||||
|
||||
security.declareProtected("View", "table_etud_in_accessible_depts")
|
||||
table_etud_in_accessible_depts = sco_find_etud.table_etud_in_accessible_depts
|
||||
|
||||
security.declareProtected("View", "search_inscr_etud_by_nip")
|
||||
search_inscr_etud_by_nip = sco_find_etud.search_inscr_etud_by_nip
|
||||
|
||||
|
||||
def manage_addZScoDoc(self, id="ScoDoc", title="Site ScoDoc", REQUEST=None):
|
||||
"Add a ZScoDoc instance to a folder."
|
||||
log("============== creating a new ScoDoc instance =============")
|
||||
zscodoc = ZScoDoc(
|
||||
id, title
|
||||
) # ne cree (presque rien), tout se passe lors du 1er accès
|
||||
self._setObject(id, zscodoc)
|
||||
if REQUEST is not None:
|
||||
REQUEST.RESPONSE.redirect("/ScoDoc/manage_workspace")
|
||||
return id
|
@ -27,7 +27,7 @@ for sem in sems:
|
||||
print sem['formsemestre_id'], sem['titre_num']
|
||||
|
||||
# Recupere la table de notes:
|
||||
nt = context.Notes._getNotesCache().get_NotesTable(context.Notes, formsemestre_id)
|
||||
nt = sco_core.get_notes_cache(context).get_NotesTable(context.Notes, formsemestre_id)
|
||||
|
||||
|
||||
"""
|
||||
|
@ -54,9 +54,10 @@ from reportlab.lib import styles
|
||||
from reportlab.lib.units import inch, cm, mm
|
||||
from reportlab.rl_config import defaultPageSize # pylint: disable=no-name-in-module
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
import app.scodoc.sco_excel
|
||||
import app.scodoc.sco_pdf
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import sco_utils as scu
|
||||
from app.scodoc import sco_excel
|
||||
from app.scodoc import sco_pdf
|
||||
from app.scodoc.sco_pdf import SU
|
||||
from app.scodoc.notes_log import log
|
||||
|
||||
|
@ -100,7 +100,7 @@ def retreive_dept():
|
||||
# Alarms by email:
|
||||
def sendAlarm(context, subj, txt):
|
||||
import sco_utils
|
||||
import mails
|
||||
import sco_emails
|
||||
import sco_preferences
|
||||
|
||||
msg = MIMEMultipart()
|
||||
@ -111,7 +111,7 @@ def sendAlarm(context, subj, txt):
|
||||
msg.epilogue = ""
|
||||
txt = MIMEText(txt, "plain", sco_utils.SCO_ENCODING)
|
||||
msg.attach(txt)
|
||||
mails.sendEmail(context, msg)
|
||||
sco_emails.sendEmail(context, msg)
|
||||
|
||||
|
||||
# Debug: log call stack
|
||||
|
@ -57,7 +57,8 @@ import pprint
|
||||
from app.scodoc.gen_tables import GenTable, SeqGenTable
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc import sco_codes_parcours # sco_codes_parcours.NEXT -> sem suivant
|
||||
|
||||
from app.scodoc import sco_core
|
||||
from app.scodoc import sco_etud
|
||||
from app.scodoc import pe_tagtable
|
||||
from app.scodoc import pe_tools
|
||||
from app.scodoc import pe_semestretag
|
||||
@ -331,7 +332,7 @@ class JuryPE:
|
||||
nt = self.get_cache_notes_d_un_semestre(
|
||||
self.context, sem["formsemestre_id"]
|
||||
)
|
||||
# context.Notes._getNotesCache().get_NotesTable(context.Notes, sem['formsemestre_id'])
|
||||
# sco_core.get_notes_cache(context).get_NotesTable(context.Notes, sem['formsemestre_id'])
|
||||
etudiantsDuSemestre = (
|
||||
nt.get_etudids()
|
||||
) # nt.identdict.keys() # identification des etudiants du semestre
|
||||
@ -1139,7 +1140,7 @@ class JuryPE:
|
||||
self, context, formsemestre_id
|
||||
): # inutile en realité !
|
||||
"""Charge la table des notes d'un formsemestre"""
|
||||
return context.Notes._getNotesCache().get_NotesTable(
|
||||
return sco_core.get_notes_cache(context).get_NotesTable(
|
||||
context.Notes, formsemestre_id
|
||||
)
|
||||
|
||||
|
@ -38,6 +38,7 @@ Created on Fri Sep 9 09:15:05 2016
|
||||
|
||||
from app.scodoc.notes_log import log
|
||||
from app.scodoc import sco_codes_parcours
|
||||
from app.scodoc import sco_core
|
||||
from app.scodoc import sco_tag_module
|
||||
from app.scodoc import pe_tagtable
|
||||
|
||||
@ -269,8 +270,8 @@ class SemestreTag(pe_tagtable.TableTag):
|
||||
# => le formsemestre_id du semestre dont vient la capitalisation
|
||||
fid_prec = fids_prec[0]
|
||||
# Lecture des notes de ce semestre
|
||||
nt_prec = self.context.Notes._getNotesCache().get_NotesTable(
|
||||
self.context.Notes, fid_prec
|
||||
nt_prec = sco_core.get_notes_cache(self.context).get_NotesTable(
|
||||
self.context, fid_prec
|
||||
) # le tableau de note du semestre considéré
|
||||
|
||||
# Y-a-t-il un module équivalent c'est à dire correspondant au même code (le module_id n'étant pas significatif en cas de changement de PPN)
|
||||
|
@ -41,9 +41,10 @@ from app.scodoc import notesdb as ndb
|
||||
from app.scodoc.scolog import logdb
|
||||
from app.scodoc.sco_exceptions import ScoValueError, ScoInvalidDateError
|
||||
from app.scodoc import sco_abs_notification
|
||||
from app.scodoc import sco_core
|
||||
from app.scodoc import sco_etud
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc import sco_etud
|
||||
|
||||
# --- Misc tools.... ------------------
|
||||
|
||||
@ -968,7 +969,7 @@ class CAbsSemEtud:
|
||||
self.etudid = etudid
|
||||
self._loaded = False
|
||||
formsemestre_id = sem["formsemestre_id"]
|
||||
context.Notes._getNotesCache().add_listener(
|
||||
sco_core.get_notes_cache(context).add_listener(
|
||||
self.invalidate, formsemestre_id, (etudid, formsemestre_id)
|
||||
)
|
||||
|
||||
@ -992,11 +993,11 @@ class CAbsSemEtud:
|
||||
debut_sem = ndb.DateDMYtoISO(self.sem["date_debut"])
|
||||
fin_sem = ndb.DateDMYtoISO(self.sem["date_fin"])
|
||||
|
||||
self._CountAbs = self.sco_abs.CountAbs(
|
||||
context, etudid=self.etudid, debut=debut_sem, fin=fin_sem
|
||||
self._CountAbs = CountAbs(
|
||||
self.context, etudid=self.etudid, debut=debut_sem, fin=fin_sem
|
||||
)
|
||||
self._CountAbsJust = self.sco_abs.CountAbsJust(
|
||||
context, etudid=self.etudid, debut=debut_sem, fin=fin_sem
|
||||
self._CountAbsJust = CountAbsJust(
|
||||
self.context, etudid=self.etudid, debut=debut_sem, fin=fin_sem
|
||||
)
|
||||
self._loaded = True
|
||||
|
||||
|
@ -37,7 +37,7 @@ from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from email.header import Header
|
||||
|
||||
from app.scodoc import mails
|
||||
from app.scodoc import sco_emails
|
||||
import app.scodoc.notesdb as ndb
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.notes_log import log
|
||||
@ -119,7 +119,7 @@ def abs_notify_send(
|
||||
for email in destinations:
|
||||
del msg["To"]
|
||||
msg["To"] = email
|
||||
mails.sendEmail(context, msg)
|
||||
sco_emails.sendEmail(context, msg)
|
||||
ndb.SimpleQuery(
|
||||
context,
|
||||
"""insert into absences_notifications (etudid, email, nbabs, nbabsjust, formsemestre_id) values (%(etudid)s, %(email)s, %(nbabs)s, %(nbabsjust)s, %(formsemestre_id)s)""",
|
||||
|
@ -39,6 +39,7 @@ from app.scodoc.scolog import logdb
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import sco_abs
|
||||
from app.scodoc import sco_core
|
||||
from app.scodoc import sco_etud
|
||||
from app.scodoc import sco_find_etud
|
||||
from app.scodoc import sco_formsemestre
|
||||
@ -124,7 +125,7 @@ def doSignaleAbsence(
|
||||
if moduleimpl_id and moduleimpl_id != "NULL":
|
||||
mod = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0]
|
||||
formsemestre_id = mod["formsemestre_id"]
|
||||
nt = context.Notes._getNotesCache().get_NotesTable(
|
||||
nt = sco_core.get_notes_cache(context).get_NotesTable(
|
||||
context.Notes, formsemestre_id
|
||||
)
|
||||
ues = nt.get_ues(etudid=etudid)
|
||||
@ -185,7 +186,7 @@ def SignaleAbsenceEtud(context, REQUEST=None): # etudid implied
|
||||
require_module = sco_preferences.get_preference(
|
||||
context, "abs_require_module", formsemestre_id
|
||||
)
|
||||
nt = context.Notes._getNotesCache().get_NotesTable(
|
||||
nt = sco_core.get_notes_cache(context).get_NotesTable(
|
||||
context.Notes, formsemestre_id
|
||||
)
|
||||
ues = nt.get_ues(etudid=etudid)
|
||||
|
@ -31,7 +31,7 @@
|
||||
"""
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc import ImportScolars
|
||||
from app.scodoc import sco_import_etuds
|
||||
from app.scodoc import sco_groups
|
||||
from app.scodoc import sco_trombino
|
||||
from app.scodoc import sco_excel
|
||||
@ -227,8 +227,8 @@ def etud_get_archived_file(context, REQUEST, etudid, archive_name, filename):
|
||||
# --- Upload d'un ensemble de fichiers (pour un groupe d'étudiants)
|
||||
def etudarchive_generate_excel_sample(context, group_id=None, REQUEST=None):
|
||||
"""Feuille excel pour import fichiers etudiants (utilisé pour admissions)"""
|
||||
fmt = ImportScolars.sco_import_format()
|
||||
data = ImportScolars.sco_import_generate_excel_sample(
|
||||
fmt = sco_import_etuds.sco_import_format()
|
||||
data = sco_import_etuds.sco_import_generate_excel_sample(
|
||||
fmt,
|
||||
context=context,
|
||||
group_ids=[group_id],
|
||||
|
@ -41,13 +41,14 @@ from email.header import Header
|
||||
|
||||
from reportlab.lib.colors import Color
|
||||
|
||||
from app.scodoc import mails
|
||||
from app.scodoc import sco_emails
|
||||
import app.scodoc.sco_utils as scu
|
||||
import app.scodoc.notesdb as ndb
|
||||
from app.scodoc.notes_log import log
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
from app.scodoc.sco_exceptions import AccessDenied
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import sco_abs
|
||||
from app.scodoc import sco_abs_views
|
||||
from app.scodoc import sco_bulletins_generator
|
||||
from app.scodoc import sco_bulletins_json
|
||||
@ -1048,7 +1049,7 @@ def mail_bulletin(context, formsemestre_id, I, pdfdata, filename, recipient_addr
|
||||
email.encoders.encode_base64(att)
|
||||
msg.attach(att)
|
||||
log("mail bulletin a %s" % msg["To"])
|
||||
mails.sendEmail(context, msg)
|
||||
sco_emails.sendEmail(context, msg)
|
||||
|
||||
|
||||
def _formsemestre_bulletinetud_header_html(
|
||||
|
@ -47,6 +47,7 @@ from app.scodoc import sco_abs
|
||||
from app.scodoc import sco_edit_module
|
||||
from app.scodoc import sco_evaluations
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_formsemestre_inscriptions
|
||||
from app.scodoc import sco_formulas
|
||||
from app.scodoc import sco_moduleimpl
|
||||
from app.scodoc import sco_etud
|
||||
@ -211,8 +212,8 @@ def do_moduleimpl_moyennes(context, nt, mod):
|
||||
inssem_set = set(
|
||||
[
|
||||
x["etudid"]
|
||||
for x in context.do_formsemestre_inscription_listinscrits(
|
||||
mod["formsemestre_id"]
|
||||
for x in sco_formsemestre_inscriptions.do_formsemestre_inscription_listinscrits(
|
||||
context, mod["formsemestre_id"]
|
||||
)
|
||||
]
|
||||
)
|
||||
|
@ -254,7 +254,7 @@ def formation_edit(context, formation_id=None, create=False, REQUEST=None):
|
||||
)
|
||||
#
|
||||
if create:
|
||||
formation_id = context.do_formation_create(tf[2], REQUEST)
|
||||
formation_id = do_formation_create(context, tf[2], REQUEST)
|
||||
else:
|
||||
do_formation_edit(context, tf[2])
|
||||
return REQUEST.RESPONSE.redirect("ue_list?formation_id=%s" % formation_id)
|
||||
|
@ -41,6 +41,7 @@ from email import Encoders # pylint: disable=no-name-in-module,import-error
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.notes_log import log
|
||||
from app.scodoc import VERSION
|
||||
|
||||
|
||||
def sendEmail(context, msg): # TODO A REECRIRE ScoDoc8
|
@ -389,7 +389,7 @@ apo_csv_store(context, csv_data, annee_scolaire, sem_id)
|
||||
|
||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(context, [sco_groups.get_default_group(context, formsemestre_id)], formsemestre_id=formsemestre_id, REQUEST=REQUEST)
|
||||
|
||||
nt = context.Notes._getNotesCache().get_NotesTable(context.Notes, formsemestre_id)
|
||||
nt = sco_core.get_notes_cache(context).get_NotesTable(context.Notes, formsemestre_id)
|
||||
|
||||
#
|
||||
s = SemSet(context, 'NSS29902')
|
||||
|
@ -37,7 +37,7 @@ from email.mime.text import MIMEText
|
||||
from email.header import Header
|
||||
from email.mime.base import MIMEBase
|
||||
|
||||
from app.scodoc import mails
|
||||
from app.scodoc import sco_emails
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.sco_utils import SCO_ENCODING
|
||||
import app.scodoc.notesdb as ndb
|
||||
@ -46,7 +46,6 @@ from app.scodoc.sco_exceptions import ScoGenError, ScoValueError
|
||||
from app.scodoc.notes_log import log
|
||||
from app.scodoc.TrivialFormulator import TrivialFormulator
|
||||
from app.scodoc import safehtml
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc.scolog import logdb
|
||||
|
||||
@ -450,7 +449,7 @@ def notify_etud_change(context, email_addr, etud, before, after, subject):
|
||||
msg["To"] = email_addr
|
||||
mime_txt = MIMEText(txt, "plain", SCO_ENCODING)
|
||||
msg.attach(mime_txt)
|
||||
mails.sendEmail(context, msg)
|
||||
sco_emails.sendEmail(context, msg)
|
||||
return txt
|
||||
|
||||
|
||||
@ -901,6 +900,7 @@ def fill_etuds_info(etuds):
|
||||
Pour chaque etudiant, ajoute ou formatte les champs
|
||||
-> informations pour fiche etudiant ou listes diverses
|
||||
"""
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_formsemestre_inscriptions
|
||||
|
||||
context = None # XXX en attendant la suppression du context ScoDoc7
|
||||
@ -1004,6 +1004,8 @@ def fill_etuds_info(etuds):
|
||||
|
||||
def descr_situation_etud(context, etudid, ne=""):
|
||||
"""chaine decrivant la situation actuelle de l'etudiant"""
|
||||
from app.scodoc import sco_formsemestre
|
||||
|
||||
cnx = ndb.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||
cursor.execute(
|
||||
|
@ -45,6 +45,7 @@ from app.scodoc import sco_core
|
||||
from app.scodoc import sco_edit_module
|
||||
from app.scodoc import sco_edit_ue
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_formsemestre_inscriptions
|
||||
from app.scodoc import sco_groups
|
||||
from app.scodoc import sco_moduleimpl
|
||||
from app.scodoc import sco_news
|
||||
@ -180,6 +181,146 @@ def do_evaluation_list_in_formsemestre(context, formsemestre_id):
|
||||
return evals
|
||||
|
||||
|
||||
def _check_evaluation_args(context, args):
|
||||
"Check coefficient, dates and duration, raises exception if invalid"
|
||||
moduleimpl_id = args["moduleimpl_id"]
|
||||
# check bareme
|
||||
note_max = args.get("note_max", None)
|
||||
if note_max is None:
|
||||
raise ScoValueError("missing note_max")
|
||||
try:
|
||||
note_max = float(note_max)
|
||||
except ValueError:
|
||||
raise ScoValueError("Invalid note_max value")
|
||||
if note_max < 0:
|
||||
raise ScoValueError("Invalid note_max value (must be positive or null)")
|
||||
# check coefficient
|
||||
coef = args.get("coefficient", None)
|
||||
if coef is None:
|
||||
raise ScoValueError("missing coefficient")
|
||||
try:
|
||||
coef = float(coef)
|
||||
except ValueError:
|
||||
raise ScoValueError("Invalid coefficient value")
|
||||
if coef < 0:
|
||||
raise ScoValueError("Invalid coefficient value (must be positive or null)")
|
||||
# check date
|
||||
jour = args.get("jour", None)
|
||||
args["jour"] = jour
|
||||
if jour:
|
||||
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0]
|
||||
sem = sco_formsemestre.get_formsemestre(context, M["formsemestre_id"])
|
||||
d, m, y = [int(x) for x in sem["date_debut"].split("/")]
|
||||
date_debut = datetime.date(y, m, d)
|
||||
d, m, y = [int(x) for x in sem["date_fin"].split("/")]
|
||||
date_fin = datetime.date(y, m, d)
|
||||
# passe par ndb.DateDMYtoISO pour avoir date pivot
|
||||
y, m, d = [int(x) for x in ndb.DateDMYtoISO(jour).split("-")]
|
||||
jour = datetime.date(y, m, d)
|
||||
if (jour > date_fin) or (jour < date_debut):
|
||||
raise ScoValueError(
|
||||
"La date de l'évaluation (%s/%s/%s) n'est pas dans le semestre !"
|
||||
% (d, m, y)
|
||||
)
|
||||
heure_debut = args.get("heure_debut", None)
|
||||
args["heure_debut"] = heure_debut
|
||||
heure_fin = args.get("heure_fin", None)
|
||||
args["heure_fin"] = heure_fin
|
||||
if jour and ((not heure_debut) or (not heure_fin)):
|
||||
raise ScoValueError("Les heures doivent être précisées")
|
||||
d = ndb.TimeDuration(heure_debut, heure_fin)
|
||||
if d and ((d < 0) or (d > 60 * 12)):
|
||||
raise ScoValueError("Heures de l'évaluation incohérentes !")
|
||||
|
||||
|
||||
def do_evaluation_create(
|
||||
context,
|
||||
moduleimpl_id=None,
|
||||
jour=None,
|
||||
heure_debut=None,
|
||||
heure_fin=None,
|
||||
description=None,
|
||||
note_max=None,
|
||||
coefficient=None,
|
||||
visibulletin=None,
|
||||
publish_incomplete=None,
|
||||
evaluation_type=None,
|
||||
numero=None,
|
||||
REQUEST=None,
|
||||
):
|
||||
"""Create an evaluation"""
|
||||
if not sco_permissions_check.can_edit_evaluation(
|
||||
context, REQUEST, moduleimpl_id=moduleimpl_id
|
||||
):
|
||||
raise AccessDenied(
|
||||
"Modification évaluation impossible pour %s"
|
||||
% scu.get_current_user_name(REQUEST)
|
||||
)
|
||||
args = locals()
|
||||
log("do_evaluation_create: args=" + str(args))
|
||||
_check_evaluation_args(context, args)
|
||||
# Check numeros
|
||||
module_evaluation_renumber(
|
||||
context, moduleimpl_id, REQUEST=REQUEST, only_if_unumbered=True
|
||||
)
|
||||
if not "numero" in args or args["numero"] is None:
|
||||
n = None
|
||||
# determine le numero avec la date
|
||||
# Liste des eval existantes triees par date, la plus ancienne en tete
|
||||
ModEvals = do_evaluation_list(
|
||||
context,
|
||||
args={"moduleimpl_id": moduleimpl_id},
|
||||
sortkey="jour asc, heure_debut asc",
|
||||
)
|
||||
if args["jour"]:
|
||||
next_eval = None
|
||||
t = (
|
||||
ndb.DateDMYtoISO(args["jour"]),
|
||||
ndb.TimetoISO8601(args["heure_debut"]),
|
||||
)
|
||||
for e in ModEvals:
|
||||
if (
|
||||
ndb.DateDMYtoISO(e["jour"]),
|
||||
ndb.TimetoISO8601(e["heure_debut"]),
|
||||
) > t:
|
||||
next_eval = e
|
||||
break
|
||||
if next_eval:
|
||||
n = module_evaluation_insert_before(
|
||||
context, ModEvals, next_eval, REQUEST
|
||||
)
|
||||
else:
|
||||
n = None # a placer en fin
|
||||
if n is None: # pas de date ou en fin:
|
||||
if ModEvals:
|
||||
log(pprint.pformat(ModEvals[-1]))
|
||||
n = ModEvals[-1]["numero"] + 1
|
||||
else:
|
||||
n = 0 # the only one
|
||||
# log("creating with numero n=%d" % n)
|
||||
args["numero"] = n
|
||||
|
||||
#
|
||||
cnx = ndb.GetDBConnexion()
|
||||
r = _evaluationEditor.create(cnx, args)
|
||||
|
||||
# news
|
||||
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_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(
|
||||
context,
|
||||
REQUEST,
|
||||
typ=sco_news.NEWS_NOTE,
|
||||
object=moduleimpl_id,
|
||||
text='Création d\'une évaluation dans <a href="%(url)s">%(titre)s</a>' % mod,
|
||||
url=mod["url"],
|
||||
)
|
||||
|
||||
return r
|
||||
|
||||
|
||||
def do_evaluation_edit(context, REQUEST, args):
|
||||
"edit an evaluation"
|
||||
evaluation_id = args["evaluation_id"]
|
||||
@ -187,9 +328,16 @@ def do_evaluation_edit(context, REQUEST, args):
|
||||
if not the_evals:
|
||||
raise ValueError("evaluation inexistante !")
|
||||
moduleimpl_id = the_evals[0]["moduleimpl_id"]
|
||||
if not sco_permissions_check.can_edit_evaluation(
|
||||
context, REQUEST, moduleimpl_id=moduleimpl_id
|
||||
):
|
||||
raise AccessDenied(
|
||||
"Modification évaluation impossible pour %s"
|
||||
% scu.get_current_user_name(REQUEST)
|
||||
)
|
||||
args["moduleimpl_id"] = moduleimpl_id
|
||||
context._check_evaluation_args(args)
|
||||
context._evaluation_check_write_access(REQUEST, moduleimpl_id=moduleimpl_id)
|
||||
_check_evaluation_args(context, args)
|
||||
|
||||
cnx = ndb.GetDBConnexion()
|
||||
context._evaluationEditor.edit(cnx, args)
|
||||
# inval cache pour ce semestre
|
||||
@ -204,7 +352,14 @@ def do_evaluation_delete(context, REQUEST, evaluation_id):
|
||||
the_evals = do_evaluation_list(context, {"evaluation_id": evaluation_id})
|
||||
if not the_evals:
|
||||
raise ValueError("evaluation inexistante !")
|
||||
|
||||
moduleimpl_id = the_evals[0]["moduleimpl_id"]
|
||||
if not sco_permissions_check.can_edit_evaluation(
|
||||
context, REQUEST, moduleimpl_id=moduleimpl_id
|
||||
):
|
||||
raise AccessDenied(
|
||||
"Modification évaluation impossible pour %s"
|
||||
% scu.get_current_user_name(REQUEST)
|
||||
)
|
||||
NotesDB = do_evaluation_get_all_notes(context, evaluation_id) # { etudid : value }
|
||||
notes = [x["value"] for x in NotesDB.values()]
|
||||
if notes:
|
||||
@ -212,8 +367,6 @@ def do_evaluation_delete(context, REQUEST, evaluation_id):
|
||||
"Impossible de supprimer cette évaluation: il reste des notes"
|
||||
)
|
||||
|
||||
moduleimpl_id = the_evals[0]["moduleimpl_id"]
|
||||
context._evaluation_check_write_access(REQUEST, moduleimpl_id=moduleimpl_id)
|
||||
cnx = ndb.GetDBConnexion()
|
||||
|
||||
context._evaluationEditor.delete(cnx, evaluation_id)
|
||||
@ -295,7 +448,9 @@ def do_evaluation_etat(
|
||||
# Il faut considerer les inscriptions au semestre
|
||||
# (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)
|
||||
insem = sco_formsemestre_inscriptions.do_formsemestre_inscription_listinscrits(
|
||||
context, formsemestre_id
|
||||
)
|
||||
insmod = sco_moduleimpl.do_moduleimpl_inscription_list(
|
||||
context, moduleimpl_id=E["moduleimpl_id"]
|
||||
)
|
||||
@ -676,7 +831,7 @@ def evaluation_date_first_completion(context, evaluation_id):
|
||||
# E = do_evaluation_list(context, args={"evaluation_id": evaluation_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)
|
||||
# insem = sco_formsemestre_inscriptions.do_formsemestre_inscription_listinscrits(context, formsemestre_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
|
||||
@ -814,9 +969,14 @@ def module_evaluation_move(context, evaluation_id, after=0, REQUEST=None, redire
|
||||
"""
|
||||
e = do_evaluation_list(context, args={"evaluation_id": evaluation_id})[0]
|
||||
redirect = int(redirect)
|
||||
|
||||
# access: can change eval ? (raises exception)
|
||||
context._evaluation_check_write_access(REQUEST, moduleimpl_id=e["moduleimpl_id"])
|
||||
# access: can change eval ?
|
||||
if not sco_permissions_check.can_edit_evaluation(
|
||||
context, REQUEST, moduleimpl_id=e["moduleimpl_id"]
|
||||
):
|
||||
raise AccessDenied(
|
||||
"Modification évaluation impossible pour %s"
|
||||
% scu.get_current_user_name(REQUEST)
|
||||
)
|
||||
|
||||
module_evaluation_renumber(
|
||||
context, e["moduleimpl_id"], REQUEST=REQUEST, only_if_unumbered=True
|
||||
@ -977,13 +1137,14 @@ def evaluation_create_form(
|
||||
formsemestre_id = M["formsemestre_id"]
|
||||
min_note_max = scu.NOTES_PRECISION # le plus petit bareme possible
|
||||
if not readonly:
|
||||
try:
|
||||
context._evaluation_check_write_access(REQUEST, moduleimpl_id=moduleimpl_id)
|
||||
except AccessDenied as e:
|
||||
if not sco_permissions_check.can_edit_evaluation(
|
||||
context, REQUEST, moduleimpl_id=moduleimpl_id
|
||||
):
|
||||
return (
|
||||
html_sco_header.sco_header(context, REQUEST)
|
||||
+ "<h2>Opération non autorisée</h2><p>"
|
||||
+ str(e)
|
||||
+ "Modification évaluation impossible pour %s"
|
||||
% scu.get_current_user_name(REQUEST)
|
||||
+ "</p>"
|
||||
+ '<p><a href="%s">Revenir</a></p>' % (str(REQUEST.HTTP_REFERER),)
|
||||
+ html_sco_header.sco_footer(context, REQUEST)
|
||||
@ -1227,7 +1388,7 @@ def evaluation_create_form(
|
||||
tf[2]["visibulletin"] = 0
|
||||
if not edit:
|
||||
# creation d'une evaluation
|
||||
evaluation_id = context.do_evaluation_create(REQUEST=REQUEST, **tf[2])
|
||||
evaluation_id = do_evaluation_create(context, REQUEST=REQUEST, **tf[2])
|
||||
return REQUEST.RESPONSE.redirect(dest_url)
|
||||
else:
|
||||
do_evaluation_edit(context, REQUEST, tf[2])
|
||||
|
@ -38,6 +38,7 @@ from app.scodoc import notesdb
|
||||
from app.scodoc.notes_log import log
|
||||
from app.scodoc.scolog import logdb
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
from app.scodoc import sco_preferences
|
||||
|
||||
|
||||
# colors, voir exemple format.py
|
||||
|
@ -28,6 +28,7 @@
|
||||
"""Recherche d'étudiants
|
||||
"""
|
||||
|
||||
from scodoc_manager import sco_mgr
|
||||
import app.scodoc.sco_utils as scu
|
||||
import app.scodoc.notesdb as ndb
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
@ -266,12 +267,6 @@ def form_search_etud_in_accessible_depts(context, REQUEST):
|
||||
"""
|
||||
|
||||
|
||||
def can_view_dept(context, REQUEST):
|
||||
"""True if auth user can access (View) this context"""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
return authuser.has_permission(Permission.ScoView)
|
||||
|
||||
|
||||
def search_etud_in_accessible_depts(context, expnom=None, code_nip=None, REQUEST=None):
|
||||
"""
|
||||
context est le ZScoDoc
|
||||
@ -279,10 +274,10 @@ def search_etud_in_accessible_depts(context, expnom=None, code_nip=None, REQUEST
|
||||
"""
|
||||
result = []
|
||||
accessible_depts = []
|
||||
deptList = context._list_depts() # definis dans Zope
|
||||
for dept in deptList:
|
||||
dept_list = sco_mgr.get_dept_ids()
|
||||
for dept in dept_list:
|
||||
# log('%s searching %s' % (str(REQUEST.AUTHENTICATED_USER),dept))
|
||||
if can_view_dept(dept, REQUEST):
|
||||
if REQUEST.AUTHENTICATED_USER.has_permission(Permission.ScoView, dept=dept):
|
||||
if expnom or code_nip:
|
||||
accessible_depts.append(dept.Scolarite.DeptId())
|
||||
etuds = search_etuds_infos(
|
||||
|
@ -35,16 +35,17 @@ import app.scodoc.sco_utils as scu
|
||||
import app.scodoc.notesdb as ndb
|
||||
from app.scodoc.notes_log import log
|
||||
from app.scodoc import sco_codes_parcours
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_tag_module
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
from app.scodoc import VERSION
|
||||
from app.scodoc import sco_edit_matiere
|
||||
from app.scodoc import sco_edit_module
|
||||
from app.scodoc import sco_edit_ue
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_news
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc import sco_tag_module
|
||||
from app.scodoc import VERSION
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
|
||||
_formationEditor = ndb.EditableTable(
|
||||
"notes_formations",
|
||||
@ -164,6 +165,8 @@ def formation_import_xml(
|
||||
"""Create a formation from XML representation
|
||||
(format dumped by formation_export( format='xml' ))
|
||||
"""
|
||||
from app.scodoc import sco_edit_formation
|
||||
|
||||
log("formation_import_xml: doc=%s" % doc)
|
||||
try:
|
||||
dom = xml.dom.minidom.parseString(doc)
|
||||
@ -199,7 +202,7 @@ def formation_import_xml(
|
||||
# create formation
|
||||
# F_unquoted = F.copy()
|
||||
# unescape_html_dict(F_unquoted)
|
||||
formation_id = context.do_formation_create(F, REQUEST)
|
||||
formation_id = sco_edit_formation.do_formation_create(context, F, REQUEST)
|
||||
log("formation %s created" % formation_id)
|
||||
ues_old2new = {} # xml ue_id : new ue_id
|
||||
modules_old2new = {} # xml module_id : new module_id
|
||||
@ -362,3 +365,24 @@ def formation_list_table(context, formation_id=None, args={}, REQUEST=None):
|
||||
context,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def formation_create_new_version(context, formation_id, redirect=True, REQUEST=None):
|
||||
"duplicate formation, with new version number"
|
||||
xml = formation_export(context, formation_id, export_ids=True, format="xml")
|
||||
new_id, modules_old2new, ues_old2new = formation_import_xml(context, REQUEST, xml)
|
||||
# news
|
||||
F = formation_list(context, args={"formation_id": new_id})[0]
|
||||
sco_news.add(
|
||||
context,
|
||||
REQUEST,
|
||||
typ=sco_news.NEWS_FORM,
|
||||
object=new_id,
|
||||
text="Nouvelle version de la formation %(acronyme)s" % F,
|
||||
)
|
||||
if redirect:
|
||||
return REQUEST.RESPONSE.redirect(
|
||||
"ue_list?formation_id=" + new_id + "&msg=Nouvelle version !"
|
||||
)
|
||||
else:
|
||||
return new_id, modules_old2new, ues_old2new
|
@ -29,16 +29,16 @@
|
||||
"""
|
||||
import time
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
import app.scodoc.notesdb as ndb
|
||||
from app.scodoc.notes_log import log
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
|
||||
from scodoc_manager import sco_mgr
|
||||
from app.scodoc import sco_codes_parcours
|
||||
from app.scodoc.sco_codes_parcours import NO_SEMESTRE_ID
|
||||
from app.scodoc import sco_core
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
from app.scodoc.notes_log import log
|
||||
from app.scodoc.sco_codes_parcours import NO_SEMESTRE_ID
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
import app.scodoc.notesdb as ndb
|
||||
import app.scodoc.sco_utils as scu
|
||||
|
||||
_formsemestreEditor = ndb.EditableTable(
|
||||
"notes_formsemestre",
|
||||
@ -219,6 +219,41 @@ def etapes_apo_str(etapes):
|
||||
return ", ".join([str(x) for x in etapes])
|
||||
|
||||
|
||||
def do_formsemestre_create(context, args, REQUEST, silent=False):
|
||||
"create a formsemestre"
|
||||
cnx = ndb.GetDBConnexion()
|
||||
formsemestre_id = _formsemestreEditor.create(cnx, args)
|
||||
if args["etapes"]:
|
||||
args["formsemestre_id"] = formsemestre_id
|
||||
write_formsemestre_etapes(context, args)
|
||||
if args["responsables"]:
|
||||
args["formsemestre_id"] = formsemestre_id
|
||||
write_formsemestre_responsables(context, args)
|
||||
|
||||
# create default partition
|
||||
partition_id = sco_groups.partition_create(
|
||||
context, formsemestre_id, default=True, redirect=0, REQUEST=REQUEST
|
||||
)
|
||||
_group_id = sco_groups.createGroup(
|
||||
context, partition_id, default=True, REQUEST=REQUEST
|
||||
)
|
||||
|
||||
# news
|
||||
if not args.has_key("titre"):
|
||||
args["titre"] = "sans titre"
|
||||
args["formsemestre_id"] = formsemestre_id
|
||||
args["url"] = "Notes/formsemestre_status?formsemestre_id=%(formsemestre_id)s" % args
|
||||
if not silent:
|
||||
sco_news.add(
|
||||
context,
|
||||
REQUEST,
|
||||
typ=sco_news.NEWS_SEM,
|
||||
text='Création du semestre <a href="%(url)s">%(titre)s</a>' % args,
|
||||
url=args["url"],
|
||||
)
|
||||
return formsemestre_id
|
||||
|
||||
|
||||
def do_formsemestre_edit(context, sem, cnx=None, **kw):
|
||||
"""Apply modifications to formsemestre.
|
||||
Update etapes and resps. Invalidate cache."""
|
||||
@ -500,7 +535,7 @@ def sem_est_courant(context, sem):
|
||||
|
||||
def scodoc_get_all_unlocked_sems(context):
|
||||
"""Liste de tous les semestres non verrouillés de tous les départements"""
|
||||
depts = context._list_depts()
|
||||
depts = sco_mgr.get_dept_ids()
|
||||
semdepts = []
|
||||
for dept in depts:
|
||||
semdepts += [
|
||||
|
@ -715,7 +715,9 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
|
||||
)
|
||||
if not edit:
|
||||
# creation du semestre
|
||||
formsemestre_id = context.do_formsemestre_create(tf[2], REQUEST)
|
||||
formsemestre_id = sco_formsemestre.do_formsemestre_create(
|
||||
context, tf[2], REQUEST
|
||||
)
|
||||
# creation des modules
|
||||
for module_id in tf[2]["tf-checked"]:
|
||||
modargs = {
|
||||
@ -1014,7 +1016,7 @@ def do_formsemestre_clone(
|
||||
args["date_debut"] = date_debut
|
||||
args["date_fin"] = date_fin
|
||||
args["etat"] = 1 # non verrouillé
|
||||
formsemestre_id = context.do_formsemestre_create(args, REQUEST)
|
||||
formsemestre_id = sco_formsemestre.do_formsemestre_create(context, args, REQUEST)
|
||||
log("created formsemestre %s" % formsemestre_id)
|
||||
# 2- create moduleimpls
|
||||
mods_orig = sco_moduleimpl.do_moduleimpl_list(
|
||||
@ -1041,7 +1043,7 @@ def do_formsemestre_clone(
|
||||
args = e.copy()
|
||||
del args["jour"] # erase date
|
||||
args["moduleimpl_id"] = mid
|
||||
_ = context.do_evaluation_create(REQUEST=REQUEST, **args)
|
||||
_ = sco_evaluations.do_evaluation_create(context, REQUEST=REQUEST, **args)
|
||||
|
||||
# 3- copy uecoefs
|
||||
objs = sco_formsemestre.formsemestre_uecoef_list(
|
||||
@ -1196,14 +1198,18 @@ def do_formsemestres_associate_new_version(context, formsemestre_ids, REQUEST=No
|
||||
|
||||
cnx = ndb.GetDBConnexion()
|
||||
# New formation:
|
||||
formation_id, modules_old2new, ues_old2new = context.formation_create_new_version(
|
||||
formation_id, redirect=False, REQUEST=REQUEST
|
||||
(
|
||||
formation_id,
|
||||
modules_old2new,
|
||||
ues_old2new,
|
||||
) = sco_formations.formation_create_new_version(
|
||||
context, formation_id, redirect=False, REQUEST=REQUEST
|
||||
)
|
||||
|
||||
for formsemestre_id in formsemestre_ids:
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
sem["formation_id"] = formation_id
|
||||
context.do_formsemestre_edit(sem, cnx=cnx, html_quote=False)
|
||||
sco_formsemestre.do_formsemestre_edit(context, sem, cnx=cnx, html_quote=False)
|
||||
_reassociate_moduleimpls(
|
||||
context, cnx, formsemestre_id, ues_old2new, modules_old2new
|
||||
)
|
||||
@ -1339,7 +1345,7 @@ def do_formsemestre_delete(context, formsemestre_id, REQUEST):
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
|
||||
# --- Destruction des modules de ce semestre
|
||||
mods = context.do_moduleimpl_list(formsemestre_id=formsemestre_id)
|
||||
mods = sco_moduleimpl.do_moduleimpl_list(formsemestre_id=formsemestre_id)
|
||||
for mod in mods:
|
||||
# evaluations
|
||||
evals = sco_evaluations.do_evaluation_list(
|
||||
@ -1474,7 +1480,7 @@ def formsemestre_change_lock(
|
||||
if etat not in (0, 1):
|
||||
raise ScoValueError("formsemestre_lock: invalid value for etat (%s)" % etat)
|
||||
args = {"formsemestre_id": formsemestre_id, "etat": etat}
|
||||
context.do_formsemestre_edit(args)
|
||||
sco_formsemestre.do_formsemestre_edit(context, args)
|
||||
if REQUEST:
|
||||
return REQUEST.RESPONSE.redirect(
|
||||
"formsemestre_status?formsemestre_id=%s" % formsemestre_id
|
||||
@ -1517,7 +1523,7 @@ def formsemestre_change_publication_bul(
|
||||
"formsemestre_change_publication_bul: invalid value for etat (%s)" % etat
|
||||
)
|
||||
args = {"formsemestre_id": formsemestre_id, "bul_hide_xml": etat}
|
||||
context.do_formsemestre_edit(args)
|
||||
sco_formsemestre.do_formsemestre_edit(context, args)
|
||||
if REQUEST:
|
||||
return REQUEST.RESPONSE.redirect(
|
||||
"formsemestre_status?formsemestre_id=%s" % formsemestre_id
|
||||
|
@ -63,7 +63,9 @@ def formsemestre_ext_create(context, etudid, sem_params, REQUEST=None):
|
||||
sem_params["modalite"] = "EXT"
|
||||
sem_params["etapes"] = None
|
||||
sem_params["responsables"] = [str(REQUEST.AUTHENTICATED_USER)]
|
||||
formsemestre_id = context.do_formsemestre_create(sem_params, REQUEST, silent=True)
|
||||
formsemestre_id = sco_formsemestre.do_formsemestre_create(
|
||||
context, sem_params, REQUEST, silent=True
|
||||
)
|
||||
# nota: le semestre est créé vide: pas de modules
|
||||
|
||||
# Inscription au semestre
|
||||
|
@ -43,7 +43,6 @@ from app.scodoc import sco_moduleimpl
|
||||
from app.scodoc import sco_groups
|
||||
from app.scodoc import sco_etud
|
||||
from app.scodoc import sco_core
|
||||
from app.scodoc import sco_formsemestre_edit
|
||||
from app.scodoc import html_sco_header
|
||||
|
||||
|
||||
@ -62,6 +61,19 @@ def do_formsemestre_inscription_list(context, *args, **kw):
|
||||
return _formsemestre_inscriptionEditor.list(cnx, *args, **kw)
|
||||
|
||||
|
||||
def do_formsemestre_inscription_listinscrits(context, formsemestre_id):
|
||||
"""Liste les inscrits (état I) à ce semestre et cache le résultat"""
|
||||
cache = sco_core.get_formsemestre_inscription_cache(context)
|
||||
r = cache.get(formsemestre_id)
|
||||
if r is None:
|
||||
# retreive list
|
||||
r = do_formsemestre_inscription_list(
|
||||
context, args={"formsemestre_id": formsemestre_id, "etat": "I"}
|
||||
)
|
||||
cache.set(formsemestre_id, r)
|
||||
return r
|
||||
|
||||
|
||||
def do_formsemestre_inscription_create(context, args, REQUEST, method=None):
|
||||
"create a formsemestre_inscription (and sco event)"
|
||||
cnx = ndb.GetDBConnexion()
|
||||
@ -126,6 +138,8 @@ def do_formsemestre_desinscription(context, etudid, formsemestre_id, REQUEST=Non
|
||||
"""Désinscription d'un étudiant.
|
||||
Si semestre extérieur et dernier inscrit, suppression de ce semestre.
|
||||
"""
|
||||
from app.scodoc import sco_formsemestre_edit
|
||||
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
# -- check lock
|
||||
if sem["etat"] != "1":
|
||||
|
@ -346,7 +346,9 @@ def formsemestre_status_menubar(context, sem, REQUEST):
|
||||
"title": "Créer/modifier les partitions...",
|
||||
"endpoint": "scolar.editPartitionForm",
|
||||
"args": {"formsemestre_id": formsemestre_id},
|
||||
"enabled": sco_groups.can_change_groups(context, REQUEST, formsemestre_id),
|
||||
"enabled": sco_groups.sco_permissions_check.can_change_groups(
|
||||
context, REQUEST, formsemestre_id
|
||||
),
|
||||
},
|
||||
]
|
||||
# 1 item / partition:
|
||||
@ -355,7 +357,10 @@ def formsemestre_status_menubar(context, sem, REQUEST):
|
||||
)
|
||||
submenu = []
|
||||
enabled = (
|
||||
sco_groups.can_change_groups(context, REQUEST, formsemestre_id) and partitions
|
||||
sco_groups.sco_permissions_check.can_change_groups(
|
||||
context, REQUEST, formsemestre_id
|
||||
)
|
||||
and partitions
|
||||
)
|
||||
for partition in partitions:
|
||||
submenu.append(
|
||||
@ -873,13 +878,17 @@ def _make_listes_sem(context, sem, REQUEST=None, with_absences=True):
|
||||
H.append("</table>")
|
||||
else:
|
||||
H.append('<p class="help indent">Aucun groupe dans cette partition')
|
||||
if sco_groups.can_change_groups(context, REQUEST, formsemestre_id):
|
||||
if sco_groups.sco_permissions_check.can_change_groups(
|
||||
context, REQUEST, formsemestre_id
|
||||
):
|
||||
H.append(
|
||||
' (<a href="affectGroups?partition_id=%s" class="stdlink">créer</a>)'
|
||||
% partition["partition_id"]
|
||||
)
|
||||
H.append("</p>")
|
||||
if sco_groups.can_change_groups(context, REQUEST, formsemestre_id):
|
||||
if sco_groups.sco_permissions_check.can_change_groups(
|
||||
context, REQUEST, formsemestre_id
|
||||
):
|
||||
H.append(
|
||||
'<h4><a href="editPartitionForm?formsemestre_id=%s">Ajouter une partition</a></h4>'
|
||||
% formsemestre_id
|
||||
|
@ -51,26 +51,12 @@ from app.scodoc import html_sco_header
|
||||
from app.scodoc import sco_codes_parcours
|
||||
from app.scodoc import sco_core
|
||||
from app.scodoc import sco_etud
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_permissions_check
|
||||
from app.scodoc.sco_exceptions import ScoException, AccessDenied, ScoValueError
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
from app.scodoc.TrivialFormulator import TrivialFormulator
|
||||
|
||||
|
||||
def can_change_groups(context, REQUEST, formsemestre_id):
|
||||
"Vrai si l'utilisateur peut changer les groupes dans ce semestre"
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
if sem["etat"] != "1":
|
||||
return False # semestre verrouillé
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
if authuser.has_permission(Permission.ScoEtudChangeGroups):
|
||||
return True # admin, chef dept
|
||||
uid = str(authuser)
|
||||
if uid in sem["responsables"]:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def checkGroupName(
|
||||
groupName,
|
||||
): # XXX unused: now allow any string as a group or partition name
|
||||
@ -275,6 +261,8 @@ def get_group_members(context, group_id, etat=None):
|
||||
|
||||
def get_group_infos(context, group_id, etat=None): # was _getlisteetud
|
||||
"""legacy code: used by group_list and trombino"""
|
||||
from app.scodoc import sco_formsemestre
|
||||
|
||||
cnx = ndb.GetDBConnexion()
|
||||
group = get_group(context, group_id)
|
||||
sem = sco_formsemestre.get_formsemestre(context, group["formsemestre_id"])
|
||||
@ -446,12 +434,14 @@ def XMLgetGroupsInPartition(context, partition_id, REQUEST=None): # was XMLgetG
|
||||
<etud etuid="" sexe="" nom="" prenom="" origin=""/>
|
||||
</groupe>
|
||||
"""
|
||||
from app.scodoc import sco_formsemestre
|
||||
|
||||
t0 = time.time()
|
||||
partition = get_partition(context, partition_id)
|
||||
formsemestre_id = partition["formsemestre_id"]
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
groups = get_partition_groups(context, partition)
|
||||
nt = context.Notes._getNotesCache().get_NotesTable(
|
||||
nt = sco_core.get_notes_cache(context).get_NotesTable(
|
||||
context.Notes, formsemestre_id
|
||||
) # > inscrdict
|
||||
etuds_set = set(nt.inscrdict)
|
||||
@ -621,9 +611,11 @@ def setGroups(
|
||||
groupsToCreate: lignes "group_name;etudid;...\n"
|
||||
groupsToDelete: group_id;group_id;...
|
||||
"""
|
||||
from app.scodoc import sco_formsemestre
|
||||
|
||||
partition = get_partition(context, partition_id)
|
||||
formsemestre_id = partition["formsemestre_id"]
|
||||
if not can_change_groups(context, REQUEST, formsemestre_id):
|
||||
if not sco_permissions_check.can_change_groups(context, REQUEST, formsemestre_id):
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
log("***setGroups: partition_id=%s" % partition_id)
|
||||
log("groupsLists=%s" % groupsLists)
|
||||
@ -710,7 +702,9 @@ def createGroup(context, partition_id, group_name="", default=False, REQUEST=Non
|
||||
"""
|
||||
partition = get_partition(context, partition_id)
|
||||
formsemestre_id = partition["formsemestre_id"]
|
||||
if REQUEST and not can_change_groups(context, REQUEST, formsemestre_id):
|
||||
if REQUEST and not sco_permissions_check.can_change_groups(
|
||||
context, REQUEST, formsemestre_id
|
||||
):
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
#
|
||||
if group_name:
|
||||
@ -747,7 +741,9 @@ def suppressGroup(context, group_id, partition_id=None, REQUEST=None):
|
||||
else:
|
||||
partition_id = group["partition_id"]
|
||||
partition = get_partition(context, partition_id)
|
||||
if not can_change_groups(context, REQUEST, partition["formsemestre_id"]):
|
||||
if not sco_permissions_check.can_change_groups(
|
||||
context, REQUEST, partition["formsemestre_id"]
|
||||
):
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
log(
|
||||
"suppressGroup: group_id=%s group_name=%s partition_name=%s"
|
||||
@ -766,7 +762,9 @@ def partition_create(
|
||||
redirect=1,
|
||||
):
|
||||
"""Create a new partition"""
|
||||
if REQUEST and not can_change_groups(context, REQUEST, formsemestre_id):
|
||||
if REQUEST and not sco_permissions_check.can_change_groups(
|
||||
context, REQUEST, formsemestre_id
|
||||
):
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
if partition_name:
|
||||
partition_name = partition_name.strip()
|
||||
@ -810,7 +808,7 @@ def getArrowIconsTags(context, REQUEST):
|
||||
def editPartitionForm(context, formsemestre_id=None, REQUEST=None):
|
||||
"""Form to create/suppress partitions"""
|
||||
# ad-hoc form
|
||||
if not can_change_groups(context, REQUEST, formsemestre_id):
|
||||
if not sco_permissions_check.can_change_groups(context, REQUEST, formsemestre_id):
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
partitions = get_partitions_list(context, formsemestre_id)
|
||||
arrow_up, arrow_down, arrow_none = getArrowIconsTags(context, REQUEST)
|
||||
@ -940,7 +938,7 @@ def partition_set_attr(context, partition_id, attr, value, REQUEST=None):
|
||||
|
||||
partition = get_partition(context, partition_id)
|
||||
formsemestre_id = partition["formsemestre_id"]
|
||||
if not can_change_groups(context, REQUEST, formsemestre_id):
|
||||
if not sco_permissions_check.can_change_groups(context, REQUEST, formsemestre_id):
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
|
||||
log("partition_set_attr(%s, %s, %s)" % (partition_id, attr, value))
|
||||
@ -963,7 +961,7 @@ def partition_delete(
|
||||
default partition cannot be suppressed (unless force)"""
|
||||
partition = get_partition(context, partition_id)
|
||||
formsemestre_id = partition["formsemestre_id"]
|
||||
if not can_change_groups(context, REQUEST, formsemestre_id):
|
||||
if not sco_permissions_check.can_change_groups(context, REQUEST, formsemestre_id):
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
|
||||
if not partition["partition_name"] and not force:
|
||||
@ -1007,7 +1005,7 @@ def partition_move(context, partition_id, after=0, REQUEST=None, redirect=1):
|
||||
"""Move before/after previous one (decrement/increment numero)"""
|
||||
partition = get_partition(context, partition_id)
|
||||
formsemestre_id = partition["formsemestre_id"]
|
||||
if not can_change_groups(context, REQUEST, formsemestre_id):
|
||||
if not sco_permissions_check.can_change_groups(context, REQUEST, formsemestre_id):
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
#
|
||||
redirect = int(redirect)
|
||||
@ -1042,7 +1040,7 @@ def partition_rename(context, partition_id, REQUEST=None):
|
||||
"""Form to rename a partition"""
|
||||
partition = get_partition(context, partition_id)
|
||||
formsemestre_id = partition["formsemestre_id"]
|
||||
if not can_change_groups(context, REQUEST, formsemestre_id):
|
||||
if not sco_permissions_check.can_change_groups(context, REQUEST, formsemestre_id):
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
H = ["<h2>Renommer une partition</h2>"]
|
||||
tf = TrivialFormulator(
|
||||
@ -1103,7 +1101,7 @@ def partition_set_name(context, partition_id, partition_name, REQUEST=None, redi
|
||||
"Partition %s déjà existante dans ce semestre !" % partition_name
|
||||
)
|
||||
|
||||
if not can_change_groups(context, REQUEST, formsemestre_id):
|
||||
if not sco_permissions_check.can_change_groups(context, REQUEST, formsemestre_id):
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
redirect = int(redirect)
|
||||
cnx = ndb.GetDBConnexion()
|
||||
@ -1128,7 +1126,7 @@ def group_set_name(context, group_id, group_name, REQUEST=None, redirect=1):
|
||||
if group["group_name"] is None:
|
||||
raise ValueError("can't set a name to default group")
|
||||
formsemestre_id = group["formsemestre_id"]
|
||||
if not can_change_groups(context, REQUEST, formsemestre_id):
|
||||
if not sco_permissions_check.can_change_groups(context, REQUEST, formsemestre_id):
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
redirect = int(redirect)
|
||||
cnx = ndb.GetDBConnexion()
|
||||
@ -1145,7 +1143,7 @@ def group_rename(context, group_id, REQUEST=None):
|
||||
"""Form to rename a group"""
|
||||
group = get_group(context, group_id)
|
||||
formsemestre_id = group["formsemestre_id"]
|
||||
if not can_change_groups(context, REQUEST, formsemestre_id):
|
||||
if not sco_permissions_check.can_change_groups(context, REQUEST, formsemestre_id):
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
H = ["<h2>Renommer un groupe de %s</h2>" % group["partition_name"]]
|
||||
tf = TrivialFormulator(
|
||||
@ -1193,7 +1191,7 @@ def groups_auto_repartition(context, partition_id=None, REQUEST=None):
|
||||
formsemestre_id = partition["formsemestre_id"]
|
||||
# renvoie sur page édition groupes
|
||||
dest_url = "affectGroups?partition_id=%s" % partition_id
|
||||
if not can_change_groups(context, REQUEST, formsemestre_id):
|
||||
if not sco_permissions_check.can_change_groups(context, REQUEST, formsemestre_id):
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
|
||||
@ -1261,7 +1259,7 @@ def groups_auto_repartition(context, partition_id=None, REQUEST=None):
|
||||
createGroup(context, partition_id, group_name, REQUEST=REQUEST)
|
||||
)
|
||||
#
|
||||
nt = context.Notes._getNotesCache().get_NotesTable(
|
||||
nt = sco_core.get_notes_cache(context).get_NotesTable(
|
||||
context.Notes, formsemestre_id
|
||||
) # > identdict
|
||||
identdict = nt.identdict
|
||||
|
@ -40,7 +40,9 @@ def affectGroups(context, partition_id, REQUEST=None):
|
||||
# Ported from DTML and adapted to new group management (nov 2009)
|
||||
partition = sco_groups.get_partition(context, partition_id)
|
||||
formsemestre_id = partition["formsemestre_id"]
|
||||
if not sco_groups.can_change_groups(context, REQUEST, formsemestre_id):
|
||||
if not sco_groups.sco_permissions_check.can_change_groups(
|
||||
context, REQUEST, formsemestre_id
|
||||
):
|
||||
raise AccessDenied("vous n'avez pas la permission d'effectuer cette opération")
|
||||
|
||||
H = [
|
||||
|
@ -53,6 +53,7 @@ from app.scodoc.sco_exceptions import (
|
||||
ScoGenError,
|
||||
)
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import sco_core
|
||||
from app.scodoc import sco_etud
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_groups
|
@ -31,7 +31,7 @@ from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from email.header import Header
|
||||
|
||||
from app.scodoc import mails
|
||||
from app.scodoc import sco_emails
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.notes_log import log
|
||||
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError, ScoException
|
||||
@ -228,4 +228,4 @@ Pour plus d'informations sur ce logiciel, voir %s
|
||||
msg.epilogue = ""
|
||||
txt = MIMEText(txt, "plain", scu.SCO_ENCODING)
|
||||
msg.attach(txt)
|
||||
mails.sendEmail(context, msg)
|
||||
sco_emails.sendEmail(context, msg)
|
||||
|
@ -107,8 +107,8 @@ def list_inscrits(context, formsemestre_id, with_dems=False):
|
||||
{ etudid : etud }
|
||||
"""
|
||||
if not with_dems:
|
||||
ins = context.Notes.do_formsemestre_inscription_listinscrits(
|
||||
formsemestre_id
|
||||
ins = sco_formsemestre_inscriptions.do_formsemestre_inscription_listinscrits(
|
||||
context, formsemestre_id
|
||||
) # optimized
|
||||
else:
|
||||
args = {"formsemestre_id": formsemestre_id}
|
||||
@ -215,8 +215,8 @@ def do_inscrit(context, sem, etudids, REQUEST=None, inscrit_groupes=False):
|
||||
def do_desinscrit(context, sem, etudids, REQUEST):
|
||||
log("do_desinscrit: %s" % etudids)
|
||||
for etudid in etudids:
|
||||
context.do_formsemestre_desinscription(
|
||||
etudid, sem["formsemestre_id"], REQUEST=REQUEST
|
||||
sco_formsemestre_inscriptions.do_formsemestre_desinscription(
|
||||
context, etudid, sem["formsemestre_id"], REQUEST=REQUEST
|
||||
)
|
||||
|
||||
|
||||
|
@ -91,7 +91,9 @@ def moduleimpl_inscriptions_edit(
|
||||
% (moduleimpl_id, mod["titre"], mod["code"]),
|
||||
]
|
||||
# Liste des inscrits à ce semestre
|
||||
inscrits = context.Notes.do_formsemestre_inscription_listinscrits(formsemestre_id)
|
||||
inscrits = sco_formsemestre_inscriptions.do_formsemestre_inscription_listinscrits(
|
||||
context, formsemestre_id
|
||||
)
|
||||
for ins in inscrits:
|
||||
etuds_info = sco_etud.get_etud_info(etudid=ins["etudid"], filled=1)
|
||||
if not etuds_info:
|
||||
|
@ -40,7 +40,7 @@ import PyRSS2Gen # pylint: disable=import-error
|
||||
import app.scodoc.sco_utils as scu
|
||||
import app.scodoc.notesdb as ndb
|
||||
from app.scodoc.notes_log import log
|
||||
from app.scodoc import mails
|
||||
from app.scodoc import sco_emails
|
||||
from app.scodoc.sco_utils import SCO_ENCODING, SCO_ANNONCES_WEBSITE
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_moduleimpl
|
||||
@ -301,4 +301,4 @@ def _send_news_by_mail(context, n):
|
||||
del msg["To"]
|
||||
msg["To"] = email_addr
|
||||
# log('xxx mail: %s' % msg)
|
||||
mails.sendEmail(context, msg)
|
||||
sco_emails.sendEmail(context, msg)
|
||||
|
@ -70,18 +70,18 @@ def _menuScolarite(context, authuser, sem, etudid):
|
||||
|
||||
if ins["etat"] != "D":
|
||||
dem_title = "Démission"
|
||||
dem_url = "formDem"
|
||||
dem_url = "scolar.formDem"
|
||||
else:
|
||||
dem_title = "Annuler la démission"
|
||||
dem_url = "doCancelDem"
|
||||
dem_url = "scolar.doCancelDem"
|
||||
|
||||
# Note: seul un etudiant inscrit (I) peut devenir défaillant.
|
||||
if ins["etat"] != sco_codes_parcours.DEF:
|
||||
def_title = "Déclarer défaillance"
|
||||
def_url = "formDef"
|
||||
def_url = "scolar.formDef"
|
||||
elif ins["etat"] == sco_codes_parcours.DEF:
|
||||
def_title = "Annuler la défaillance"
|
||||
def_url = "doCancelDef"
|
||||
def_url = "scolar.doCancelDef"
|
||||
def_enabled = (
|
||||
(ins["etat"] != "D")
|
||||
and authuser.has_permission(Permission.ScoEtudInscrit)
|
||||
|
@ -9,9 +9,7 @@ from app.scodoc.sco_permissions import Permission
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import sco_etud
|
||||
from app.scodoc import sco_exceptions
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_moduleimpl
|
||||
from app.scodoc import sco_parcours_dut
|
||||
|
||||
|
||||
def can_edit_notes(context, authuser, moduleimpl_id, allow_ens=True):
|
||||
@ -21,6 +19,9 @@ def can_edit_notes(context, authuser, moduleimpl_id, allow_ens=True):
|
||||
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).
|
||||
"""
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_parcours_dut
|
||||
|
||||
uid = str(authuser)
|
||||
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0]
|
||||
sem = sco_formsemestre.get_formsemestre(context, M["formsemestre_id"])
|
||||
@ -49,6 +50,39 @@ def can_edit_notes(context, authuser, moduleimpl_id, allow_ens=True):
|
||||
return True
|
||||
|
||||
|
||||
def can_edit_evaluation(context, REQUEST, moduleimpl_id=None):
|
||||
"""Vérifie que l'on a le droit de modifier, créer ou détruire une
|
||||
évaluation dans ce module.
|
||||
Sinon, lance une exception.
|
||||
(nb: n'implique pas le droit de saisir ou modifier des notes)
|
||||
"""
|
||||
# was _evaluation_check_write_access
|
||||
# AccessDenied("Modification évaluation impossible pour %s" % (uid,))
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_moduleimpl
|
||||
|
||||
# acces pour resp. moduleimpl et resp. form semestre (dir etud)
|
||||
if moduleimpl_id is None:
|
||||
raise ValueError("no moduleimpl specified") # bug
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
uid = str(authuser)
|
||||
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0]
|
||||
sem = sco_formsemestre.get_formsemestre(context, M["formsemestre_id"])
|
||||
|
||||
if (
|
||||
authuser.has_permission(Permission.ScoEditAllEvals)
|
||||
or uid == M["responsable_id"]
|
||||
or uid in sem["responsables"]
|
||||
):
|
||||
return True
|
||||
elif sem["ens_can_edit_eval"]:
|
||||
for ens in M["ens"]:
|
||||
if ens["ens_id"] == uid:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def can_suppress_annotation(context, annotation_id, REQUEST):
|
||||
"""True if current user can suppress this annotation
|
||||
Seuls l'auteur de l'annotation et le chef de dept peuvent supprimer
|
||||
@ -60,13 +94,9 @@ def can_suppress_annotation(context, annotation_id, REQUEST):
|
||||
raise sco_exceptions.ScoValueError("annotation inexistante !")
|
||||
anno = annos[0]
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
# note: les anciennes installations n'ont pas le role ScoEtudSupprAnnotations
|
||||
# c'est pourquoi on teste aussi ScoEtudInscrit (normalement détenue par le chef)
|
||||
return (
|
||||
(str(authuser) == anno["zope_authenticated_user"])
|
||||
or authuser.has_permission(Permission.ScoEtudSupprAnnotations)
|
||||
or authuser.has_permission(Permission.ScoEtudInscrit)
|
||||
)
|
||||
str(authuser) == anno["zope_authenticated_user"]
|
||||
) or authuser.has_permission(Permission.ScoEtudAddAnnotations)
|
||||
|
||||
|
||||
def can_edit_suivi(context, REQUEST=None):
|
||||
@ -77,6 +107,8 @@ def can_edit_suivi(context, REQUEST=None):
|
||||
|
||||
def can_validate_sem(context, REQUEST, formsemestre_id):
|
||||
"Vrai si utilisateur peut saisir decision de jury dans ce semestre"
|
||||
from app.scodoc import sco_formsemestre
|
||||
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
if sem["etat"] != "1":
|
||||
return False # semestre verrouillé
|
||||
@ -86,6 +118,7 @@ def can_validate_sem(context, REQUEST, formsemestre_id):
|
||||
|
||||
def can_edit_pv(context, REQUEST, formsemestre_id):
|
||||
"Vrai si utilisateur peut editer un PV de jury de ce semestre"
|
||||
from app.scodoc import sco_formsemestre
|
||||
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
if is_chef_or_diretud(context, REQUEST, sem):
|
||||
@ -114,6 +147,8 @@ def check_access_diretud(
|
||||
"""Check if access granted: responsable or ScoImplement
|
||||
Return True|False, HTML_error_page
|
||||
"""
|
||||
from app.scodoc import sco_formsemestre
|
||||
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
header = html_sco_header.sco_header(
|
||||
@ -137,3 +172,19 @@ def check_access_diretud(
|
||||
)
|
||||
else:
|
||||
return True, ""
|
||||
|
||||
|
||||
def can_change_groups(context, REQUEST, formsemestre_id):
|
||||
"Vrai si l'utilisateur peut changer les groupes dans ce semestre"
|
||||
from app.scodoc import sco_formsemestre
|
||||
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
if sem["etat"] != "1":
|
||||
return False # semestre verrouillé
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
if authuser.has_permission(Permission.ScoEtudChangeGroups):
|
||||
return True # admin, chef dept
|
||||
uid = str(authuser)
|
||||
if uid in sem["responsables"]:
|
||||
return True
|
||||
return False
|
||||
|
@ -46,6 +46,7 @@ from app.scodoc.sco_permissions import Permission
|
||||
from app.scodoc.TrivialFormulator import TrivialFormulator, TF
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import htmlutils
|
||||
from app.scodoc import sco_abs
|
||||
from app.scodoc import sco_core
|
||||
from app.scodoc import sco_edit_module
|
||||
from app.scodoc import sco_evaluations
|
||||
|
@ -50,7 +50,7 @@ from app.scodoc.sco_exceptions import ScoValueError
|
||||
from app.scodoc.sco_pdf import SU
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import htmlutils
|
||||
from app.scodoc import ImportScolars
|
||||
from app.scodoc import sco_import_etuds
|
||||
from app.scodoc import sco_excel
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_groups
|
||||
@ -470,8 +470,8 @@ def _listeappel_photos_pdf(context, groups_infos, REQUEST):
|
||||
# --------------------- Upload des photos de tout un groupe
|
||||
def photos_generate_excel_sample(context, group_ids=[], REQUEST=None):
|
||||
"""Feuille excel pour import fichiers photos"""
|
||||
fmt = ImportScolars.sco_import_format()
|
||||
data = ImportScolars.sco_import_generate_excel_sample(
|
||||
fmt = sco_import_etuds.sco_import_format()
|
||||
data = sco_import_etuds.sco_import_generate_excel_sample(
|
||||
fmt,
|
||||
context=context,
|
||||
group_ids=group_ids,
|
||||
|
@ -164,7 +164,7 @@ def external_ue_inscrit_et_note(
|
||||
evaluation_id = ModEvals[0]["evaluation_id"]
|
||||
else:
|
||||
# crée une évaluation:
|
||||
evaluation_id = context.do_evaluation_create(
|
||||
evaluation_id = sco_evaluations.do_evaluation_create(context,
|
||||
REQUEST=REQUEST,
|
||||
moduleimpl_id=moduleimpl_id,
|
||||
note_max=20.0,
|
||||
|
@ -385,6 +385,15 @@ def UsersURL():
|
||||
return "NotImplemented"
|
||||
|
||||
|
||||
def get_current_user_name(REQUEST):
|
||||
"""return a displayable string identifying the current user.
|
||||
XXX For now, the login, but will be the name. #sco8
|
||||
"""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
uid = str(authuser)
|
||||
return uid
|
||||
|
||||
|
||||
# ---- Simple python utilities
|
||||
|
||||
|
||||
|
@ -81,8 +81,10 @@ from app.scodoc.TrivialFormulator import TrivialFormulator
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import sco_abs
|
||||
from app.scodoc import sco_abs_notification, sco_abs_views
|
||||
from app.scodoc import sco_abs_notification
|
||||
from app.scodoc import sco_abs_views
|
||||
from app.scodoc import sco_compute_moy
|
||||
from app.scodoc import sco_core
|
||||
from app.scodoc import sco_etud
|
||||
from app.scodoc import sco_excel
|
||||
from app.scodoc import sco_formsemestre
|
||||
@ -248,7 +250,9 @@ def SignaleAbsenceGrHebdo(
|
||||
else:
|
||||
# Si aucun etudiant n'est inscrit au module choisi...
|
||||
moduleimpl_id = None
|
||||
nt = context.Notes._getNotesCache().get_NotesTable(context.Notes, formsemestre_id)
|
||||
nt = sco_core.get_notes_cache(context).get_NotesTable(
|
||||
context.Notes, formsemestre_id
|
||||
)
|
||||
sem = sco_formsemestre.do_formsemestre_list(
|
||||
context, {"formsemestre_id": formsemestre_id}
|
||||
)[0]
|
||||
@ -421,7 +425,7 @@ def SignaleAbsenceGrSemestre(
|
||||
base_url = base_url_noweeks + "&nbweeks=%s" % nbweeks # sans le moduleimpl_id
|
||||
|
||||
if etuds:
|
||||
nt = context.Notes._getNotesCache().get_NotesTable(
|
||||
nt = sco_core.get_notes_cache(context).get_NotesTable(
|
||||
context.Notes, formsemestre_id
|
||||
)
|
||||
sem = sco_formsemestre.do_formsemestre_list(
|
||||
@ -638,7 +642,7 @@ def _gen_form_saisie_groupe(
|
||||
# UE capitalisee dans semestre courant ?
|
||||
cap = []
|
||||
if etud["cursem"]:
|
||||
nt = context.Notes._getNotesCache().get_NotesTable(
|
||||
nt = sco_core.get_notes_cache(context).get_NotesTable(
|
||||
context.Notes, etud["cursem"]["formsemestre_id"]
|
||||
) # > get_ues, get_etud_ue_status
|
||||
for ue in nt.get_ues():
|
||||
|
@ -41,7 +41,7 @@ def sco_exemple(etudid="NON"):
|
||||
}
|
||||
|
||||
|
||||
# En ScoDoc 7, on a souvent des vues qui en appellent d'autres
|
||||
# En ScoDoc 7, on avait des vues qui en appellaient d'autres
|
||||
# avec context.sco_exemple( etudid="E12" )
|
||||
@bp.route("/<scodoc_dept>/Scolarite/sco_exemple2")
|
||||
@login_required
|
||||
|
@ -486,33 +486,11 @@ def formation_import_xml_form(context, REQUEST):
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/formation_create_new_version")
|
||||
@permission_required(Permission.ScoChangeFormation)
|
||||
@scodoc7func(context)
|
||||
def formation_create_new_version(context, formation_id, redirect=True, REQUEST=None):
|
||||
"duplicate formation, with new version number"
|
||||
xml = sco_formations.formation_export(
|
||||
context, formation_id, export_ids=True, format="xml"
|
||||
)
|
||||
new_id, modules_old2new, ues_old2new = sco_formations.formation_import_xml(
|
||||
context, REQUEST, xml
|
||||
)
|
||||
# news
|
||||
F = sco_formations.formation_list(context, args={"formation_id": new_id})[0]
|
||||
sco_news.add(
|
||||
context,
|
||||
REQUEST,
|
||||
typ=sco_news.NEWS_FORM,
|
||||
object=new_id,
|
||||
text="Nouvelle version de la formation %(acronyme)s" % F,
|
||||
)
|
||||
if redirect:
|
||||
return REQUEST.RESPONSE.redirect(
|
||||
"ue_list?formation_id=" + new_id + "&msg=Nouvelle version !"
|
||||
)
|
||||
else:
|
||||
return new_id, modules_old2new, ues_old2new
|
||||
|
||||
sco_publish(
|
||||
"/formation_create_new_version",
|
||||
sco_formations.formation_create_new_version,
|
||||
Permission.ScoChangeFormation,
|
||||
)
|
||||
|
||||
# --- UE
|
||||
sco_publish(
|
||||
@ -579,42 +557,6 @@ sco_publish("/ue_move", sco_edit_formation.ue_move, Permission.ScoChangeFormatio
|
||||
|
||||
|
||||
# --- Semestres de formation
|
||||
@bp.route("/do_formsemestre_create")
|
||||
@permission_required(Permission.ScoImplement)
|
||||
@scodoc7func(context)
|
||||
def do_formsemestre_create(context, args, REQUEST, silent=False):
|
||||
"create a formsemestre"
|
||||
cnx = ndb.GetDBConnexion()
|
||||
formsemestre_id = sco_formsemestre._formsemestreEditor.create(cnx, args)
|
||||
if args["etapes"]:
|
||||
args["formsemestre_id"] = formsemestre_id
|
||||
sco_formsemestre.write_formsemestre_etapes(context, args)
|
||||
if args["responsables"]:
|
||||
args["formsemestre_id"] = formsemestre_id
|
||||
sco_formsemestre.write_formsemestre_responsables(context, args)
|
||||
|
||||
# create default partition
|
||||
partition_id = sco_groups.partition_create(
|
||||
context, formsemestre_id, default=True, redirect=0, REQUEST=REQUEST
|
||||
)
|
||||
_group_id = sco_groups.createGroup(
|
||||
context, partition_id, default=True, REQUEST=REQUEST
|
||||
)
|
||||
|
||||
# news
|
||||
if not args.has_key("titre"):
|
||||
args["titre"] = "sans titre"
|
||||
args["formsemestre_id"] = formsemestre_id
|
||||
args["url"] = "Notes/formsemestre_status?formsemestre_id=%(formsemestre_id)s" % args
|
||||
if not silent:
|
||||
sco_news.add(
|
||||
context,
|
||||
REQUEST,
|
||||
typ=sco_news.NEWS_SEM,
|
||||
text='Création du semestre <a href="%(url)s">%(titre)s</a>' % args,
|
||||
url=args["url"],
|
||||
)
|
||||
return formsemestre_id
|
||||
|
||||
|
||||
@bp.route("/formsemestre_list")
|
||||
@ -1285,14 +1227,9 @@ def do_formsemestre_inscription_listinscrits(
|
||||
context, formsemestre_id, format=None, REQUEST=None
|
||||
):
|
||||
"""Liste les inscrits (état I) à ce semestre et cache le résultat"""
|
||||
cache = sco_core.get_formsemestre_inscription_cache(context)
|
||||
r = cache.get(formsemestre_id)
|
||||
if r is None:
|
||||
# retreive list
|
||||
r = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
|
||||
context, args={"formsemestre_id": formsemestre_id, "etat": "I"}
|
||||
)
|
||||
cache.set(formsemestre_id, r)
|
||||
r = sco_formsemestre_inscriptions.do_formsemestre_inscription_listinscrits(
|
||||
context, formsemestre_id
|
||||
)
|
||||
return scu.sendResult(REQUEST, r, format=format, name="inscrits")
|
||||
|
||||
|
||||
@ -1365,7 +1302,9 @@ def formsemestre_desinscription(
|
||||
parameters={"etudid": etudid, "formsemestre_id": formsemestre_id},
|
||||
)
|
||||
|
||||
context.do_formsemestre_desinscription(etudid, formsemestre_id, REQUEST=REQUEST)
|
||||
sco_formsemestre_inscriptions.do_formsemestre_desinscription(
|
||||
context, etudid, formsemestre_id, REQUEST=REQUEST
|
||||
)
|
||||
|
||||
return (
|
||||
html_sco_header.sco_header(context, REQUEST)
|
||||
@ -1458,170 +1397,6 @@ sco_publish(
|
||||
# --- Evaluations
|
||||
|
||||
|
||||
def _evaluation_check_write_access(context, REQUEST, moduleimpl_id=None):
|
||||
"""Vérifie que l'on a le droit de modifier, créer ou détruire une
|
||||
évaluation dans ce module.
|
||||
Sinon, lance une exception.
|
||||
(nb: n'implique pas le droit de saisir ou modifier des notes)
|
||||
"""
|
||||
# acces pour resp. moduleimpl et resp. form semestre (dir etud)
|
||||
if moduleimpl_id is None:
|
||||
raise ValueError("no moduleimpl specified") # bug
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
uid = str(authuser)
|
||||
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0]
|
||||
sem = sco_formsemestre.get_formsemestre(context, M["formsemestre_id"])
|
||||
|
||||
if (
|
||||
(not authuser.has_permission(Permission.ScoEditAllEvals))
|
||||
and uid != M["responsable_id"]
|
||||
and uid not in sem["responsables"]
|
||||
):
|
||||
if sem["ens_can_edit_eval"]:
|
||||
for ens in M["ens"]:
|
||||
if ens["ens_id"] == uid:
|
||||
return # ok
|
||||
raise AccessDenied("Modification évaluation impossible pour %s" % (uid,))
|
||||
|
||||
|
||||
@bp.route("/do_evaluation_create")
|
||||
@permission_required(Permission.ScoEnsView)
|
||||
@scodoc7func(context)
|
||||
def do_evaluation_create(
|
||||
context,
|
||||
moduleimpl_id=None,
|
||||
jour=None,
|
||||
heure_debut=None,
|
||||
heure_fin=None,
|
||||
description=None,
|
||||
note_max=None,
|
||||
coefficient=None,
|
||||
visibulletin=None,
|
||||
publish_incomplete=None,
|
||||
evaluation_type=None,
|
||||
numero=None,
|
||||
REQUEST=None,
|
||||
**kw
|
||||
):
|
||||
"""Create an evaluation"""
|
||||
args = locals()
|
||||
log("do_evaluation_create: args=" + str(args))
|
||||
context._evaluation_check_write_access(REQUEST, moduleimpl_id=moduleimpl_id)
|
||||
context._check_evaluation_args(args)
|
||||
# Check numeros
|
||||
sco_evaluations.module_evaluation_renumber(
|
||||
context, moduleimpl_id, REQUEST=REQUEST, only_if_unumbered=True
|
||||
)
|
||||
if not "numero" in args or args["numero"] is None:
|
||||
n = None
|
||||
# determine le numero avec la date
|
||||
# Liste des eval existantes triees par date, la plus ancienne en tete
|
||||
ModEvals = sco_evaluations.do_evaluation_list(
|
||||
context,
|
||||
args={"moduleimpl_id": moduleimpl_id},
|
||||
sortkey="jour asc, heure_debut asc",
|
||||
)
|
||||
if args["jour"]:
|
||||
next_eval = None
|
||||
t = (
|
||||
ndb.DateDMYtoISO(args["jour"]),
|
||||
ndb.TimetoISO8601(args["heure_debut"]),
|
||||
)
|
||||
for e in ModEvals:
|
||||
if (
|
||||
ndb.DateDMYtoISO(e["jour"]),
|
||||
ndb.TimetoISO8601(e["heure_debut"]),
|
||||
) > t:
|
||||
next_eval = e
|
||||
break
|
||||
if next_eval:
|
||||
n = sco_evaluations.module_evaluation_insert_before(
|
||||
context, ModEvals, next_eval, REQUEST
|
||||
)
|
||||
else:
|
||||
n = None # a placer en fin
|
||||
if n is None: # pas de date ou en fin:
|
||||
if ModEvals:
|
||||
log(pprint.pformat(ModEvals[-1]))
|
||||
n = ModEvals[-1]["numero"] + 1
|
||||
else:
|
||||
n = 0 # the only one
|
||||
# log("creating with numero n=%d" % n)
|
||||
args["numero"] = n
|
||||
|
||||
#
|
||||
cnx = ndb.GetDBConnexion()
|
||||
r = sco_evaluations._evaluationEditor.create(cnx, args)
|
||||
|
||||
# news
|
||||
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_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(
|
||||
context,
|
||||
REQUEST,
|
||||
typ=sco_news.NEWS_NOTE,
|
||||
object=moduleimpl_id,
|
||||
text='Création d\'une évaluation dans <a href="%(url)s">%(titre)s</a>' % mod,
|
||||
url=mod["url"],
|
||||
)
|
||||
|
||||
return r
|
||||
|
||||
|
||||
def _check_evaluation_args(context, args):
|
||||
"Check coefficient, dates and duration, raises exception if invalid"
|
||||
moduleimpl_id = args["moduleimpl_id"]
|
||||
# check bareme
|
||||
note_max = args.get("note_max", None)
|
||||
if note_max is None:
|
||||
raise ScoValueError("missing note_max")
|
||||
try:
|
||||
note_max = float(note_max)
|
||||
except ValueError:
|
||||
raise ScoValueError("Invalid note_max value")
|
||||
if note_max < 0:
|
||||
raise ScoValueError("Invalid note_max value (must be positive or null)")
|
||||
# check coefficient
|
||||
coef = args.get("coefficient", None)
|
||||
if coef is None:
|
||||
raise ScoValueError("missing coefficient")
|
||||
try:
|
||||
coef = float(coef)
|
||||
except ValueError:
|
||||
raise ScoValueError("Invalid coefficient value")
|
||||
if coef < 0:
|
||||
raise ScoValueError("Invalid coefficient value (must be positive or null)")
|
||||
# check date
|
||||
jour = args.get("jour", None)
|
||||
args["jour"] = jour
|
||||
if jour:
|
||||
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0]
|
||||
sem = sco_formsemestre.get_formsemestre(context, M["formsemestre_id"])
|
||||
d, m, y = [int(x) for x in sem["date_debut"].split("/")]
|
||||
date_debut = datetime.date(y, m, d)
|
||||
d, m, y = [int(x) for x in sem["date_fin"].split("/")]
|
||||
date_fin = datetime.date(y, m, d)
|
||||
# passe par ndb.DateDMYtoISO pour avoir date pivot
|
||||
y, m, d = [int(x) for x in ndb.DateDMYtoISO(jour).split("-")]
|
||||
jour = datetime.date(y, m, d)
|
||||
if (jour > date_fin) or (jour < date_debut):
|
||||
raise ScoValueError(
|
||||
"La date de l'évaluation (%s/%s/%s) n'est pas dans le semestre !"
|
||||
% (d, m, y)
|
||||
)
|
||||
heure_debut = args.get("heure_debut", None)
|
||||
args["heure_debut"] = heure_debut
|
||||
heure_fin = args.get("heure_fin", None)
|
||||
args["heure_fin"] = heure_fin
|
||||
if jour and ((not heure_debut) or (not heure_fin)):
|
||||
raise ScoValueError("Les heures doivent être précisées")
|
||||
d = ndb.TimeDuration(heure_debut, heure_fin)
|
||||
if d and ((d < 0) or (d > 60 * 12)):
|
||||
raise ScoValueError("Heures de l'évaluation incohérentes !")
|
||||
|
||||
|
||||
@bp.route("/evaluation_delete")
|
||||
@permission_required(Permission.ScoEnsView)
|
||||
@scodoc7func(context)
|
||||
|
@ -85,7 +85,7 @@ from app.scodoc.gen_tables import GenTable
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import html_sidebar
|
||||
from app.scodoc import imageresize
|
||||
from app.scodoc import ImportScolars
|
||||
from app.scodoc import sco_import_etuds
|
||||
from app.scodoc import sco_abs
|
||||
from app.scodoc import sco_archives_etud
|
||||
from app.scodoc import sco_codes_parcours
|
||||
@ -1736,7 +1736,7 @@ Les champs avec un astérisque (*) doivent être présents (nulls non autorisés
|
||||
<table>
|
||||
<tr><td><b>Attribut</b></td><td><b>Type</b></td><td><b>Description</b></td></tr>"""
|
||||
]
|
||||
for t in ImportScolars.sco_import_format(
|
||||
for t in sco_import_etuds.sco_import_format(
|
||||
with_codesemestre=(formsemestre_id == None)
|
||||
):
|
||||
if int(t[3]):
|
||||
@ -1752,7 +1752,7 @@ Les champs avec un astérisque (*) doivent être présents (nulls non autorisés
|
||||
elif tf[0] == -1:
|
||||
return REQUEST.RESPONSE.redirect(dest_url)
|
||||
else:
|
||||
return ImportScolars.students_import_excel(
|
||||
return sco_import_etuds.students_import_excel(
|
||||
context,
|
||||
tf[2]["csvfile"],
|
||||
REQUEST=REQUEST,
|
||||
@ -1771,8 +1771,8 @@ def import_generate_excel_sample(context, REQUEST, with_codesemestre="1"):
|
||||
with_codesemestre = int(with_codesemestre)
|
||||
else:
|
||||
with_codesemestre = 0
|
||||
format = ImportScolars.sco_import_format()
|
||||
data = ImportScolars.sco_import_generate_excel_sample(
|
||||
format = sco_import_etuds.sco_import_format()
|
||||
data = sco_import_etuds.sco_import_generate_excel_sample(
|
||||
format, with_codesemestre, exclude_cols=["photo_filename"], REQUEST=REQUEST
|
||||
)
|
||||
return sco_excel.sendExcelFile(REQUEST, data, "ImportEtudiants.xls")
|
||||
@ -1787,8 +1787,8 @@ def import_generate_admission_sample(context, REQUEST, formsemestre_id):
|
||||
group = sco_groups.get_group(
|
||||
context, sco_groups.get_default_group(context, formsemestre_id)
|
||||
)
|
||||
fmt = ImportScolars.sco_import_format()
|
||||
data = ImportScolars.sco_import_generate_excel_sample(
|
||||
fmt = sco_import_etuds.sco_import_format()
|
||||
data = sco_import_etuds.sco_import_generate_excel_sample(
|
||||
fmt,
|
||||
only_tables=["identite", "admissions", "adresse"],
|
||||
exclude_cols=["nationalite", "foto", "photo_filename"],
|
||||
@ -1889,7 +1889,7 @@ def form_students_import_infos_admissions(context, REQUEST, formsemestre_id=None
|
||||
Seule la première feuille du classeur sera utilisée.
|
||||
<div id="adm_table_description_format">
|
||||
"""
|
||||
+ ImportScolars.adm_table_description_format(context).html()
|
||||
+ sco_import_etuds.adm_table_description_format(context).html()
|
||||
+ """</div>"""
|
||||
)
|
||||
|
||||
@ -1913,7 +1913,7 @@ def _students_import_admission(
|
||||
context, csvfile, type_admission="", REQUEST=None, formsemestre_id=None
|
||||
):
|
||||
"import donnees admission from Excel file (v2016)"
|
||||
diag = ImportScolars.scolars_import_admission(
|
||||
diag = sco_import_etuds.scolars_import_admission(
|
||||
csvfile,
|
||||
context.Notes,
|
||||
REQUEST,
|
||||
|
10
refactor.py
Normal file → Executable file
10
refactor.py
Normal file → Executable file
@ -9,7 +9,7 @@
|
||||
|
||||
- remplace context.xxx par module.xxx
|
||||
|
||||
./refactor.py refactor method module app/scodoc/*.py
|
||||
./refactor.py refactor module.method app/scodoc/*.py
|
||||
|
||||
|
||||
|
||||
@ -34,14 +34,6 @@ import tempfile
|
||||
import shutil
|
||||
import click
|
||||
|
||||
# import flask
|
||||
|
||||
# import app
|
||||
# from app import create_app, cli, db
|
||||
# from app.auth.models import User, Role, UserRole
|
||||
|
||||
# from app.views import notes
|
||||
|
||||
TYPES_TO_SCAN = {
|
||||
types.FunctionType,
|
||||
# types.ClassType,
|
||||
|
Loading…
Reference in New Issue
Block a user