Compare commits

...

4 Commits

94 changed files with 1956 additions and 4130 deletions

View File

@ -55,20 +55,9 @@ Installer le bon vieux `pyExcelerator` dans l'environnement:
## Migration ZScolar
### Méthodes qui ne devraient plus être publiées:
security.declareProtected(ScoView, "get_preferences")
def get_preferences(context, formsemestre_id=None):
"Get preferences for this instance (a dict-like instance)"
return sco_preferences.sem_preferences(context, formsemestre_id)
security.declareProtected(ScoView, "get_preference")
def get_preference(context, name, formsemestre_id=None):
"""Returns value of named preference.
All preferences have a sensible default value (see sco_preferences.py),
this function always returns a usable value for all defined preferences names.
"""
return sco_preferences.get_base_preferences(context).get(formsemestre_id, name)

View File

@ -76,7 +76,7 @@ class ZResponse(object):
return flask.redirect(url) # http 302
def setHeader(self, header, value):
self.headers[header.tolower()] = value
self.headers[header.lower()] = value
def permission_required(permission):

View File

@ -240,14 +240,16 @@ def students_import_excel(
dest = "formsemestre_status?formsemestre_id=%s" % formsemestre_id
else:
dest = context.NotesURL()
H = [context.sco_header(REQUEST, page_title="Import etudiants")]
H = [
html_sco_header.sco_header(context, REQUEST, page_title="Import etudiants")
]
H.append("<ul>")
for d in diag:
H.append("<li>%s</li>" % d)
H.append("</ul>")
H.append("<p>Import terminé !</p>")
H.append('<p><a class="stdlink" href="%s">Continuer</a></p>' % dest)
return "\n".join(H) + context.sco_footer(REQUEST)
return "\n".join(H) + html_sco_header.sco_footer(context, REQUEST)
def scolars_import_excel_file(
@ -266,7 +268,7 @@ def scolars_import_excel_file(
cnx = context.GetDBConnexion(autocommit=False)
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
annee_courante = time.localtime()[0]
always_require_ine = context.get_preference("always_require_ine")
always_require_ine = sco_preferences.get_preference(context, "always_require_ine")
exceldata = datafile.read()
if not exceldata:
raise ScoValueError("Ficher excel vide ou invalide")
@ -696,7 +698,7 @@ def scolars_import_admission(
nline += 1
diag.append("%d lignes importées" % n_import)
if n_import > 0:
context._inval_cache(formsemestre_id=formsemestre_id)
sco_core.inval_cache(context, formsemestre_id=formsemestre_id)
return diag
@ -789,6 +791,8 @@ def adm_table_description_format(context):
rows=Fmt.values(),
html_sortable=True,
html_class="table_leftalign",
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
return tab

View File

@ -55,12 +55,12 @@ import sco_entreprises
def entreprise_header(context, REQUEST=None, page_title=""):
"common header for all Entreprises pages"
return context.sco_header(REQUEST, container=context, page_title=page_title)
return html_sco_header.sco_header(context, REQUEST, container=context, page_title=page_title)
def entreprise_footer(context, REQUEST):
"common entreprise footer"
return context.sco_footer(REQUEST)
return html_sco_header.sco_footer(context, REQUEST)
class ZEntreprises(
@ -111,7 +111,9 @@ class ZEntreprises(
<ul class="insidebar">"""
% params,
]
if REQUEST.AUTHENTICATED_USER.has_permission(ScoEntrepriseChange, self):
if REQUEST.AUTHENTICATED_USER.has_permission(
Permission.ScoEntrepriseChange, self
):
H.append(
"""<li class="insidebar"><a href="%(ScoURL)s/Entreprises/entreprise_create" class="sidebar">Nouvelle entreprise</a> </li>"""
% params
@ -138,7 +140,9 @@ class ZEntreprises(
<li class="insidebar"><a href="%(ScoURL)s/Entreprises/entreprise_correspondant_list?entreprise_id=%(entreprise_id)s" class="sidebar">Corresp.</a></li>"""
% params
) # """
if REQUEST.AUTHENTICATED_USER.has_permission(ScoEntrepriseChange, self):
if REQUEST.AUTHENTICATED_USER.has_permission(
Permission.ScoEntrepriseChange, self
):
H.append(
"""<li class="insidebar"><a href="%(ScoURL)s/Entreprises/entreprise_correspondant_create?entreprise_id=%(entreprise_id)s" class="sidebar">Nouveau Corresp.</a></li>"""
% params
@ -147,7 +151,9 @@ class ZEntreprises(
"""<li class="insidebar"><a href="%(ScoURL)s/Entreprises/entreprise_contact_list?entreprise_id=%(entreprise_id)s" class="sidebar">Contacts</a></li>"""
% params
)
if REQUEST.AUTHENTICATED_USER.has_permission(ScoEntrepriseChange, self):
if REQUEST.AUTHENTICATED_USER.has_permission(
Permission.ScoEntrepriseChange, self
):
H.append(
"""<li class="insidebar"><a href="%(ScoURL)s/Entreprises/entreprise_contact_create?entreprise_id=%(entreprise_id)s" class="sidebar">Nouveau "contact"</a></li>"""
% params
@ -156,7 +162,9 @@ class ZEntreprises(
#
H.append("""<br/><br/>%s""" % scu.icontag("entreprise_side_img"))
if not REQUEST.AUTHENTICATED_USER.has_permission(ScoEntrepriseChange, self):
if not REQUEST.AUTHENTICATED_USER.has_permission(
Permission.ScoEntrepriseChange, self
):
H.append("""<br/><em>(Lecture seule)</em>""")
H.append("""</div> </div> <!-- end of sidebar -->""")
return "".join(H)
@ -336,7 +344,9 @@ class ZEntreprises(
H.append(tab.html())
if REQUEST.AUTHENTICATED_USER.has_permission(ScoEntrepriseChange, self):
if REQUEST.AUTHENTICATED_USER.has_permission(
Permission.ScoEntrepriseChange, self
):
if entreprise_id:
H.append(
"""<p class="entreprise_create"><a class="entreprise_create" href="entreprise_contact_create?entreprise_id=%(entreprise_id)s">nouveau "contact"</a></p>
@ -443,7 +453,9 @@ class ZEntreprises(
H.append(tab.html())
if REQUEST.AUTHENTICATED_USER.has_permission(ScoEntrepriseChange, self):
if REQUEST.AUTHENTICATED_USER.has_permission(
Permission.ScoEntrepriseChange, self
):
H.append(
"""<p class="entreprise_create"><a class="entreprise_create" href="entreprise_correspondant_create?entreprise_id=%(entreprise_id)s">Ajouter un correspondant dans l'entreprise %(nom)s</a></p>
"""
@ -556,7 +568,9 @@ class ZEntreprises(
if tf[0] == 0:
H.append(tf[1])
if REQUEST.AUTHENTICATED_USER.has_permission(ScoEntrepriseChange, self):
if REQUEST.AUTHENTICATED_USER.has_permission(
Permission.ScoEntrepriseChange, self
):
H.append(
"""<p class="entreprise_descr"><a class="entreprise_delete" href="entreprise_contact_delete?entreprise_contact_id=%s">Supprimer ce contact</a> </p>"""
% entreprise_contact_id
@ -1130,7 +1144,7 @@ class ZEntreprises(
def entreprise_edit(self, entreprise_id, REQUEST=None, start=1):
"""Form. edit entreprise"""
authuser = REQUEST.AUTHENTICATED_USER
readonly = not authuser.has_permission(ScoEntrepriseChange, self)
readonly = not authuser.has_permission(Permission.ScoEntrepriseChange, self)
F = sco_entreprises.do_entreprise_list(
self, args={"entreprise_id": entreprise_id}
)[0]

View File

@ -74,6 +74,7 @@ except:
import sco_utils as scu
import VERSION
import mails
from notes_log import log
import sco_find_etud
import sco_users
@ -94,6 +95,7 @@ from sco_permissions import (
ScoSuperAdmin,
)
from sco_exceptions import ScoValueError, ScoLockedFormError, ScoGenError, AccessDenied
import html_sco_header
class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Implicit):
@ -131,7 +133,9 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
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(ScoSuperAdmin, self):
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>"""
@ -262,8 +266,8 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
if not REQUEST.AUTHENTICATED_USER.has_role("Manager"):
raise AccessDenied("vous n'avez pas le droit d'effectuer cette opération")
H = [
self.scodoc_top_html_header(
REQUEST, page_title="ScoDoc: changement mot de passe"
html_sco_header.scodoc_top_html_header(
self, REQUEST, page_title="ScoDoc: changement mot de passe"
)
]
if message:
@ -294,7 +298,8 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
[
d.id
for d in self._list_depts()
if (not viewable) or authuser.has_permission(ScoView, d.Scolarite)
if (not viewable)
or authuser.has_permission(Permission.ScoView, d.Scolarite)
],
name="depts",
format=format,
@ -364,54 +369,6 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
+ """ supprimé du serveur web (la base de données n'est pas affectée)!</p><p><a href="/ScoDoc">Continuer</a></p>"""
)
_top_level_css = """
<style type="text/css">
</style>"""
_html_begin = """<?xml version="1.0" encoding="%(encoding)s"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>%(page_title)s</title>
<meta http-equiv="Content-Type" content="text/html; charset=%(encoding)s" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="LANG" content="fr" />
<meta name="DESCRIPTION" content="ScoDoc" />
<link type="text/css" rel="stylesheet" href="/ScoDoc/static/libjs/jquery-ui-1.10.4.custom/css/smoothness/jquery-ui-1.10.4.custom.min.css" />
<link href="/ScoDoc/static/css/scodoc.css" rel="stylesheet" type="text/css" />
<link href="/ScoDoc/static/css/menu.css" rel="stylesheet" type="text/css" />
<script language="javascript" type="text/javascript" src="/ScoDoc/static/libjs/menu.js"></script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/libjs/sorttable.js"></script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/libjs/bubble.js"></script>
<script type="text/javascript">
window.onload=function(){enableTooltips("gtrcontent")};
</script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/jQuery/jquery.js"></script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/jQuery/jquery-migrate-1.2.0.min.js"></script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/libjs/jquery.field.min.js"></script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/libjs/jquery-ui-1.10.4.custom/js/jquery-ui-1.10.4.custom.min.js"></script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/libjs/qtip/jquery.qtip-3.0.3.min.js"></script>
<link type="text/css" rel="stylesheet" href="/ScoDoc/static/libjs/qtip/jquery.qtip-3.0.3.min.css" />
<script language="javascript" type="text/javascript" src="/ScoDoc/static/js/scodoc.js"></script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/js/etud_info.js"></script>
"""
def scodoc_top_html_header(self, REQUEST, page_title="ScoDoc"):
H = [
self._html_begin
% {"page_title": "ScoDoc: bienvenue", "encoding": scu.SCO_ENCODING},
self._top_level_css,
"""</head><body class="gtrcontent" id="gtrcontent">""",
scu.CUSTOM_HTML_HEADER_CNX,
]
return "\n".join(H)
security.declareProtected("View", "index_html")
def index_html(self, REQUEST=None, message=None):
@ -438,7 +395,9 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
pass
H = [
self.scodoc_top_html_header(REQUEST, page_title="ScoDoc: bienvenue"),
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:
@ -480,7 +439,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
else:
dest_folder = ""
for deptFolder in self._list_depts():
if authuser.has_permission(ScoView, deptFolder.Scolarite):
if authuser.has_permission(Permission.ScoView, deptFolder.Scolarite):
link_cls = "link_accessible"
else:
link_cls = "link_unauthorized"
@ -561,7 +520,7 @@ E. Viennet (Université Paris 13).</p>
authuser = REQUEST.AUTHENTICATED_USER
try:
dept = getattr(self, deptfoldername)
if authuser.has_permission(ScoView, dept):
if authuser.has_permission(Permission.ScoView, dept):
return REQUEST.RESPONSE.redirect("ScoDoc/%s/Scolarite" % deptfoldername)
except:
log(
@ -570,7 +529,7 @@ E. Viennet (Université Paris 13).</p>
)
H = [
self.standard_html_header(REQUEST),
html_sco_header.standard_html_header(),
"""<div style="margin: 1em;">
<h2>Scolarité du département %s</h2>"""
% deptfoldername,
@ -584,7 +543,7 @@ E. Viennet (Université Paris 13).</p>
</div>
"""
% self.ScoDocURL(),
self.standard_html_footer(REQUEST),
html_sco_header.standard_html_footer(),
]
return "\n".join(H)
@ -623,69 +582,6 @@ E. Viennet (Université Paris 13).</p>
return "<!-- query string -->\n" + "\n".join(H)
security.declareProtected("View", "standard_html_header")
def standard_html_header(self, REQUEST=None):
"""Standard HTML header for pages outside depts"""
# not used in ZScolar, see sco_header
return """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<title>ScoDoc: accueil</title>
<META http-equiv="Content-Type" content="text/html; charset=%s">
<META http-equiv="Content-Style-Type" content="text/css">
<META name="LANG" content="fr">
<META name="DESCRIPTION" content="ScoDoc: gestion scolarite">
<link HREF="/ScoDoc/static/css/scodoc.css" rel="stylesheet" type="text/css"/>
</head><body>%s""" % (
scu.SCO_ENCODING,
scu.CUSTOM_HTML_HEADER_CNX,
)
security.declareProtected("View", "standard_html_footer")
def standard_html_footer(self, REQUEST=None):
"""Le pied de page HTML de la page d'accueil."""
return """<p class="footer">
Problème de connexion (identifiant, mot de passe): <em>contacter votre responsable ou chef de département</em>.</p>
<p>Probl&egrave;mes et suggestions sur le logiciel: <a href="mailto:%s">%s</a></p>
<p><em>ScoDoc est un logiciel libre développé par Emmanuel Viennet.</em></p>
</body></html>""" % (
scu.SCO_USERS_LIST,
scu.SCO_USERS_LIST,
)
# sendEmail is not used through the web
def sendEmail(self, msg):
# sends an email to the address using the mailhost, if there is one
try:
mail_host = self.MailHost
except:
log("warning: sendEmail: no MailHost found !")
return
# a failed notification shouldn't cause a Zope error on a site.
try:
mail_host.send(msg.as_string())
log("sendEmail: ok")
except Exception as e:
log("sendEmail: exception while sending message")
log(e)
pass
def sendEmailFromException(self, msg):
# Send email by hand, as it seems to be not possible to use Zope Mail Host
# from an exception handler (see https://bugs.launchpad.net/zope2/+bug/246748)
log("sendEmailFromException")
try:
p = os.popen("sendmail -t", "w") # old brute force method
p.write(msg.as_string())
exitcode = p.close()
if exitcode:
log("sendmail exit code: %s" % exitcode)
except:
log("an exception occurred sending mail")
security.declareProtected("View", "standard_error_message")
def standard_error_message(
@ -733,18 +629,18 @@ Problème de connexion (identifiant, mot de passe): <em>contacter votre responsa
elif error_type in ("ScoValueError", "FormatError"):
# Not a bug, presents a gentle message to the user:
H = [
self.standard_html_header(REQUEST),
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(self.standard_html_footer(REQUEST))
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(self.standard_html_header(REQUEST))
H.append(html_sco_header.standard_html_header())
except:
pass
H.append(
@ -782,7 +678,7 @@ Problème de connexion (identifiant, mot de passe): <em>contacter votre responsa
% params
)
try:
H.append(self.standard_html_footer(REQUEST))
H.append(html_sco_header.standard_html_footer())
except:
log("no footer found for error page")
pass
@ -798,81 +694,12 @@ ErrorType: %(error_type)s
% params
)
self.send_debug_alert(txt, REQUEST=REQUEST)
mails.send_debug_alert(context, txt, REQUEST=REQUEST)
# ---
log("done processing exception")
# log( '\n page=\n' + '\n'.join(H) )
return "\n".join(H)
def _report_request(self, REQUEST, fmt="txt"):
"""string describing current request for bug reports"""
QUERY_STRING = REQUEST.get("QUERY_STRING", "")
if QUERY_STRING:
QUERY_STRING = "?" + QUERY_STRING
if fmt == "txt":
REFERER = REQUEST.get("HTTP_REFERER", "")
HTTP_USER_AGENT = REQUEST.get("HTTP_USER_AGENT", "")
else:
REFERER = "na"
HTTP_USER_AGENT = "na"
params = dict(
AUTHENTICATED_USER=REQUEST.get("AUTHENTICATED_USER", ""),
dt=time.asctime(),
URL=REQUEST.get("URL", ""),
QUERY_STRING=QUERY_STRING,
METHOD=REQUEST.get("REQUEST_METHOD", ""),
REFERER=REFERER,
HTTP_USER_AGENT=HTTP_USER_AGENT,
form=REQUEST.get("form", ""),
HTTP_X_FORWARDED_FOR=REQUEST.get("HTTP_X_FORWARDED_FOR", ""),
svn_version=scu.get_svn_version(self.file_path),
SCOVERSION=VERSION.SCOVERSION,
)
txt = (
"""
Version: %(SCOVERSION)s
User: %(AUTHENTICATED_USER)s
Date: %(dt)s
URL: %(URL)s%(QUERY_STRING)s
Method: %(METHOD)s
REFERER: %(REFERER)s
Form: %(form)s
Origin: %(HTTP_X_FORWARDED_FOR)s
Agent: %(HTTP_USER_AGENT)s
"""
% params
)
if fmt == "html":
txt = txt.replace("\n", "<br/>")
return txt
security.declareProtected(
ScoSuperAdmin, "send_debug_alert"
) # not called through the web
def send_debug_alert(self, txt, REQUEST=None):
"""Send an alert email (bug report) to ScoDoc developpers"""
if not scu.SCO_EXC_MAIL:
log("send_debug_alert: email disabled")
return
if REQUEST:
txt = self._report_request(REQUEST) + txt
URL = REQUEST.get("URL", "")
else:
URL = "send_debug_alert"
msg = MIMEMultipart()
subj = Header("[scodoc] exc %s" % URL, scu.SCO_ENCODING)
msg["Subject"] = subj
recipients = [scu.SCO_EXC_MAIL]
msg["To"] = " ,".join(recipients)
msg["From"] = "scodoc-alert"
msg.epilogue = ""
msg.attach(MIMEText(txt, "plain", scu.SCO_ENCODING))
self.sendEmailFromException(msg)
log("Sent mail alert:\n" + txt)
security.declareProtected("View", "scodoc_admin")
def scodoc_admin(self, REQUEST=None):
@ -882,7 +709,9 @@ Agent: %(HTTP_USER_AGENT)s
return e
H = [
self.scodoc_top_html_header(REQUEST, page_title="ScoDoc: bienvenue"),
html_sco_header.scodoc_top_html_header(
self, REQUEST, page_title="ScoDoc: bienvenue"
),
"""
<h3>Administration ScoDoc</h3>

View File

@ -141,7 +141,7 @@ class ZScoUsers(
H = [self.sco_header(REQUEST, page_title="Gestion des utilisateurs")]
H.append("<h2>Gestion des utilisateurs</h2>")
if authuser.has_permission(ScoUsersAdmin, self):
if authuser.has_permission(Permission.ScoUsersAdmin, self):
H.append(
'<p><a href="create_user_form" class="stdlink">Ajouter un utilisateur</a>'
)
@ -170,7 +170,7 @@ class ZScoUsers(
with_olds=with_olds,
format=format,
REQUEST=REQUEST,
with_links=authuser.has_permission(ScoUsersAdmin, self),
with_links=authuser.has_permission(Permission.ScoUsersAdmin, self),
)
if format != "html":
return L
@ -338,7 +338,7 @@ class ZScoUsers(
if str(authuser) == user_name:
return True
# has permission ?
if not authuser.has_permission(ScoUsersAdmin, self):
if not authuser.has_permission(Permission.ScoUsersAdmin, self):
return False
# Ok, now check that authuser can manage users from this departement
# Get user info
@ -499,11 +499,11 @@ class ZScoUsers(
"<p>L' utilisateur '%s' n'est pas défini dans ce module.</p>"
% user_name
)
if authuser.has_permission(ScoEditAllNotes, self):
if authuser.has_permission(Permission.ScoEditAllNotes, self):
H.append("<p>(il peut modifier toutes les notes)</p>")
if authuser.has_permission(ScoEditAllEvals, self):
if authuser.has_permission(Permission.ScoEditAllEvals, self):
H.append("<p>(il peut modifier toutes les évaluations)</p>")
if authuser.has_permission(ScoImplement, self):
if authuser.has_permission(Permission.ScoImplement, self):
H.append("<p>(il peut creer des formations)</p>")
else:
H.append(
@ -520,7 +520,7 @@ class ZScoUsers(
<li><a class="stdlink" href="form_change_password?user_name=%(user_name)s">changer le mot de passe</a></li>"""
% info[0]
)
if authuser.has_permission(ScoUsersAdmin, self):
if authuser.has_permission(Permission.ScoUsersAdmin, self):
H.append(
"""
<li><a class="stdlink" href="create_user_form?user_name=%(user_name)s&edit=1">modifier/déactiver ce compte</a></li>
@ -560,7 +560,7 @@ class ZScoUsers(
b = "non"
H.append("<li>%s : %s</li>" % (permname, b))
H.append("</ul></div>")
if authuser.has_permission(ScoUsersAdmin, self):
if authuser.has_permission(Permission.ScoUsersAdmin, self):
H.append(
'<p><a class="stdlink" href="%s/Users">Liste de tous les utilisateurs</a></p>'
% self.ScoURL()
@ -602,13 +602,13 @@ class ZScoUsers(
else:
H.append("<h2>Création d'un utilisateur</h2>")
if authuser.has_permission(ScoSuperAdmin, self):
if authuser.has_permission(Permission.ScoSuperAdmin, self):
H.append("""<p class="warning">Vous êtes super administrateur !</p>""")
# Noms de roles pouvant etre attribues aux utilisateurs via ce dialogue
# si pas SuperAdmin, restreint aux rôles EnsX, SecrX, DeptX
#
if authuser.has_permission(ScoSuperAdmin, self):
if authuser.has_permission(Permission.ScoSuperAdmin, self):
log("create_user_form called by %s (super admin)" % (auth_name,))
editable_roles = set(self._all_roles())
else:

File diff suppressed because it is too large Load Diff

View File

@ -60,7 +60,7 @@ import sco_bulletins_xml
def go(app, n=0, verbose=True):
context = app.ScoDoc.objectValues("Folder")[n].Scolarite
if verbose:
print("context in dept ", context.DeptId())
print("context in dept ", sco_core.get_dept_id())
return context
@ -72,9 +72,9 @@ def go_dept(app, dept, verbose=True):
except AttributeError:
# ignore other folders, like old "icons"
continue
if context.DeptId() == dept:
if sco_core.get_dept_id() == dept:
if verbose:
print("context in dept ", context.DeptId())
print("context in dept ", sco_core.get_dept_id())
return context
raise ValueError("dep %s not found" % dept)

View File

@ -626,7 +626,7 @@ class GenTable:
if with_html_headers:
H.append(
self.html_header
or context.sco_header(
or html_sco_header.sco_header(context,
REQUEST,
page_title=page_title,
javascripts=javascripts,
@ -637,7 +637,7 @@ class GenTable:
H.append(html_title)
H.append(self.html())
if with_html_headers:
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
elif format == "pdf":
objects = self.pdf()

View File

@ -28,7 +28,7 @@
import cgi
import sco_utils as scu
from sco_formsemestre_status import formsemestre_page_title
import VERSION
"""
HTML Header/Footer for ScoDoc pages
@ -50,6 +50,87 @@ BOOTSTRAP_MULTISELECT_CSS = [
"libjs/bootstrap-multiselect/bootstrap-multiselect.css",
]
def standard_html_header():
"""Standard HTML header for pages outside depts"""
# not used in ZScolar, see sco_header
return """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<title>ScoDoc: accueil</title>
<META http-equiv="Content-Type" content="text/html; charset=%s">
<META http-equiv="Content-Style-Type" content="text/css">
<META name="LANG" content="fr">
<META name="DESCRIPTION" content="ScoDoc: gestion scolarite">
<link HREF="/ScoDoc/static/css/scodoc.css" rel="stylesheet" type="text/css"/>
</head><body>%s""" % (
scu.SCO_ENCODING,
scu.CUSTOM_HTML_HEADER_CNX,
)
def standard_html_footer():
"""Le pied de page HTML de la page d'accueil."""
return """<p class="footer">
Problème de connexion (identifiant, mot de passe): <em>contacter votre responsable ou chef de département</em>.</p>
<p>Probl&egrave;mes et suggestions sur le logiciel: <a href="mailto:%s">%s</a></p>
<p><em>ScoDoc est un logiciel libre développé par Emmanuel Viennet.</em></p>
</body></html>""" % (
scu.SCO_USERS_LIST,
scu.SCO_USERS_LIST,
)
_TOP_LEVEL_CSS = """
<style type="text/css">
</style>"""
_HTML_BEGIN = """<?xml version="1.0" encoding="%(encoding)s"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>%(page_title)s</title>
<meta http-equiv="Content-Type" content="text/html; charset=%(encoding)s" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="LANG" content="fr" />
<meta name="DESCRIPTION" content="ScoDoc" />
<link type="text/css" rel="stylesheet" href="/ScoDoc/static/libjs/jquery-ui-1.10.4.custom/css/smoothness/jquery-ui-1.10.4.custom.min.css" />
<link href="/ScoDoc/static/css/scodoc.css" rel="stylesheet" type="text/css" />
<link href="/ScoDoc/static/css/menu.css" rel="stylesheet" type="text/css" />
<script language="javascript" type="text/javascript" src="/ScoDoc/static/libjs/menu.js"></script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/libjs/sorttable.js"></script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/libjs/bubble.js"></script>
<script type="text/javascript">
window.onload=function(){enableTooltips("gtrcontent")};
</script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/jQuery/jquery.js"></script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/jQuery/jquery-migrate-1.2.0.min.js"></script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/libjs/jquery.field.min.js"></script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/libjs/jquery-ui-1.10.4.custom/js/jquery-ui-1.10.4.custom.min.js"></script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/libjs/qtip/jquery.qtip-3.0.3.min.js"></script>
<link type="text/css" rel="stylesheet" href="/ScoDoc/static/libjs/qtip/jquery.qtip-3.0.3.min.css" />
<script language="javascript" type="text/javascript" src="/ScoDoc/static/js/scodoc.js"></script>
<script language="javascript" type="text/javascript" src="/ScoDoc/static/js/etud_info.js"></script>
"""
def scodoc_top_html_header(context, REQUEST, page_title="ScoDoc"):
H = [
HTML_BEGIN % {"page_title": "ScoDoc: bienvenue", "encoding": scu.SCO_ENCODING},
TOP_LEVEL_CSS,
"""</head><body class="gtrcontent" id="gtrcontent">""",
scu.CUSTOM_HTML_HEADER_CNX,
]
return "\n".join(H)
# Header:
def sco_header(
context,
@ -73,14 +154,6 @@ def sco_header(
):
"Main HTML page header for ScoDoc"
# If running for first time, initialize roles and permissions
try:
ri = context.roles_initialized
except:
ri = None # old instances does not have this attribute
if ri == "0":
context._setup_initial_roles_and_permissions()
# context est une instance de ZScolar. container est une instance qui "acquiert" ZScolar
if container:
context = container # je pense que cela suffit pour ce qu'on veut.
@ -94,7 +167,7 @@ def sco_header(
head_message = REQUEST.form["head_message"]
params = {
"page_title": page_title or context.title_or_id(),
"page_title": page_title or VERSION.SCONAME,
"no_side_bar": no_side_bar,
"ScoURL": context.ScoURL(),
"encoding": scu.SCO_ENCODING,
@ -229,7 +302,7 @@ def sco_header(
H.append(scu.CUSTOM_HTML_HEADER)
#
if not no_side_bar:
H.append(context.sidebar(REQUEST))
H.append(html_sidebar.sidebar(context, REQUEST))
H.append("""<div class="gtrcontent" id="gtrcontent">""")
#
# Barre menu semestre:
@ -263,3 +336,30 @@ def sco_footer(context, REQUEST=None):
return (
"""</div><!-- /gtrcontent -->""" + scu.CUSTOM_HTML_FOOTER + """</body></html>"""
)
def html_sem_header(
context,
REQUEST,
title,
sem=None,
with_page_header=True,
with_h2=True,
page_title=None,
**args
):
"Titre d'une page semestre avec lien vers tableau de bord"
# sem now unused and thus optional...
if with_page_header:
h = sco_header(
context, REQUEST, page_title="%s" % (page_title or title), **args
)
else:
h = ""
if with_h2:
return h + """<h2 class="formsemestre">%s</h2>""" % (title)
else:
return h
from sco_formsemestre_status import formsemestre_page_title

View File

@ -53,7 +53,7 @@ def sidebar_common(context, REQUEST=None):
'<a class="scodoc_title" href="about">ScoDoc</a>',
'<div id="authuser"><a id="authuserlink" href="%(ScoURL)s/Users/userinfo">%(authuser)s</a><br/><a id="deconnectlink" href="%(ScoURL)s/acl_users/logout">déconnexion</a></div>'
% params,
context.sidebar_dept(REQUEST),
sidebar_dept(context, REQUEST),
"""<h2 class="insidebar">Scolarit&eacute;</h2>
<a href="%(ScoURL)s" class="sidebar">Semestres</a> <br/>
<a href="%(NotesURL)s" class="sidebar">Programmes</a> <br/>
@ -62,14 +62,14 @@ def sidebar_common(context, REQUEST=None):
% params,
]
if authuser.has_permission(ScoUsersAdmin, context) or authuser.has_permission(
ScoUsersView, context
):
if authuser.has_permission(
Permission.ScoUsersAdmin, context
) or authuser.has_permission(ScoUsersView, context):
H.append(
"""<a href="%(UsersURL)s" class="sidebar">Utilisateurs</a> <br/>""" % params
)
if authuser.has_permission(ScoChangePreferences, context):
if authuser.has_permission(Permission.ScoChangePreferences, context):
H.append(
"""<a href="%(ScoURL)s/edit_preferences" class="sidebar">Paramétrage</a> <br/>"""
% params
@ -120,7 +120,7 @@ def sidebar(context, REQUEST=None):
)
H.append("<ul>")
if REQUEST.AUTHENTICATED_USER.has_permission(ScoAbsChange, context):
if REQUEST.AUTHENTICATED_USER.has_permission(Permission.ScoAbsChange, context):
H.append(
"""
<li> <a href="%(ScoURL)s/Absences/SignaleAbsenceEtud?etudid=%(etudid)s">Ajouter</a></li>
@ -129,7 +129,7 @@ def sidebar(context, REQUEST=None):
"""
% params
)
if context.get_preference("handle_billets_abs"):
if sco_preferences.get_preference(context, "handle_billets_abs"):
H.append(
"""<li> <a href="%(ScoURL)s/Absences/listeBilletsEtud?etudid=%(etudid)s">Billets</a></li>"""
% params
@ -166,9 +166,9 @@ def sidebar_dept(context, REQUEST=None):
"""Partie supérieure de la marge de gauche"""
infos = {
"BASE0": REQUEST.BASE0,
"DeptIntranetTitle": context.get_preference("DeptIntranetTitle"),
"DeptIntranetURL": context.get_preference("DeptIntranetURL"),
"DeptName": context.get_preference("DeptName"),
"DeptIntranetTitle": sco_preferences.get_preference(context, "DeptIntranetTitle"),
"DeptIntranetURL": sco_preferences.get_preference(context, "DeptIntranetURL"),
"DeptName": sco_preferences.get_preference(context, "DeptName"),
"ScoURL": context.ScoURL(),
}

141
app/scodoc/mails.py Normal file
View File

@ -0,0 +1,141 @@
# -*- 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
#
##############################################################################
"""Gestion des emails
"""
# XXX WIP: à ré-écrire pour ScoDoc 8 (étaient des méthodes de ZScoDoc)
import os
from email.MIMEMultipart import ( # pylint: disable=no-name-in-module,import-error
MIMEMultipart,
)
from email.MIMEText import MIMEText # pylint: disable=no-name-in-module,import-error
from email.MIMEBase import MIMEBase # pylint: disable=no-name-in-module,import-error
from email.Header import Header # pylint: disable=no-name-in-module,import-error
from email import Encoders # pylint: disable=no-name-in-module,import-error
import sco_utils as scu
from notes_log import log
def sendEmail(context, msg): # TODO A REECRIRE ScoDoc8
"""Send an email to the address using the mailhost, if there is one."""
raise NotImplementedError()
try:
mail_host = context.MailHost
except:
log("warning: sendEmail: no MailHost found !")
return
# a failed notification shouldn't cause a Zope error on a site.
try:
mail_host.send(msg.as_string())
log("sendEmail: ok")
except Exception as e:
log("sendEmail: exception while sending message")
log(e)
pass
def sendEmailFromException(context, msg):
# Send email by hand, as it seems to be not possible to use Zope Mail Host
# from an exception handler (see https://bugs.launchpad.net/zope2/+bug/246748)
log("sendEmailFromException")
try:
p = os.popen("sendmail -t", "w") # old brute force method
p.write(msg.as_string())
exitcode = p.close()
if exitcode:
log("sendmail exit code: %s" % exitcode)
except:
log("an exception occurred sending mail")
def send_debug_alert(context, txt, REQUEST=None):
"""Send an alert email (bug report) to ScoDoc developpers"""
if not scu.SCO_EXC_MAIL:
log("send_debug_alert: email disabled")
return
if REQUEST:
txt = _report_request(context, REQUEST) + txt
URL = REQUEST.get("URL", "")
else:
URL = "send_debug_alert"
msg = MIMEMultipart()
subj = Header("[scodoc] exc %s" % URL, scu.SCO_ENCODING)
msg["Subject"] = subj
recipients = [scu.SCO_EXC_MAIL]
msg["To"] = " ,".join(recipients)
msg["From"] = "scodoc-alert"
msg.epilogue = ""
msg.attach(MIMEText(txt, "plain", scu.SCO_ENCODING))
sendEmailFromException(context, msg)
log("Sent mail alert:\n" + txt)
def _report_request(context, REQUEST, fmt="txt"):
"""string describing current request for bug reports"""
QUERY_STRING = REQUEST.get("QUERY_STRING", "")
if QUERY_STRING:
QUERY_STRING = "?" + QUERY_STRING
if fmt == "txt":
REFERER = REQUEST.get("HTTP_REFERER", "")
HTTP_USER_AGENT = REQUEST.get("HTTP_USER_AGENT", "")
else:
REFERER = "na"
HTTP_USER_AGENT = "na"
params = dict(
AUTHENTICATED_USER=REQUEST.get("AUTHENTICATED_USER", ""),
dt=time.asctime(),
URL=REQUEST.get("URL", ""),
QUERY_STRING=QUERY_STRING,
METHOD=REQUEST.get("REQUEST_METHOD", ""),
REFERER=REFERER,
HTTP_USER_AGENT=HTTP_USER_AGENT,
form=REQUEST.get("form", ""),
HTTP_X_FORWARDED_FOR=REQUEST.get("HTTP_X_FORWARDED_FOR", ""),
svn_version=scu.get_svn_version(context.file_path),
SCOVERSION=VERSION.SCOVERSION,
)
txt = (
"""
Version: %(SCOVERSION)s
User: %(AUTHENTICATED_USER)s
Date: %(dt)s
URL: %(URL)s%(QUERY_STRING)s
Method: %(METHOD)s
REFERER: %(REFERER)s
Form: %(form)s
Origin: %(HTTP_X_FORWARDED_FOR)s
Agent: %(HTTP_USER_AGENT)s
"""
% params
)
if fmt == "html":
txt = txt.replace("\n", "<br/>")
return txt

View File

@ -21,6 +21,8 @@ from email.MIMEBase import MIMEBase # pylint: disable=no-name-in-module,import-
from email.Header import Header # pylint: disable=no-name-in-module,import-error
from email import Encoders # pylint: disable=no-name-in-module,import-error
import mails
# Simple & stupid file logguer, used only to debug
# (logging to SQL is done in scolog)
@ -115,12 +117,12 @@ def sendAlarm(context, subj, txt):
msg = MIMEMultipart()
subj = Header(subj, sco_utils.SCO_ENCODING)
msg["Subject"] = subj
msg["From"] = context.get_preference("email_from_addr")
msg["From"] = sco_preferences.get_preference(context, "email_from_addr")
msg["To"] = ALARM_DESTINATION
msg.epilogue = ""
txt = MIMEText(txt, "plain", sco_utils.SCO_ENCODING)
msg.attach(txt)
context.sendEmail(msg)
mails.sendEmail(context, msg)
# Debug: log call stack

View File

@ -32,7 +32,7 @@ import time
import pdb
import inspect
import sco_core
import scolars
import sco_groups
from notes_log import log, logCallStack
@ -173,7 +173,9 @@ class NotesTable:
self.moduleimpl_stats = {} # { moduleimpl_id : {stats} }
self._uecoef = {} # { ue_id : coef } cache coef manuels ue cap
self._evaluations_etats = None # liste des evaluations avec état
self.use_ue_coefs = context.get_preference("use_ue_coefs", formsemestre_id)
self.use_ue_coefs = sco_preferences.get_preference(
context, "use_ue_coefs", formsemestre_id
)
# Infos sur les etudiants
self.inscrlist = context.do_formsemestre_inscription_list(
args={"formsemestre_id": formsemestre_id}
@ -309,7 +311,7 @@ class NotesTable:
# fallback *** should not occur ***
# txt = '\nkey missing in cmprows !!!\nx=%s\ny=%s\n' % (str(x),str(y))
# txt += '\nrangalpha=%s' % str(rangalpha) + '\n\nT=%s' % str(T)
# context.send_debug_alert(txt, REQUEST=None)
# send_debug_alert(txt, REQUEST=None)
# return cmp(x,y)
T.sort(cmprows)
@ -1173,7 +1175,7 @@ class NotesTable:
"comp_ue_capitalisees: recomputing UE moy (etudid=%s, ue_id=%s formsemestre_id=%s)"
% (etudid, ue_cap["ue_id"], ue_cap["formsemestre_id"])
)
nt_cap = self.context._getNotesCache().get_NotesTable(
nt_cap = self.sco_core.get_notes_cache(context).get_NotesTable(
self.context, ue_cap["formsemestre_id"]
) # > UE capitalisees par un etud
moy_ue_cap = nt_cap.get_etud_ue_status(etudid, ue_cap["ue_id"])[
@ -1421,7 +1423,9 @@ class CacheNotesTable:
self.cache = {}
self.pdfcache = {}
self._call_all_listeners()
context.get_evaluations_cache().inval_cache()
sco_core.get_evaluations_cache(
context,
).inval_cache()
else:
# formsemestre_id modifié:
# on doit virer formsemestre_id et tous les semestres
@ -1438,7 +1442,9 @@ class CacheNotesTable:
)
del self.cache[formsemestre_id]
self._call_listeners(formsemestre_id)
context.get_evaluations_cache().inval_cache()
sco_core.get_evaluations_cache(
context,
).inval_cache()
for formsemestre_id in to_trash:
for (

View File

@ -71,7 +71,7 @@ def get_code_latex_from_scodoc_preference(
Extrait le template (ou le tag d'annotation au regard du champ fourni) des préférences LaTeX
et s'assure qu'il est renvoyé au format unicode
"""
template_latex = context.get_preference(champ, formsemestre_id)
template_latex = sco_preferences.get_preference(context, champ, formsemestre_id)
# Conversion du template en unicode:
if template_latex:
template_latex = template_latex.decode(scu.SCO_ENCODING)
@ -235,7 +235,7 @@ def get_code_latex_avis_etudiant(
def get_annotation_PE(context, etudid, tag_annotation_pe):
"""Renvoie l'annotation PE dans la liste de ces annotations ;
Cette annotation est reconnue par la présence d'un tag **PE**
(cf. context.get_preferences -> pe_tag_annotation_avis_latex).
(cf. .get_preferences -> pe_tag_annotation_avis_latex).
Result: chaine unicode
"""

View File

@ -54,7 +54,9 @@ import pe_avislatex
def _pe_view_sem_recap_form(context, formsemestre_id, REQUEST=None):
H = [
context.sco_header(REQUEST, page_title="Avis de poursuite d'études"),
html_sco_header.sco_header(
context, REQUEST, page_title="Avis de poursuite d'études"
),
"""<h2 class="formsemestre">Génération des avis de poursuites d'études</h2>
<p class="help">
Cette fonction génère un ensemble de fichiers permettant d'éditer des avis de poursuites d'études.
@ -77,7 +79,7 @@ def _pe_view_sem_recap_form(context, formsemestre_id, REQUEST=None):
formsemestre_id=formsemestre_id
),
]
return "\n".join(H) + context.sco_footer(REQUEST)
return "\n".join(H) + html_sco_header.sco_footer(context, REQUEST)
def pe_view_sem_recap(
@ -95,7 +97,7 @@ def pe_view_sem_recap(
"""
if REQUEST and REQUEST.method == "GET":
return _pe_view_sem_recap_form(context, formsemestre_id, REQUEST=REQUEST)
prefs = context.get_preferences(formsemestre_id=formsemestre_id)
prefs = sco_preferences.SemPreferences(context, formsemestre_id=formsemestre_id)
semBase = sco_formsemestre.get_formsemestre(context, formsemestre_id)

View File

@ -45,7 +45,7 @@ import sco_compute_moy
def is_work_saturday(context):
"Vrai si le samedi est travaillé"
return int(context.get_preference("work_saturday"))
return int(sco_preferences.get_preference(context, "work_saturday"))
def MonthNbDays(month, year):

View File

@ -37,7 +37,7 @@ from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.header import Header
import mails
import notesdb as ndb
import sco_utils as scu
from notes_log import log
@ -71,7 +71,9 @@ def do_abs_notify(context, sem, etudid, date, nbabs, nbabsjust):
formsemestre_id = sem["formsemestre_id"]
else:
formsemestre_id = None
prefs = context.get_preferences(formsemestre_id=sem["formsemestre_id"])
prefs = sco_preferences.SemPreferences(
context, formsemestre_id=sem["formsemestre_id"]
)
destinations = abs_notify_get_destinations(
context, sem, prefs, etudid, date, nbabs, nbabsjust
@ -81,7 +83,7 @@ def do_abs_notify(context, sem, etudid, date, nbabs, nbabsjust):
return # abort
# Vérification fréquence (pour ne pas envoyer de mails trop souvent)
abs_notify_max_freq = context.get_preference("abs_notify_max_freq")
abs_notify_max_freq = sco_preferences.get_preference(context, "abs_notify_max_freq")
destinations_filtered = []
for email_addr in destinations:
nbdays_since_last_notif = user_nbdays_since_last_notif(
@ -114,7 +116,7 @@ def abs_notify_send(
for email in destinations:
del msg["To"]
msg["To"] = email
context.sendEmail(msg)
mails.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)""",
@ -179,10 +181,10 @@ def abs_notify_is_above_threshold(context, etudid, nbabs, nbabsjust, formsemestr
(nbabs > abs_notify_abs_threshold)
(nbabs - nbabs_last_notified) > abs_notify_abs_increment
"""
abs_notify_abs_threshold = context.get_preference(
abs_notify_abs_threshold = sco_preferences.get_preference(context,
"abs_notify_abs_threshold", formsemestre_id
)
abs_notify_abs_increment = context.get_preference(
abs_notify_abs_increment = sco_preferences.get_preference(context,
"abs_notify_abs_increment", formsemestre_id
)
nbabs_last_notified = etud_nbabs_last_notified(context, etudid, formsemestre_id)

View File

@ -88,7 +88,13 @@ def doSignaleAbsence(
nbadded += 2
else:
context._AddAbsence(
etudid, jour, demijournee, estjust, REQUEST, description_abs, moduleimpl_id
etudid,
jour,
demijournee,
estjust,
REQUEST,
description_abs,
moduleimpl_id,
)
nbadded += 1
#
@ -110,8 +116,10 @@ def doSignaleAbsence(
if modimpl["moduleimpl_id"] == moduleimpl_id:
M = "dans le module %s" % modimpl["module"]["code"]
H = [
context.sco_header(
REQUEST, page_title="Signalement d'une absence pour %(nomprenom)s" % etud
html_sco_header.sco_header(
context,
REQUEST,
page_title="Signalement d'une absence pour %(nomprenom)s" % etud,
),
"""<h2>Signalement d'absences</h2>""",
]
@ -134,7 +142,7 @@ def doSignaleAbsence(
% etud
)
H.append(sco_find_etud.form_search_etud(context, REQUEST))
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
@ -145,7 +153,7 @@ def SignaleAbsenceEtud(context, REQUEST=None): # etudid implied
etudid = etud["etudid"]
disabled = False
if not etud["cursem"]:
require_module = context.get_preference(
require_module = sco_preferences.get_preference(context,
"abs_require_module"
) # on utilise la pref globale car pas de sem courant
if require_module:
@ -156,7 +164,7 @@ def SignaleAbsenceEtud(context, REQUEST=None): # etudid implied
menu_module = ""
else:
formsemestre_id = etud["cursem"]["formsemestre_id"]
require_module = context.get_preference("abs_require_module", formsemestre_id)
require_module = sco_preferences.get_preference(context, "abs_require_module", formsemestre_id)
nt = context.Notes._getNotesCache().get_NotesTable(
context.Notes, formsemestre_id
)
@ -197,8 +205,10 @@ def SignaleAbsenceEtud(context, REQUEST=None): # etudid implied
menu_module += """</select></p>"""
H = [
context.sco_header(
REQUEST, page_title="Signalement d'une absence pour %(nomprenom)s" % etud
html_sco_header.sco_header(
context,
REQUEST,
page_title="Signalement d'une absence pour %(nomprenom)s" % etud,
),
"""<table><tr><td>
<h2>Signalement d'une absence pour %(nomprenom)s</h2>
@ -252,7 +262,7 @@ Raison: <input type="text" name="description" size="42"/> (optionnel)
"menu_module": menu_module,
"disabled": "disabled" if disabled else "",
},
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)
@ -310,8 +320,10 @@ def doJustifAbsence(
nbadded += 1
#
H = [
context.sco_header(
REQUEST, page_title="Justification d'une absence pour %(nomprenom)s" % etud
html_sco_header.sco_header(
context,
REQUEST,
page_title="Justification d'une absence pour %(nomprenom)s" % etud,
),
"""<h2>Justification d'absences</h2>""",
]
@ -336,7 +348,7 @@ def doJustifAbsence(
% etud
)
H.append(sco_find_etud.form_search_etud(context, REQUEST))
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
@ -346,8 +358,10 @@ def JustifAbsenceEtud(context, REQUEST=None): # etudid implied
etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0]
etudid = etud["etudid"]
H = [
context.sco_header(
REQUEST, page_title="Justification d'une absence pour %(nomprenom)s" % etud
html_sco_header.sco_header(
context,
REQUEST,
page_title="Justification d'une absence pour %(nomprenom)s" % etud,
),
"""<table><tr><td>
<h2>Justification d'une absence pour %(nomprenom)s</h2>
@ -390,7 +404,7 @@ Raison: <input type="text" name="description" size="42"/> (optionnel)
</form> """
% etud,
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)
@ -415,8 +429,10 @@ def doAnnuleAbsence(
nbadded += 1
#
H = [
context.sco_header(
REQUEST, page_title="Annulation d'une absence pour %(nomprenom)s" % etud
html_sco_header.sco_header(
context,
REQUEST,
page_title="Annulation d'une absence pour %(nomprenom)s" % etud,
),
"""<h2>Annulation d'absences pour %(nomprenom)s</h2>""" % etud,
]
@ -441,7 +457,7 @@ autre absence pour <b>%(nomprenom)s</b></a></li>
% etud
)
H.append(sco_find_etud.form_search_etud(context, REQUEST))
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
@ -452,8 +468,10 @@ def AnnuleAbsenceEtud(context, REQUEST=None): # etudid implied
etudid = etud["etudid"]
H = [
context.sco_header(
REQUEST, page_title="Annulation d'une absence pour %(nomprenom)s" % etud
html_sco_header.sco_header(
context,
REQUEST,
page_title="Annulation d'une absence pour %(nomprenom)s" % etud,
),
"""<table><tr><td>
<h2><font color="#FF0000">Annulation</font> d'une absence pour %(nomprenom)s</h2>
@ -526,7 +544,7 @@ def AnnuleAbsenceEtud(context, REQUEST=None): # etudid implied
</form>
</td></tr></table>"""
% etud,
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)
@ -551,7 +569,8 @@ def doAnnuleJustif(
nbadded += 1
#
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Annulation d'une justification pour %(nomprenom)s" % etud,
),
@ -578,7 +597,7 @@ autre absence pour <b>%(nomprenom)s</b></a></li>
% etud
)
H.append(sco_find_etud.form_search_etud(context, REQUEST))
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
@ -586,7 +605,7 @@ def EtatAbsences(context, REQUEST=None):
"""Etat des absences: choix du groupe"""
# crude portage from 1999 DTML
H = [
context.sco_header(REQUEST, page_title="Etat des absences"),
html_sco_header.sco_header(context, REQUEST, page_title="Etat des absences"),
"""<h2>Etat des absences pour un groupe</h2>
<form action="EtatAbsencesGr" method="GET">""",
formChoixSemestreGroupe(context),
@ -603,7 +622,7 @@ def EtatAbsences(context, REQUEST=None):
</td></tr></table>
</form>"""
% (scu.AnneeScolaire(REQUEST), datetime.datetime.now().strftime("%d/%m/%Y")),
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)
@ -666,7 +685,8 @@ def CalAbs(context, REQUEST=None): # etud implied
#
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Calendrier des absences de %(nomprenom)s" % etud,
cssstyles=["css/calabs.css"],
@ -706,7 +726,7 @@ def CalAbs(context, REQUEST=None): # etud implied
H.append("selected")
H.append(""">%s</option>""" % y)
H.append("""</select></form>""")
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
@ -746,7 +766,9 @@ def ListeAbsEtud(
base_url=base_url_nj,
filename="abs_" + scu.make_filename(etud["nomprenom"]),
caption="Absences non justifiées de %(nomprenom)s" % etud,
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
tab_absjust = GenTable(
titles=titles,
@ -757,7 +779,9 @@ def ListeAbsEtud(
base_url=base_url_j,
filename="absjust_" + scu.make_filename(etud["nomprenom"]),
caption="Absences justifiées de %(nomprenom)s" % etud,
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
# Formats non HTML et demande d'une seule table:
@ -771,7 +795,9 @@ def ListeAbsEtud(
# Mise en forme HTML:
H = []
H.append(
context.sco_header(REQUEST, page_title="Absences de %s" % etud["nomprenom"])
html_sco_header.sco_header(
context, REQUEST, page_title="Absences de %s" % etud["nomprenom"]
)
)
H.append(
"""<h2>Absences de %s (à partir du %s)</h2>"""
@ -789,7 +815,7 @@ def ListeAbsEtud(
H.append(tab_absjust.html())
else:
H.append("""<h3>Pas d'absences justifiées</h3>""")
return "\n".join(H) + context.sco_footer(REQUEST)
return "\n".join(H) + html_sco_header.sco_footer(context, REQUEST)
elif format == "text":
T = []
@ -822,7 +848,8 @@ def absences_index_html(context, REQUEST=None):
authuser = REQUEST.AUTHENTICATED_USER
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Gestion des absences",
cssstyles=["css/calabs.css"],
@ -838,7 +865,7 @@ def absences_index_html(context, REQUEST=None):
H.append(
"""<ul><li><a href="EtatAbsences">Afficher l'état des absences (pour tout un groupe)</a></li>"""
)
if context.get_preference("handle_billets_abs"):
if sco_preferences.get_preference(context, "handle_billets_abs"):
H.append(
"""<li><a href="listeBillets">Traitement des billets d'absence en attente</a></li>"""
)
@ -846,7 +873,7 @@ def absences_index_html(context, REQUEST=None):
"""<p>Pour signaler, annuler ou justifier une absence, choisissez d'abord l'étudiant concerné:</p>"""
)
H.append(sco_find_etud.form_search_etud(context, REQUEST))
if authuser.has_permission(ScoAbsChange, context):
if authuser.has_permission(Permission.ScoAbsChange, context):
H.extend(
(
"""<hr/>
@ -871,7 +898,7 @@ saisir les absences de toute cette semaine.</p>
"""<p class="scoinfo">Vous n'avez pas l'autorisation d'ajouter, justifier ou supprimer des absences.</p>"""
)
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)

View File

@ -65,7 +65,9 @@ _help_txt = """
def apo_compare_csv_form(context, REQUEST=None):
"""Form: submit 2 CSV files to compare them."""
H = [
context.sco_header(REQUEST, page_title="Comparaison de fichiers Apogée"),
html_sco_header.sco_header(
context, REQUEST, page_title="Comparaison de fichiers Apogée"
),
"""<h2>Comparaison de fichiers Apogée</h2>
<form id="apo_csv_add" action="apo_compare_csv" method="post" enctype="multipart/form-data">
""",
@ -84,7 +86,7 @@ def apo_compare_csv_form(context, REQUEST=None):
<input type="submit" value="Comparer ces fichiers"/>
</div>
</form>""",
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)
@ -95,14 +97,16 @@ def apo_compare_csv(context, A_file, B_file, autodetect=True, REQUEST=None):
B = _load_apo_data(B_file, autodetect=autodetect)
H = [
context.sco_header(REQUEST, page_title="Comparaison de fichiers Apogée"),
html_sco_header.sco_header(
context, REQUEST, page_title="Comparaison de fichiers Apogée"
),
"<h2>Comparaison de fichiers Apogée</h2>",
_help_txt,
'<div class="apo_compare_csv">',
_apo_compare_csv(context, A, B, REQUEST=None),
"</div>",
"""<p><a href="apo_compare_csv_form" class="stdlink">Autre comparaison</a></p>""",
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)
@ -263,7 +267,9 @@ def apo_table_compare_etud_results(context, A, B, REQUEST=None):
columns_ids=("nip", "nom", "prenom", "elt_code", "type_res", "val_A", "val_B"),
html_class="table_leftalign",
html_with_td_classes=True,
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
return T

View File

@ -379,7 +379,9 @@ class ApoEtud(dict):
dict: with N, B, J, R keys, ou None si elt non trouvé
"""
etudid = self.etud["etudid"]
nt = context._getNotesCache().get_NotesTable(context, sem["formsemestre_id"])
nt = sco_core.get_notes_cache(
context,
).get_NotesTable(context, sem["formsemestre_id"])
if etudid not in nt.identdict:
return None # etudiant non inscrit dans ce semestre
@ -487,9 +489,9 @@ class ApoEtud(dict):
# l'étudiant n'a pas de semestre courant ?!
log("comp_elt_annuel: %s no cur_sem" % etudid)
return VOID_APO_RES
cur_nt = context._getNotesCache().get_NotesTable(
context, cur_sem["formsemestre_id"]
)
cur_nt = sco_core.get_notes_cache(
context,
).get_NotesTable(context, cur_sem["formsemestre_id"])
cur_decision = cur_nt.get_etud_decision_sem(etudid)
if not cur_decision:
# pas de decision => pas de résultat annuel
@ -506,9 +508,9 @@ class ApoEtud(dict):
decision_apo = code_scodoc_to_apo(cur_decision["code"])
autre_nt = context._getNotesCache().get_NotesTable(
context, autre_sem["formsemestre_id"]
)
autre_nt = sco_core.get_notes_cache(
context,
).get_NotesTable(context, autre_sem["formsemestre_id"])
autre_decision = autre_nt.get_etud_decision_sem(etudid)
if not autre_decision:
# pas de decision dans l'autre => pas de résultat annuel
@ -571,9 +573,9 @@ class ApoEtud(dict):
# prend le plus recent avec decision
cur_sem = None
for sem in cur_sems:
nt = context._getNotesCache().get_NotesTable(
context, sem["formsemestre_id"]
)
nt = sco_core.get_notes_cache(
context,
).get_NotesTable(context, sem["formsemestre_id"])
decision = nt.get_etud_decision_sem(self.etud["etudid"])
if decision:
cur_sem = sem
@ -633,9 +635,9 @@ class ApoEtud(dict):
else:
autre_sem = None
for sem in autres_sems:
nt = context._getNotesCache().get_NotesTable(
context, sem["formsemestre_id"]
)
nt = sco_core.get_notes_cache(
context,
).get_NotesTable(context, sem["formsemestre_id"])
decision = nt.get_etud_decision_sem(self.etud["etudid"])
if decision:
autre_sem = sem
@ -968,9 +970,9 @@ class ApoData:
s.add(code)
continue
# associé à une UE:
nt = self.context._getNotesCache().get_NotesTable(
self.context, sem["formsemestre_id"]
)
nt = self.sco_core.get_notes_cache(
context,
).get_NotesTable(self.context, sem["formsemestre_id"])
for ue in nt.get_ues():
if ue["code_apogee"] == code:
s.add(code)

View File

@ -93,7 +93,7 @@ class BaseArchiver:
:return: path to directory of archives for this object (eg formsemestre_id or etudid).
If directory does not yet exist, create it.
"""
dept_dir = os.path.join(self.root, context.DeptId())
dept_dir = os.path.join(self.root, sco_core.get_dept_id())
try:
scu.GSL.acquire()
if not os.path.isdir(dept_dir):
@ -111,7 +111,7 @@ class BaseArchiver:
"""
:return: list of archive oids
"""
base = os.path.join(self.root, context.DeptId()) + os.path.sep
base = os.path.join(self.root, sco_core.get_dept_id()) + os.path.sep
dirs = glob.glob(base + "*")
return [os.path.split(x)[1] for x in dirs]
@ -299,7 +299,8 @@ def do_formsemestre_archive(
if data:
data = "\n".join(
[
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Moyennes archivées le %s" % date,
head_message="Moyennes archivées le %s" % date,
@ -308,7 +309,7 @@ def do_formsemestre_archive(
'<h2 class="fontorange">Valeurs archivées le %s</h2>' % date,
'<style type="text/css">table.notes_recapcomplet tr { color: rgb(185,70,0); }</style>',
data,
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
)
PVArchive.store(archive_id, "Tableau_moyennes.html", data)
@ -381,7 +382,8 @@ def formsemestre_archive(context, REQUEST, formsemestre_id, group_ids=[]):
)
H = [
context.html_sem_header(
html_sco_header.html_sem_header(
context,
REQUEST,
"Archiver les PV et résultats du semestre",
sem=sem,
@ -400,7 +402,7 @@ enregistrés et non modifiables, on peut les retrouver ultérieurement.
F = [
"""<p><em>Note: les documents sont aussi affectés par les réglages sur la page "<a href="edit_preferences">Paramétrage</a>" (accessible à l'administrateur du département).</em>
</p>""",
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
descr = [
@ -503,7 +505,11 @@ def formsemestre_list_archives(context, REQUEST, formsemestre_id):
L.append(a)
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
H = [context.html_sem_header(REQUEST, "Archive des PV et résultats ", sem)]
H = [
html_sco_header.html_sem_header(
context, REQUEST, "Archive des PV et résultats ", sem
)
]
if not L:
H.append("<p>aucune archive enregistrée</p>")
else:
@ -529,7 +535,7 @@ def formsemestre_list_archives(context, REQUEST, formsemestre_id):
H.append("</ul></li>")
H.append("</ul>")
return "\n".join(H) + context.sco_footer(REQUEST)
return "\n".join(H) + html_sco_header.sco_footer(context, REQUEST)
def formsemestre_get_archived_file(

View File

@ -53,7 +53,7 @@ EtudsArchive = EtudsArchiver()
def can_edit_etud_archive(context, authuser):
"""True si l'utilisateur peut modifier les archives etudiantes"""
return authuser.has_permission(ScoEtudAddAnnotations, context)
return authuser.has_permission(Permission.ScoEtudAddAnnotations, context)
def etud_list_archives_html(context, REQUEST, etudid):
@ -131,7 +131,7 @@ def etud_upload_file_form(context, REQUEST, etudid):
)
etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0]
H = [
context.sco_header(
html_sco_header.sco_header(context,
REQUEST,
page_title="Chargement d'un document associé à %(nomprenom)s" % etud,
),
@ -162,7 +162,7 @@ def etud_upload_file_form(context, REQUEST, etudid):
cancelbutton="Annuler",
)
if tf[0] == 0:
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
return "\n".join(H) + tf[1] + html_sco_header.sco_footer(context, REQUEST)
elif tf[0] == -1:
return REQUEST.RESPONSE.redirect(
context.NotesURL() + "/ficheEtud?etudid=" + etudid
@ -252,7 +252,7 @@ def etudarchive_generate_excel_sample(context, group_id=None, REQUEST=None):
def etudarchive_import_files_form(context, group_id, REQUEST=None):
"""Formualaire pour importation fichiers d'un groupe"""
H = [
context.sco_header(
html_sco_header.sco_header(context,
REQUEST, page_title="Import de fichiers associés aux étudiants"
),
"""<h2 class="formsemestre">Téléchargement de fichier associés aux étudiants</h2>
@ -276,7 +276,7 @@ def etudarchive_import_files_form(context, group_id, REQUEST=None):
"""
% group_id,
]
F = context.sco_footer(REQUEST)
F = html_sco_header.sco_footer(context, REQUEST)
tf = TrivialFormulator(
REQUEST.URL0,
REQUEST.form,
@ -329,4 +329,4 @@ def etudarchive_import_files(
r = sco_trombino.zip_excel_import_files(
context, xlsfile, zipfile, REQUEST, callback, filename_title, page_title
)
return r + context.sco_footer(REQUEST)
return r + html_sco_header.sco_footer(context, REQUEST)

View File

@ -41,6 +41,7 @@ from email.header import Header
from reportlab.lib.colors import Color
import mails
import sco_utils as scu
import notesdb as ndb
from notes_log import log
@ -84,7 +85,7 @@ def make_context_dict(context, sem, etud):
C.update(etud)
# copie preferences
for name in sco_preferences.PREFS_NAMES:
C[name] = context.get_preference(name, sem["formsemestre_id"])
C[name] = sco_preferences.get_preference(context, name, sem["formsemestre_id"])
# ajoute groupes et group_0, group_1, ...
sco_groups.etud_add_group_infos(context, etud, sem)
@ -115,8 +116,8 @@ def formsemestre_bulletinetud_dict(
if not version in ("short", "long", "selectedevals"):
raise ValueError("invalid version code !")
prefs = context.get_preferences(formsemestre_id)
nt = context._getNotesCache().get_NotesTable(
prefs = sco_preferences.SemPreferences(context, formsemestre_id)
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > toutes notes
@ -336,7 +337,7 @@ def formsemestre_bulletinetud_dict(
# log('cap details %s' % ue_status['moy'])
if ue_status["moy"] != "NA" and ue_status["formsemestre_id"]:
# detail des modules de l'UE capitalisee
nt_cap = context._getNotesCache().get_NotesTable(
nt_cap = sco_core.get_notes_cache(context).get_NotesTable(
context, ue_status["formsemestre_id"]
) # > toutes notes
@ -402,9 +403,11 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
(ajoute les informations aux modimpls)
Result: liste de modules de l'UE avec les infos dans chacun (seulement ceux où l'étudiant est inscrit).
"""
bul_show_mod_rangs = context.get_preference("bul_show_mod_rangs", formsemestre_id)
bul_show_abs_modules = context.get_preference(
"bul_show_abs_modules", formsemestre_id
bul_show_mod_rangs = sco_preferences.get_preference(
context, "bul_show_mod_rangs", formsemestre_id
)
bul_show_abs_modules = sco_preferences.get_preference(
context, "bul_show_abs_modules", formsemestre_id
)
if bul_show_abs_modules:
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
@ -477,7 +480,9 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
'<a class="bull_link" href="moduleimpl_status?moduleimpl_id=%s" title="%s">'
% (modimpl["moduleimpl_id"], mod["mod_descr_txt"])
)
if context.get_preference("bul_show_codemodules", formsemestre_id):
if sco_preferences.get_preference(
context, "bul_show_codemodules", formsemestre_id
):
mod["code"] = modimpl["module"]["code"]
mod["code_html"] = link_mod + mod["code"] + "</a>"
else:
@ -496,7 +501,9 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
'<a class="bull_link" href="moduleimpl_status?moduleimpl_id=%s" title="%s">'
% (modimpl["moduleimpl_id"], mod_descr)
)
if context.get_preference("bul_show_codemodules", formsemestre_id):
if sco_preferences.get_preference(
context, "bul_show_codemodules", formsemestre_id
):
mod["code_txt"] = modimpl["module"]["code"]
mod["code_html"] = link_mod + mod["code_txt"] + "</a>"
else:
@ -557,7 +564,9 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
# Evaluations incomplètes ou futures:
mod["evaluations_incompletes"] = []
if context.get_preference("bul_show_all_evals", formsemestre_id):
if sco_preferences.get_preference(
context, "bul_show_all_evals", formsemestre_id
):
complete_eval_ids = set([e["evaluation_id"] for e in evals])
all_evals = context.do_evaluation_list(
args={"moduleimpl_id": modimpl["moduleimpl_id"]}
@ -831,7 +840,7 @@ def formsemestre_bulletinetud(
R.append('<div id="radar_bulletin"></div>')
# --- Pied de page
R.append(context.sco_footer(REQUEST))
R.append(html_sco_header.sco_footer(context, REQUEST))
return "".join(R)
@ -841,8 +850,10 @@ def can_send_bulletin_by_mail(context, formsemestre_id, REQUEST):
authuser = REQUEST.AUTHENTICATED_USER
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
return (
context.get_preference("bul_mail_allowed_for_all", formsemestre_id)
or authuser.has_permission(ScoImplement, context)
sco_preferences.get_preference(
context, "bul_mail_allowed_for_all", formsemestre_id
)
or authuser.has_permission(Permission.ScoImplement, context)
or str(authuser) in sem["responsables"]
)
@ -970,10 +981,18 @@ def mail_bulletin(context, formsemestre_id, I, pdfdata, filename, recipient_addr
If bul_mail_list_abs pref is true, put list of absences in mail body (text).
"""
etud = I["etud"]
webmaster = context.get_preference("bul_mail_contact_addr", formsemestre_id)
dept = scu.unescape_html(context.get_preference("DeptName", formsemestre_id))
copy_addr = context.get_preference("email_copy_bulletins", formsemestre_id)
intro_mail = context.get_preference("bul_intro_mail", formsemestre_id)
webmaster = sco_preferences.get_preference(
context, "bul_mail_contact_addr", formsemestre_id
)
dept = scu.unescape_html(
sco_preferences.get_preference(context, "DeptName", formsemestre_id)
)
copy_addr = sco_preferences.get_preference(
context, "email_copy_bulletins", formsemestre_id
)
intro_mail = sco_preferences.get_preference(
context, "bul_intro_mail", formsemestre_id
)
if intro_mail:
hea = intro_mail % {
@ -984,7 +1003,7 @@ def mail_bulletin(context, formsemestre_id, I, pdfdata, filename, recipient_addr
else:
hea = ""
if context.get_preference("bul_mail_list_abs"):
if sco_preferences.get_preference(context, "bul_mail_list_abs"):
hea += "\n\n" + sco_abs_views.ListeAbsEtud(
context, etud["etudid"], with_evals=False, format="text"
)
@ -993,7 +1012,9 @@ def mail_bulletin(context, formsemestre_id, I, pdfdata, filename, recipient_addr
subj = Header("Relevé de notes de %s" % etud["nomprenom"], scu.SCO_ENCODING)
recipients = [recipient_addr]
msg["Subject"] = subj
msg["From"] = context.get_preference("email_from_addr", formsemestre_id)
msg["From"] = sco_preferences.get_preference(
context, "email_from_addr", formsemestre_id
)
msg["To"] = " ,".join(recipients)
if copy_addr:
msg["Bcc"] = copy_addr.strip()
@ -1010,7 +1031,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"])
context.sendEmail(msg)
mails.sendEmail(context, msg)
def _formsemestre_bulletinetud_header_html(
@ -1026,7 +1047,8 @@ def _formsemestre_bulletinetud_header_html(
authuser = REQUEST.AUTHENTICATED_USER
uid = str(authuser)
H = [
context.sco_header(
html_sco_header.sco_header(
context,
page_title="Bulletin de %(nomprenom)s" % etud,
REQUEST=REQUEST,
javascripts=[
@ -1077,7 +1099,7 @@ def _formsemestre_bulletinetud_header_html(
"url": "formsemestre_edit_options?formsemestre_id=%s&target_url=%s"
% (formsemestre_id, qurl),
"enabled": (uid in sem["responsables"])
or authuser.has_permission(ScoImplement, context),
or authuser.has_permission(Permission.ScoImplement, context),
},
{
"title": 'Version papier (pdf, format "%s")'
@ -1120,14 +1142,14 @@ def _formsemestre_bulletinetud_header_html(
% (etudid, formsemestre_id),
"enabled": (
(authuser in sem["responsables"])
or (authuser.has_permission(ScoEtudInscrit, context))
or (authuser.has_permission(Permission.ScoEtudInscrit, context))
),
},
{
"title": "Enregistrer un semestre effectué ailleurs",
"url": "formsemestre_ext_create_form?etudid=%s&formsemestre_id=%s"
% (etudid, formsemestre_id),
"enabled": authuser.has_permission(ScoImplement, context),
"enabled": authuser.has_permission(Permission.ScoImplement, context),
},
{
"title": "Enregistrer une validation d'UE antérieure",
@ -1196,7 +1218,7 @@ def formsemestre_bulletins_choice(
"""Choix d'une version de bulletin"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
H = [
context.html_sem_header(REQUEST, title, sem),
html_sco_header.html_sem_header(context, REQUEST, title, sem),
"""
<form name="f" method="GET" action="%s">
<input type="hidden" name="formsemestre_id" value="%s"></input>
@ -1219,7 +1241,7 @@ def formsemestre_bulletins_choice(
H.append("""<p class="help">""" + explanation + """</p>""")
return "\n".join(H) + context.sco_footer(REQUEST)
return "\n".join(H) + html_sco_header.sco_footer(context, REQUEST)
expl_bull = """Versions des bulletins:<ul><li><bf>courte</bf>: moyennes des modules</li><li><bf>intermédiaire</bf>: moyennes des modules et notes des évaluations sélectionnées</li><li><bf>complète</bf>: toutes les notes</li><ul>"""

View File

@ -87,7 +87,7 @@ def bulletin_get_class(class_name):
def bulletin_get_class_name_displayed(context, formsemestre_id):
"""Le nom du générateur utilisé, en clair"""
bul_class_name = context.get_preference("bul_class_name", formsemestre_id)
bul_class_name = sco_preferences.get_preference(context, "bul_class_name", formsemestre_id)
try:
gen_class = bulletin_get_class(bul_class_name)
return gen_class.description
@ -121,7 +121,7 @@ class BulletinGenerator:
self.server_name = server_name
# Store preferences for convenience:
formsemestre_id = self.infos["formsemestre_id"]
self.preferences = context.get_preferences(formsemestre_id)
self.preferences = sco_preferences.SemPreferences(context, formsemestre_id)
self.diagnostic = None # error message if any problem
# Common PDF styles:
# - Pour tous les champs du bulletin sauf les cellules de table:
@ -223,7 +223,9 @@ class BulletinGenerator:
margins=self.margins,
server_name=self.server_name,
filigranne=self.filigranne,
preferences=self.context.get_preferences(formsemestre_id),
preferences=self.sco_preferences.SemPreferences(
context, formsemestre_id
),
)
)
document.build(objects)
@ -273,7 +275,7 @@ def make_formsemestre_bulletinetud(
raise ValueError("invalid version code !")
formsemestre_id = infos["formsemestre_id"]
bul_class_name = context.get_preference("bul_class_name", formsemestre_id)
bul_class_name = sco_preferences.get_preference(context, "bul_class_name", formsemestre_id)
try:
gen_class = bulletin_get_class(bul_class_name)
except:

View File

@ -147,7 +147,7 @@ def formsemestre_bulletinetud_published_dict(
context, pid
)
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > toutes notes
ues = nt.get_ues()
@ -156,7 +156,8 @@ def formsemestre_bulletinetud_published_dict(
mg = scu.fmt_note(nt.get_etud_moy_gen(etudid))
if (
nt.get_moduleimpls_attente()
or context.get_preference("bul_show_rangs", formsemestre_id) == 0
or sco_preferences.get_preference(context, "bul_show_rangs", formsemestre_id)
== 0
):
# n'affiche pas le rang sur le bulletin s'il y a des
# notes en attente dans ce semestre
@ -209,7 +210,9 @@ def formsemestre_bulletinetud_published_dict(
value=scu.fmt_note(ue_status["cur_moy_ue"]),
min=scu.fmt_note(ue["min"]),
max=scu.fmt_note(ue["max"]),
moy=scu.fmt_note(ue["moy"]), # CM : ajout pour faire apparaitre la moyenne des UE
moy=scu.fmt_note(
ue["moy"]
), # CM : ajout pour faire apparaitre la moyenne des UE
),
rang=str(nt.ue_rangs[ue["ue_id"]][0][etudid]),
effectif=str(nt.ue_rangs[ue["ue_id"]][1]),
@ -249,7 +252,9 @@ def formsemestre_bulletinetud_published_dict(
m["note"][k] = scu.fmt_note(m["note"][k])
u["module"].append(m)
if context.get_preference("bul_show_mod_rangs", formsemestre_id):
if sco_preferences.get_preference(
context, "bul_show_mod_rangs", formsemestre_id
):
m["rang"] = dict(
value=nt.mod_rangs[modimpl["moduleimpl_id"]][0][etudid]
)
@ -276,14 +281,18 @@ def formsemestre_bulletinetud_published_dict(
),
coefficient=e["coefficient"],
evaluation_type=e["evaluation_type"],
evaluation_id=e["evaluation_id"], # CM : ajout pour permettre de faire le lien sur les bulletins en ligne avec l'évaluation
evaluation_id=e[
"evaluation_id"
], # CM : ajout pour permettre de faire le lien sur les bulletins en ligne avec l'évaluation
description=scu.quote_xml_attr(e["description"]),
note=val,
)
)
# Evaluations incomplètes ou futures:
complete_eval_ids = set([e["evaluation_id"] for e in evals])
if context.get_preference("bul_show_all_evals", formsemestre_id):
if sco_preferences.get_preference(
context, "bul_show_all_evals", formsemestre_id
):
all_evals = context.do_evaluation_list(
args={"moduleimpl_id": modimpl["moduleimpl_id"]}
)
@ -327,7 +336,7 @@ def formsemestre_bulletinetud_published_dict(
)
# --- Absences
if context.get_preference("bul_show_abs", formsemestre_id):
if sco_preferences.get_preference(context, "bul_show_abs", formsemestre_id):
AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid)
nbabs = AbsEtudSem.CountAbs()
nbabsjust = AbsEtudSem.CountAbsJust()
@ -336,7 +345,7 @@ def formsemestre_bulletinetud_published_dict(
# --- Decision Jury
if (
context.get_preference("bul_show_decision", formsemestre_id)
sco_preferences.get_preference(context, "bul_show_decision", formsemestre_id)
or xml_with_decisions
):
infos, dpv = sco_bulletins.etud_descr_situation_semestre(
@ -344,7 +353,9 @@ def formsemestre_bulletinetud_published_dict(
etudid,
formsemestre_id,
format="xml",
show_uevalid=context.get_preference("bul_show_uevalid", formsemestre_id),
show_uevalid=sco_preferences.get_preference(
context, "bul_show_uevalid", formsemestre_id
),
)
d["situation"] = scu.quote_xml_attr(infos["situation"])
if dpv:
@ -367,7 +378,7 @@ def formsemestre_bulletinetud_published_dict(
d["decision_ue"] = []
if decision[
"decisions_ue"
]: # and context.get_preference('bul_show_uevalid', formsemestre_id): always publish (car utile pour export Apogee)
]: # and sco_preferences.get_preference(context, 'bul_show_uevalid', formsemestre_id): always publish (car utile pour export Apogee)
for ue_id in decision["decisions_ue"].keys():
ue = context.do_ue_list({"ue_id": ue_id})[0]
d["decision_ue"].append(

View File

@ -90,7 +90,7 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
formsemestre_id = self.infos["formsemestre_id"]
context = self.context
bul_show_abs_modules = context.get_preference(
bul_show_abs_modules = sco_preferences.get_preference(context,
"bul_show_abs_modules", formsemestre_id
)
@ -106,7 +106,7 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
H = ['<table class="notes_bulletin" style="background-color: %s;">' % bgcolor]
if context.get_preference("bul_show_minmax", formsemestre_id):
if sco_preferences.get_preference(context, "bul_show_minmax", formsemestre_id):
minmax = (
'<span class="bul_minmax" title="[min, max] promo">[%s, %s]</span>'
% (I["moy_min"], I["moy_max"])
@ -131,7 +131,7 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
if mod["mod_moy_txt"] == "NI":
continue # saute les modules où on n'est pas inscrit
H.append('<tr class="notes_bulletin_row_mod%s">' % rowstyle)
if context.get_preference("bul_show_minmax_mod", formsemestre_id):
if sco_preferences.get_preference(context, "bul_show_minmax_mod", formsemestre_id):
rang_minmax = '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' % (
mod["mod_rang_txt"],
scu.fmt_note(mod["stats"]["min"]),
@ -178,7 +178,7 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
rowstyle = ""
plusminus = minuslink #
if ue["ue_status"]["is_capitalized"]:
if context.get_preference("bul_show_ue_cap_details", formsemestre_id):
if sco_preferences.get_preference(context, "bul_show_ue_cap_details", formsemestre_id):
plusminus = minuslink
hide = ""
else:
@ -208,7 +208,7 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
)
H.append('<tr class="notes_bulletin_row_ue">')
if context.get_preference("bul_show_minmax", formsemestre_id):
if sco_preferences.get_preference(context, "bul_show_minmax", formsemestre_id):
moy_txt = (
'%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>'
% (
@ -316,7 +316,7 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
# le dir. des etud peut ajouter des appreciations,
# mais aussi le chef (perm. ScoEtudInscrit)
can_edit_app = (str(authuser) in self.infos["responsables"]) or (
authuser.has_permission(ScoEtudInscrit, self.context)
authuser.has_permission(Permission.ScoEtudInscrit, self.context)
)
H.append('<div class="bull_appreciations">')
if I["appreciations_list"]:
@ -444,11 +444,11 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
S = BulTableStyle()
P = [] # elems pour gen. pdf
formsemestre_id = I["formsemestre_id"]
bul_show_abs_modules = context.get_preference(
bul_show_abs_modules = sco_preferences.get_preference(context,
"bul_show_abs_modules", formsemestre_id
)
if context.get_preference("bul_show_minmax", formsemestre_id):
if sco_preferences.get_preference(context, "bul_show_minmax", formsemestre_id):
minmax = ' <font size="8">[%s, %s]</font>' % (I["moy_min"], I["moy_max"])
else:
minmax = ""
@ -470,7 +470,7 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
if mod["mod_moy_txt"] == "NI":
continue # saute les modules où on n'est pas inscrit
S.modline(ue_type=ue_type)
if context.get_preference("bul_show_minmax_mod", formsemestre_id):
if sco_preferences.get_preference(context, "bul_show_minmax_mod", formsemestre_id):
rang_minmax = '%s <font size="8">[%s, %s]</font>' % (
mod["mod_rang_txt"],
scu.fmt_note(mod["stats"]["min"]),
@ -510,11 +510,11 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
coef_ue = ""
ue_descr = "(en cours, non prise en compte)"
S.ueline()
if context.get_preference("bul_show_ue_cap_details", formsemestre_id):
if sco_preferences.get_preference(context, "bul_show_ue_cap_details", formsemestre_id):
list_modules(ue["modules_capitalized"])
ue_type = "cur"
if context.get_preference("bul_show_minmax", formsemestre_id):
if sco_preferences.get_preference(context, "bul_show_minmax", formsemestre_id):
moy_txt = '%s <font size="8">[%s, %s]</font>' % (
ue["cur_moy_ue_txt"],
ue["min"],

View File

@ -83,10 +83,10 @@ def pdfassemblebulletins(
return ""
# Paramètres de mise en page
margins = (
context.get_preference("left_margin", formsemestre_id),
context.get_preference("top_margin", formsemestre_id),
context.get_preference("right_margin", formsemestre_id),
context.get_preference("bottom_margin", formsemestre_id),
sco_preferences.get_preference(context, "left_margin", formsemestre_id),
sco_preferences.get_preference(context, "top_margin", formsemestre_id),
sco_preferences.get_preference(context, "right_margin", formsemestre_id),
sco_preferences.get_preference(context, "bottom_margin", formsemestre_id),
)
report = cStringIO.StringIO() # in-memory document, no disk file
@ -102,7 +102,7 @@ def pdfassemblebulletins(
margins=margins,
pagesbookmarks=pagesbookmarks,
filigranne=filigranne,
preferences=context.get_preferences(formsemestre_id),
preferences=sco_preferences.SemPreferences(context, formsemestre_id),
)
)
document.build(objects)
@ -143,7 +143,7 @@ def process_field(
return text
# --- PDF format:
# handle logos:
image_dir = scu.SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/"
image_dir = scu.SCODOC_LOGOS_DIR + "/logos_" + sco_core.get_dept_id() + "/"
if not os.path.exists(image_dir):
image_dir = scu.SCODOC_LOGOS_DIR + "/" # use global logos
text = re.sub(
@ -165,13 +165,15 @@ def get_formsemestre_bulletins_pdf(
context, formsemestre_id, REQUEST, version="selectedevals"
):
"document pdf et filename"
cached = context._getNotesCache().get_bulletins_pdf(formsemestre_id, version)
cached = sco_core.get_notes_cache(
context,
).get_bulletins_pdf(formsemestre_id, version)
if cached:
return cached[1], cached[0]
fragments = []
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
# Make each bulletin
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etudids, get_sexnom
bookmarks = {}
@ -191,7 +193,9 @@ def get_formsemestre_bulletins_pdf(
bookmarks[i] = scu.suppress_accents(nt.get_sexnom(etudid))
i = i + 1
#
infos = {"DeptName": context.get_preference("DeptName", formsemestre_id)}
infos = {
"DeptName": sco_preferences.get_preference(context, "DeptName", formsemestre_id)
}
if REQUEST:
server_name = REQUEST.BASE0
else:
@ -215,9 +219,9 @@ def get_formsemestre_bulletins_pdf(
filename = "bul-%s-%s.pdf" % (sem["titre_num"], dt)
filename = scu.unescape_html(filename).replace(" ", "_").replace("&", "")
# fill cache
context._getNotesCache().store_bulletins_pdf(
formsemestre_id, version, filename, pdfdoc
)
sco_core.get_notes_cache(
context,
).store_bulletins_pdf(formsemestre_id, version, filename, pdfdoc)
return pdfdoc, filename
@ -241,7 +245,7 @@ def get_etud_bulletins_pdf(context, etudid, REQUEST, version="selectedevals"):
filigrannes[i] = filigranne
bookmarks[i] = sem["session_id"] # eg RT-DUT-FI-S1-2015
i = i + 1
infos = {"DeptName": context.get_preference("DeptName")}
infos = {"DeptName": sco_preferences.get_preference(context, "DeptName")}
if REQUEST:
server_name = REQUEST.BASE0
else:

View File

@ -85,7 +85,7 @@ et sur page "réglages bulletin" (avec formsemestre_id)
# def _sig_filename(context, side, formsemestre_id=None):
# if not side in ("left", "right"):
# raise ValueError("side must be left or right")
# dirs = [SCODOC_LOGOS_DIR, context.DeptId()]
# dirs = [SCODOC_LOGOS_DIR, sco_core.get_dept_id()]
# if formsemestre_id:
# dirs.append(formsemestre_id)
# dirs.append("bul_sig_{}".format(side))

View File

@ -105,7 +105,7 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
columns_ids=colkeys,
pdf_table_style=pdf_style,
pdf_col_widths=[colWidths[k] for k in colkeys],
preferences=self.context.get_preferences(formsemestre_id),
preferences=self.sco_preferences.SemPreferences(context, formsemestre_id),
html_class="notes_bulletin",
html_class_ignore_default=True,
html_with_td_classes=True,
@ -153,7 +153,7 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
# le dir. des etud peut ajouter des appreciations,
# mais aussi le chef (perm. ScoEtudInscrit)
can_edit_app = (str(self.authuser) in self.infos["responsables"]) or (
self.authuser.has_permission(ScoEtudInscrit, self.context)
self.authuser.has_permission(Permission.ScoEtudInscrit, self.context)
)
H.append('<div class="bull_appreciations">')
for app in self.infos["appreciations_list"]:
@ -286,7 +286,7 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
context = self.context
P = [] # elems pour générer table avec gen_table (liste de dicts)
formsemestre_id = I["formsemestre_id"]
prefs = context.get_preferences(formsemestre_id)
prefs = sco_preferences.SemPreferences(context, formsemestre_id)
# Colonnes à afficher:
with_col_abs = prefs["bul_show_abs_modules"]

View File

@ -76,7 +76,7 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard):
I = self.infos
context = self.context
formsemestre_id = I["formsemestre_id"]
prefs = context.get_preferences(formsemestre_id)
prefs = sco_preferences.SemPreferences(context, formsemestre_id)
P = [] # elems pour générer table avec gen_table (liste de dicts)
@ -195,7 +195,7 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard):
ue_type = None
# --- UE capitalisée:
if ue["ue_status"]["is_capitalized"]:
if context.get_preference("bul_show_ue_cap_details", formsemestre_id):
if sco_preferences.get_preference(context, "bul_show_ue_cap_details", formsemestre_id):
nb_modules = len(ue["modules_capitalized"])
hidden = False
cssstyle = ""

View File

@ -130,7 +130,7 @@ def make_xml_formsemestre_bulletinetud(
context, pid
)
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > toutes notes
ues = nt.get_ues()
@ -139,7 +139,8 @@ def make_xml_formsemestre_bulletinetud(
mg = scu.fmt_note(nt.get_etud_moy_gen(etudid))
if (
nt.get_moduleimpls_attente()
or context.get_preference("bul_show_rangs", formsemestre_id) == 0
or sco_preferences.get_preference(context, "bul_show_rangs", formsemestre_id)
== 0
):
# n'affiche pas le rang sur le bulletin s'il y a des
# notes en attente dans ce semestre
@ -247,7 +248,9 @@ def make_xml_formsemestre_bulletinetud(
moy=scu.fmt_note(modstat["moy"]),
)
doc._pop()
if context.get_preference("bul_show_mod_rangs", formsemestre_id):
if sco_preferences.get_preference(
context, "bul_show_mod_rangs", formsemestre_id
):
doc._push()
doc.rang(value=nt.mod_rangs[modimpl["moduleimpl_id"]][0][etudid])
doc._pop()
@ -283,7 +286,9 @@ def make_xml_formsemestre_bulletinetud(
doc._pop()
# Evaluations incomplètes ou futures:
complete_eval_ids = set([e["evaluation_id"] for e in evals])
if context.get_preference("bul_show_all_evals", formsemestre_id):
if sco_preferences.get_preference(
context, "bul_show_all_evals", formsemestre_id
):
all_evals = context.do_evaluation_list(
args={"moduleimpl_id": modimpl["moduleimpl_id"]}
)
@ -336,7 +341,7 @@ def make_xml_formsemestre_bulletinetud(
doc._pop()
doc._pop()
# --- Absences
if context.get_preference("bul_show_abs", formsemestre_id):
if sco_preferences.get_preference(context, "bul_show_abs", formsemestre_id):
AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid)
nbabs = AbsEtudSem.CountAbs()
nbabsjust = AbsEtudSem.CountAbsJust()
@ -345,7 +350,7 @@ def make_xml_formsemestre_bulletinetud(
doc._pop()
# --- Decision Jury
if (
context.get_preference("bul_show_decision", formsemestre_id)
sco_preferences.get_preference(context, "bul_show_decision", formsemestre_id)
or xml_with_decisions
):
infos, dpv = sco_bulletins.etud_descr_situation_semestre(
@ -353,7 +358,9 @@ def make_xml_formsemestre_bulletinetud(
etudid,
formsemestre_id,
format="xml",
show_uevalid=context.get_preference("bul_show_uevalid", formsemestre_id),
show_uevalid=sco_preferences.get_preference(
context, "bul_show_uevalid", formsemestre_id
),
)
doc.situation(scu.quote_xml_attr(infos["situation"]))
if dpv:
@ -383,7 +390,7 @@ def make_xml_formsemestre_bulletinetud(
if decision[
"decisions_ue"
]: # and context.get_preference('bul_show_uevalid', formsemestre_id): always publish (car utile pour export Apogee)
]: # and sco_preferences.get_preference(context, 'bul_show_uevalid', formsemestre_id): always publish (car utile pour export Apogee)
for ue_id in decision["decisions_ue"].keys():
ue = context.do_ue_list({"ue_id": ue_id})[0]
doc._push()

View File

@ -7,6 +7,9 @@
import types
import sco_utils as scu
from notes_table import NOTES_CACHE_INST, CacheNotesTable
from scodoc_manager import sco_mgr
from sco_exceptions import ScoInvalidDept
def sco_get_version(context, REQUEST=None):
@ -16,4 +19,76 @@ def sco_get_version(context, REQUEST=None):
def test_refactor(context, x=1):
x = context.toto()
y = ("context=" + context.module_is_locked("alpha")) + "23"
y = ("context=" + sco_edit_module.module_is_locked(context, "alpha")) + "23"
z = html_sco_header.sco_header(
context,
a_long_argument_hahahahaha=1,
another_very_long_arggggggggggggg=2,
z=6,
u=99,
kkkkkk=1,
)
def get_dept_id():
if g.scodoc_dept in sco_mgr.get_dept_ids():
return g.scodoc_dept
raise ScoInvalidDept("département invalide: %s" % g.scodoc_dept)
#
# Cache global: chaque instance, repérée par sa connexion db, a un cache
# qui est recréé à la demande
#
CACHE_formsemestre_inscription = {}
CACHE_evaluations = {}
# cache notes evaluations
def get_evaluations_cache(context):
"""returns cache for evaluations"""
u = context.GetDBConnexionString()
if CACHE_evaluations.has_key(u):
return CACHE_evaluations[u]
else:
log("get_evaluations_cache: new simpleCache")
CACHE_evaluations[u] = sco_cache.simpleCache()
return CACHE_evaluations[u]
def get_notes_cache(context):
"returns CacheNotesTable instance for us"
u = sco_mgr.get_db_uri() # identifie le dept de facon unique
if not NOTES_CACHE_INST.has_key(u):
log("getNotesCache: creating cache for %s" % u)
NOTES_CACHE_INST[u] = CacheNotesTable()
return NOTES_CACHE_INST[u]
def inval_cache(
context, formsemestre_id=None, pdfonly=False, formsemestre_id_list=None
): # >
"expire cache pour un semestre (ou tous si pas d'argument)"
if formsemestre_id_list:
for formsemestre_id in formsemestre_id_list:
get_notes_cache(context).inval_cache(
context, formsemestre_id=formsemestre_id, pdfonly=pdfonly
)
# Affecte aussi cache inscriptions
get_formsemestre_inscription_cache(context).inval_cache(key=formsemestre_id)
else:
get_notes_cache(context).inval_cache(
context, formsemestre_id=formsemestre_id, pdfonly=pdfonly
)
# Affecte aussi cache inscriptions
get_formsemestre_inscription_cache(context).inval_cache(key=formsemestre_id)
# Cache inscriptions semestres
def get_formsemestre_inscription_cache(context, format=None):
u = context.GetDBConnexionString()
if CACHE_formsemestre_inscription.has_key(u):
return CACHE_formsemestre_inscription[u]
else:
log("get_formsemestre_inscription_cache: new simpleCache")
CACHE_formsemestre_inscription[u] = sco_cache.simpleCache()
return CACHE_formsemestre_inscription[u]

View File

@ -124,7 +124,7 @@ def formsemestre_table_estim_cost(
),
rows=T,
html_sortable=True,
preferences=context.get_preferences(formsemestre_id),
preferences=sco_preferences.SemPreferences(context, formsemestre_id),
html_class="table_leftalign table_listegroupe",
xls_before_table=[
["%(titre)s %(num_sem)s %(modalitestr)s" % sem],
@ -193,9 +193,12 @@ def formsemestre_estim_cost(
coef_tp,
)
tab.html_before_table = h
tab.base_url = (
"%s?formsemestre_id=%s&n_group_td=%s&n_group_tp=%s&coef_tp=%s"
% (REQUEST.URL0, formsemestre_id, n_group_td, n_group_tp, coef_tp)
tab.base_url = "%s?formsemestre_id=%s&n_group_td=%s&n_group_tp=%s&coef_tp=%s" % (
REQUEST.URL0,
formsemestre_id,
n_group_td,
n_group_tp,
coef_tp,
)
return tab.make_page(context, format=format, REQUEST=REQUEST)

View File

@ -110,9 +110,9 @@ def table_debouche_etudids(context, etudids, keep_numeric=True):
es = [(sems[i]["date_fin_iso"], i) for i in range(len(sems))]
imax = max(es)[1]
last_sem = sems[imax]
nt = context._getNotesCache().get_NotesTable(
context, last_sem["formsemestre_id"]
)
nt = sco_core.get_notes_cache(
context,
).get_NotesTable(context, last_sem["formsemestre_id"])
row = {
"etudid": etudid,
"civilite": etud["civilite"],
@ -183,7 +183,9 @@ def table_debouche_etudids(context, etudids, keep_numeric=True):
# html_col_width='4em',
html_sortable=True,
html_class="table_leftalign table_listegroupe",
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
return tab
@ -191,11 +193,11 @@ def table_debouche_etudids(context, etudids, keep_numeric=True):
def report_debouche_ask_date(context, REQUEST=None):
"""Formulaire demande date départ"""
return (
context.sco_header(REQUEST)
html_sco_header.sco_header(context, REQUEST)
+ """<form method="GET">
Date de départ de la recherche: <input type="text" name="start_year" value="" size=10/>
</form>"""
+ context.sco_footer(REQUEST)
+ html_sco_header.sco_footer(context, REQUEST)
)

View File

@ -118,7 +118,7 @@ def index_html(context, REQUEST=None, showcodes=0, showsemtable=0):
"""<hr/>
<h2>Semestres de %s</h2>
"""
% context.get_preference("DeptName")
% sco_preferences.get_preference(context, "DeptName")
)
H.append(_sem_table_gt(context, sems).html())
H.append("</table>")
@ -138,7 +138,7 @@ Chercher étape courante: <input name="etape_apo" type="text" size="8" spellchec
)
#
authuser = REQUEST.AUTHENTICATED_USER
if authuser.has_permission(ScoEtudInscrit, context):
if authuser.has_permission(Permission.ScoEtudInscrit, context):
H.append(
"""<hr>
<h3>Gestion des étudiants</h3>
@ -151,7 +151,7 @@ Chercher étape courante: <input name="etape_apo" type="text" size="8" spellchec
"""
)
#
if authuser.has_permission(ScoEditApo, context):
if authuser.has_permission(Permission.ScoEditApo, context):
H.append(
"""<hr>
<h3>Exports Apogée</h3>
@ -171,7 +171,11 @@ Chercher étape courante: <input name="etape_apo" type="text" size="8" spellchec
"""
)
#
return context.sco_header(REQUEST) + "\n".join(H) + context.sco_footer(REQUEST)
return (
html_sco_header.sco_header(context, REQUEST)
+ "\n".join(H)
+ html_sco_header.sco_footer(context, REQUEST)
)
def _sem_table(context, sems):
@ -239,7 +243,9 @@ def _sem_table_gt(context, sems, showcodes=False):
html_sortable=True,
# base_url = '%s?formsemestre_id=%s' % (REQUEST.URL0, formsemestre_id),
# caption='Maquettes enregistrées',
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
return tab

View File

@ -66,7 +66,7 @@ SCO_DUMP_LOCK = "/tmp/scodump.lock"
def sco_dump_and_send_db(context, REQUEST=None):
"""Dump base de données du département courant et l'envoie anonymisée pour debug"""
H = [context.sco_header(REQUEST, page_title="Assistance technique")]
H = [html_sco_header.sco_header(context, REQUEST, page_title="Assistance technique")]
# get currect (dept) DB name:
cursor = ndb.SimpleQuery(context, "SELECT current_database()", {})
db_name = cursor.fetchone()[0]
@ -123,7 +123,7 @@ def sco_dump_and_send_db(context, REQUEST=None):
fcntl.flock(x, fcntl.LOCK_UN)
log("sco_dump_and_send_db: done.")
return "\n".join(H) + context.sco_footer(REQUEST)
return "\n".join(H) + html_sco_header.sco_footer(context, REQUEST)
def _duplicate_db(db_name, ano_db_name):
@ -188,7 +188,7 @@ def _send_db(context, REQUEST, ano_db_name):
scu.SCO_DUMP_UP_URL,
files=files,
data={
"dept_name": context.get_preference("DeptName"),
"dept_name": sco_preferences.get_preference(context, "DeptName"),
"serial": _get_scodoc_serial(context),
"sco_user": str(REQUEST.AUTHENTICATED_USER),
"sent_by": context.Users.user_info(str(REQUEST.AUTHENTICATED_USER))[

View File

@ -35,6 +35,7 @@ from TrivialFormulator import TrivialFormulator, TF, tf_error_message
import sco_codes_parcours
import sco_formsemestre
from sco_exceptions import ScoValueError
import sco_formation
def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST=None):
@ -45,7 +46,9 @@ def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST
F = F[0]
H = [
context.sco_header(REQUEST, page_title="Suppression d'une formation"),
html_sco_header.sco_header(
context, REQUEST, page_title="Suppression d'une formation"
),
"""<h2>Suppression de la formation %(titre)s (%(acronyme)s)</h2>""" % F,
]
@ -85,7 +88,7 @@ def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST
% context.NotesURL()
)
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
@ -98,7 +101,9 @@ def formation_edit(context, formation_id=None, create=False, REQUEST=None):
"""Edit or create a formation"""
if create:
H = [
context.sco_header(REQUEST, page_title="Création d'une formation"),
html_sco_header.sco_header(
context, REQUEST, page_title="Création d'une formation"
),
"""<h2>Création d'une formation</h2>
<p class="help">Une "formation" décrit une filière, comme un DUT ou une Licence. La formation se subdivise en unités pédagogiques (UE, matières, modules). Elle peut se diviser en plusieurs semestres (ou sessions), qui seront mis en place séparément.
@ -120,7 +125,9 @@ def formation_edit(context, formation_id=None, create=False, REQUEST=None):
is_locked = context.formation_has_locked_sems(formation_id)
submitlabel = "Modifier les valeurs"
H = [
context.sco_header(REQUEST, page_title="Modification d'une formation"),
html_sco_header.sco_header(
context, REQUEST, page_title="Modification d'une formation"
),
"""<h2>Modification de la formation %(acronyme)s</h2>""" % initvalues,
]
if is_locked:
@ -190,7 +197,7 @@ def formation_edit(context, formation_id=None, create=False, REQUEST=None):
submitlabel=submitlabel,
)
if tf[0] == 0:
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
return "\n".join(H) + tf[1] + html_sco_header.sco_footer(context, REQUEST)
elif tf[0] == -1:
return REQUEST.RESPONSE.redirect(context.NotesURL())
else:
@ -213,7 +220,7 @@ def formation_edit(context, formation_id=None, create=False, REQUEST=None):
"Valeurs incorrectes: il existe déjà une formation avec même titre, acronyme et version."
)
+ tf[1]
+ context.sco_footer(REQUEST)
+ html_sco_header.sco_footer(context, REQUEST)
)
#
if create:
@ -223,6 +230,32 @@ def formation_edit(context, formation_id=None, create=False, REQUEST=None):
return REQUEST.RESPONSE.redirect("ue_list?formation_id=%s" % formation_id)
def do_formation_create(context, args, REQUEST):
"create a formation"
cnx = context.GetDBConnexion()
# check unique acronyme/titre/version
a = args.copy()
if a.has_key("formation_id"):
del a["formation_id"]
F = context.formation_list(args=a)
if len(F) > 0:
log("do_formation_create: error: %d formations matching args=%s" % (len(F), a))
raise ScoValueError("Formation non unique (%s) !" % str(a))
# Si pas de formation_code, l'enleve (default SQL)
if args.has_key("formation_code") and not args["formation_code"]:
del args["formation_code"]
#
r = _formationEditor.create(cnx, args)
sco_news.add(
context,
REQUEST,
typ=NEWS_FORM,
text="Création de la formation %(titre)s (%(acronyme)s)" % args,
)
return r
def do_formation_edit(context, args):
"edit a formation"
# log('do_formation_edit( args=%s )'%args)
@ -238,12 +271,12 @@ def do_formation_edit(context, args):
del args["formation_code"]
cnx = context.GetDBConnexion()
context._formationEditor.edit(cnx, args)
sco_formation._formationEditor.edit(cnx, args)
# Invalide les semestres utilisant cette formation:
for sem in sco_formsemestre.do_formsemestre_list(
context, args={"formation_id": args["formation_id"]}
):
context._inval_cache(
formsemestre_id=sem["formsemestre_id"]
sco_core.inval_cache(
context, formsemestre_id=sem["formsemestre_id"]
) # > formation modif.

View File

@ -40,7 +40,9 @@ def matiere_create(context, ue_id=None, REQUEST=None):
"""Creation d'une matiere"""
UE = context.do_ue_list(args={"ue_id": ue_id})[0]
H = [
context.sco_header(REQUEST, page_title="Création d'une matière"),
html_sco_header.sco_header(
context, REQUEST, page_title="Création d'une matière"
),
"""<h2>Création d'une matière dans l'UE %(titre)s (%(acronyme)s)</h2>""" % UE,
"""<p class="help">Les matières sont des groupes de modules dans une UE
d'une formation donnée. Les matières servent surtout pour la
@ -78,7 +80,7 @@ associé.
dest_url = context.NotesURL() + "/ue_list?formation_id=" + UE["formation_id"]
if tf[0] == 0:
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
return "\n".join(H) + tf[1] + html_sco_header.sco_footer(context, REQUEST)
elif tf[0] == -1:
return REQUEST.RESPONSE.redirect(dest_url)
else:
@ -89,7 +91,7 @@ associé.
"\n".join(H)
+ tf_error_message("Titre de matière déjà existant dans cette UE")
+ tf[1]
+ context.sco_footer(REQUEST)
+ html_sco_header.sco_footer(context, REQUEST)
)
_ = context.do_matiere_create(tf[2], REQUEST)
return REQUEST.RESPONSE.redirect(dest_url)
@ -100,7 +102,9 @@ def matiere_delete(context, matiere_id=None, REQUEST=None):
M = context.do_matiere_list(args={"matiere_id": matiere_id})[0]
UE = context.do_ue_list(args={"ue_id": M["ue_id"]})[0]
H = [
context.sco_header(REQUEST, page_title="Suppression d'une matière"),
html_sco_header.sco_header(
context, REQUEST, page_title="Suppression d'une matière"
),
"<h2>Suppression de la matière %(titre)s" % M,
" dans l'UE (%(acronyme)s))</h2>" % UE,
]
@ -114,7 +118,7 @@ def matiere_delete(context, matiere_id=None, REQUEST=None):
cancelbutton="Annuler",
)
if tf[0] == 0:
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
return "\n".join(H) + tf[1] + html_sco_header.sco_footer(context, REQUEST)
elif tf[0] == -1:
return REQUEST.RESPONSE.redirect(dest_url)
else:
@ -138,7 +142,9 @@ def matiere_edit(context, matiere_id=None, REQUEST=None):
ue_names = ["%(acronyme)s (%(titre)s)" % u for u in ues]
ue_ids = [u["ue_id"] for u in ues]
H = [
context.sco_header(REQUEST, page_title="Modification d'une matière"),
html_sco_header.sco_header(
context, REQUEST, page_title="Modification d'une matière"
),
"""<h2>Modification de la matière %(titre)s""" % F,
"""(formation %(acronyme)s, version %(version)s)</h2>""" % Fo,
]
@ -182,7 +188,9 @@ associé.
dest_url = context.NotesURL() + "/ue_list?formation_id=" + U["formation_id"]
if tf[0] == 0:
return "\n".join(H) + tf[1] + help + context.sco_footer(REQUEST)
return (
"\n".join(H) + tf[1] + help + html_sco_header.sco_footer(context, REQUEST)
)
elif tf[0] == -1:
return REQUEST.RESPONSE.redirect(dest_url)
else:
@ -195,7 +203,7 @@ associé.
"\n".join(H)
+ tf_error_message("Titre de matière déjà existant dans cette UE")
+ tf[1]
+ context.sco_footer(REQUEST)
+ html_sco_header.sco_footer(context, REQUEST)
)
# changement d'UE ?
@ -210,3 +218,18 @@ associé.
context.do_matiere_edit(tf[2])
return REQUEST.RESPONSE.redirect(dest_url)
def matiere_is_locked(context, matiere_id):
"""True if matiere should not be modified
(contains modules used in a locked formsemestre)
"""
r = ndb.SimpleDictFetch(
context,
"""SELECT ma.* from notes_matieres ma, notes_modules mod, notes_formsemestre sem, notes_moduleimpl mi
WHERE ma.matiere_id = mod.matiere_id AND mi.module_id = mod.module_id AND mi.formsemestre_id = sem.formsemestre_id
AND ma.matiere_id = %(matiere_id)s AND sem.etat = 0
""",
{"matiere_id": matiere_id},
)
return len(r) > 0

View File

@ -66,7 +66,7 @@ def module_create(context, matiere_id=None, REQUEST=None):
parcours = sco_codes_parcours.get_parcours_from_code(Fo["type_parcours"])
semestres_indices = range(1, parcours.NB_SEM + 1)
H = [
context.sco_header(REQUEST, page_title="Création d'un module"),
html_sco_header.sco_header(context, REQUEST, page_title="Création d'un module"),
"""<h2>Création d'un module dans la matière %(titre)s""" % M,
""" (UE %(acronyme)s)</h2>""" % UE,
_MODULE_HELP,
@ -170,7 +170,7 @@ def module_create(context, matiere_id=None, REQUEST=None):
submitlabel="Créer ce module",
)
if tf[0] == 0:
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
return "\n".join(H) + tf[1] + html_sco_header.sco_footer(context, REQUEST)
else:
context.do_module_create(tf[2], REQUEST)
return REQUEST.RESPONSE.redirect(
@ -187,7 +187,9 @@ def module_delete(context, module_id=None, REQUEST=None):
raise ScoValueError("Module inexistant !")
Mod = Mods[0]
H = [
context.sco_header(REQUEST, page_title="Suppression d'un module"),
html_sco_header.sco_header(
context, REQUEST, page_title="Suppression d'un module"
),
"""<h2>Suppression du module %(titre)s (%(code)s)</h2>""" % Mod,
]
@ -201,7 +203,7 @@ def module_delete(context, module_id=None, REQUEST=None):
cancelbutton="Annuler",
)
if tf[0] == 0:
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
return "\n".join(H) + tf[1] + html_sco_header.sco_footer(context, REQUEST)
elif tf[0] == -1:
return REQUEST.RESPONSE.redirect(dest_url)
else:
@ -226,7 +228,7 @@ def module_edit(context, module_id=None, REQUEST=None):
if not Mod:
raise ScoValueError("invalid module !")
Mod = Mod[0]
unlocked = not context.module_is_locked(module_id)
unlocked = not module_is_locked(context, module_id)
Fo = context.formation_list(args={"formation_id": Mod["formation_id"]})[0]
parcours = sco_codes_parcours.get_parcours_from_code(Fo["type_parcours"])
M = ndb.SimpleDictFetch(
@ -243,7 +245,8 @@ def module_edit(context, module_id=None, REQUEST=None):
dest_url = context.NotesURL() + "/ue_list?formation_id=" + Mod["formation_id"]
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Modification du module %(titre)s" % Mod,
cssstyles=["libjs/jQuery-tagEditor/jquery.tag-editor.css"],
@ -375,7 +378,7 @@ def module_edit(context, module_id=None, REQUEST=None):
)
if tf[0] == 0:
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
return "\n".join(H) + tf[1] + html_sco_header.sco_footer(context, REQUEST)
elif tf[0] == -1:
return REQUEST.RESPONSE.redirect(dest_url)
else:
@ -412,12 +415,16 @@ def module_list(context, formation_id, REQUEST=None):
raise ScoValueError("invalid formation !")
F = context.formation_list(args={"formation_id": formation_id})[0]
H = [
context.sco_header(REQUEST, page_title="Liste des modules de %(titre)s" % F),
html_sco_header.sco_header(
context, REQUEST, page_title="Liste des modules de %(titre)s" % F
),
"""<h2>Listes des modules dans la formation %(titre)s (%(acronyme)s)</h2>"""
% F,
'<ul class="notes_module_list">',
]
editable = REQUEST.AUTHENTICATED_USER.has_permission(ScoChangeFormation, context)
editable = REQUEST.AUTHENTICATED_USER.has_permission(
Permission.ScoChangeFormation, context
)
for Mod in context.do_module_list(args={"formation_id": formation_id}):
H.append('<li class="notes_module_list">%s' % Mod)
@ -428,11 +435,29 @@ def module_list(context, formation_id, REQUEST=None):
)
H.append("</li>")
H.append("</ul>")
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
#
def module_is_locked(context, module_id):
"""True if module should not be modified
(used in a locked formsemestre)
"""
r = ndb.SimpleDictFetch(
context,
"""SELECT mi.* from notes_modules mod, notes_formsemestre sem, notes_moduleimpl mi
WHERE mi.module_id = mod.module_id AND mi.formsemestre_id = sem.formsemestre_id
AND mi.module_id = %(module_id)s AND sem.etat = 0
""",
{"module_id": module_id},
)
return len(r) > 0
def module_count_moduleimpls(context, module_id):
"Number of moduleimpls using this module"
mods = sco_moduleimpl.do_moduleimpl_list(context, module_id=module_id)
return len(mods)
def formation_add_malus_modules(context, formation_id, titre=None, REQUEST=None):

View File

@ -73,7 +73,9 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None):
parcours = sco_codes_parcours.get_parcours_from_code(Fo["type_parcours"])
H = [
context.sco_header(REQUEST, page_title=title, javascripts=["js/edit_ue.js"]),
html_sco_header.sco_header(
context, REQUEST, page_title=title, javascripts=["js/edit_ue.js"]
),
"<h2>" + title,
" (formation %(acronyme)s, version %(version)s)</h2>" % Fo,
"""
@ -186,7 +188,7 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None):
if tf[0] == 0:
X = """<div id="ue_list_code"></div>
"""
return "\n".join(H) + tf[1] + X + context.sco_footer(REQUEST)
return "\n".join(H) + tf[1] + X + html_sco_header.sco_footer(context, REQUEST)
else:
if create:
if not tf[2]["ue_code"]:
@ -300,14 +302,16 @@ def ue_list(context, formation_id=None, msg="", REQUEST=None):
ue_list.sort(key=lambda u: (u["semestre_id"], u["numero"]))
has_duplicate_ue_codes = len(set([ue["ue_code"] for ue in ue_list])) != len(ue_list)
perm_change = authuser.has_permission(ScoChangeFormation, context)
perm_change = authuser.has_permission(Permission.ScoChangeFormation, context)
# editable = (not locked) and perm_change
# On autorise maintanant la modification des formations qui ont des semestres verrouillés,
# sauf si cela affect les notes passées (verrouillées):
# - pas de modif des modules utilisés dans des semestres verrouillés
# - pas de changement des codes d'UE utilisés dans des semestres verrouillés
editable = perm_change
tag_editable = authuser.has_permission(ScoEditFormationTags, context) or perm_change
tag_editable = (
authuser.has_permission(Permission.ScoEditFormationTags, context) or perm_change
)
if locked:
lockicon = scu.icontag("lock32_img", title="verrouillé")
else:
@ -321,7 +325,8 @@ def ue_list(context, formation_id=None, msg="", REQUEST=None):
"delete_small_dis_img", title="Suppression impossible (module utilisé)"
)
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
cssstyles=["libjs/jQuery-tagEditor/jquery.tag-editor.css"],
javascripts=[
@ -464,7 +469,7 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module
'<span class="ue_type">%s</span>'
% sco_codes_parcours.UE_TYPE_NAME[UE["type"]]
)
ue_editable = editable and not context.ue_is_locked(UE["ue_id"])
ue_editable = editable and not ue_is_locked(context, UE["ue_id"])
if ue_editable:
H.append(
'<a class="stdlink" href="ue_edit?ue_id=%(ue_id)s">modifier</a>' % UE
@ -477,21 +482,25 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module
for Mat in Matlist:
if not parcours.UE_IS_MODULE:
H.append('<li class="notes_matiere_list">')
if editable and not context.matiere_is_locked(Mat["matiere_id"]):
if editable and not sco_edit_matiere.matiere_is_locked(
context, Mat["matiere_id"]
):
H.append(
'<a class="stdlink" href="matiere_edit?matiere_id=%(matiere_id)s">'
% Mat
)
H.append("%(titre)s" % Mat)
if editable and not context.matiere_is_locked(Mat["matiere_id"]):
if editable and not sco_edit_matiere.matiere_is_locked(
context, Mat["matiere_id"]
):
H.append("</a>")
H.append('<ul class="notes_module_list">')
Modlist = context.do_module_list(args={"matiere_id": Mat["matiere_id"]})
im = 0
for Mod in Modlist:
Mod["nb_moduleimpls"] = context.module_count_moduleimpls(
Mod["module_id"]
Mod["nb_moduleimpls"] = sco_edit_module.module_count_moduleimpls(
context, Mod["module_id"]
)
klass = "notes_module_list"
if Mod["module_type"] == scu.MODULE_MALUS:
@ -523,9 +532,7 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module
H.append(delete_disabled_icon)
H.append("</span>")
mod_editable = (
editable # and not context.module_is_locked(Mod['module_id'])
)
mod_editable = editable # and not sco_edit_module.module_is_locked(context, Mod['module_id'])
if mod_editable:
H.append(
'<a class="discretelink" title="Modifier le module numéro %(numero)s, utilisé par %(nb_moduleimpls)d sessions" href="module_edit?module_id=%(module_id)s">'
@ -653,7 +660,7 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module
H.append("</li>")
H.append("</ul>")
if authuser.has_permission(ScoImplement, context):
if authuser.has_permission(Permission.ScoImplement, context):
H.append(
"""<ul>
<li><a class="stdlink" href="formsemestre_createwithmodules?formation_id=%(formation_id)s&semestre_id=1">Mettre en place un nouveau semestre de formation %(acronyme)s</a>
@ -667,7 +674,7 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module
warn, _ = sco_formsemestre_validation.check_formation_ues(context, formation_id)
H.append(warn)
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "".join(H)
@ -730,7 +737,7 @@ def do_ue_edit(context, args, bypass_lock=False, dont_invalidate_cache=False):
# check
ue_id = args["ue_id"]
ue = context.do_ue_list({"ue_id": ue_id})[0]
if (not bypass_lock) and context.ue_is_locked(ue["ue_id"]):
if (not bypass_lock) and ue_is_locked(context, ue["ue_id"]):
raise ScoLockedFormError()
# check: acronyme unique dans cette formation
if args.has_key("acronyme"):
@ -753,8 +760,8 @@ def do_ue_edit(context, args, bypass_lock=False, dont_invalidate_cache=False):
for sem in sco_formsemestre.do_formsemestre_list(
context, args={"formation_id": ue["formation_id"]}
):
context._inval_cache(
formsemestre_id=sem["formsemestre_id"]
sco_core.inval_cache(
context, formsemestre_id=sem["formsemestre_id"]
) # > formation (ue) modif.
@ -780,6 +787,22 @@ def edit_ue_set_code_apogee(context, id=None, value=None, REQUEST=None):
return value
def ue_is_locked(context, ue_id):
"""True if UE should not be modified
(contains modules used in a locked formsemestre)
"""
r = ndb.SimpleDictFetch(
context,
"""SELECT ue.* FROM notes_ue ue, notes_modules mod, notes_formsemestre sem, notes_moduleimpl mi
WHERE ue.ue_id = mod.ue_id
AND mi.module_id = mod.module_id AND mi.formsemestre_id = sem.formsemestre_id
AND ue.ue_id = %(ue_id)s AND sem.etat = 0
""",
{"ue_id": ue_id},
)
return len(r) > 0
# ---- Table recap formation
def formation_table_recap(context, formation_id, format="html", REQUEST=None):
"""Table recapitulant formation."""
@ -794,8 +817,8 @@ def formation_table_recap(context, formation_id, format="html", REQUEST=None):
for Mat in Matlist:
Modlist = context.do_module_list(args={"matiere_id": Mat["matiere_id"]})
for Mod in Modlist:
Mod["nb_moduleimpls"] = context.module_count_moduleimpls(
Mod["module_id"]
Mod["nb_moduleimpls"] = sco_edit_module.module_count_moduleimpls(
context, Mod["module_id"]
)
#
T.append(
@ -858,7 +881,9 @@ def formation_table_recap(context, formation_id, format="html", REQUEST=None):
page_title=title,
html_title="<h2>" + title + "</h2>",
pdf_title=title,
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
return tab.make_page(context, format=format, REQUEST=REQUEST)

View File

@ -52,7 +52,7 @@ def formsemestre_get_ics_url(context, sem):
Par exemple:
https://example.fr/agenda/{sem[etapes][0]}
"""
ics_url_tmpl = context.get_preference("edt_sem_ics_url", sem["formsemestre_id"])
ics_url_tmpl = sco_preferences.get_preference(context, "edt_sem_ics_url", sem["formsemestre_id"])
if not ics_url_tmpl:
return None
try:
@ -98,7 +98,7 @@ def get_edt_transcodage_groups(context, formsemestre_id):
edt2sco = {}
sco2edt = {}
msg = "" # message erreur, '' si ok
txt = context.get_preference("edt_groups2scodoc", formsemestre_id)
txt = sco_preferences.get_preference(context, "edt_groups2scodoc", formsemestre_id)
if not txt:
return edt2sco, sco2edt, msg
@ -163,7 +163,7 @@ def experimental_calendar(context, group_id=None, formsemestre_id=None, REQUEST=
"""experimental page"""
return "\n".join(
[
context.sco_header(
html_sco_header.sco_header(context,
REQUEST,
javascripts=[
"libjs/purl.js",
@ -195,7 +195,7 @@ def experimental_calendar(context, group_id=None, formsemestre_id=None, REQUEST=
"""</form><div id="loading">loading...</div>
<div id="calendar"></div>
""",
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
"""<script>
$(document).ready(function() {

View File

@ -76,7 +76,9 @@ def apo_semset_maq_status(
block_export_res_modules = int(block_export_res_modules)
block_export_res_sdj = int(block_export_res_sdj)
prefs = context.get_preferences()
prefs = sco_preferences.SemPreferences(
context,
)
tab_archives = table_apo_csv_list(context, semset, REQUEST=REQUEST)
@ -98,7 +100,8 @@ def apo_semset_maq_status(
ok_for_export &= semset["jury_ok"]
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Export Apogée",
javascripts=["js/apo_semset_maq_status.js"],
@ -420,7 +423,7 @@ def apo_semset_maq_status(
"""
% (APO_INPUT_ENCODING,)
)
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
@ -474,7 +477,9 @@ def table_apo_csv_list(context, semset, REQUEST=None):
html_sortable=True,
# base_url = '%s?formsemestre_id=%s' % (REQUEST.URL0, formsemestre_id),
# caption='Maquettes enregistrées',
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
return tab
@ -559,8 +564,12 @@ def _view_etuds_page(
etuds.sort(key=lambda x: (x["nom"], x["prenom"]))
H = [
context.sco_header(
REQUEST, page_title=title, init_qtip=True, javascripts=["js/etud_info.js"]
html_sco_header.sco_header(
context,
REQUEST,
page_title=title,
init_qtip=True,
javascripts=["js/etud_info.js"],
),
"<h2>%s</h2>" % title,
]
@ -579,7 +588,9 @@ def _view_etuds_page(
html_sortable=True,
html_class="table_leftalign",
filename="students_apo",
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
if format != "html":
return tab.make_page(context, format=format, REQUEST=REQUEST)
@ -591,7 +602,7 @@ def _view_etuds_page(
% semset_id
)
return "\n".join(H) + context.sco_footer(REQUEST)
return "\n".join(H) + html_sco_header.sco_footer(context, REQUEST)
def view_apo_csv_store(
@ -704,7 +715,8 @@ def view_apo_csv(context, etape_apo="", semset_id="", format="html", REQUEST=Non
) = sco_etape_apogee.apo_csv_semset_check(context, semset)
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Maquette Apogée enregistrée pour %s" % etape_apo,
init_qtip=True,
@ -728,7 +740,11 @@ def view_apo_csv(context, etape_apo="", semset_id="", format="html", REQUEST=Non
# Liste des étudiants (sans les résultats pour le moment): TODO
etuds = apo_data.etuds
if not etuds:
return "\n".join(H) + "<p>Aucun étudiant</p>" + context.sco_footer(REQUEST)
return (
"\n".join(H)
+ "<p>Aucun étudiant</p>"
+ html_sco_header.sco_footer(context, REQUEST)
)
# Ajout infos sur ScoDoc vs Apogee
for e in etuds:
@ -758,7 +774,9 @@ def view_apo_csv(context, etape_apo="", semset_id="", format="html", REQUEST=Non
base_url="%s?etape_apo=%s&semset_id=%s" % (REQUEST.URL0, etape_apo, semset_id),
filename="students_" + etape_apo,
caption="Etudiants Apogée en " + etape_apo,
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
if format != "html":
@ -771,7 +789,7 @@ def view_apo_csv(context, etape_apo="", semset_id="", format="html", REQUEST=Non
"""<div><a class="stdlink" href="apo_semset_maq_status?semset_id=%s">Retour</a>
</div>"""
% semset_id,
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)
@ -794,7 +812,9 @@ def apo_csv_export_results(
# nota: on peut éventuellement exporter même si tout n'est pas ok
# mais le lien via le tableau de bord n'est pas actif
# Les fichiers résultats ne sont pas stockés: pas besoin de permission particulière
prefs = context.get_preferences()
prefs = sco_preferences.SemPreferences(
context,
)
export_res_etape = prefs["export_res_etape"] and not int(block_export_res_etape)
export_res_sem = prefs["export_res_sem"] and not int(block_export_res_sem)
export_res_ues = prefs["export_res_ues"] and not int(block_export_res_ues)
@ -835,7 +855,7 @@ def apo_csv_export_results(
)
basename = (
context.get_preference("DeptName")
sco_preferences.get_preference(context, "DeptName")
+ str(annee_scolaire)
+ "-%s-" % periode
+ "-".join(etapes_apo)

View File

@ -104,7 +104,7 @@ def do_evaluation_delete(context, REQUEST, evaluation_id):
context._evaluationEditor.delete(cnx, evaluation_id)
# inval cache pour ce semestre
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0]
context._inval_cache(formsemestre_id=M["formsemestre_id"]) # > eval delete
sco_core.inval_cache(context, formsemestre_id=M["formsemestre_id"]) # > eval delete
# news
mod = context.do_module_list(args={"module_id": M["module_id"]})[0]
mod["moduleimpl_id"] = M["moduleimpl_id"]
@ -406,7 +406,7 @@ def _eval_etat(evals):
def do_evaluation_etat_in_sem(context, formsemestre_id, REQUEST=None):
"""-> nb_eval_completes, nb_evals_en_cours, nb_evals_vides,
date derniere modif, attente"""
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > liste evaluations et moduleimpl en attente
evals = nt.get_sem_evaluation_etat_list()
@ -429,7 +429,7 @@ def do_evaluation_etat_in_mod(context, nt, moduleimpl_id):
def formsemestre_evaluations_cal(context, formsemestre_id, REQUEST=None):
"""Page avec calendrier de toutes les evaluations de ce semestre"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > liste evaluations
@ -494,8 +494,12 @@ def formsemestre_evaluations_cal(context, formsemestre_id, REQUEST=None):
)
H = [
context.html_sem_header(
REQUEST, "Evaluations du semestre", sem, cssstyles=["css/calabs.css"]
html_sco_header.html_sem_header(
context,
REQUEST,
"Evaluations du semestre",
sem,
cssstyles=["css/calabs.css"],
),
'<div class="cal_evaluations">',
CalHTML,
@ -508,7 +512,7 @@ def formsemestre_evaluations_cal(context, formsemestre_id, REQUEST=None):
"""<p><a href="formsemestre_evaluations_delai_correction?formsemestre_id=%s" class="stdlink">voir les délais de correction</a></p>
"""
% (formsemestre_id,),
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)
@ -561,7 +565,7 @@ def formsemestre_evaluations_delai_correction(
N'indique pas les évaluations de ratrapage ni celles des modules de bonus/malus.
"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > liste evaluations
@ -622,7 +626,7 @@ def formsemestre_evaluations_delai_correction(
html_sortable=True,
html_title="<h2>Correction des évaluations du semestre</h2>",
caption="Correction des évaluations du semestre",
preferences=context.get_preferences(formsemestre_id),
preferences=sco_preferences.SemPreferences(context, formsemestre_id),
base_url="%s?formsemestre_id=%s" % (REQUEST.URL0, formsemestre_id),
origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "",
filename=scu.make_filename("evaluations_delais_" + sem["titreannee"]),
@ -825,12 +829,12 @@ def evaluation_create_form(
context._evaluation_check_write_access(REQUEST, moduleimpl_id=moduleimpl_id)
except AccessDenied as e:
return (
context.sco_header(REQUEST)
html_sco_header.sco_header(context, REQUEST)
+ "<h2>Opération non autorisée</h2><p>"
+ str(e)
+ "</p>"
+ '<p><a href="%s">Revenir</a></p>' % (str(REQUEST.HTTP_REFERER),)
+ context.sco_footer(REQUEST)
+ html_sco_header.sco_footer(context, REQUEST)
)
if readonly:
edit = True # montre les donnees existantes
@ -1054,8 +1058,15 @@ def evaluation_create_form(
dest_url = "moduleimpl_status?moduleimpl_id=%s" % M["moduleimpl_id"]
if tf[0] == 0:
head = context.sco_header(REQUEST, page_title=page_title)
return head + "\n".join(H) + "\n" + tf[1] + help + context.sco_footer(REQUEST)
head = html_sco_header.sco_header(context, REQUEST, page_title=page_title)
return (
head
+ "\n".join(H)
+ "\n"
+ tf[1]
+ help
+ html_sco_header.sco_footer(context, REQUEST)
)
elif tf[0] == -1:
return REQUEST.RESPONSE.redirect(dest_url)
else:

View File

@ -571,7 +571,7 @@ def Excel_feuille_listeappel(
(
"%s %s (%s - %s)"
% (
context.get_preference("DeptName", formsemestre_id),
sco_preferences.get_preference(context, "DeptName", formsemestre_id),
notesdb.unquote(sem["titre_num"]),
sem["date_debut"],
sem["date_fin"],

View File

@ -77,7 +77,7 @@ def _build_results_table(context, start_date=None, end_date=None, types_parcours
{}
) # etudid : { formsemestre_id d'inscription le plus recent dans les dates considérées, etud }
for formsemestre_id in formsemestre_ids_parcours:
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etudids
etudids = nt.get_etudids()
@ -104,7 +104,9 @@ def _build_results_table(context, start_date=None, end_date=None, types_parcours
origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "",
html_class="table_leftalign",
html_sortable=True,
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
return tab, semlist
@ -196,7 +198,7 @@ def _build_results_list(context, dpv_by_sem, etuds_infos):
int(sem["annee_debut"]), sem["mois_debut_ord"]
)
r["sid"] = "{} {} {}".format(
sem["sem_id_txt"], context.DeptId(), sem["modalite"]
sem["sem_id_txt"], sco_core.get_dept_id(), sem["modalite"]
)
rows.append(r)
@ -279,7 +281,8 @@ def scodoc_table_results(
info_sems.append("</ul>")
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Export résultats",
init_qtip=True,
@ -307,7 +310,7 @@ def scodoc_table_results(
""",
"\n".join(info_sems),
"""</div>""",
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)

View File

@ -35,7 +35,7 @@ import sco_utils as scu
import notesdb as ndb
from notes_log import log
from gen_tables import GenTable
import html_sco_header
import scolars
import sco_formsemestre
import sco_groups
@ -88,9 +88,11 @@ def form_search_etud(
if add_headers:
return (
context.sco_header(REQUEST, page_title="Choix d'un étudiant")
html_sco_header.sco_header(
context, REQUEST, page_title="Choix d'un étudiant"
)
+ "\n".join(H)
+ context.sco_footer(REQUEST)
+ html_sco_header.sco_footer(context, REQUEST)
)
else:
return "\n".join(H)
@ -122,7 +124,8 @@ def search_etud_in_dept(context, expnom="", REQUEST=None):
return context.ficheEtud(etudid=etuds[0]["etudid"], REQUEST=REQUEST)
H = [
context.sco_header(
html_sco_header.sco_header(
context,
page_title="Recherche d'un étudiant",
no_side_bar=True,
init_qtip=True,
@ -158,7 +161,9 @@ def search_etud_in_dept(context, expnom="", REQUEST=None):
rows=etuds,
html_sortable=True,
html_class="table_leftalign",
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
H.append(tab.html())
if len(etuds) > 20: # si la page est grande
@ -175,7 +180,7 @@ def search_etud_in_dept(context, expnom="", REQUEST=None):
H.append(
"""<p class="help">La recherche porte sur tout ou partie du NOM ou du NIP de l'étudiant</p>"""
)
return "\n".join(H) + context.sco_footer(REQUEST)
return "\n".join(H) + html_sco_header.sco_footer(context, REQUEST)
# Was chercheEtudsInfo()
@ -266,7 +271,7 @@ 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(ScoView, context)
return authuser.has_permission(Permission.ScoView, context)
def search_etud_in_accessible_depts(context, expnom=None, code_nip=None, REQUEST=None):
@ -336,9 +341,11 @@ def table_etud_in_accessible_depts(context, expnom=None, REQUEST=None):
H.append("</div>")
return (
context.scodoc_top_html_header(REQUEST, page_title="Choix d'un étudiant")
html_sco_header.scodoc_top_html_header(
context, REQUEST, page_title="Choix d'un étudiant"
)
+ "\n".join(H)
+ context.standard_html_footer(REQUEST)
+ html_sco_header.standard_html_footer()
)

View File

@ -42,6 +42,22 @@ from sco_exceptions import ScoValueError
from sco_permissions import ScoChangeFormation
import VERSION
_formationEditor = ndb.EditableTable(
"notes_formations",
"formation_id",
(
"formation_id",
"acronyme",
"titre",
"titre_officiel",
"version",
"formation_code",
"type_parcours",
"code_specialite",
),
sortkey="acronyme",
)
def formation_export(
context, formation_id, export_ids=False, export_tags=True, format=None, REQUEST=None
@ -217,7 +233,9 @@ def formation_list_table(context, formation_id=None, args={}, REQUEST=None):
"edit_img", border="0", alt="modifier", title="Modifier titres et code"
)
editable = REQUEST.AUTHENTICATED_USER.has_permission(ScoChangeFormation, context)
editable = REQUEST.AUTHENTICATED_USER.has_permission(
Permission.ScoChangeFormation, context
)
# Traduit/ajoute des champs à afficher:
for f in formations:
@ -315,5 +333,7 @@ def formation_list_table(context, formation_id=None, args={}, REQUEST=None):
base_url="%s?formation_id=%s" % (REQUEST.URL0, formation_id),
page_title=title,
pdf_title=title,
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)

View File

@ -226,7 +226,9 @@ def do_formsemestre_edit(context, sem, cnx=None, **kw):
write_formsemestre_etapes(context, sem)
write_formsemestre_responsables(context, sem)
context._inval_cache(formsemestre_id=sem["formsemestre_id"]) # > modif formsemestre
sco_core.inval_cache(
context, formsemestre_id=sem["formsemestre_id"]
) # > modif formsemestre
def read_formsemestre_responsables(context, formsemestre_id):
@ -543,9 +545,13 @@ def table_formsemestres(
"etapes_apo_str": "Apo.",
}
if sems:
preferences = context.get_preferences(sems[0]["formsemestre_id"])
preferences = sco_preferences.SemPreferences(
context, sems[0]["formsemestre_id"]
)
else:
preferences = context.get_preferences()
preferences = sco_preferences.SemPreferences(
context,
)
tab = GenTable(
columns_ids=columns_ids,
rows=sems,

View File

@ -84,7 +84,7 @@ def formsemestre_custommenu_edit(context, formsemestre_id, REQUEST=None):
context.NotesURL() + "/formsemestre_status?formsemestre_id=%s" % formsemestre_id
)
H = [
context.html_sem_header(REQUEST, "Modification du menu du semestre ", sem),
html_sco_header.html_sem_header(context, REQUEST, "Modification du menu du semestre ", sem),
"""<p class="help">Ce menu, spécifique à chaque semestre, peut être utilisé pour placer des liens vers vos applications préférées.</p>
<p class="help">Procédez en plusieurs fois si vous voulez ajouter plusieurs items.</p>""",
]
@ -127,7 +127,7 @@ def formsemestre_custommenu_edit(context, formsemestre_id, REQUEST=None):
name="tf",
)
if tf[0] == 0:
return "\n".join(H) + "\n" + tf[1] + context.sco_footer(REQUEST)
return "\n".join(H) + "\n" + tf[1] + html_sco_header.sco_footer(context, REQUEST)
elif tf[0] == -1:
return REQUEST.RESPONSE.redirect(dest_url)
else:

View File

@ -30,6 +30,7 @@
import notesdb as ndb
import sco_utils as scu
import sco_core
import sco_groups
from notes_log import log
from TrivialFormulator import TrivialFormulator, TF
@ -55,7 +56,8 @@ def _default_sem_title(F):
def formsemestre_createwithmodules(context, REQUEST=None):
"""Page création d'un semestre"""
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Création d'un semestre",
javascripts=["libjs/AutoSuggest.js"],
@ -64,7 +66,7 @@ def formsemestre_createwithmodules(context, REQUEST=None):
),
"""<h2>Mise en place d'un semestre de formation</h2>""",
do_formsemestre_createwithmodules(context, REQUEST=REQUEST),
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)
@ -74,7 +76,8 @@ def formsemestre_editwithmodules(context, REQUEST, formsemestre_id):
# portage from dtml
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
H = [
context.html_sem_header(
html_sco_header.html_sem_header(
context,
REQUEST,
"Modification du semestre",
sem,
@ -98,14 +101,14 @@ def formsemestre_editwithmodules(context, REQUEST, formsemestre_id):
<p class="help">Les modules ont toujours un responsable. Par défaut, c'est le directeur des études.</p>"""
)
return "\n".join(H) + context.sco_footer(REQUEST)
return "\n".join(H) + html_sco_header.sco_footer(context, REQUEST)
def can_edit_sem(context, REQUEST, formsemestre_id="", sem=None):
"""Return sem if user can edit it, False otherwise"""
sem = sem or sco_formsemestre.get_formsemestre(context, formsemestre_id)
authuser = REQUEST.AUTHENTICATED_USER
if not authuser.has_permission(ScoImplement, context): # pas chef
if not authuser.has_permission(Permission.ScoImplement, context): # pas chef
if not sem["resp_can_edit"] or str(authuser) not in sem["responsables"]:
return False
return sem
@ -118,7 +121,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
formsemestre_id = REQUEST.form["formsemestre_id"]
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
authuser = REQUEST.AUTHENTICATED_USER
if not authuser.has_permission(ScoImplement, context):
if not authuser.has_permission(Permission.ScoImplement, context):
if not edit:
# il faut ScoImplement pour creer un semestre
raise AccessDenied("vous n'avez pas le droit d'effectuer cette opération")
@ -186,7 +189,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
else:
semestre_id_labels.append(sid)
# Liste des modules dans ce semestre de cette formation
# on pourrait faire un simple context.module_list( )
# on pourrait faire un simple module_list( )
# mais si on veut l'ordre du PPN (groupe par UE et matieres) il faut:
mods = [] # liste de dicts
uelist = context.do_ue_list({"formation_id": formation_id})
@ -382,8 +385,8 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
"size": 32,
"title": "Element(s) Apogée:",
"explanation": "du semestre (ex: VRTW1). Séparés par des virgules.",
"allow_null": not context.get_preference(
"always_require_apo_sem_codes"
"allow_null": not sco_preferences.get_preference(
context, "always_require_apo_sem_codes"
),
},
)
@ -395,8 +398,8 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
"size": 32,
"title": "Element(s) Apogée:",
"explanation": "de l'année (ex: VRT1A). Séparés par des virgules.",
"allow_null": not context.get_preference(
"always_require_apo_sem_codes"
"allow_null": not sco_preferences.get_preference(
context, "always_require_apo_sem_codes"
),
},
)
@ -434,7 +437,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
},
),
]
if authuser.has_permission(ScoImplement, context):
if authuser.has_permission(Permission.ScoImplement, context):
modform += [
(
"resp_can_edit",
@ -641,7 +644,9 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
# check dates
if ndb.DateDMYtoISO(tf[2]["date_debut"]) > ndb.DateDMYtoISO(tf[2]["date_fin"]):
msg = '<ul class="tf-msg"><li class="tf-msg">Dates de début et fin incompatibles !</li></ul>'
if context.get_preference("always_require_apo_sem_codes") and not any(
if sco_preferences.get_preference(
context, "always_require_apo_sem_codes"
) and not any(
[tf[2]["etape_apo" + str(n)] for n in range(0, scu.EDIT_NB_ETAPES + 1)]
):
msg = '<ul class="tf-msg"><li class="tf-msg">Code étape Apogée manquant</li></ul>'
@ -866,7 +871,8 @@ def formsemestre_clone(context, formsemestre_id, REQUEST=None):
}
H = [
context.html_sem_header(
html_sco_header.html_sem_header(
context,
REQUEST,
"Copie du semestre",
sem,
@ -948,7 +954,7 @@ def formsemestre_clone(context, formsemestre_id, REQUEST=None):
if ndb.DateDMYtoISO(tf[2]["date_debut"]) > ndb.DateDMYtoISO(tf[2]["date_fin"]):
msg = '<ul class="tf-msg"><li class="tf-msg">Dates de début et fin incompatibles !</li></ul>'
if tf[0] == 0 or msg:
return "".join(H) + msg + tf[1] + context.sco_footer(REQUEST)
return "".join(H) + msg + tf[1] + html_sco_header.sco_footer(context, REQUEST)
elif tf[0] == -1: # cancel
return REQUEST.RESPONSE.redirect(
"formsemestre_status?formsemestre_id=%s" % formsemestre_id
@ -1034,7 +1040,7 @@ def do_formsemestre_clone(
# NB: don't copy notes_formsemestre_custommenu (usually specific)
# 4- Copy new style preferences
prefs = context.get_preferences(orig_formsemestre_id)
prefs = sco_preferences.SemPreferences(context, orig_formsemestre_id)
if orig_formsemestre_id in prefs.base_prefs.prefs:
for pname in prefs.base_prefs.prefs[orig_formsemestre_id]:
@ -1222,7 +1228,9 @@ def formsemestre_delete(context, formsemestre_id, REQUEST=None):
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
F = context.formation_list(args={"formation_id": sem["formation_id"]})[0]
H = [
context.html_sem_header(REQUEST, "Suppression du semestre", sem),
html_sco_header.html_sem_header(
context, REQUEST, "Suppression du semestre", sem
),
"""<div class="ue_warning"><span>Attention !</span>
<p class="help">A n'utiliser qu'en cas d'erreur lors de la saisie d'une formation. Normalement,
<b>un semestre ne doit jamais être supprimé</b> (on perd la mémoire des notes et de tous les événements liés à ce semestre !).</p>
@ -1262,7 +1270,7 @@ def formsemestre_delete(context, formsemestre_id, REQUEST=None):
)
else:
H.append(tf[1])
return "\n".join(H) + context.sco_footer(REQUEST)
return "\n".join(H) + html_sco_header.sco_footer(context, REQUEST)
elif tf[0] == -1: # cancel
return REQUEST.RESPONSE.redirect(
context.NotesURL()
@ -1336,7 +1344,9 @@ def do_formsemestre_delete(context, formsemestre_id, REQUEST):
"DELETE FROM notes_evaluation WHERE evaluation_id=%(evaluation_id)s",
e,
)
context.get_evaluations_cache().inval_cache(key=e["evaluation_id"])
sco_core.get_evaluations_cache(
context,
).inval_cache(key=e["evaluation_id"])
sco_moduleimpl.do_moduleimpl_delete(
context, mod["moduleimpl_id"], formsemestre_id=formsemestre_id
@ -1403,7 +1413,7 @@ def formsemestre_edit_options(context, formsemestre_id, target_url=None, REQUEST
ok, err = context._check_access_diretud(formsemestre_id, REQUEST)
if not ok:
return err
return context.get_preferences(formsemestre_id).edit(
return sco_preferences.SemPreferences(context, formsemestre_id).edit(
REQUEST=REQUEST, categories=["bul"]
)
@ -1500,7 +1510,7 @@ def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST=
return err
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
footer = context.sco_footer(REQUEST)
footer = html_sco_header.sco_footer(context, REQUEST)
help = """<p class="help">
Seuls les modules ont un coefficient. Cependant, il est nécessaire d'affecter un coefficient aux UE capitalisée pour pouvoir les prendre en compte dans la moyenne générale.
</p>
@ -1522,7 +1532,12 @@ def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST=
<p class="warning">Les coefficients indiqués ici ne s'appliquent que pour le traitement des UE capitalisées.
</p>
"""
H = [context.html_sem_header(REQUEST, "Coefficients des UE du semestre", sem), help]
H = [
html_sco_header.html_sem_header(
context, REQUEST, "Coefficients des UE du semestre", sem
),
help,
]
#
ues, modimpls = notes_table.get_sem_ues_modimpls(context, formsemestre_id)
for ue in ues:
@ -1628,12 +1643,12 @@ def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST=
z.append("</ul>")
else:
z = ["""<h3>Aucune modification</h3>"""]
context._inval_cache(
formsemestre_id=formsemestre_id
sco_core.inval_cache(
context, formsemestre_id=formsemestre_id
) # > modif coef UE cap (modifs notes de _certains_ etudiants)
header = context.html_sem_header(
REQUEST, "Coefficients des UE du semestre", sem
header = html_sco_header.html_sem_header(
context, REQUEST, "Coefficients des UE du semestre", sem
)
return (
header
@ -1663,9 +1678,11 @@ def get_formsemestre_session_id(context, sem, F, parcours):
# F = context.formation_list( args={ 'formation_id' : sem['formation_id'] } )[0]
# parcours = sco_codes_parcours.get_parcours_from_code(F['type_parcours'])
ImputationDept = context.get_preference("ImputationDept", sem["formsemestre_id"])
ImputationDept = sco_preferences.get_preference(
context, "ImputationDept", sem["formsemestre_id"]
)
if not ImputationDept:
ImputationDept = context.get_preference("DeptName")
ImputationDept = sco_preferences.get_preference(context, "DeptName")
ImputationDept = ImputationDept.upper()
parcours_type = parcours.NAME
modalite = sem["modalite"]

View File

@ -77,7 +77,7 @@ def formsemestre_ext_create_form(context, etudid, formsemestre_id, REQUEST=None)
"""Formulaire creation/inscription à un semestre extérieur"""
etud = context.getEtudInfo(etudid=etudid, filled=1)[0]
H = [
context.sco_header(REQUEST),
html_sco_header.sco_header(context, REQUEST),
"""<h2>Enregistrement d'une inscription antérieure dans un autre établissement</h2>
<p class="help">
Cette opération créé un semestre extérieur ("ancien") et y inscrit juste cet étudiant.
@ -94,7 +94,7 @@ def formsemestre_ext_create_form(context, etudid, formsemestre_id, REQUEST=None)
"""<h3><a href="ficheEtud?etudid=%s" class="stdlink">Etudiant %s</a></h3>"""
% (etudid, etud["nomprenom"]),
]
F = context.sco_footer(REQUEST)
F = html_sco_header.sco_footer(context, REQUEST)
orig_sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
# Ne propose que des semestres de semestre_id strictement inférieur au semestre courant
# et seulement si pas inscrit au même semestre_id d'un semestre ordinaire ScoDoc.
@ -256,10 +256,13 @@ def formsemestre_ext_edit_ue_validations(
def _make_page(context, etud, sem, tf, message="", REQUEST=None):
nt = context._getNotesCache().get_NotesTable(context, sem["formsemestre_id"])
nt = sco_core.get_notes_cache(
context,
).get_NotesTable(context, sem["formsemestre_id"])
moy_gen = nt.get_etud_moy_gen(etud["etudid"])
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Validation des UE d'un semestre extérieur",
javascripts=["js/formsemestre_ext_edit_ue_validations.js"],
@ -285,7 +288,7 @@ def _make_page(context, etud, sem, tf, message="", REQUEST=None):
</a></div>
"""
% (sem["formsemestre_id"], etud["etudid"]),
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return H

View File

@ -120,7 +120,10 @@ def formsemestre_inscription_with_modules_form(
Si only_ext, ne montre que les semestre extérieurs.
"""
etud = context.getEtudInfo(etudid=etudid, filled=1)[0]
H = [context.sco_header(REQUEST), "<h2>Inscription de %s" % etud["nomprenom"]]
H = [
html_sco_header.sco_header(context, REQUEST),
"<h2>Inscription de %s" % etud["nomprenom"],
]
if only_ext:
H.append(" dans un semestre extérieur")
H.append(
@ -130,7 +133,7 @@ def formsemestre_inscription_with_modules_form(
</p>
<h3>Choisir un semestre:</h3>"""
)
F = context.sco_footer(REQUEST)
F = html_sco_header.sco_footer(context, REQUEST)
sems = sco_formsemestre.do_formsemestre_list(context, args={"etat": "1"})
insem = context.do_formsemestre_inscription_list(
args={"etudid": etudid, "etat": "I"}
@ -177,11 +180,14 @@ def formsemestre_inscription_with_modules(
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
etud = context.getEtudInfo(etudid=etudid, filled=1)[0]
H = [
context.html_sem_header(
REQUEST, "Inscription de %s dans ce semestre" % etud["nomprenom"], sem
html_sco_header.html_sem_header(
context,
REQUEST,
"Inscription de %s dans ce semestre" % etud["nomprenom"],
sem,
)
]
F = context.sco_footer(REQUEST)
F = html_sco_header.sco_footer(context, REQUEST)
# Check 1: déjà inscrit ici ?
ins = context.Notes.do_formsemestre_inscription_list({"etudid": etudid})
already = False
@ -273,13 +279,13 @@ def formsemestre_inscription_option(context, etudid, formsemestre_id, REQUEST=No
raise ScoValueError("Modification impossible: semestre verrouille")
etud = context.getEtudInfo(etudid=etudid, filled=1)[0]
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etud_ue_status
F = context.sco_footer(REQUEST)
F = html_sco_header.sco_footer(context, REQUEST)
H = [
context.sco_header(REQUEST)
html_sco_header.sco_header(context, REQUEST)
+ "<h2>Inscription de %s aux modules de %s (%s - %s)</h2>"
% (etud["nomprenom"], sem["titre_num"], sem["date_debut"], sem["date_fin"])
]
@ -549,13 +555,13 @@ def do_moduleimpl_incription_options(
if REQUEST:
H = [
context.sco_header(REQUEST),
html_sco_header.sco_header(context, REQUEST),
"""<h3>Modifications effectuées</h3>
<p><a class="stdlink" href="%s/ficheEtud?etudid=%s">
Retour à la fiche étudiant</a></p>
"""
% (context.ScoURL(), etudid),
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)
@ -584,7 +590,7 @@ def list_inscrits_ailleurs(context, formsemestre_id):
Pour chacun, donne la liste des semestres.
{ etudid : [ liste de sems ] }
"""
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etudids
etudids = nt.get_etudids()
@ -600,8 +606,11 @@ def formsemestre_inscrits_ailleurs(context, formsemestre_id, REQUEST=None):
"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
H = [
context.html_sem_header(
REQUEST, "Inscriptions multiples parmi les étudiants du semestre ", sem
html_sco_header.html_sem_header(
context,
REQUEST,
"Inscriptions multiples parmi les étudiants du semestre ",
sem,
)
]
insd = list_inscrits_ailleurs(context, formsemestre_id)
@ -639,4 +648,4 @@ def formsemestre_inscrits_ailleurs(context, formsemestre_id, REQUEST=None):
)
else:
H.append("""<p>Aucun étudiant en inscription multiple (c'est normal) !</p>""")
return "\n".join(H) + context.sco_footer(REQUEST)
return "\n".join(H) + html_sco_header.sco_footer(context, REQUEST)

View File

@ -157,7 +157,7 @@ def formsemestre_status_menubar(context, sem, REQUEST):
"url": "formsemestre_editwithmodules?formation_id=%(formation_id)s&formsemestre_id=%(formsemestre_id)s"
% sem,
"enabled": (
authuser.has_permission(ScoImplement, context)
authuser.has_permission(Permission.ScoImplement, context)
or (
str(REQUEST.AUTHENTICATED_USER) in sem["responsables"]
and sem["resp_can_edit"]
@ -171,7 +171,7 @@ def formsemestre_status_menubar(context, sem, REQUEST):
"url": "formsemestre_edit_preferences?formsemestre_id=%(formsemestre_id)s"
% sem,
"enabled": (
authuser.has_permission(ScoImplement, context)
authuser.has_permission(Permission.ScoImplement, context)
or (
str(REQUEST.AUTHENTICATED_USER) in sem["responsables"]
and sem["resp_can_edit"]
@ -184,14 +184,14 @@ def formsemestre_status_menubar(context, sem, REQUEST):
"title": "Réglages bulletins",
"url": "formsemestre_edit_options?formsemestre_id=" + formsemestre_id,
"enabled": (uid in sem["responsables"])
or authuser.has_permission(ScoImplement, context),
or authuser.has_permission(Permission.ScoImplement, context),
"helpmsg": "Change les options",
},
{
"title": change_lock_msg,
"url": "formsemestre_change_lock?formsemestre_id=" + formsemestre_id,
"enabled": (uid in sem["responsables"])
or authuser.has_permission(ScoImplement, context),
or authuser.has_permission(Permission.ScoImplement, context),
"helpmsg": "",
},
{
@ -216,21 +216,21 @@ def formsemestre_status_menubar(context, sem, REQUEST):
{
"title": "Cloner ce semestre",
"url": "formsemestre_clone?formsemestre_id=" + formsemestre_id,
"enabled": authuser.has_permission(ScoImplement, context),
"enabled": authuser.has_permission(Permission.ScoImplement, context),
"helpmsg": "",
},
{
"title": "Associer à une nouvelle version du programme",
"url": "formsemestre_associate_new_version?formsemestre_id="
+ formsemestre_id,
"enabled": authuser.has_permission(ScoChangeFormation, context)
"enabled": authuser.has_permission(Permission.ScoChangeFormation, context)
and (sem["etat"] == "1"),
"helpmsg": "",
},
{
"title": "Supprimer ce semestre",
"url": "formsemestre_delete?formsemestre_id=" + formsemestre_id,
"enabled": authuser.has_permission(ScoImplement, context),
"enabled": authuser.has_permission(Permission.ScoImplement, context),
"helpmsg": "",
},
]
@ -254,41 +254,41 @@ def formsemestre_status_menubar(context, sem, REQUEST):
{
"title": "Passage des étudiants depuis d'autres semestres",
"url": "formsemestre_inscr_passage?formsemestre_id=" + formsemestre_id,
"enabled": authuser.has_permission(ScoEtudInscrit, context)
"enabled": authuser.has_permission(Permission.ScoEtudInscrit, context)
and (sem["etat"] == "1"),
},
{
"title": "Synchroniser avec étape Apogée",
"url": "formsemestre_synchro_etuds?formsemestre_id=" + formsemestre_id,
"enabled": authuser.has_permission(ScoView, context)
and context.get_preference("portal_url")
"enabled": authuser.has_permission(Permission.ScoView, context)
and sco_preferences.get_preference(context, "portal_url")
and (sem["etat"] == "1"),
},
{
"title": "Inscrire un étudiant",
"url": "formsemestre_inscription_with_modules_etud?formsemestre_id="
+ formsemestre_id,
"enabled": authuser.has_permission(ScoEtudInscrit, context)
"enabled": authuser.has_permission(Permission.ScoEtudInscrit, context)
and (sem["etat"] == "1"),
},
{
"title": "Importer des étudiants dans ce semestre (table Excel)",
"url": "form_students_import_excel?formsemestre_id=" + formsemestre_id,
"enabled": authuser.has_permission(ScoEtudInscrit, context)
"enabled": authuser.has_permission(Permission.ScoEtudInscrit, context)
and (sem["etat"] == "1"),
},
{
"title": "Import/export des données admission",
"url": "form_students_import_infos_admissions?formsemestre_id="
+ formsemestre_id,
"enabled": authuser.has_permission(ScoView, context),
"enabled": authuser.has_permission(Permission.ScoView, context),
},
{
"title": "Resynchroniser données identité",
"url": "formsemestre_import_etud_admission?formsemestre_id="
+ formsemestre_id,
"enabled": authuser.has_permission(ScoEtudChangeAdr, context)
and context.get_preference("portal_url"),
"enabled": authuser.has_permission(Permission.ScoEtudChangeAdr, context)
and sco_preferences.get_preference(context, "portal_url"),
},
{
"title": "Exporter table des étudiants",
@ -518,7 +518,9 @@ def fill_formsemestre(context, sem, REQUEST=None):
)
else:
sem["locklink"] = ""
if context.get_preference("bul_display_publication", formsemestre_id):
if sco_preferences.get_preference(
context, "bul_display_publication", formsemestre_id
):
if sem["bul_hide_xml"] != "0":
eyeicon = scu.icontag("hide_img", border="0", title="Bulletins NON publiés")
else:
@ -565,10 +567,12 @@ def formsemestre_description_table(
Liste des modules et de leurs coefficients
"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > liste evaluations
use_ue_coefs = context.get_preference("use_ue_coefs", formsemestre_id)
use_ue_coefs = sco_preferences.get_preference(
context, "use_ue_coefs", formsemestre_id
)
F = context.formation_list(args={"formation_id": sem["formation_id"]})[0]
parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"])
Mlist = sco_moduleimpl.do_moduleimpl_withmodule_list(
@ -654,7 +658,7 @@ def formsemestre_description_table(
sums = {"_css_row_class": "moyenne sortbottom", "ects": sum_ects, "Coef.": sum_coef}
R.append(sums)
columns_ids = ["UE", "Code", "Module", "Coef."]
if context.get_preference("bul_show_ects", formsemestre_id):
if sco_preferences.get_preference(context, "bul_show_ects", formsemestre_id):
columns_ids += ["ects"]
columns_ids += ["Inscrits", "Responsable", "Enseignants"]
if with_evals:
@ -687,11 +691,11 @@ def formsemestre_description_table(
base_url="%s?formsemestre_id=%s&with_evals=%s"
% (REQUEST.URL0, formsemestre_id, with_evals),
page_title=title,
html_title=context.html_sem_header(
REQUEST, "Description du semestre", sem, with_page_header=False
html_title=html_sco_header.html_sem_header(
context, REQUEST, "Description du semestre", sem, with_page_header=False
),
pdf_title=title,
preferences=context.get_preferences(formsemestre_id),
preferences=sco_preferences.SemPreferences(context, formsemestre_id),
)
@ -718,21 +722,7 @@ def formsemestre_description(
return tab.make_page(context, format=format, REQUEST=REQUEST)
def formsemestre_lists(context, formsemestre_id, REQUEST=None):
"""Listes des étudiants
XXX (ancienne page, remplacée par groups_view, va être supprimée)
"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
H = [
context.html_sem_header(REQUEST, "", sem),
_make_listes_sem(context, sem, REQUEST),
context.sco_footer(REQUEST),
]
return "\n".join(H)
# genere liste html pour accès aux groupes de ce semestre
# XXX #sco8 vérifier si c'est encore utilisé !
def _make_listes_sem(context, sem, REQUEST=None, with_absences=True):
context = context
authuser = REQUEST.AUTHENTICATED_USER
@ -750,7 +740,7 @@ def _make_listes_sem(context, sem, REQUEST=None, with_absences=True):
#
H = []
# pas de menu absences si pas autorise:
if with_absences and not authuser.has_permission(ScoAbsChange, context):
if with_absences and not authuser.has_permission(Permission.ScoAbsChange, context):
with_absences = False
#
@ -896,8 +886,8 @@ def formsemestre_status_head(
page_title = page_title or "Modules de "
H = [
context.html_sem_header(
REQUEST, page_title, sem, with_page_header=False, with_h2=False
html_sco_header.html_sem_header(
context, REQUEST, page_title, sem, with_page_header=False, with_h2=False
),
"""<table>
<tr><td class="fichetitre2">Formation: </td><td>
@ -941,7 +931,7 @@ Il y a des notes en attente ! Le classement des étudiants n'a qu'une valeur ind
H.append(
'<p class="fontorange"><em>Attention: ce semestre couvre plusieurs années scolaires !</em></p>'
)
# elif context.get_preference('bul_display_publication', formsemestre_id):
# elif sco_preferences.get_preference(context, 'bul_display_publication', formsemestre_id):
# H.append('<p><em>Bulletins publiés sur le portail</em></p>')
return "".join(H)
@ -965,14 +955,18 @@ def formsemestre_status(context, formsemestre_id=None, REQUEST=None):
)
H = [
context.sco_header(REQUEST, page_title="Semestre %s" % sem["titreannee"]),
html_sco_header.sco_header(
context, REQUEST, page_title="Semestre %s" % sem["titreannee"]
),
'<div class="formsemestre_status">',
formsemestre_status_head(
context, formsemestre_id=formsemestre_id, page_title="Tableau de bord"
),
"""<p><b style="font-size: 130%">Tableau de bord: </b><span class="help">cliquez sur un module pour saisir des notes</span></p>""",
]
nt = context._getNotesCache().get_NotesTable(context, formsemestre_id)
nt = sco_core.get_notes_cache(
context,
).get_NotesTable(context, formsemestre_id)
if nt.expr_diagnostics:
H.append(html_expr_diagnostic(context, nt.expr_diagnostics))
H.append(
@ -1019,7 +1013,7 @@ def formsemestre_status(context, formsemestre_id=None, REQUEST=None):
prev_ue_id = ue["ue_id"]
acronyme = ue["acronyme"]
titre = ue["titre"]
if context.get_preference("use_ue_coefs", formsemestre_id):
if sco_preferences.get_preference(context, "use_ue_coefs", formsemestre_id):
titre += " <b>(coef. %s)</b>" % (ue["coefficient"] or 0.0)
H.append(
"""<tr class="formsemestre_status_ue"><td colspan="4">
@ -1130,14 +1124,18 @@ def formsemestre_status(context, formsemestre_id=None, REQUEST=None):
H.append("</td></tr>")
H.append("</table></p>")
if context.get_preference("use_ue_coefs", formsemestre_id):
if sco_preferences.get_preference(context, "use_ue_coefs", formsemestre_id):
H.append(
"""
<p class="infop">utilise les coefficients d'UE pour calculer la moyenne générale.</p>
"""
)
# --- LISTE DES ETUDIANTS
H += ['<div id="groupes">', context.make_listes_sem(sem, REQUEST), "</div>"]
H += [
'<div id="groupes">',
_make_listes_sem(context, sem, REQUEST),
"</div>",
]
# --- Lien mail enseignants:
adrlist = list(mails_enseignants - set([""]))
if adrlist:
@ -1145,4 +1143,4 @@ def formsemestre_status(context, formsemestre_id=None, REQUEST=None):
'<p><a class="stdlink" href="mailto:?cc=%s">Courrier aux %d enseignants du semestre</a></p>'
% (",".join(adrlist), len(adrlist))
)
return "".join(H) + context.sco_footer(REQUEST)
return "".join(H) + html_sco_header.sco_footer(context, REQUEST)

View File

@ -58,7 +58,7 @@ def formsemestre_validation_etud_form(
readonly=True,
REQUEST=None,
):
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_table_moyennes_triees, get_etud_decision_sem
T = nt.get_table_moyennes_triees()
@ -97,7 +97,8 @@ def formsemestre_validation_etud_form(
raise ScoValueError("validation: semestre verrouille")
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Parcours %(nomprenom)s" % etud,
javascripts=["js/recap_parcours.js"],
@ -119,7 +120,7 @@ def formsemestre_validation_etud_form(
% (formsemestre_id, etud_index_next, etud_n["nomprenom"])
)
Footer.append("</p>")
Footer.append(context.sco_footer(REQUEST))
Footer.append(html_sco_header.sco_footer(context, REQUEST))
H.append('<table style="width: 100%"><tr><td>')
if not check:
@ -214,7 +215,7 @@ def formsemestre_validation_etud_form(
'<a href="formsemestre_validation_suppress_etud?etudid=%s&formsemestre_id=%s" class="stdlink">Supprimer décision existante</a>'
% (etudid, formsemestre_id)
)
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
# Infos sur decisions déjà saisies
@ -257,7 +258,7 @@ def formsemestre_validation_etud_form(
H.append('<input type="hidden" name="sortcol" value="%s"/>' % sortcol)
H.append("</form></div>")
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
# Explication sur barres actuelles
@ -401,9 +402,9 @@ def formsemestre_validation_etud_manu(
def _redirect_valid_choice(
formsemestre_id, etudid, Se, choice, desturl, sortcol, REQUEST
):
adr = (
"formsemestre_validation_etud_form?formsemestre_id=%s&etudid=%s&check=1"
% (formsemestre_id, etudid)
adr = "formsemestre_validation_etud_form?formsemestre_id=%s&etudid=%s&check=1" % (
formsemestre_id,
etudid,
)
if sortcol:
adr += "&sortcol=" + sortcol
@ -522,7 +523,7 @@ def formsemestre_recap_parcours_table(
else:
ass = ""
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, sem["formsemestre_id"]
) # > get_ues, get_etud_moy_gen, get_etud_ue_status
if is_cur:
@ -656,7 +657,9 @@ def formsemestre_recap_parcours_table(
H.append("</tr>")
# 3eme ligne: ECTS
if (
context.get_preference("bul_show_ects", sem["formsemestre_id"])
sco_preferences.get_preference(
context, "bul_show_ects", sem["formsemestre_id"]
)
or nt.parcours.ECTS_ONLY
):
etud_moy_infos = nt.get_etud_moy_infos(etudid)
@ -822,8 +825,8 @@ def formsemestre_validation_auto(context, formsemestre_id, REQUEST):
"Formulaire saisie automatisee des decisions d'un semestre"
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
H = [
context.html_sem_header(
REQUEST, "Saisie automatique des décisions du semestre", sem
html_sco_header.html_sem_header(
context, REQUEST, "Saisie automatique des décisions du semestre", sem
),
"""
<ul>
@ -843,7 +846,7 @@ def formsemestre_validation_auto(context, formsemestre_id, REQUEST):
</form>
"""
% formsemestre_id,
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)
@ -852,7 +855,7 @@ def do_formsemestre_validation_auto(context, formsemestre_id, REQUEST):
"Saisie automatisee des decisions d'un semestre"
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
next_semestre_id = sem["semestre_id"] + 1
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etudids, get_etud_decision_sem,
etudids = nt.get_etudids()
@ -913,7 +916,7 @@ def do_formsemestre_validation_auto(context, formsemestre_id, REQUEST):
"do_formsemestre_validation_auto: %d validations, %d conflicts"
% (nb_valid, len(conflicts))
)
H = [context.sco_header(REQUEST, page_title="Saisie automatique")]
H = [html_sco_header.sco_header(context, REQUEST, page_title="Saisie automatique")]
H.append(
"""<h2>Saisie automatique des décisions du semestre %s</h2>
<p>Opération effectuée.</p>
@ -936,7 +939,7 @@ def do_formsemestre_validation_auto(context, formsemestre_id, REQUEST):
'<a href="formsemestre_recapcomplet?formsemestre_id=%s&modejury=1&hidemodules=1&hidebac=1&pref_override=0">continuer</a>'
% formsemestre_id
)
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
@ -954,7 +957,7 @@ def formsemestre_fix_validation_ues(context, formsemestre_id, REQUEST=None):
N'affecte que le semestre indiqué, pas les précédents.
"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etudids, get_etud_decision_sem, get_ues, get_etud_decision_ues, get_etud_ue_status
etudids = nt.get_etudids()
@ -1011,7 +1014,9 @@ def formsemestre_fix_validation_ues(context, formsemestre_id, REQUEST=None):
cnx.commit()
#
H = [
context.sco_header(REQUEST, page_title="Réparation des codes UE"),
html_sco_header.sco_header(
context, REQUEST, page_title="Réparation des codes UE"
),
sco_formsemestre_status.formsemestre_status_head(
context, REQUEST=REQUEST, formsemestre_id=formsemestre_id
),
@ -1023,10 +1028,12 @@ def formsemestre_fix_validation_ues(context, formsemestre_id, REQUEST=None):
"</li><li>".join(modifs),
"</li></ul>",
]
context._inval_cache(formsemestre_id=formsemestre_id) # > modif decision UE
sco_core.inval_cache(
context, formsemestre_id=formsemestre_id
) # > modif decision UE
else:
H.append("<h2>Aucune modification: codes UE corrects ou inexistants</h2>")
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
@ -1069,7 +1076,8 @@ def formsemestre_validate_previous_ue(context, formsemestre_id, etudid, REQUEST=
Fo = context.formation_list(args={"formation_id": sem["formation_id"]})[0]
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Validation UE",
javascripts=["js/validate_previous_ue.js"],
@ -1160,7 +1168,13 @@ def formsemestre_validate_previous_ue(context, formsemestre_id, etudid, REQUEST=
<div id="ue_list_code"><!-- filled by ue_sharing_code --></div>
"""
warn, ue_multiples = check_formation_ues(context, Fo["formation_id"])
return "\n".join(H) + tf[1] + X + warn + context.sco_footer(REQUEST)
return (
"\n".join(H)
+ tf[1]
+ X
+ warn
+ html_sco_header.sco_footer(context, REQUEST)
)
elif tf[0] == -1:
return REQUEST.RESPONSE.redirect(
context.NotesURL()
@ -1207,7 +1221,7 @@ def do_formsemestre_validate_previous_ue(
"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
cnx = context.GetDBConnexion(autocommit=False)
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etud_ue_status
if ue_coefficient != None:
@ -1256,8 +1270,8 @@ def _invalidate_etud_formation_caches(context, etudid, formation_id):
{"etudid": etudid, "formation_id": formation_id},
)
for fsid in [s["formsemestre_id"] for s in r]:
context._inval_cache(
formsemestre_id=fsid
sco_core.inval_cache(
context, formsemestre_id=fsid
) # > modif decision UE (inval tous semestres avec cet etudiant, ok mais conservatif)

View File

@ -62,7 +62,7 @@ def can_change_groups(context, REQUEST, formsemestre_id):
if sem["etat"] != "1":
return False # semestre verrouillé
authuser = REQUEST.AUTHENTICATED_USER
if authuser.has_permission(ScoEtudChangeGroups, context):
if authuser.has_permission(Permission.ScoEtudChangeGroups, context):
return True # admin, chef dept
uid = str(authuser)
if uid in sem["responsables"]:
@ -818,8 +818,11 @@ def editPartitionForm(context, formsemestre_id=None, REQUEST=None):
)
#
H = [
context.sco_header(
REQUEST, page_title="Partitions...", javascripts=["js/editPartitionForm.js"]
html_sco_header.sco_header(
context,
REQUEST,
page_title="Partitions...",
javascripts=["js/editPartitionForm.js"],
),
r"""<script type="text/javascript">
function checkname() {
@ -926,7 +929,7 @@ def editPartitionForm(context, formsemestre_id=None, REQUEST=None):
</div>
"""
)
return "\n".join(H) + context.sco_footer(REQUEST)
return "\n".join(H) + html_sco_header.sco_footer(context, REQUEST)
def partition_set_attr(context, partition_id, attr, value, REQUEST=None):
@ -1061,11 +1064,11 @@ def partition_rename(context, partition_id, REQUEST=None):
)
if tf[0] == 0:
return (
context.sco_header(REQUEST)
html_sco_header.sco_header(context, REQUEST)
+ "\n".join(H)
+ "\n"
+ tf[1]
+ context.sco_footer(REQUEST)
+ html_sco_header.sco_footer(context, REQUEST)
)
elif tf[0] == -1:
return REQUEST.RESPONSE.redirect(
@ -1164,11 +1167,11 @@ def group_rename(context, group_id, REQUEST=None):
)
if tf[0] == 0:
return (
context.sco_header(REQUEST)
html_sco_header.sco_header(context, REQUEST)
+ "\n".join(H)
+ "\n"
+ tf[1]
+ context.sco_footer(REQUEST)
+ html_sco_header.sco_footer(context, REQUEST)
)
elif tf[0] == -1:
return REQUEST.RESPONSE.redirect(
@ -1207,7 +1210,9 @@ def groups_auto_repartition(context, partition_id=None, REQUEST=None):
]
H = [
context.sco_header(REQUEST, page_title="Répartition des groupes"),
html_sco_header.sco_header(
context, REQUEST, page_title="Répartition des groupes"
),
"<h2>Répartition des groupes de %s</h2>" % partition["partition_name"],
"<p>Semestre %s</p>" % sem["titreannee"],
"""<p class="help">Les groupes existants seront <b>effacés</b> et remplacés par
@ -1227,7 +1232,9 @@ def groups_auto_repartition(context, partition_id=None, REQUEST=None):
name="tf",
)
if tf[0] == 0:
return "\n".join(H) + "\n" + tf[1] + context.sco_footer(REQUEST)
return (
"\n".join(H) + "\n" + tf[1] + html_sco_header.sco_footer(context, REQUEST)
)
elif tf[0] == -1:
return REQUEST.RESPONSE.redirect(dest_url)
else:
@ -1248,7 +1255,7 @@ def groups_auto_repartition(context, partition_id=None, REQUEST=None):
# checkGroupName(group_name)
# except:
# H.append('<p class="warning">Nom de groupe invalide: %s</p>'%group_name)
# return '\n'.join(H) + tf[1] + context.sco_footer(REQUEST)
# return '\n'.join(H) + tf[1] + html_sco_header.sco_footer(context, REQUEST)
group_ids.append(
createGroup(context, partition_id, group_name, REQUEST=REQUEST)
)
@ -1298,7 +1305,7 @@ def get_prev_moy(context, etudid, formsemestre_id):
etud = info[0]
Se = sco_parcours_dut.SituationEtudParcours(context, etud, formsemestre_id)
if Se.prev:
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, Se.prev["formsemestre_id"]
) # > get_etud_moy_gen
return nt.get_etud_moy_gen(etudid)

View File

@ -49,7 +49,7 @@ def affectGroups(context, partition_id, REQUEST=None):
raise AccessDenied("vous n'avez pas la permission d'effectuer cette opération")
H = [
context.sco_header(
html_sco_header.sco_header(context,
REQUEST,
page_title="Affectation aux groupes",
javascripts=["js/groupmgr.js"],
@ -99,6 +99,6 @@ Editer groupes de
</div>
""",
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)

View File

@ -102,8 +102,12 @@ def groups_view(
)
H = [
context.sco_header(
REQUEST, javascripts=JAVASCRIPTS, cssstyles=CSSSTYLES, init_qtip=True
html_sco_header.sco_header(
context,
REQUEST,
javascripts=JAVASCRIPTS,
cssstyles=CSSSTYLES,
init_qtip=True,
)
]
# Menu choix groupe
@ -150,7 +154,7 @@ def groups_view(
)
)
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
@ -578,7 +582,7 @@ def groups_table(
else:
filename = "etudiants_%s" % groups_infos.groups_filename
prefs = context.get_preferences(groups_infos.formsemestre_id)
prefs = sco_preferences.SemPreferences(context, groups_infos.formsemestre_id)
tab = GenTable(
rows=groups_infos.members,
columns_ids=columns_ids,
@ -851,13 +855,13 @@ def tab_absences_html(context, groups_infos, etat=None, REQUEST=None):
# Lien pour verif codes INE/NIP
# (pour tous les etudiants du semestre)
group_id = sco_groups.get_default_group(context, groups_infos.formsemestre_id)
if authuser.has_permission(ScoEtudInscrit, context):
if authuser.has_permission(Permission.ScoEtudInscrit, context):
H.append(
'<li><a class="stdlink" href="check_group_apogee?group_id=%s&etat=%s">Vérifier codes Apogée</a> (de tous les groupes)</li>'
% (group_id, etat or "")
)
# Lien pour ajout fichiers étudiants
if authuser.has_permission(ScoEtudAddAnnotations, context):
if authuser.has_permission(Permission.ScoEtudAddAnnotations, context):
H.append(
"""<li><a class="stdlink" href="etudarchive_import_files_form?group_id=%s">Télécharger des fichiers associés aux étudiants (e.g. dossiers d'admission)</a></li>"""
% (group_id)
@ -880,7 +884,7 @@ def form_choix_jour_saisie_hebdo(
):
"""Formulaire choix jour semaine pour saisie."""
authuser = REQUEST.AUTHENTICATED_USER
if not authuser.has_permission(ScoAbsChange, context):
if not authuser.has_permission(Permission.ScoAbsChange, context):
return ""
sem = groups_infos.formsemestre
first_monday = sco_abs.ddmmyyyy(sem["date_debut"]).prev_monday()
@ -921,7 +925,7 @@ def form_choix_jour_saisie_hebdo(
# Formulaire saisie absences semaine
def form_choix_saisie_semaine(context, groups_infos, REQUEST=None):
authuser = REQUEST.AUTHENTICATED_USER
if not authuser.has_permission(ScoAbsChange, context):
if not authuser.has_permission(Permission.ScoAbsChange, context):
return ""
# construit l'URL "destination"
# (a laquelle on revient apres saisie absences)
@ -979,7 +983,7 @@ def export_groups_as_moodle_csv(context, formsemestre_id=None, REQUEST=None):
elts.append(group_name)
T.append({"email": etud["email"], "semestre_groupe": "-".join(elts)})
# Make table
prefs = context.get_preferences(formsemestre_id)
prefs = sco_preferences.SemPreferences(context, formsemestre_id)
tab = GenTable(
rows=T,
columns_ids=("email", "semestre_groupe"),

View File

@ -33,6 +33,7 @@ from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.header import Header
import mails
import notesdb as ndb
import sco_utils as scu
from notes_log import log
@ -226,9 +227,9 @@ Pour plus d'informations sur ce logiciel, voir %s
msg["Subject"] = Header("Mot de passe ScoDoc", scu.SCO_ENCODING)
else:
msg["Subject"] = Header("Votre accès ScoDoc", scu.SCO_ENCODING)
msg["From"] = context.get_preference("email_from_addr")
msg["From"] = sco_preferences.get_preference(context, "email_from_addr")
msg["To"] = u["email"]
msg.epilogue = ""
txt = MIMEText(txt, "plain", scu.SCO_ENCODING)
msg.attach(txt)
context.sendEmail(msg)
mails.sendEmail(context, msg)

View File

@ -278,8 +278,10 @@ def formsemestre_inscr_passage(
# -- check lock
if sem["etat"] != "1":
raise ScoValueError("opération impossible: semestre verrouille")
header = context.sco_header(REQUEST, page_title="Passage des étudiants")
footer = context.sco_footer(REQUEST)
header = html_sco_header.sco_header(
context, REQUEST, page_title="Passage des étudiants"
)
footer = html_sco_header.sco_footer(context, REQUEST)
H = [header]
if type(etuds) == type(""):
etuds = etuds.split(",") # vient du form de confirmation
@ -412,8 +414,8 @@ def build_page(
inscrit_groupes_checked = ""
H = [
context.html_sem_header(
REQUEST, "Passages dans le semestre", sem, with_page_header=False
html_sco_header.html_sem_header(
context, REQUEST, "Passages dans le semestre", sem, with_page_header=False
),
"""<form method="post" action="%s">""" % REQUEST.URL0,
"""<input type="hidden" name="formsemestre_id" value="%(formsemestre_id)s"/>
@ -628,6 +630,8 @@ def etuds_select_box_xls(context, src_cat):
columns_ids=columns_ids,
rows=etuds,
caption="%(title)s. %(help)s" % src_cat["infos"],
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
return tab.excel()

View File

@ -301,9 +301,9 @@ def _make_table_notes(
grc = inscr["etat"]
code = "" # code pour listings anonyme, à la place du nom
if context.get_preference("anonymous_lst_code") == "INE":
if sco_preferences.get_preference(context, "anonymous_lst_code") == "INE":
code = etud["code_ine"]
elif context.get_preference("anonymous_lst_code") == "NIP":
elif sco_preferences.get_preference(context, "anonymous_lst_code") == "NIP":
code = etud["code_nip"]
if not code: # laisser le code vide n'aurait aucun sens, prenons l'etudid
code = etudid
@ -472,7 +472,7 @@ def _make_table_notes(
html_title=html_title,
pdf_title=pdf_title,
html_class="table_leftalign notes_evaluation",
preferences=context.get_preferences(M["formsemestre_id"]),
preferences=sco_preferences.SemPreferences(context, M["formsemestre_id"]),
# html_generate_cells=False # la derniere ligne (moyennes) est incomplete
)
@ -645,7 +645,7 @@ def _add_moymod_column(
):
"""Ajoute la colonne moymod à rows"""
col_id = "moymod"
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etud_mod_moy
nb_notes = 0
@ -775,7 +775,9 @@ def evaluation_check_absences_html(
if with_header:
H = [
context.html_sem_header(REQUEST, "Vérification absences à l'évaluation"),
html_sco_header.html_sem_header(
context, REQUEST, "Vérification absences à l'évaluation"
),
sco_evaluations.evaluation_describe(
context, evaluation_id=evaluation_id, REQUEST=REQUEST
),
@ -851,7 +853,7 @@ def evaluation_check_absences_html(
etudlist(AbsButExc)
if with_header:
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
@ -859,8 +861,11 @@ def formsemestre_check_absences_html(context, formsemestre_id, REQUEST=None):
"""Affiche etat verification absences pour toutes les evaluations du semestre !"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
H = [
context.html_sem_header(
REQUEST, "Vérification absences aux évaluations de ce semestre", sem
html_sco_header.html_sem_header(
context,
REQUEST,
"Vérification absences aux évaluations de ce semestre",
sem,
),
"""<p class="help">Vérification de la cohérence entre les notes saisies et les absences signalées.
Sont listés tous les modules avec des évaluations.<br/>Aucune action n'est effectuée:
@ -890,5 +895,5 @@ def formsemestre_check_absences_html(context, formsemestre_id, REQUEST=None):
)
if evals:
H.append("</div>")
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)

View File

@ -54,7 +54,11 @@ def formsemestre_table_etuds_lycees(
primostr = "du "
title = "Lycées des étudiants %ssemestre " % primostr + sem["titreannee"]
return _table_etuds_lycees(
context, etuds, group_lycees, title, context.get_preferences(formsemestre_id)
context,
etuds,
group_lycees,
title,
sco_preferences.SemPreferences(context, formsemestre_id),
)
@ -70,7 +74,9 @@ def scodoc_table_etuds_lycees(context, format="html", REQUEST=None):
etuds,
False,
"Lycées de TOUS les étudiants",
context.get_preferences(),
sco_preferences.SemPreferences(
context,
),
no_links=True,
)
tab.base_url = REQUEST.URL0
@ -78,7 +84,8 @@ def scodoc_table_etuds_lycees(context, format="html", REQUEST=None):
if format != "html":
return t
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title=tab.page_title,
init_google_maps=True,
@ -91,7 +98,7 @@ def scodoc_table_etuds_lycees(context, format="html", REQUEST=None):
"""<div id="lyc_map_canvas"></div>
""",
js_coords_lycees(etuds_by_lycee),
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)
@ -194,7 +201,8 @@ def formsemestre_etuds_lycees(
)
]
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title=tab.page_title,
init_google_maps=True,
@ -207,7 +215,7 @@ def formsemestre_etuds_lycees(
"""<div id="lyc_map_canvas"></div>
""",
js_coords_lycees(etuds_by_lycee),
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)

View File

@ -64,8 +64,8 @@ def do_moduleimpl_create(context, args):
"create a moduleimpl"
cnx = context.GetDBConnexion()
r = _moduleimplEditor.create(cnx, args)
context._inval_cache(
formsemestre_id=args["formsemestre_id"]
sco_core.inval_cache(
context, formsemestre_id=args["formsemestre_id"]
) # > creation moduleimpl
return r
@ -91,7 +91,9 @@ def do_moduleimpl_delete(context, oid, formsemestre_id=None):
)
# --- destruction du moduleimpl
_moduleimplEditor.delete(cnx, oid)
context._inval_cache(formsemestre_id=formsemestre_id) # > moduleimpl_delete
sco_core.inval_cache(
context, formsemestre_id=formsemestre_id
) # > moduleimpl_delete
def do_moduleimpl_list(
@ -113,7 +115,7 @@ def do_moduleimpl_edit(context, args, formsemestre_id=None, cnx=None):
cnx = context.GetDBConnexion()
_moduleimplEditor.edit(cnx, args)
context._inval_cache(formsemestre_id=formsemestre_id) # > modif moduleimpl
sco_core.inval_cache(context, formsemestre_id=formsemestre_id) # > modif moduleimpl
def do_moduleimpl_withmodule_list(
@ -197,7 +199,9 @@ def do_moduleimpl_inscription_create(context, args, REQUEST=None, formsemestre_i
cnx = context.GetDBConnexion()
log("do_moduleimpl_inscription_create: " + str(args))
r = _moduleimpl_inscriptionEditor.create(cnx, args)
context._inval_cache(formsemestre_id=formsemestre_id) # > moduleimpl_inscription
sco_core.inval_cache(
context, formsemestre_id=formsemestre_id
) # > moduleimpl_inscription
if REQUEST:
scolog.logdb(
REQUEST,
@ -214,7 +218,9 @@ def do_moduleimpl_inscription_delete(context, oid, formsemestre_id=None):
"delete moduleimpl_inscription"
cnx = context.GetDBConnexion()
_moduleimpl_inscriptionEditor.delete(cnx, oid)
context._inval_cache(formsemestre_id=formsemestre_id) # > moduleimpl_inscription
sco_core.inval_cache(
context, formsemestre_id=formsemestre_id
) # > moduleimpl_inscription
def do_moduleimpl_inscrit_etuds(
@ -259,7 +265,9 @@ def do_moduleimpl_inscrit_etuds(
formsemestre_id=formsemestre_id,
)
context._inval_cache(formsemestre_id=formsemestre_id) # > moduleimpl_inscrit_etuds
sco_core.inval_cache(
context, formsemestre_id=formsemestre_id
) # > moduleimpl_inscrit_etuds
def do_ens_list(context, *args, **kw):
@ -302,7 +310,7 @@ def can_change_module_resp(context, REQUEST, moduleimpl_id):
authuser = REQUEST.AUTHENTICATED_USER
uid = str(authuser)
# admin ou resp. semestre avec flag resp_can_change_resp
if not authuser.has_permission(ScoImplement, context) and (
if not authuser.has_permission(Permission.ScoImplement, context) and (
(uid not in sem["responsables"]) or (not sem["resp_can_change_ens"])
):
raise AccessDenied("Modification impossible pour %s" % uid)
@ -325,7 +333,7 @@ def can_change_ens(context, REQUEST, moduleimpl_id, raise_exc=True):
# admin, resp. module ou resp. semestre
if (
uid != M["responsable_id"]
and not authuser.has_permission(ScoImplement, context)
and not authuser.has_permission(Permission.ScoImplement, context)
and (uid not in sem["responsables"])
):
if raise_exc:

View File

@ -62,13 +62,14 @@ def moduleimpl_inscriptions_edit(
# -- check lock
if sem["etat"] != "1":
raise ScoValueError("opération impossible: semestre verrouille")
header = context.sco_header(
header = html_sco_header.sco_header(
context,
REQUEST,
page_title="Inscription au module",
init_qtip=True,
javascripts=["js/etud_info.js"],
)
footer = context.sco_footer(REQUEST)
footer = html_sco_header.sco_footer(context, REQUEST)
H = [
header,
"""<h2>Inscriptions au module <a href="moduleimpl_status?moduleimpl_id=%s">%s</a> (%s)</a></h2>
@ -245,7 +246,10 @@ def moduleimpl_inscriptions_stats(context, formsemestre_id, REQUEST=None):
context, formsemestre_id
)
can_change = authuser.has_permission(ScoEtudInscrit, context) and sem["etat"] == "1"
can_change = (
authuser.has_permission(Permission.ScoEtudInscrit, context)
and sem["etat"] == "1"
)
# Liste des modules
Mlist = sco_moduleimpl.do_moduleimpl_withmodule_list(
@ -270,7 +274,11 @@ def moduleimpl_inscriptions_stats(context, formsemestre_id, REQUEST=None):
mod["nb_inscrits"] = nb_inscrits
options.append(mod)
# Page HTML:
H = [context.html_sem_header(REQUEST, "Inscriptions aux modules du semestre")]
H = [
html_sco_header.html_sem_header(
context, REQUEST, "Inscriptions aux modules du semestre"
)
]
H.append("<h3>Inscrits au semestre: %d étudiants</h3>" % len(inscrits))
@ -390,7 +398,7 @@ def moduleimpl_inscriptions_stats(context, formsemestre_id, REQUEST=None):
"""
)
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
@ -455,7 +463,7 @@ def get_etuds_with_capitalized_ue(context, formsemestre_id):
returns { ue_id : [ { infos } ] }
"""
UECaps = scu.DictDefault(defaultvalue=[])
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_ues, get_etud_ue_status
inscrits = context.do_formsemestre_inscription_list(
@ -529,8 +537,8 @@ def do_etud_desinscrit_ue(context, etudid, formsemestre_id, ue_id, REQUEST=None)
msg="desinscription UE %s" % ue_id,
commit=False,
)
context._inval_cache(
formsemestre_id=formsemestre_id
sco_core.inval_cache(
context, formsemestre_id=formsemestre_id
) # > desinscription etudiant des modules

View File

@ -148,7 +148,9 @@ def moduleimpl_status(context, moduleimpl_id=None, partition_id=None, REQUEST=No
context, moduleimpl_id=M["moduleimpl_id"]
)
nt = context._getNotesCache().get_NotesTable(context, formsemestre_id)
nt = sco_core.get_notes_cache(
context,
).get_NotesTable(context, formsemestre_id)
ModEvals = context.do_evaluation_list({"moduleimpl_id": moduleimpl_id})
ModEvals.sort(
key=lambda x: (x["numero"], x["jour"], x["heure_debut"]), reverse=True
@ -162,7 +164,9 @@ def moduleimpl_status(context, moduleimpl_id=None, partition_id=None, REQUEST=No
arrow_up, arrow_down, arrow_none = sco_groups.getArrowIconsTags(context, REQUEST)
#
H = [
context.sco_header(REQUEST, page_title="Module %(titre)s" % Mod),
html_sco_header.sco_header(
context, REQUEST, page_title="Module %(titre)s" % Mod
),
"""<h2 class="formsemestre">Module <tt>%(code)s</tt> %(titre)s</h2>""" % Mod,
# XXX """caneditevals=%s caneditnotes=%s""" % (caneditevals,caneditnotes),
"""<div class="moduleimpl_tableaubord">
@ -217,7 +221,7 @@ def moduleimpl_status(context, moduleimpl_id=None, partition_id=None, REQUEST=No
"""<tr><td class="fichetitre2">Inscrits: </td><td> %d étudiants"""
% len(ModInscrits)
)
if authuser.has_permission(ScoEtudInscrit, context):
if authuser.has_permission(Permission.ScoEtudInscrit, context):
H.append(
"""<a class="stdlink" style="margin-left:2em;" href="moduleimpl_inscriptions_edit?moduleimpl_id=%s">modifier</a>"""
% M["moduleimpl_id"]
@ -619,5 +623,5 @@ def moduleimpl_status(context, moduleimpl_id=None, partition_id=None, REQUEST=No
scu.icontag("status_visible_img"),
)
)
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "".join(H)

View File

@ -39,6 +39,7 @@ from email.header import Header
import notesdb as ndb # pylint: disable=unused-wildcard-import
from notes_log import log
import mails
import scolars
from sco_utils import SCO_ENCODING, SCO_ANNONCES_WEBSITE
import sco_formsemestre
@ -253,7 +254,7 @@ def _send_news_by_mail(context, n):
"""Notify by email"""
infos = _get_formsemestre_infos_from_news(context, n)
formsemestre_id = infos.get("formsemestre_id", None)
prefs = context.get_preferences(formsemestre_id=formsemestre_id)
prefs = sco_preferences.SemPreferences(context, formsemestre_id=formsemestre_id)
destinations = prefs["emails_notifications"] or ""
destinations = [x.strip() for x in destinations.split(",")]
destinations = [x for x in destinations if x]
@ -298,4 +299,4 @@ def _send_news_by_mail(context, n):
del msg["To"]
msg["To"] = email_addr
# log('xxx mail: %s' % msg)
context.sendEmail(msg)
mails.sendEmail(context, msg)

View File

@ -42,6 +42,7 @@ import sco_formsemestre
from scolars import format_telephone, format_pays, make_etud_args
import sco_formsemestre_status
import htmlutils
import html_sco_header
from sco_bulletins import etud_descr_situation_semestre
import sco_parcours_dut
import sco_codes_parcours
@ -67,80 +68,78 @@ def _menuScolarite(context, authuser, sem, etudid):
return lockicon # no menu
if not authuser.has_permission(
ScoEtudInscrit, context
) and not authuser.has_permission(ScoEtudChangeGroups, context):
) and not authuser.has_permission(Permission.ScoEtudChangeGroups, context):
return "" # no menu
ins = sem["ins"]
args = {"etudid": etudid, "formsemestre_id": ins["formsemestre_id"]}
if ins["etat"] != "D":
dem_title = "Démission"
dem_url = (
"formDem?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s" % args
)
dem_url = "formDem?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s" % args
else:
dem_title = "Annuler la démission"
dem_url = (
"doCancelDem?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s"
% args
"doCancelDem?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s" % args
)
# 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?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s" % args
)
def_url = "formDef?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s" % args
elif ins["etat"] == sco_codes_parcours.DEF:
def_title = "Annuler la défaillance"
def_url = (
"doCancelDef?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s"
% args
"doCancelDef?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s" % args
)
def_enabled = (
(ins["etat"] != "D")
and authuser.has_permission(ScoEtudInscrit, context)
and authuser.has_permission(Permission.ScoEtudInscrit, context)
and not locked
)
items = [
# { 'title' : 'Changer de groupe',
# 'url' : 'formChangeGroup?etudid=%s&formsemestre_id=%s' % (etudid,ins['formsemestre_id']),
# 'enabled' : authuser.has_permission(ScoEtudChangeGroups,context) and not locked,
# 'enabled' : authuser.has_permission(Permission.ScoEtudChangeGroups,context) and not locked,
# },
{
"title": dem_title,
"url": dem_url,
"enabled": authuser.has_permission(ScoEtudInscrit, context) and not locked,
"enabled": authuser.has_permission(Permission.ScoEtudInscrit, context)
and not locked,
},
{
"title": "Validation du semestre (jury)",
"url": "Notes/formsemestre_validation_etud_form?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s"
% args,
"enabled": authuser.has_permission(ScoEtudInscrit, context) and not locked,
"enabled": authuser.has_permission(Permission.ScoEtudInscrit, context)
and not locked,
},
{"title": def_title, "url": def_url, "enabled": def_enabled},
{
"title": "Inscrire à un module optionnel (ou au sport)",
"url": "Notes/formsemestre_inscription_option?formsemestre_id=%(formsemestre_id)s&etudid=%(etudid)s"
% args,
"enabled": authuser.has_permission(ScoEtudInscrit, context) and not locked,
"enabled": authuser.has_permission(Permission.ScoEtudInscrit, context)
and not locked,
},
{
"title": "Désinscrire (en cas d'erreur)",
"url": "Notes/formsemestre_desinscription?formsemestre_id=%(formsemestre_id)s&etudid=%(etudid)s"
% args,
"enabled": authuser.has_permission(ScoEtudInscrit, context) and not locked,
"enabled": authuser.has_permission(Permission.ScoEtudInscrit, context)
and not locked,
},
{
"title": "Inscrire à un autre semestre",
"url": "Notes/formsemestre_inscription_with_modules_form?etudid=%(etudid)s"
% args,
"enabled": authuser.has_permission(ScoEtudInscrit, context),
"enabled": authuser.has_permission(Permission.ScoEtudInscrit, context),
},
{
"title": "Enregistrer un semestre effectué ailleurs",
"url": "Notes/formsemestre_ext_create_form?formsemestre_id=%(formsemestre_id)s&etudid=%(etudid)s"
% args,
"enabled": authuser.has_permission(ScoImplement, context),
"enabled": authuser.has_permission(Permission.ScoImplement, context),
},
]
@ -206,7 +205,7 @@ def ficheEtud(context, etudid=None, REQUEST=None):
else:
info["emaillink"] = "<em>(pas d'adresse e-mail)</em>"
# champs dependant des permissions
if authuser.has_permission(ScoEtudChangeAdr, context):
if authuser.has_permission(Permission.ScoEtudChangeAdr, context):
info["modifadresse"] = (
'<a class="stdlink" href="formChangeCoordonnees?etudid=%s">modifier adresse</a>'
% etudid
@ -272,7 +271,7 @@ def ficheEtud(context, etudid=None, REQUEST=None):
else:
# non inscrit
l = ["<p><b>Etudiant%s non inscrit%s" % (info["ne"], info["ne"])]
if authuser.has_permission(ScoEtudInscrit, context):
if authuser.has_permission(Permission.ScoEtudInscrit, context):
l.append(
'<a href="%s/Notes/formsemestre_inscription_with_modules_form?etudid=%s">inscrire</a></li>'
% (context.ScoURL(), etudid)
@ -483,7 +482,7 @@ def ficheEtud(context, etudid=None, REQUEST=None):
</div>
"""
header = context.sco_header(
header = html_sco_header.sco_header(context,
REQUEST,
page_title="Fiche étudiant %(prenom)s %(nom)s" % info,
cssstyles=["libjs/jQuery-tagEditor/jquery.tag-editor.css"],
@ -496,7 +495,7 @@ def ficheEtud(context, etudid=None, REQUEST=None):
"js/etud_debouche.js",
],
)
return header + tmpl % info + context.sco_footer(REQUEST)
return header + tmpl % info + html_sco_header.sco_footer(context, REQUEST)
def menus_etud(context, REQUEST=None):
@ -517,17 +516,17 @@ def menus_etud(context, REQUEST=None):
{
"title": "Changer la photo",
"url": "formChangePhoto?etudid=%(etudid)s" % etud,
"enabled": authuser.has_permission(ScoEtudChangeAdr, context),
"enabled": authuser.has_permission(Permission.ScoEtudChangeAdr, context),
},
{
"title": "Changer les données identité/admission",
"url": "etudident_edit_form?etudid=%(etudid)s" % etud,
"enabled": authuser.has_permission(ScoEtudInscrit, context),
"enabled": authuser.has_permission(Permission.ScoEtudInscrit, context),
},
{
"title": "Supprimer cet étudiant...",
"url": "etudident_delete?etudid=%(etudid)s" % etud,
"enabled": authuser.has_permission(ScoEtudInscrit, context),
"enabled": authuser.has_permission(Permission.ScoEtudInscrit, context),
},
{
"title": "Voir le journal...",
@ -594,9 +593,9 @@ def etud_info_html(context, etudid, with_photo="1", REQUEST=None, debug=False):
H += "</div>"
if debug:
return (
context.standard_html_header(context)
html_sco_header.standard_html_header()
+ H
+ context.standard_html_footer(context)
+ html_sco_header.standard_html_footer()
)
else:
return H

View File

@ -104,7 +104,7 @@ class DecisionSem:
def SituationEtudParcours(context, etud, formsemestre_id):
"""renvoie une instance de SituationEtudParcours (ou sous-classe spécialisée)"""
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etud_decision_sem, get_etud_moy_gen, get_ues, get_etud_ue_status, etud_check_conditions_ues
parcours = nt.parcours
@ -295,7 +295,7 @@ class SituationEtudParcoursGeneric:
sem["semestre_id"] == n1
and sem["formation_code"] == self.formation["formation_code"]
):
nt = self.context._getNotesCache().get_NotesTable(
nt = self.sco_core.get_notes_cache(context).get_NotesTable(
self.context, sem["formsemestre_id"]
) # > get_etud_decision_sem
decision = nt.get_etud_decision_sem(self.etudid)
@ -311,7 +311,7 @@ class SituationEtudParcoursGeneric:
sont validés. En sortie, sem_idx_set contient ceux qui n'ont pas été validés."""
for sem in self.get_semestres():
if sem["formation_code"] == self.formation["formation_code"]:
nt = self.context._getNotesCache().get_NotesTable(
nt = self.sco_core.get_notes_cache(context).get_NotesTable(
self.context, sem["formsemestre_id"]
) # > get_etud_decision_sem
decision = nt.get_etud_decision_sem(self.etudid)
@ -329,7 +329,7 @@ class SituationEtudParcoursGeneric:
ue_acros = {} # acronyme ue : 1
nb_max_ue = 0
for sem in sems:
nt = self.context._getNotesCache().get_NotesTable(
nt = self.sco_core.get_notes_cache(context).get_NotesTable(
self.context, sem["formsemestre_id"]
) # > get_ues
ues = nt.get_ues(filter_sport=True)
@ -399,7 +399,7 @@ class SituationEtudParcoursGeneric:
if not sem:
code = "" # non inscrit à ce semestre
else:
nt = self.context._getNotesCache().get_NotesTable(
nt = self.sco_core.get_notes_cache(context).get_NotesTable(
self.context, sem["formsemestre_id"]
) # > get_etud_decision_sem
decision = nt.get_etud_decision_sem(self.etudid)
@ -471,7 +471,7 @@ class SituationEtudParcoursGeneric:
# Verifications basiques:
# ?
# Code etat du semestre precedent:
nt = self.context._getNotesCache().get_NotesTable(
nt = self.sco_core.get_notes_cache(context).get_NotesTable(
self.context, prev["formsemestre_id"]
) # > get_etud_decision_sem, get_etud_moy_gen, etud_check_conditions_ues
self.prev_decision = nt.get_etud_decision_sem(self.etudid)
@ -530,7 +530,7 @@ class SituationEtudParcoursGeneric:
sem["formation_code"] == self.formation["formation_code"]
and sem["semestre_id"] == s
):
nt = self.context._getNotesCache().get_NotesTable(
nt = self.sco_core.get_notes_cache(context).get_NotesTable(
self.context, sem["formsemestre_id"]
) # > get_etud_decision_sem
decision = nt.get_etud_decision_sem(self.etudid)
@ -629,8 +629,8 @@ class SituationEtudParcoursGeneric:
REQUEST=REQUEST,
)
self.context._inval_cache(
formsemestre_id=self.prev["formsemestre_id"]
self.sco_core.inval_cache(
context, formsemestre_id=self.prev["formsemestre_id"]
) # > modif decisions jury (sem, UE)
# -- supprime autorisations venant de ce formsemestre
@ -659,17 +659,17 @@ class SituationEtudParcoursGeneric:
except:
cnx.rollback()
raise
self.context._inval_cache(
formsemestre_id=self.formsemestre_id
self.sco_core.inval_cache(
context, formsemestre_id=self.formsemestre_id
) # > modif decisions jury et autorisations inscription
if decision.formsemestre_id_utilise_pour_compenser:
# inval aussi le semestre utilisé pour compenser:
self.context._inval_cache(
formsemestre_id=decision.formsemestre_id_utilise_pour_compenser
self.sco_core.inval_cache(
context, formsemestre_id=decision.formsemestre_id_utilise_pour_compenser
) # > modif decision jury
for formsemestre_id in to_invalidate:
self.context._inval_cache(
formsemestre_id=formsemestre_id
self.sco_core.inval_cache(
context, formsemestre_id=formsemestre_id
) # > modif decision jury
@ -908,7 +908,7 @@ def formsemestre_validate_ues(
"""
valid_semestre = CODES_SEM_VALIDES.get(code_etat_sem, False)
cnx = context.GetDBConnexion(autocommit=False)
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_ues, get_etud_ue_status
ue_ids = [x["ue_id"] for x in nt.get_ues(etudid=etudid, filter_sport=True)]

View File

@ -200,7 +200,7 @@ class ScolarsPageTemplate(PageTemplate):
# XXX COPIED from sco_pvpdf, to be refactored (no time now)
# Search background in dept specific dir, then in global config dir
for image_dir in (
SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/",
SCODOC_LOGOS_DIR + "/logos_" + sco_core.get_dept_id() + "/",
SCODOC_LOGOS_DIR + "/", # global logos
):
for suffix in LOGOS_IMAGES_ALLOWED_TYPES:

View File

@ -315,7 +315,7 @@ def get_new_filename(context, etudid):
"""Constructs a random filename to store a new image.
The path is constructed as: Fxx/etudid
"""
dept = context.DeptId()
dept = sco_core.get_dept_id()
return find_new_dir() + dept + "_" + etudid
@ -344,7 +344,7 @@ def copy_portal_photo_to_fs(context, etud, REQUEST=None):
url = photo_portal_url(context, etud)
if not url:
return None, "%(nomprenom)s: pas de code NIP" % etud
portal_timeout = context.get_preference("portal_timeout")
portal_timeout = sco_preferences.get_preference(context, "portal_timeout")
f = None
try:
log("copy_portal_photo_to_fs: getting %s" % url)

View File

@ -309,7 +309,7 @@ def do_placement(context, REQUEST):
listetud.append((nom, prenom))
random.shuffle(listetud)
sem_preferences = context.get_preferences()
sem_preferences = sco_preferences.SemPreferences(context)
space = sem_preferences.get("feuille_placement_emargement")
maxlines = sem_preferences.get("feuille_placement_positions")
@ -386,7 +386,7 @@ def do_placement(context, REQUEST):
+ "",
pdf_title=pdf_title,
# pdf_shorttitle = '',
preferences=context.get_preferences(M["formsemestre_id"]),
preferences=sco_preferences.SemPreferences(context, M["formsemestre_id"]),
# html_generate_cells=False # la derniere ligne (moyennes) est incomplete
)
t = tab.make_page(
@ -406,7 +406,7 @@ def placement_eval_selectetuds(context, evaluation_id, REQUEST=None):
page_title = 'Placement "%s"' % theeval["description"]
else:
page_title = "Placement des étudiants"
H = [context.sco_header(REQUEST, page_title=page_title)]
H = [html_sco_header.sco_header(context, REQUEST, page_title=page_title)]
formid = "placementfile"
if not REQUEST.form.get("%s-submitted" % formid, False):
@ -436,7 +436,7 @@ def placement_eval_selectetuds(context, evaluation_id, REQUEST=None):
</ul>
"""
)
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)

View File

@ -55,7 +55,7 @@ class PortalInterface:
def get_portal_url(self, context):
"URL of portal"
portal_url = context.get_preference("portal_url")
portal_url = sco_preferences.get_preference(context, "portal_url")
if not self.warning:
if portal_url:
log("Portal URL=%s" % portal_url)
@ -66,7 +66,7 @@ class PortalInterface:
def get_etapes_url(self, context):
"Full URL of service giving list of etapes (in XML)"
etapes_url = context.get_preference("etapes_url")
etapes_url = sco_preferences.get_preference(context, "etapes_url")
if not etapes_url:
# Default:
portal_url = self.get_portal_url(context)
@ -81,7 +81,7 @@ class PortalInterface:
def get_etud_url(self, context):
"Full URL of service giving list of students (in XML)"
etud_url = context.get_preference("etud_url")
etud_url = sco_preferences.get_preference(context, "etud_url")
if not etud_url:
# Default:
portal_url = self.get_portal_url(context)
@ -96,7 +96,7 @@ class PortalInterface:
def get_photo_url(self, context):
"Full URL of service giving photo of student"
photo_url = context.get_preference("photo_url")
photo_url = sco_preferences.get_preference(context, "photo_url")
if not photo_url:
# Default:
portal_url = self.get_portal_url(context)
@ -111,7 +111,7 @@ class PortalInterface:
def get_maquette_url(self, context):
"""Full URL of service giving Apogee maquette pour une étape (fichier "CSV")"""
maquette_url = context.get_preference("maquette_url")
maquette_url = sco_preferences.get_preference(context, "maquette_url")
if not maquette_url:
# Default:
portal_url = self.get_portal_url(context)
@ -122,7 +122,7 @@ class PortalInterface:
def get_portal_api_version(self, context):
"API version of the portal software"
api_ver = context.get_preference("portal_api")
api_ver = sco_preferences.get_preference(context, "portal_api")
if not api_ver:
# Default:
api_ver = 1
@ -151,7 +151,7 @@ def get_inscrits_etape(context, code_etape, anneeapogee=None, ntrials=2):
api_ver = get_portal_api_version(context)
if not etud_url:
return []
portal_timeout = context.get_preference("portal_timeout")
portal_timeout = sco_preferences.get_preference(context, "portal_timeout")
if api_ver > 1:
req = (
etud_url
@ -203,7 +203,7 @@ def query_apogee_portal(context, **args):
# Ne fonctionne pas avec l'API 2 sur nom et prenom
# XXX TODO : va poser problème pour la page modif données étudiants : A VOIR
return []
portal_timeout = context.get_preference("portal_timeout")
portal_timeout = sco_preferences.get_preference(context, "portal_timeout")
req = etud_url + "?" + urllib.urlencode(args.items())
doc = scu.query_portal(req, timeout=portal_timeout) # sco_utils
return xml_to_list_of_dicts(doc, req=req)
@ -323,7 +323,7 @@ def get_etud_apogee(context, code_nip):
etud_url = get_etud_url(context)
if not etud_url:
return {}
portal_timeout = context.get_preference("portal_timeout")
portal_timeout = sco_preferences.get_preference(context, "portal_timeout")
req = etud_url + "?" + urllib.urlencode((("nip", code_nip),))
doc = scu.query_portal(req, timeout=portal_timeout)
d = _normalize_apo_fields(xml_to_list_of_dicts(doc, req=req))
@ -356,7 +356,7 @@ def _parse_etapes_from_xml(context, doc):
"""
may raise exception if invalid xml doc
"""
xml_etapes_by_dept = context.get_preference("xml_etapes_by_dept")
xml_etapes_by_dept = sco_preferences.get_preference(context, "xml_etapes_by_dept")
# parser XML
dom = xml.dom.minidom.parseString(doc)
infos = {}
@ -384,7 +384,7 @@ def get_etapes_apogee(context):
etapes_url = get_etapes_url(context)
infos = {}
if etapes_url:
portal_timeout = context.get_preference("portal_timeout")
portal_timeout = sco_preferences.get_preference(context, "portal_timeout")
log(
"get_etapes_apogee: requesting '%s' with timeout=%s"
% (etapes_url, portal_timeout)
@ -432,9 +432,9 @@ def get_etapes_apogee_dept(context):
Returns [ ( code, intitule) ], ordonnée
"""
xml_etapes_by_dept = context.get_preference("xml_etapes_by_dept")
xml_etapes_by_dept = sco_preferences.get_preference(context, "xml_etapes_by_dept")
if xml_etapes_by_dept:
portal_dept_name = context.get_preference("portal_dept_name")
portal_dept_name = sco_preferences.get_preference(context, "portal_dept_name")
log('get_etapes_apogee_dept: portal_dept_name="%s"' % portal_dept_name)
else:
portal_dept_name = ""
@ -558,7 +558,7 @@ def get_maquette_apogee(context, etape="", annee_scolaire=""):
maquette_url = get_maquette_url(context)
if not maquette_url:
return None
portal_timeout = context.get_preference("portal_timeout")
portal_timeout = sco_preferences.get_preference(context, "portal_timeout")
req = (
maquette_url
+ "?"

View File

@ -54,9 +54,9 @@ def etud_get_poursuite_info(context, sem, etud):
for s in etud["sems"]:
if s["semestre_id"] == sem_id:
etudid = etud["etudid"]
nt = context._getNotesCache().get_NotesTable(
context, s["formsemestre_id"]
)
nt = sco_core.get_notes_cache(
context,
).get_NotesTable(context, s["formsemestre_id"])
dec = nt.get_etud_decision_sem(etudid)
# Moyennes et rangs des UE
ues = nt.get_ues(filter_sport=True)
@ -203,7 +203,7 @@ def formsemestre_poursuite_report(
html_sortable=True,
html_class="table_leftalign table_listegroupe",
pdf_link=False, # pas d'export pdf
preferences=context.get_preferences(formsemestre_id),
preferences=sco_preferences.SemPreferences(context, formsemestre_id),
)
tab.filename = scu.make_filename("poursuite " + sem["titreannee"])

View File

@ -79,18 +79,18 @@ des tuples (name, value, formsemestre_id).
Si formsemestre_id est NULL, la valeur concerne tous les semestres,
sinon, elle ne concerne que le semestre indiqué.
* Utilisation dans ScoDoc
* Utilisation dans ScoDoc7
- lire une valeur:
context.get_preference(name, formsemestre_id)
get_preference(context, name, formsemestre_id)
nb: les valeurs sont des chaines, sauf:
. si le type est spécfié (float ou int)
. les boolcheckbox qui sont des entiers 0 ou 1
- avoir un mapping (read only) de toutes les valeurs:
context.get_preferences(formsemestre_id)
sco_preferences.SemPreferences(context,formsemestre_id)
- editer les preferences globales:
sco_preferences.get_base_preferences(self).edit(REQUEST=REQUEST)
- editer les preferences d'un semestre:
sem_preferences(context,formsemestre_id).edit()
SemPreferences(context,formsemestre_id).edit()
* Implémentation: sco_preferences.py
@ -109,7 +109,7 @@ Une instance unique par site (département, repéré par URL).
.deleteformsemestre_id, name)
.edit() (HTML dialog)
class sem_preferences(context,formsemestre_id)
class SemPreferences(context,formsemestre_id)
Une instance par semestre, et une instance pour prefs globales.
L'attribut .base_prefs point sur sco_base_preferences.
.__getitem__ [name]
@ -1941,7 +1941,7 @@ class sco_base_preferences:
def edit(self, REQUEST):
"""HTML dialog: edit global preferences"""
H = [
self.context.sco_header(REQUEST, page_title="Préférences"),
self.html_sco_header.sco_header(context, REQUEST, page_title="Préférences"),
"<h2>Préférences globales pour %s</h2>" % self.context.ScoURL(),
"""<p class="help">Ces paramètres s'appliquent par défaut à tous les semestres, sauf si ceux-ci définissent des valeurs spécifiques.</p>
<p class="msg">Attention: cliquez sur "Enregistrer les modifications" en bas de page pour appliquer vos changements !</p>
@ -1956,7 +1956,9 @@ class sco_base_preferences:
submitlabel="Enregistrer les modifications",
)
if tf[0] == 0:
return "\n".join(H) + tf[1] + self.context.sco_footer(REQUEST)
return (
"\n".join(H) + tf[1] + self.html_sco_header.sco_footer(context, REQUEST)
)
elif tf[0] == -1:
return REQUEST.RESPONSE.redirect(self.context.ScoURL()) # cancel
else:
@ -1979,7 +1981,7 @@ def get_base_preferences(context):
return _SCO_BASE_PREFERENCES[u]
class sem_preferences:
class SemPreferences:
def __init__(self, context, formsemestre_id=None):
self.context = context
self.formsemestre_id = formsemestre_id
@ -2065,7 +2067,9 @@ function set_global_pref(el, pref_name) {
+ "/formsemestre_status?formsemestre_id=%s" % self.formsemestre_id
)
if tf[0] == 0:
return "\n".join(H) + tf[1] + self.context.sco_footer(REQUEST)
return (
"\n".join(H) + tf[1] + self.html_sco_header.sco_footer(context, REQUEST)
)
elif tf[0] == -1:
return REQUEST.RESPONSE.redirect(
dest_url + "&head_message=Annulé"
@ -2183,6 +2187,13 @@ def _build_form(self, categories=[], global_edit=False):
return form
def get_preference(context, name, formsemestre_id=None):
"""Returns value of named preference.
All preferences have a sensible default value, so this function always returns a usable value for all defined preferences names.
"""
return get_base_preferences(context).get(formsemestre_id, name)
#
def doc_preferences(context):
""" Liste les preferences en MarkDown, pour la documentation"""

View File

@ -44,7 +44,7 @@ import VERSION
def feuille_preparation_jury(context, formsemestre_id, REQUEST):
"Feuille excel pour preparation des jurys"
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etudids, get_etud_moy_gen, get_ues, get_etud_ue_status, get_etud_decision_sem, identdict,
etudids = nt.get_etudids(sorted=True) # tri par moy gen
@ -77,7 +77,7 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST):
etud = info[0]
Se = sco_parcours_dut.SituationEtudParcours(context, etud, formsemestre_id)
if Se.prev:
ntp = context._getNotesCache().get_NotesTable(
ntp = sco_core.get_notes_cache(context).get_NotesTable(
context, Se.prev["formsemestre_id"]
) # > get_ues, get_etud_ue_status, get_etud_moy_gen, get_etud_decision_sem
for ue in ntp.get_ues(filter_sport=True):
@ -161,9 +161,9 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST):
L.append([]) # empty line
titles = ["Rang"]
if context.get_preference("prepa_jury_nip"):
if sco_preferences.get_preference(context, "prepa_jury_nip"):
titles.append("NIP")
if context.get_preference("prepa_jury_ine"):
if sco_preferences.get_preference(context, "prepa_jury_ine"):
titles.append("INE")
titles += [
"etudid",
@ -223,9 +223,9 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST):
for etudid in etudids:
etud = nt.identdict[etudid]
l = [str(i)]
if context.get_preference("prepa_jury_nip"):
if sco_preferences.get_preference(context, "prepa_jury_nip"):
l.append(etud["code_nip"])
if context.get_preference("prepa_jury_ine"):
if sco_preferences.get_preference(context, "prepa_jury_ine"):
l.append(etud["code_ine"])
l += [
etudid,

View File

@ -210,7 +210,7 @@ def dict_pvjury(
'decisions_dict' : { etudid : decision (comme ci-dessus) },
}
"""
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etudids, get_etud_etat, get_etud_decision_sem, get_etud_decision_ues
if etudids is None:
@ -412,10 +412,10 @@ def pvjury_table(
columns_ids += ["prev_decision"]
columns_ids += ["decision"]
if context.get_preference("bul_show_mention", formsemestre_id):
if sco_preferences.get_preference(context, "bul_show_mention", formsemestre_id):
columns_ids += ["mention"]
columns_ids += ["ue_cap"]
if context.get_preference("bul_show_ects", formsemestre_id):
if sco_preferences.get_preference(context, "bul_show_ects", formsemestre_id):
columns_ids += ["ects"]
# XXX if not dpv["semestre_non_terminal"]:
@ -448,12 +448,14 @@ def pvjury_table(
}
if with_paragraph_nom:
cell_style = styles.ParagraphStyle({})
cell_style.fontSize = context.get_preference(
"SCOLAR_FONT_SIZE", formsemestre_id
cell_style.fontSize = sco_preferences.get_preference(
context, "SCOLAR_FONT_SIZE", formsemestre_id
)
cell_style.fontName = context.get_preference("PV_FONTNAME", formsemestre_id)
cell_style.leading = 1.0 * context.get_preference(
"SCOLAR_FONT_SIZE", formsemestre_id
cell_style.fontName = sco_preferences.get_preference(
context, "PV_FONTNAME", formsemestre_id
)
cell_style.leading = 1.0 * sco_preferences.get_preference(
context, "SCOLAR_FONT_SIZE", formsemestre_id
) # vertical space
i = e["identite"]
l["nomprenom"] = [
@ -498,13 +500,13 @@ def formsemestre_pvjury(
"""Page récapitulant les décisions de jury
dpv: result of dict_pvjury
"""
footer = context.sco_footer(REQUEST)
footer = html_sco_header.sco_footer(context, REQUEST)
dpv = dict_pvjury(context, formsemestre_id, with_prev=True)
if not dpv:
if format == "html":
return (
context.sco_header(REQUEST)
html_sco_header.sco_header(context, REQUEST)
+ "<h2>Aucune information disponible !</h2>"
+ footer
)
@ -528,7 +530,7 @@ def formsemestre_pvjury(
caption="Décisions jury pour " + sem["titreannee"],
html_class="table_leftalign",
html_sortable=True,
preferences=context.get_preferences(formsemestre_id),
preferences=sco_preferences.SemPreferences(context, formsemestre_id),
)
if format != "html":
return tab.make_page(
@ -540,7 +542,8 @@ def formsemestre_pvjury(
)
tab.base_url = "%s?formsemestre_id=%s" % (REQUEST.URL0, formsemestre_id)
H = [
context.html_sem_header(
html_sco_header.html_sem_header(
context,
REQUEST,
"Décisions du jury pour le semestre",
sem,
@ -589,7 +592,7 @@ def formsemestre_pvjury(
columns_ids=("code", "count", "expl"),
html_class="table_leftalign",
html_sortable=True,
preferences=context.get_preferences(formsemestre_id),
preferences=sco_preferences.SemPreferences(context, formsemestre_id),
).html()
)
H.append("<p></p>") # force space at bottom
@ -629,7 +632,8 @@ def formsemestre_pvjury_pdf(
etudids = [m["etudid"] for m in groups_infos.members]
H = [
context.html_sem_header(
html_sco_header.html_sem_header(
context,
REQUEST,
"Edition du PV de jury %s" % etuddescr,
sem=sem,
@ -645,7 +649,7 @@ def formsemestre_pvjury_pdf(
F = [
"""<p><em>Voir aussi si besoin les réglages sur la page "Paramétrage" (accessible à l'administrateur du département).</em>
</p>""",
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
descr = descrform_pvjury(context, sem)
if etudid:
@ -811,7 +815,8 @@ def formsemestre_lettres_individuelles(
etudids = [m["etudid"] for m in groups_infos.members]
H = [
context.html_sem_header(
html_sco_header.html_sem_header(
context,
REQUEST,
"Edition des lettres individuelles",
sem=sem,
@ -824,7 +829,7 @@ def formsemestre_lettres_individuelles(
"""
% formsemestre_id,
]
F = context.sco_footer(REQUEST)
F = html_sco_header.sco_footer(context, REQUEST)
descr = descrform_lettres_individuelles()
menu_choix_groupe = (
"""<div class="group_ids_sel_menu">Groupes d'étudiants à lister: """

View File

@ -201,7 +201,7 @@ class CourrierIndividuelTemplate(PageTemplate):
self.logo_header = None
# Search logos in dept specific dir, then in global scu.CONFIG dir
for image_dir in (
scu.SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/",
scu.SCODOC_LOGOS_DIR + "/logos_" + sco_core.get_dept_id() + "/",
scu.SCODOC_LOGOS_DIR + "/", # global logos
):
for suffix in scu.LOGOS_IMAGES_ALLOWED_TYPES:
@ -348,7 +348,7 @@ def pdf_lettres_individuelles(
context.fillEtudsInfo(etuds)
#
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
prefs = context.get_preferences(formsemestre_id)
prefs = sco_preferences.SemPreferences(context, formsemestre_id)
params = {
"date_jury": date_jury,
"date_commission": date_commission,
@ -358,7 +358,9 @@ def pdf_lettres_individuelles(
}
# copie preferences
for name in sco_preferences.PREFS_NAMES:
params[name] = context.get_preference(name, sem["formsemestre_id"])
params[name] = sco_preferences.get_preference(
context, name, sem["formsemestre_id"]
)
bookmarks = {}
objects = [] # list of PLATYPUS objects
@ -429,7 +431,9 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None, context
objects = []
style = reportlab.lib.styles.ParagraphStyle({})
style.fontSize = 14
style.fontName = context.get_preference("PV_FONTNAME", formsemestre_id)
style.fontName = sco_preferences.get_preference(
context, "PV_FONTNAME", formsemestre_id
)
style.leading = 18
style.alignment = TA_JUSTIFY
@ -443,8 +447,8 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None, context
else:
params["decisions_ue_descr_plural"] = ""
params["INSTITUTION_CITY"] = context.get_preference(
"INSTITUTION_CITY", formsemestre_id
params["INSTITUTION_CITY"] = sco_preferences.get_preference(
context, "INSTITUTION_CITY", formsemestre_id
)
if decision["prev_decision_sem"]:
params["prev_semestre_id"] = decision["prev"]["semestre_id"]
@ -512,7 +516,9 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None, context
# Corps de la lettre:
objects += sco_bulletins_pdf.process_field(
context,
context.get_preference("PV_LETTER_TEMPLATE", sem["formsemestre_id"]),
sco_preferences.get_preference(
context, "PV_LETTER_TEMPLATE", sem["formsemestre_id"]
),
params,
style,
suppress_empty_pars=True,
@ -523,7 +529,9 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None, context
# chef de département.
if Se.semestre_non_terminal:
sig = (
context.get_preference("PV_LETTER_PASSAGE_SIGNATURE", formsemestre_id)
sco_preferences.get_preference(
context, "PV_LETTER_PASSAGE_SIGNATURE", formsemestre_id
)
% params
)
sig = _simulate_br(sig, '<para leftindent="%(htab1)s">')
@ -538,7 +546,9 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None, context
)
else:
sig = (
context.get_preference("PV_LETTER_DIPLOMA_SIGNATURE", formsemestre_id)
sco_preferences.get_preference(
context, "PV_LETTER_DIPLOMA_SIGNATURE", formsemestre_id
)
% params
)
sig = _simulate_br(sig, '<para leftindent="%(htab1)s">')
@ -580,13 +590,17 @@ def _make_signature_image(signature, leftindent, formsemestre_id, context=None):
im = PILImage.open(f)
width, height = im.size
pdfheight = (
1.0 * context.get_preference("pv_sig_image_height", formsemestre_id) * mm
1.0
* sco_preferences.get_preference(
context, "pv_sig_image_height", formsemestre_id
)
* mm
)
f.seek(0, 0)
style = styles.ParagraphStyle({})
style.leading = 1.0 * context.get_preference(
"SCOLAR_FONT_SIZE", formsemestre_id
style.leading = 1.0 * sco_preferences.get_preference(
context, "SCOLAR_FONT_SIZE", formsemestre_id
) # vertical space
style.leftIndent = leftindent
return Table(
@ -666,7 +680,7 @@ def pvjury_pdf(
author="%s %s (E. Viennet)" % (VERSION.SCONAME, VERSION.SCOVERSION),
title=SU("PV du jury de %s" % sem["titre_num"]),
subject="PV jury",
preferences=context.get_preferences(formsemestre_id),
preferences=sco_preferences.SemPreferences(context, formsemestre_id),
)
)
@ -702,14 +716,18 @@ def _pvjury_pdf_type(
style = reportlab.lib.styles.ParagraphStyle({})
style.fontSize = 12
style.fontName = context.get_preference("PV_FONTNAME", formsemestre_id)
style.fontName = sco_preferences.get_preference(
context, "PV_FONTNAME", formsemestre_id
)
style.leading = 18
style.alignment = TA_JUSTIFY
indent = 1 * cm
bulletStyle = reportlab.lib.styles.ParagraphStyle({})
bulletStyle.fontSize = 12
bulletStyle.fontName = context.get_preference("PV_FONTNAME", formsemestre_id)
bulletStyle.fontName = sco_preferences.get_preference(
context, "PV_FONTNAME", formsemestre_id
)
bulletStyle.leading = 12
bulletStyle.alignment = TA_JUSTIFY
bulletStyle.firstLineIndent = 0
@ -727,7 +745,7 @@ def _pvjury_pdf_type(
"""
% (
titre_jury,
context.get_preference("DeptName", formsemestre_id),
sco_preferences.get_preference(context, "DeptName", formsemestre_id),
sem["anneescolaire"],
),
style,
@ -745,7 +763,7 @@ def _pvjury_pdf_type(
objects += sco_pdf.makeParas(
"""<para align="center"><b>Semestre: %s</b></para>""" % sem["titre"], style
)
if context.get_preference("PV_TITLE_WITH_VDI", formsemestre_id):
if sco_preferences.get_preference(context, "PV_TITLE_WITH_VDI", formsemestre_id):
objects += sco_pdf.makeParas(
"""<para align="center">VDI et Code: %s</para>""" % (VDICode or ""), style
)
@ -757,11 +775,13 @@ def _pvjury_pdf_type(
objects += sco_pdf.makeParas(
"<para>"
+ context.get_preference("PV_INTRO", formsemestre_id)
+ sco_preferences.get_preference(context, "PV_INTRO", formsemestre_id)
% {
"Decnum": numeroArrete,
"VDICode": VDICode,
"UnivName": context.get_preference("UnivName", formsemestre_id),
"UnivName": sco_preferences.get_preference(
context, "UnivName", formsemestre_id
),
"Type": titre_jury,
"Date": date_commission, # deprecated
"date_commission": date_commission,
@ -787,10 +807,14 @@ def _pvjury_pdf_type(
titles = [titles.get(x, "") for x in columns_ids]
# Make a new cell style and put all cells in paragraphs
cell_style = styles.ParagraphStyle({})
cell_style.fontSize = context.get_preference("SCOLAR_FONT_SIZE", formsemestre_id)
cell_style.fontName = context.get_preference("PV_FONTNAME", formsemestre_id)
cell_style.leading = 1.0 * context.get_preference(
"SCOLAR_FONT_SIZE", formsemestre_id
cell_style.fontSize = sco_preferences.get_preference(
context, "SCOLAR_FONT_SIZE", formsemestre_id
)
cell_style.fontName = sco_preferences.get_preference(
context, "PV_FONTNAME", formsemestre_id
)
cell_style.leading = 1.0 * sco_preferences.get_preference(
context, "SCOLAR_FONT_SIZE", formsemestre_id
) # vertical space
LINEWIDTH = 0.5
table_style = [
@ -798,7 +822,7 @@ def _pvjury_pdf_type(
"FONTNAME",
(0, 0),
(-1, 0),
context.get_preference("PV_FONTNAME", formsemestre_id),
sco_preferences.get_preference(context, "PV_FONTNAME", formsemestre_id),
),
("LINEBELOW", (0, 0), (-1, 0), LINEWIDTH, Color(0, 0, 0)),
("GRID", (0, 0), (-1, -1), LINEWIDTH, Color(0, 0, 0)),
@ -817,7 +841,7 @@ def _pvjury_pdf_type(
widths = [6 * cm, 2.8 * cm, 2.8 * cm, None, None, None, None]
if dpv["has_prev"]:
widths[2:2] = [2.8 * cm]
if context.get_preference("bul_show_mention", formsemestre_id):
if sco_preferences.get_preference(context, "bul_show_mention", formsemestre_id):
widths += [None]
objects.append(Table(Pt, repeatRows=1, colWidths=widths, style=table_style))
@ -826,8 +850,10 @@ def _pvjury_pdf_type(
"""<para spaceBefore="10mm" align="right">
%s, %s</para>"""
% (
context.get_preference("DirectorName", formsemestre_id) or "",
context.get_preference("DirectorTitle", formsemestre_id) or "",
sco_preferences.get_preference(context, "DirectorName", formsemestre_id)
or "",
sco_preferences.get_preference(context, "DirectorTitle", formsemestre_id)
or "",
),
style,
)
@ -848,7 +874,7 @@ def _pvjury_pdf_type(
"FONTNAME",
(0, 0),
(-1, 0),
context.get_preference("PV_FONTNAME", formsemestre_id),
sco_preferences.get_preference(context, "PV_FONTNAME", formsemestre_id),
),
("LINEBELOW", (0, 0), (-1, -1), LINEWIDTH, Color(0, 0, 0)),
("LINEABOVE", (0, 0), (-1, -1), LINEWIDTH, Color(0, 0, 0)),

View File

@ -75,7 +75,9 @@ def formsemestre_recapcomplet(
) # cache les colonnes des modules
pref_override = int(pref_override)
if pref_override:
hidebac = int(context.get_preference("recap_hidebac", formsemestre_id))
hidebac = int(
sco_preferences.get_preference(context, "recap_hidebac", formsemestre_id)
)
else:
hidebac = int(hidebac)
xml_with_decisions = int(xml_with_decisions)
@ -84,7 +86,8 @@ def formsemestre_recapcomplet(
H = []
if not isFile:
H += [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Récapitulatif",
no_side_bar=True,
@ -177,13 +180,13 @@ def formsemestre_recapcomplet(
% formsemestre_id
)
H.append("</p>")
if context.get_preference("use_ue_coefs", formsemestre_id):
if sco_preferences.get_preference(context, "use_ue_coefs", formsemestre_id):
H.append(
"""
<p class="infop">utilise les coefficients d'UE pour calculer la moyenne générale.</p>
"""
)
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "".join(H) # HTML or binary data...
@ -271,7 +274,7 @@ def make_formsemestre_recapcomplet(
sem = sco_formsemestre.do_formsemestre_list(
context, args={"formsemestre_id": formsemestre_id}
)[0]
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_modimpls, get_ues, get_table_moyennes_triees, get_etud_decision_sem, get_etud_etat, get_etud_rang, get_nom_short, get_mod_stats, nt.moy_moy, get_etud_decision_sem,
modimpls = nt.get_modimpls()
@ -486,7 +489,9 @@ def make_formsemestre_recapcomplet(
if key == "nb_valid_evals":
l.append("")
elif key == "coef":
if context.get_preference("use_ue_coefs", formsemestre_id):
if sco_preferences.get_preference(
context, "use_ue_coefs", formsemestre_id
):
l.append("%2.3f" % ue["coefficient"])
else:
l.append("")
@ -853,7 +858,7 @@ def _formsemestre_recapcomplet_xml(
):
"XML export: liste tous les bulletins XML."
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_table_moyennes_triees
T = nt.get_table_moyennes_triees()
@ -920,7 +925,7 @@ def _formsemestre_recapcomplet_json(
"bulletins": [],
}
bulletins = J["bulletins"]
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_table_moyennes_triees
T = nt.get_table_moyennes_triees()

View File

@ -55,7 +55,7 @@ MAX_ETUD_IN_DESCR = 20
def formsemestre_etuds_stats(context, sem, only_primo=False):
"""Récupère liste d'etudiants avec etat et decision."""
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, sem["formsemestre_id"]
) # > get_table_moyennes_triees, identdict, get_etud_decision_sem, get_etud_etat,
T = nt.get_table_moyennes_triees()
@ -192,7 +192,7 @@ def _results_by_category(
bottom_titles=bottom_titles,
html_col_width="4em",
html_sortable=True,
preferences=context.get_preferences(formsemestre_id),
preferences=sco_preferences.SemPreferences(context, formsemestre_id),
)
@ -355,7 +355,7 @@ def formsemestre_report_counts(
if format != "html":
return t
H = [
context.sco_header(REQUEST, page_title=title),
html_sco_header.sco_header(context, REQUEST, page_title=title),
t,
"\n".join(F),
"""<p class="help">Le tableau affiche le nombre d'étudiants de ce semestre dans chacun
@ -363,7 +363,7 @@ def formsemestre_report_counts(
pour les lignes et les colonnes. Le <tt>codedecision</tt> est le code de la décision
du jury.
</p>""",
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)
@ -404,7 +404,7 @@ def table_suivi_cohorte(
logt("table_suivi_cohorte: start")
# 1-- Liste des semestres posterieurs dans lesquels ont été les etudiants de sem
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etudids, get_etud_decision_sem
etudids = nt.get_etudids()
@ -458,7 +458,7 @@ def table_suivi_cohorte(
s["members"] = orig_set.intersection(inset)
nb_dipl = 0 # combien de diplomes dans ce semestre ?
if s["semestre_id"] == nt.parcours.NB_SEM:
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, s["formsemestre_id"]
) # > get_etud_decision_sem
for etudid in s["members"]:
@ -643,7 +643,7 @@ def table_suivi_cohorte(
caption="Suivi cohorte " + pp + sem["titreannee"] + dbac,
page_title="Suivi cohorte " + sem["titreannee"],
html_class="table_cohorte",
preferences=context.get_preferences(formsemestre_id),
preferences=sco_preferences.SemPreferences(context, formsemestre_id),
)
# Explication: liste des semestres associés à chaque date
if not P:
@ -744,7 +744,7 @@ def formsemestre_suivi_cohorte(
)
H = [
context.sco_header(REQUEST, page_title=tab.page_title),
html_sco_header.sco_header(context, REQUEST, page_title=tab.page_title),
"""<h2 class="formsemestre">Suivi cohorte: devenir des étudiants de ce semestre</h2>""",
_gen_form_selectetuds(
formsemestre_id,
@ -765,7 +765,7 @@ def formsemestre_suivi_cohorte(
t,
help,
expl,
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)
@ -908,7 +908,7 @@ def _descr_etud_set(context, etudids):
def _count_dem_reo(context, formsemestre_id, etudids):
"count nb of demissions and reorientation in this etud set"
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etud_etat, get_etud_decision_sem
dems = set()
@ -974,7 +974,7 @@ def get_codeparcoursetud(context, etud, prefix="", separator=""):
i = len(sems) - 1
while i >= 0:
s = sems[i] # 'sems' est a l'envers, du plus recent au plus ancien
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, s["formsemestre_id"]
) # > get_etud_etat, get_etud_decision_sem
p.append(_codesem(s, prefix=prefix))
@ -1021,7 +1021,7 @@ def tsp_etud_list(
"""
# log('tsp_etud_list(%s, bac="%s")' % (formsemestre_id,bac))
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etudids,
etudids = nt.get_etudids()
@ -1155,7 +1155,7 @@ def table_suivi_parcours(
"nb": len(etuds),
"codeparcours": len(etuds),
},
preferences=context.get_preferences(formsemestre_id),
preferences=sco_preferences.SemPreferences(context, formsemestre_id),
)
return tab
@ -1215,7 +1215,8 @@ def formsemestre_suivi_parcours(
]
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title=tab.page_title,
init_qtip=True,
@ -1224,7 +1225,7 @@ def formsemestre_suivi_parcours(
"""<h2 class="formsemestre">Parcours suivis par les étudiants de ce semestre</h2>""",
"\n".join(F),
t,
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
return "\n".join(H)
@ -1272,7 +1273,7 @@ def graph_parcours(
nxt = {}
etudid = etud["etudid"]
for s in etud["sems"]: # du plus recent au plus ancien
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, s["formsemestre_id"]
) # > get_etud_decision_sem, get_etud_etat
dec = nt.get_etud_decision_sem(etudid)
@ -1543,7 +1544,8 @@ def formsemestre_graph_parcours(
)
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Parcours étudiants de %(titreannee)s" % sem,
no_side_bar=True,
@ -1582,7 +1584,7 @@ def formsemestre_graph_parcours(
passant la souris sur le chiffre).
</p>"""
% MAX_ETUD_IN_DESCR,
context.sco_footer(REQUEST),
html_sco_header.sco_footer(context, REQUEST),
]
REQUEST.RESPONSE.setHeader("content-type", "application/xhtml+xml")
return "\n".join(H)

View File

@ -44,6 +44,7 @@ from sco_exceptions import (
ScoValueError,
)
from sco_permissions import ScoEditAllNotes
import sco_core
import sco_formsemestre
import sco_moduleimpl
import sco_groups
@ -74,12 +75,12 @@ def can_edit_notes(context, authuser, moduleimpl_id, allow_ens=True):
if sco_parcours_dut.formsemestre_has_decisions(context, sem["formsemestre_id"]):
# il y a des décisions de jury dans ce semestre !
return (
authuser.has_permission(ScoEditAllNotes, context)
authuser.has_permission(Permission.ScoEditAllNotes, context)
or uid in sem["responsables"]
)
else:
if (
(not authuser.has_permission(ScoEditAllNotes, context))
(not authuser.has_permission(Permission.ScoEditAllNotes, context))
and uid != M["responsable_id"]
and uid not in sem["responsables"]
):
@ -342,10 +343,10 @@ def do_evaluation_set_missing(
diag = "Valeur %s invalide" % value
if diag:
return (
context.sco_header(REQUEST)
html_sco_header.sco_header(context, REQUEST)
+ '<h2>%s</h2><p><a href="saisie_notes?evaluation_id=%s">Recommencer</a>'
% (diag, evaluation_id)
+ context.sco_footer(REQUEST)
+ html_sco_header.sco_footer(context, REQUEST)
)
# Confirm action
if not dialog_confirmed:
@ -381,7 +382,7 @@ def do_evaluation_set_missing(
url=mod["url"],
)
return (
context.sco_header(REQUEST)
html_sco_header.sco_header(context, REQUEST)
+ """<h2>%d notes changées</h2>
<ul>
<li><a class="stdlink" href="saisie_notes?evaluation_id=%s">
@ -391,7 +392,7 @@ def do_evaluation_set_missing(
</ul>
"""
% (nb_changed, evaluation_id, M["moduleimpl_id"])
+ context.sco_footer(REQUEST)
+ html_sco_header.sco_footer(context, REQUEST)
)
@ -458,7 +459,11 @@ def evaluation_suppress_alln(context, evaluation_id, REQUEST, dialog_confirmed=F
url=mod["url"],
)
return context.sco_header(REQUEST) + "\n".join(H) + context.sco_footer(REQUEST)
return (
html_sco_header.sco_header(context, REQUEST)
+ "\n".join(H)
+ html_sco_header.sco_footer(context, REQUEST)
)
def _notes_add(context, uid, evaluation_id, notes, comment=None, do_it=True):
@ -577,15 +582,19 @@ def _notes_add(context, uid, evaluation_id, notes, comment=None, do_it=True):
log("*** exception in _notes_add")
if do_it:
# inval cache
context._inval_cache(
formsemestre_id=M["formsemestre_id"]
sco_core.inval_cache(
context, formsemestre_id=M["formsemestre_id"]
) # > modif notes (exception)
cnx.rollback() # abort
raise # re-raise exception
if do_it:
cnx.commit()
context._inval_cache(formsemestre_id=M["formsemestre_id"]) # > modif notes
context.get_evaluations_cache().inval_cache(key=evaluation_id)
sco_core.inval_cache(
context, formsemestre_id=M["formsemestre_id"]
) # > modif notes
sco_core.get_evaluations_cache(
context,
).inval_cache(key=evaluation_id)
return nb_changed, nb_suppress, existing_decisions
@ -601,14 +610,14 @@ def saisie_notes_tableur(context, evaluation_id, group_ids=[], REQUEST=None):
formsemestre_id = M["formsemestre_id"]
if not can_edit_notes(context, authuser, E["moduleimpl_id"]):
return (
context.sco_header(REQUEST)
html_sco_header.sco_header(context, REQUEST)
+ "<h2>Modification des notes impossible pour %s</h2>" % authusername
+ """<p>(vérifiez que le semestre n'est pas verrouillé et que vous
avez l'autorisation d'effectuer cette opération)</p>
<p><a href="moduleimpl_status?moduleimpl_id=%s">Continuer</a></p>
"""
% E["moduleimpl_id"]
+ context.sco_footer(REQUEST)
+ html_sco_header.sco_footer(context, REQUEST)
)
if E["description"]:
@ -627,7 +636,8 @@ def saisie_notes_tableur(context, evaluation_id, group_ids=[], REQUEST=None):
)
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title=page_title,
javascripts=sco_groups_view.JAVASCRIPTS,
@ -762,7 +772,7 @@ def saisie_notes_tableur(context, evaluation_id, group_ids=[], REQUEST=None):
</ol>
"""
)
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)
@ -845,7 +855,7 @@ def has_existing_decision(context, M, E, etudid):
Si oui, return True
"""
formsemestre_id = M["formsemestre_id"]
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etud_decision_sem, get_etud_decision_ues
if nt.get_etud_decision_sem(etudid):
@ -881,14 +891,14 @@ def saisie_notes(context, evaluation_id, group_ids=[], REQUEST=None):
# (admin, respformation, and responsable_id)
if not can_edit_notes(context, authuser, E["moduleimpl_id"]):
return (
context.sco_header(REQUEST)
html_sco_header.sco_header(context, REQUEST)
+ "<h2>Modification des notes impossible pour %s</h2>" % authusername
+ """<p>(vérifiez que le semestre n'est pas verrouillé et que vous
avez l'autorisation d'effectuer cette opération)</p>
<p><a href="moduleimpl_status?moduleimpl_id=%s">Continuer</a></p>
"""
% E["moduleimpl_id"]
+ context.sco_footer(REQUEST)
+ html_sco_header.sco_footer(context, REQUEST)
)
# Informations sur les groupes à afficher:
@ -908,7 +918,8 @@ def saisie_notes(context, evaluation_id, group_ids=[], REQUEST=None):
# HTML page:
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title=page_title,
javascripts=sco_groups_view.JAVASCRIPTS + ["js/saisie_notes.js"],
@ -977,7 +988,7 @@ def saisie_notes(context, evaluation_id, group_ids=[], REQUEST=None):
</div>"""
)
H.append(context.sco_footer(REQUEST))
H.append(html_sco_header.sco_footer(context, REQUEST))
return "\n".join(H)

View File

@ -229,9 +229,9 @@ class SemSet(dict):
self["etuds_without_nip"] = set() # etudids
self["jury_ok"] = True
for sem in self.sems:
nt = context._getNotesCache().get_NotesTable(
context, sem["formsemestre_id"]
)
nt = sco_core.get_notes_cache(
context,
).get_NotesTable(context, sem["formsemestre_id"])
sem["etuds"] = nt.identdict.values()
sem["nips"] = {e["code_nip"] for e in sem["etuds"] if e["code_nip"]}
sem["etuds_without_nip"] = {
@ -459,14 +459,17 @@ def semset_page(context, format="html", REQUEST=None):
html_sortable=True,
html_class="table_leftalign",
filename="semsets",
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
if format != "html":
return tab.make_page(context, format=format, REQUEST=REQUEST)
page_title = "Ensembles de semestres"
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title=page_title,
init_qtip=True,
@ -526,4 +529,4 @@ def semset_page(context, format="html", REQUEST=None):
"""
)
return "\n".join(H) + context.sco_footer(REQUEST)
return "\n".join(H) + html_sco_header.sco_footer(context, REQUEST)

View File

@ -90,7 +90,7 @@ def formsemestre_synchro_etuds(
sem["etape_apo_str"] = sco_formsemestre.formsemestre_etape_apo_str(sem)
# Write access ?
authuser = REQUEST.AUTHENTICATED_USER
if not authuser.has_permission(ScoEtudInscrit, context):
if not authuser.has_permission(Permission.ScoEtudInscrit, context):
read_only = True
if read_only:
submitted = False
@ -105,8 +105,10 @@ def formsemestre_synchro_etuds(
"""
% sem
)
header = context.sco_header(REQUEST, page_title="Synchronisation étudiants")
footer = context.sco_footer(REQUEST)
header = html_sco_header.sco_header(
context, REQUEST, page_title="Synchronisation étudiants"
)
footer = html_sco_header.sco_footer(context, REQUEST)
base_url = "%s?formsemestre_id=%s" % (REQUEST.URL0, formsemestre_id)
if anneeapogee:
base_url += "&anneeapogee=%s" % anneeapogee
@ -667,7 +669,8 @@ def do_import_etuds_from_portal(context, sem, a_importer, etudsapo_ident, REQUES
)
cnx.commit()
log("do_import_etuds_from_portal: re-raising exception")
context._inval_cache() # > import: modif identite, adresses, inscriptions
# > import: modif identite, adresses, inscriptions
sco_core.inval_cache(context)
raise
sco_news.add(
@ -846,7 +849,7 @@ def formsemestre_import_etud_admission(
changed_mails.append((info, etud["mail"]))
else:
unknowns.append(code_nip)
context._inval_cache(formsemestre_id=sem["formsemestre_id"])
sco_core.inval_cache(context, formsemestre_id=sem["formsemestre_id"])
return no_nip, unknowns, changed_mails

View File

@ -237,7 +237,7 @@ def module_tag_set(context, module_id="", taglist=[], REQUEST=None):
authuser = REQUEST.AUTHENTICATED_USER
tag_editable = authuser.has_permission(
ScoEditFormationTags, context
) or authuser.has_permission(ScoChangeFormation, context)
) or authuser.has_permission(Permission.ScoChangeFormation, context)
if not tag_editable:
raise AccessDenied("Modification des tags impossible pour %s" % authuser)
#
@ -273,7 +273,9 @@ def get_etud_tagged_modules(context, etudid, tagname):
etud = context.getEtudInfo(etudid=etudid, filled=True)[0]
R = []
for sem in etud["sems"]:
nt = context._getNotesCache().get_NotesTable(context, sem["formsemestre_id"])
nt = sco_core.get_notes_cache(
context,
).get_NotesTable(context, sem["formsemestre_id"])
modimpls = nt.get_modimpls()
for modimpl in modimpls:
tags = module_tag_list(context, module_id=modimpl["module_id"])
@ -341,5 +343,5 @@ sem = etud['sems'][0]
[ tm['moy'] for tm in get_etud_tagged_modules(context, etudid, 'allo') ]
# si besoin après modif par le Web:
# context._inval_cache()
# sco_core.inval_cache(context)
"""

View File

@ -95,11 +95,11 @@ def trombino(
return _listeappel_photos_pdf(context, groups_infos, REQUEST)
else:
raise Exception("invalid format")
# return _trombino_html_header(context, REQUEST) + trombino_html(context, group, members, REQUEST=REQUEST) + context.sco_footer(REQUEST)
# return _trombino_html_header(context, REQUEST) + trombino_html(context, group, members, REQUEST=REQUEST) + html_sco_header.sco_footer(context, REQUEST)
def _trombino_html_header(context, REQUEST):
return context.sco_header(REQUEST, javascripts=["js/trombino.js"])
return html_sco_header.sco_header(context, REQUEST, javascripts=["js/trombino.js"])
def trombino_html(context, groups_infos, REQUEST=None):
@ -242,8 +242,10 @@ def trombino_copy_photos(context, group_ids=[], REQUEST=None, dialog_confirmed=F
back_url = "groups_view?%s&curtab=tab-photos" % groups_infos.groups_query_args
portal_url = sco_portal_apogee.get_portal_url(context)
header = context.sco_header(REQUEST, page_title="Chargement des photos")
footer = context.sco_footer(REQUEST)
header = html_sco_header.sco_header(
context, REQUEST, page_title="Chargement des photos"
)
footer = html_sco_header.sco_footer(context, REQUEST)
if not portal_url:
return (
header
@ -374,7 +376,7 @@ def _trombino_pdf(context, groups_infos, REQUEST):
sco_pdf.ScolarsPageTemplate(
document,
context=context,
preferences=context.get_preferences(sem["formsemestre_id"]),
preferences=sco_preferences.SemPreferences(context, sem["formsemestre_id"]),
)
)
document.build(objects)
@ -451,7 +453,7 @@ def _listeappel_photos_pdf(context, groups_infos, REQUEST):
sco_pdf.ScolarsPageTemplate(
document,
context,
preferences=context.get_preferences(sem["formsemestre_id"]),
preferences=sco_preferences.SemPreferences(context, sem["formsemestre_id"]),
)
)
document.build(objects)
@ -490,7 +492,9 @@ def photos_import_files_form(context, group_ids=[], REQUEST=None):
back_url = "groups_view?%s&curtab=tab-photos" % groups_infos.groups_query_args
H = [
context.sco_header(REQUEST, page_title="Import des photos des étudiants"),
html_sco_header.sco_header(
context, REQUEST, page_title="Import des photos des étudiants"
),
"""<h2 class="formsemestre">Téléchargement des photos des étudiants</h2>
<p><b>Vous pouvez aussi charger les photos individuellement via la fiche de chaque étudiant (menu "Etudiant" / "Changer la photo").</b></p>
<p class="help">Cette page permet de charger en une seule fois les photos de plusieurs étudiants.<br/>
@ -508,7 +512,7 @@ def photos_import_files_form(context, group_ids=[], REQUEST=None):
"""
% groups_infos.groups_query_args,
]
F = context.sco_footer(REQUEST)
F = html_sco_header.sco_footer(context, REQUEST)
REQUEST.form["group_ids"] = groups_infos.group_ids
tf = TrivialFormulator(
REQUEST.URL0,

View File

@ -72,10 +72,10 @@ def pdf_trombino_tours(
context, group_ids, formsemestre_id=formsemestre_id, REQUEST=REQUEST
)
DeptName = context.get_preference("DeptName")
DeptFullName = context.get_preference("DeptFullName")
UnivName = context.get_preference("UnivName")
InstituteName = context.get_preference("InstituteName")
DeptName = sco_preferences.get_preference(context, "DeptName")
DeptFullName = sco_preferences.get_preference(context, "DeptFullName")
UnivName = sco_preferences.get_preference(context, "UnivName")
InstituteName = sco_preferences.get_preference(context, "InstituteName")
# Generate PDF page
StyleSheet = styles.getSampleStyleSheet()
objects = []
@ -277,7 +277,11 @@ def pdf_trombino_tours(
document = BaseDocTemplate(report)
document.addPageTemplates(
ScolarsPageTemplate(
document, context=context, preferences=context.get_preferences()
document,
context=context,
preferences=sco_preferences.SemPreferences(
context,
),
)
)
document.build(objects)
@ -297,10 +301,10 @@ def pdf_feuille_releve_absences(
):
"""Generation de la feuille d'absence en fichier PDF, avec photos"""
NB_CELL_AM = context.get_preference("feuille_releve_abs_AM")
NB_CELL_PM = context.get_preference("feuille_releve_abs_PM")
NB_CELL_AM = sco_preferences.get_preference(context, "feuille_releve_abs_AM")
NB_CELL_PM = sco_preferences.get_preference(context, "feuille_releve_abs_PM")
COLWIDTH = 0.85 * cm
if context.get_preference("feuille_releve_abs_samedi"):
if sco_preferences.get_preference(context, "feuille_releve_abs_samedi"):
days = sco_abs.DAYNAMES[:6] # Lundi, ..., Samedi
else:
days = sco_abs.DAYNAMES[:5] # Lundi, ..., Vendredi
@ -311,10 +315,10 @@ def pdf_feuille_releve_absences(
context, group_ids, formsemestre_id=formsemestre_id, REQUEST=REQUEST
)
DeptName = context.get_preference("DeptName")
DeptFullName = context.get_preference("DeptFullName")
UnivName = context.get_preference("UnivName")
InstituteName = context.get_preference("InstituteName")
DeptName = sco_preferences.get_preference(context, "DeptName")
DeptFullName = sco_preferences.get_preference(context, "DeptFullName")
UnivName = sco_preferences.get_preference(context, "UnivName")
InstituteName = sco_preferences.get_preference(context, "InstituteName")
# Generate PDF page
StyleSheet = styles.getSampleStyleSheet()
objects = [
@ -461,17 +465,21 @@ def pdf_feuille_releve_absences(
# Build document
report = StringIO() # in-memory document, no disk file
filename = "absences-%s-%s.pdf" % (DeptName, groups_infos.groups_filename)
if context.get_preference("feuille_releve_abs_taille") == "A3":
if sco_preferences.get_preference(context, "feuille_releve_abs_taille") == "A3":
taille = A3
elif context.get_preference("feuille_releve_abs_taille") == "A4":
elif sco_preferences.get_preference(context, "feuille_releve_abs_taille") == "A4":
taille = A4
if context.get_preference("feuille_releve_abs_format") == "Paysage":
if sco_preferences.get_preference(context, "feuille_releve_abs_format") == "Paysage":
document = BaseDocTemplate(report, pagesize=landscape(taille))
else:
document = BaseDocTemplate(report, pagesize=taille)
document.addPageTemplates(
ScolarsPageTemplate(
document, context=context, preferences=context.get_preferences()
document,
context=context,
preferences=sco_preferences.SemPreferences(
context,
),
)
)
document.build(objects)

View File

@ -81,7 +81,7 @@ def external_ue_create(
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
# Contrôle d'accès:
authuser = REQUEST.AUTHENTICATED_USER
if not authuser.has_permission(ScoImplement, context):
if not authuser.has_permission(Permission.ScoImplement, context):
if not sem["resp_can_edit"] or str(authuser) not in sem["responsables"]:
raise AccessDenied("vous n'avez pas le droit d'effectuer cette opération")
#
@ -210,7 +210,7 @@ def external_ue_create_form(context, formsemestre_id, etudid, REQUEST=None):
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
# Contrôle d'accès:
authuser = REQUEST.AUTHENTICATED_USER
if not authuser.has_permission(ScoImplement, context):
if not authuser.has_permission(Permission.ScoImplement, context):
if not sem["resp_can_edit"] or str(authuser) not in sem["responsables"]:
raise AccessDenied("vous n'avez pas le droit d'effectuer cette opération")
@ -219,7 +219,7 @@ def external_ue_create_form(context, formsemestre_id, etudid, REQUEST=None):
existing_external_ue = get_existing_external_ue(context, formation_id)
H = [
context.html_sem_header(
html_sco_header.html_sem_header(context,
REQUEST,
"Ajout d'une UE externe pour %(nomprenom)s" % etud,
sem,
@ -233,7 +233,7 @@ def external_ue_create_form(context, formsemestre_id, etudid, REQUEST=None):
</p>
""",
]
html_footer = context.sco_footer(REQUEST)
html_footer = html_sco_header.sco_footer(context, REQUEST)
Fo = context.formation_list(args={"formation_id": sem["formation_id"]})[0]
parcours = sco_codes_parcours.get_parcours_from_code(Fo["type_parcours"])
ue_types = parcours.ALLOWED_UE_TYPES

View File

@ -52,6 +52,7 @@ import sco_utils as scu
import notesdb as ndb
from notes_log import log
from gen_tables import GenTable
import sco_core
import sco_formsemestre
import sco_moduleimpl
import VERSION
@ -95,7 +96,7 @@ class NotesOperation(dict):
# # il y a-t-il une modif plus recente ?
# if self['current_notes_by_etud']['date'] <= self['date'] + OPERATION_DATE_TOLERANCE:
#
# + invalider cache context.get_evaluations_cache().inval_cache(key=evaluation_id)
# + invalider cache sco_core.get_evaluations_cache(context, ).inval_cache(key=evaluation_id)
def list_operations(context, evaluation_id):
@ -157,7 +158,7 @@ def evaluation_list_operations(context, REQUEST, evaluation_id):
html_sortable=False,
html_title="<h2>Opérations sur l'évaluation %s du %s</h2>"
% (E["description"], E["jour"]),
preferences=context.get_preferences(M["formsemestre_id"]),
preferences=sco_preferences.SemPreferences(context, M["formsemestre_id"]),
)
return tab.make_page(context, REQUEST=REQUEST)
@ -200,7 +201,7 @@ def formsemestre_list_saisies_notes(
html_class="table_leftalign table_coldate",
html_sortable=True,
caption="Saisies de notes dans %s" % sem["titreannee"],
preferences=context.get_preferences(formsemestre_id),
preferences=sco_preferences.SemPreferences(context, formsemestre_id),
base_url="%s?formsemestre_id=%s" % (REQUEST.URL0, formsemestre_id),
origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "",
)

View File

@ -936,6 +936,10 @@ def confirm_dialog(
if helpmsg:
H.append('<p class="help">' + helpmsg + "</p>")
if add_headers and REQUEST:
return context.sco_header(REQUEST) + "\n".join(H) + context.sco_footer(REQUEST)
return (
html_sco_header.sco_header(context, REQUEST)
+ "\n".join(H)
+ html_sco_header.sco_footer(context, REQUEST)
)
else:
return "\n".join(H)

View File

@ -29,6 +29,7 @@
"""
import time
import mail
import sco_utils as scu
from sco_utils import SCO_ENCODING
from sco_exceptions import ScoGenError, ScoValueError
@ -384,7 +385,9 @@ def identite_edit(cnx, args, context=None, REQUEST=None):
notify_to = None
if context:
try:
notify_to = context.get_preference("notify_etud_changes_to")
notify_to = sco_preferences.get_preference(
context, "notify_etud_changes_to"
)
except:
pass
@ -451,11 +454,11 @@ def notify_etud_change(context, email_addr, etud, before, after, subject):
msg = MIMEMultipart()
subj = Header("[ScoDoc] " + subject, SCO_ENCODING)
msg["Subject"] = subj
msg["From"] = context.get_preference("email_from_addr")
msg["From"] = sco_preferences.get_preference(context, "email_from_addr")
msg["To"] = email_addr
mime_txt = MIMEText(txt, "plain", SCO_ENCODING)
msg.attach(mime_txt)
context.sendEmail(msg)
mails.sendEmail(context, msg)
return txt
@ -497,7 +500,9 @@ def adresse_edit(cnx, args, context=None):
notify_to = None
if context:
try:
notify_to = context.get_preference("notify_etud_changes_to")
notify_to = sco_preferences.get_preference(
context, "notify_etud_changes_to"
)
except:
pass
if notify_to:
@ -889,7 +894,7 @@ def fillEtudsInfo(context, etuds):
# open('/tmp/t','w').write( str(etuds) )
for etud in etuds:
etudid = etud["etudid"]
etud["dept"] = context.DeptId()
etud["dept"] = sco_core.get_dept_id()
adrs = adresse_list(cnx, {"etudid": etudid})
if not adrs:
# certains "vieux" etudiants n'ont pas d'adresse

View File

@ -95,6 +95,16 @@ from app.scodoc.sco_abs import ddmmyyyy
CSSSTYLES = html_sco_header.BOOTSTRAP_MULTISELECT_CSS
context = ScoDoc7Context(globals())
def sco_publish(route, function, permission):
"""Declare a route for a python function,
protected by permission and called following ScoDoc 7 Zope standards.
"""
bp.route(route)(permission_required(permission)(scodoc7func(context)(function)))
def _toboolean(x):
"convert a value to boolean (ensure backward compat with OLD intranet code)"
if type(x) == type(""):
@ -694,7 +704,9 @@ def SignaleAbsenceGrHebdo(
)
if not groups_infos.members:
return (
context.sco_header(page_title="Saisie des absences", REQUEST=REQUEST)
html_sco_header.sco_header(
context, page_title="Saisie des absences", REQUEST=REQUEST
)
+ "<h3>Aucun étudiant !</h3>"
+ context.sco_footer(REQUEST)
)
@ -706,7 +718,7 @@ def SignaleAbsenceGrHebdo(
)
formsemestre_id = groups_infos.formsemestre_id
require_module = context.get_preference("abs_require_module", formsemestre_id)
require_module = sco_preferences.get_preference(context, "abs_require_module", formsemestre_id)
etuds = [
context.getEtudInfo(etudid=m["etudid"], filled=True)[0]
for m in groups_infos.members
@ -748,7 +760,8 @@ def SignaleAbsenceGrHebdo(
gr_tit = p + ' <span class="fontred">' + groups_infos.groups_titles + "</span>"
H = [
context.sco_header(
html_sco_header.sco_header(
context,
page_title="Saisie hebdomadaire des absences",
init_qtip=True,
javascripts=html_sco_header.BOOTSTRAP_MULTISELECT_JS
@ -860,12 +873,14 @@ def SignaleAbsenceGrSemestre(
)
if not groups_infos.members:
return (
context.sco_header(page_title="Saisie des absences", REQUEST=REQUEST)
html_sco_header.sco_header(
context, page_title="Saisie des absences", REQUEST=REQUEST
)
+ "<h3>Aucun étudiant !</h3>"
+ context.sco_footer(REQUEST)
)
formsemestre_id = groups_infos.formsemestre_id
require_module = context.get_preference("abs_require_module", formsemestre_id)
require_module = sco_preferences.get_preference(context, "abs_require_module", formsemestre_id)
etuds = [
context.getEtudInfo(etudid=m["etudid"], filled=True)[0]
for m in groups_infos.members
@ -951,7 +966,8 @@ def SignaleAbsenceGrSemestre(
gr_tit = p + '<span class="fontred">' + groups_infos.groups_titles + "</span>"
H = [
context.sco_header(
html_sco_header.sco_header(
context,
page_title="Saisie des absences",
init_qtip=True,
javascripts=["js/etud_info.js", "js/abs_ajax.js"],
@ -1428,7 +1444,7 @@ def EtatAbsencesGr(
tab = GenTable(
columns_ids=columns_ids,
rows=T,
preferences=context.get_preferences(formsemestre_id),
preferences=sco_preferences.SemPreferences(context, formsemestre_id),
titles={
"etatincursem": "Etat",
"nomprenom": "Nom",
@ -1440,7 +1456,8 @@ def EtatAbsencesGr(
},
html_sortable=True,
html_class="table_leftalign",
html_header=context.sco_header(
html_header=html_sco_header.sco_header(
context,
REQUEST,
page_title=title,
init_qtip=True,
@ -1490,7 +1507,11 @@ def EtatAbsencesDate(
groups_infos = sco_groups_view.DisplayedGroupsInfos(
context, group_ids, REQUEST=REQUEST
)
H = [context.sco_header(page_title="Etat des absences", REQUEST=REQUEST)]
H = [
html_sco_header.sco_header(
context, page_title="Etat des absences", REQUEST=REQUEST
)
]
if date:
dateiso = notesdb.DateDMYtoISO(date)
nbetud = 0
@ -1631,8 +1652,8 @@ def AddBilletAbsenceForm(context, etudid, REQUEST=None):
"""
etud = context.getEtudInfo(etudid=etudid, filled=1, REQUEST=REQUEST)[0]
H = [
context.sco_header(
REQUEST, page_title="Billet d'absence de %s" % etud["nomprenom"]
html_sco_header.sco_header(
context, REQUEST, page_title="Billet d'absence de %s" % etud["nomprenom"]
)
]
tf = TrivialFormulator(
@ -1724,7 +1745,9 @@ def _tableBillets(context, billets, etud=None, title=""):
columns_ids=columns_ids,
page_title=title,
html_title="<h2>%s</h2>" % title,
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
rows=billets,
html_sortable=True,
)
@ -1752,7 +1775,7 @@ def listeBilletsEtud(context, etudid=False, REQUEST=None, format="html"):
@scodoc7func(context)
def XMLgetBilletsEtud(context, etudid=False, REQUEST=None):
"""Liste billets pour un etudiant"""
if not context.get_preference("handle_billets_abs"):
if not sco_preferences.get_preference(context, "handle_billets_abs"):
return ""
t0 = time.time()
r = context.listeBilletsEtud(etudid, REQUEST=REQUEST, format="xml")
@ -1770,7 +1793,9 @@ def listeBillets(context, REQUEST=None):
tab = context._tableBillets(billets)
T = tab.html()
H = [
context.sco_header(REQUEST, page_title="Billet d'absence non traités"),
html_sco_header.sco_header(
context, REQUEST, page_title="Billet d'absence non traités"
),
"<h2>Billets d'absence en attente de traitement (%d)</h2>" % len(billets),
]
@ -1880,7 +1905,8 @@ def ProcessBilletAbsenceForm(context, billet_id, REQUEST=None):
etud = context.getEtudInfo(etudid=etudid, filled=1, REQUEST=REQUEST)[0]
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Traitement billet d'absence de %s" % etud["nomprenom"],
),

View File

@ -67,68 +67,67 @@ from app.scodoc.sco_exceptions import (
ScoGenError,
AccessDenied,
)
from app.scodoc.sco_pdf import PDFLOCK
import app.scodoc.VERSION as VERSION
from app.scodoc.sco_news import NEWS_INSCR, NEWS_NOTE, NEWS_FORM, NEWS_SEM, NEWS_MISC
from app.scodoc.gen_tables import GenTable
from app.scodoc.sco_permissions import Permission, ScoImplement
from app.scodoc.TrivialFormulator import TrivialFormulator
import app.scodoc.htmlutils as htmlutils
import app.scodoc.sco_excel as sco_excel
from app.scodoc import sco_core
from app.scodoc import htmlutils
from app.scodoc import notes_table
from app.scodoc import pe_view
from app.scodoc import sco_apogee_compare
from app.scodoc import sco_apogee_csv
from app.scodoc import sco_archives
from app.scodoc import sco_bulletins
from app.scodoc import sco_bulletins_pdf
from app.scodoc import sco_cache
from app.scodoc import sco_codes_parcours
from app.scodoc import sco_compute_moy
from app.scodoc import sco_cost_formation
from app.scodoc import sco_debouche
from app.scodoc import sco_edit_formation
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_etape_apogee_view
from app.scodoc import sco_evaluations
from app.scodoc import sco_excel
from app.scodoc import sco_export_results
from app.scodoc import sco_formations
from app.scodoc import sco_formsemestre
from app.scodoc import sco_formsemestre_custommenu
from app.scodoc import sco_formsemestre_edit
from app.scodoc import sco_formsemestre_exterieurs
from app.scodoc import sco_formsemestre_inscriptions
from app.scodoc import sco_formsemestre_status
from app.scodoc import sco_formsemestre_validation
from app.scodoc import sco_groups
from app.scodoc import sco_inscr_passage
from app.scodoc import sco_liste_notes
from app.scodoc import sco_lycee
from app.scodoc import sco_moduleimpl
from app.scodoc import sco_moduleimpl_inscriptions
from app.scodoc import sco_moduleimpl_status
from app.scodoc import sco_news
from app.scodoc import sco_parcours_dut
from app.scodoc import sco_placement
from app.scodoc import sco_poursuite_dut
from app.scodoc import sco_prepajury
from app.scodoc import sco_pvjury
from app.scodoc import sco_pvpdf
from app.scodoc import sco_recapcomplet
from app.scodoc import sco_report
from app.scodoc import sco_saisie_notes
from app.scodoc import sco_semset
from app.scodoc import sco_synchro_etuds
from app.scodoc import sco_tag_module
from app.scodoc import sco_ue_external
from app.scodoc import sco_undo_notes
from app.scodoc import scolars
from app.scodoc.gen_tables import GenTable
from app.scodoc import sco_cache as sco_cache
from app.scodoc import scolars as scolars
from app.scodoc import sco_news as sco_news
from app.scodoc.sco_news import NEWS_INSCR, NEWS_NOTE, NEWS_FORM, NEWS_SEM, NEWS_MISC
from app.scodoc import sco_formsemestre as sco_formsemestre
from app.scodoc import sco_formsemestre_edit as sco_formsemestre_edit
from app.scodoc import sco_formsemestre_status as sco_formsemestre_status
from app.scodoc import sco_formsemestre_inscriptions as sco_formsemestre_inscriptions
from app.scodoc import sco_formsemestre_custommenu as sco_formsemestre_custommenu
from app.scodoc import sco_moduleimpl as sco_moduleimpl
from app.scodoc import sco_moduleimpl_status as sco_moduleimpl_status
from app.scodoc import sco_moduleimpl_inscriptions as sco_moduleimpl_inscriptions
from app.scodoc import sco_evaluations as sco_evaluations
from app.scodoc import sco_groups as sco_groups
from app.scodoc import sco_edit_ue as sco_edit_ue
from app.scodoc import sco_edit_formation as sco_edit_formation
from app.scodoc import sco_edit_matiere as sco_edit_matiere
from app.scodoc import sco_edit_module as sco_edit_module
from app.scodoc import sco_tag_module as sco_tag_module
from app.scodoc import sco_bulletins as sco_bulletins
from app.scodoc import sco_bulletins_pdf as sco_bulletins_pdf
from app.scodoc import sco_compute_moy as sco_compute_moy
from app.scodoc import sco_recapcomplet as sco_recapcomplet
from app.scodoc import sco_liste_notes as sco_liste_notes
from app.scodoc import sco_saisie_notes as sco_saisie_notes
from app.scodoc import sco_placement as sco_placement
from app.scodoc import sco_undo_notes as sco_undo_notes
from app.scodoc import sco_formations as sco_formations
from app.scodoc import sco_report as sco_report
from app.scodoc import sco_lycee as sco_lycee
from app.scodoc import sco_poursuite_dut as sco_poursuite_dut
from app.scodoc import pe_view as pe_view
from app.scodoc import sco_debouche as sco_debouche
from app.scodoc import sco_ue_external as sco_ue_external
from app.scodoc import sco_cost_formation as sco_cost_formation
from app.scodoc import sco_formsemestre_validation as sco_formsemestre_validation
from app.scodoc import sco_parcours_dut as sco_parcours_dut
from app.scodoc import sco_codes_parcours as sco_codes_parcours
from app.scodoc import sco_pvjury as sco_pvjury
from app.scodoc import sco_pvpdf as sco_pvpdf
from app.scodoc import sco_prepajury as sco_prepajury
from app.scodoc import sco_inscr_passage as sco_inscr_passage
from app.scodoc import sco_synchro_etuds as sco_synchro_etuds
from app.scodoc import sco_archives as sco_archives
from app.scodoc import sco_apogee_csv as sco_apogee_csv
from app.scodoc import sco_etape_apogee_view as sco_etape_apogee_view
from app.scodoc import sco_apogee_compare as sco_apogee_compare
from app.scodoc import sco_semset as sco_semset
from app.scodoc import sco_export_results as sco_export_results
from app.scodoc import sco_formsemestre_exterieurs as sco_formsemestre_exterieurs
from app.scodoc.sco_pdf import PDFLOCK
from app.scodoc import notes_table as notes_table
from app.scodoc.notes_table import NOTES_CACHE_INST, CacheNotesTable
import app.scodoc.VERSION as VERSION
context = ScoDoc7Context(globals())
def sco_publish(route, function, permission):
@ -163,42 +162,8 @@ sco_publish("/essai2", essai2, Permission.ScoImplement)
# ---------------------
#
# Cache global: chaque instance, repérée par sa connexion db, a un cache
# qui est recréé à la demande
#
CACHE_formsemestre_inscription = {}
CACHE_evaluations = {}
# ---------------
def _getNotesCache(context):
"returns CacheNotesTable instance for us"
u = sco_mgr.get_db_uri() # identifie le dept de facon unique
if not NOTES_CACHE_INST.has_key(u):
log("getNotesCache: creating cache for %s" % u)
NOTES_CACHE_INST[u] = CacheNotesTable()
return NOTES_CACHE_INST[u]
def _inval_cache(
context, formsemestre_id=None, pdfonly=False, formsemestre_id_list=None
): # >
"expire cache pour un semestre (ou tous si pas d'argument)"
if formsemestre_id_list:
for formsemestre_id in formsemestre_id_list:
context._getNotesCache().inval_cache(
context, formsemestre_id=formsemestre_id, pdfonly=pdfonly
)
# Affecte aussi cache inscriptions
context.get_formsemestre_inscription_cache().inval_cache(
key=formsemestre_id
)
else:
context._getNotesCache().inval_cache(
context, formsemestre_id=formsemestre_id, pdfonly=pdfonly
)
# Affecte aussi cache inscriptions
context.get_formsemestre_inscription_cache().inval_cache(key=formsemestre_id)
@bp.route("/clearcache")
@ -210,7 +175,7 @@ def clearcache(context, REQUEST=None):
# Debugging code: compare results before and after cache reconstruction
# (_should_ be identicals !)
# Compare XML representation
cache = context._getNotesCache()
cache = sco_core.get_notes_cache(context)
formsemestre_ids = cache.get_cached_formsemestre_ids()
docs_before = []
for formsemestre_id in formsemestre_ids:
@ -405,10 +370,14 @@ sco_publish(
def index_html(context, REQUEST=None):
"Page accueil formations"
editable = REQUEST.AUTHENTICATED_USER.has_permission(ScoChangeFormation, context)
editable = REQUEST.AUTHENTICATED_USER.has_permission(
Permission.ScoChangeFormation, g.scodoc_dept
)
H = [
context.sco_header(REQUEST, page_title="Programmes formations"),
html_sco_header.sco_header(
context, REQUEST, page_title="Programmes formations"
),
"""<h2>Programmes pédagogiques</h2>
""",
]
@ -435,52 +404,14 @@ def index_html(context, REQUEST=None):
# --------------------------------------------------------------------
# --- Formations
_formationEditor = ndb.EditableTable(
"notes_formations",
"formation_id",
(
"formation_id",
"acronyme",
"titre",
"titre_officiel",
"version",
"formation_code",
"type_parcours",
"code_specialite",
),
sortkey="acronyme",
sco_publish(
"/do_formation_create",
sco_edit_formation.do_formation_create,
Permission.ScoChangeFormation,
)
@bp.route("/do_formation_create")
@permission_required(Permission.ScoChangeFormation)
@scodoc7func(context)
def do_formation_create(context, args, REQUEST):
"create a formation"
cnx = context.GetDBConnexion()
# check unique acronyme/titre/version
a = args.copy()
if a.has_key("formation_id"):
del a["formation_id"]
F = context.formation_list(args=a)
if len(F) > 0:
log("do_formation_create: error: %d formations matching args=%s" % (len(F), a))
raise ScoValueError("Formation non unique (%s) !" % str(a))
# Si pas de formation_code, l'enleve (default SQL)
if args.has_key("formation_code") and not args["formation_code"]:
del args["formation_code"]
#
r = context._formationEditor.create(cnx, args)
sco_news.add(
context,
REQUEST,
typ=NEWS_FORM,
text="Création de la formation %(titre)s (%(acronyme)s)" % args,
)
return r
@bp.route("/do_formation_delete")
@permission_required(Permission.ScoChangeFormation)
@scodoc7func(context)
@ -497,7 +428,7 @@ def do_formation_delete(context, oid, REQUEST):
for ue in ues:
context._do_ue_delete(ue["ue_id"], REQUEST=REQUEST, force=True)
context._formationEditor.delete(cnx, oid)
_formationEditor.delete(cnx, oid)
# news
sco_news.add(
@ -523,7 +454,7 @@ def formation_list(context, format=None, REQUEST=None, formation_id=None, args={
else:
args = {"formation_id": formation_id}
cnx = context.GetDBConnexion()
r = context._formationEditor.list(cnx, args=args)
r = _formationEditor.list(cnx, args=args)
# log('%d formations found' % len(r))
return scu.sendResult(REQUEST, r, name="formation", format=format)
@ -556,7 +487,9 @@ def formation_import_xml(context, file, REQUEST):
def formation_import_xml_form(context, REQUEST):
"form import d'une formation en XML"
H = [
context.sco_header(page_title="Import d'une formation", REQUEST=REQUEST),
html_sco_header.sco_header(
context, page_title="Import d'une formation", REQUEST=REQUEST
),
"""<h2>Import d'une formation</h2>
<p>Création d'une formation (avec UE, matières, modules)
à partir un fichier XML (réservé aux utilisateurs avertis)</p>
@ -677,7 +610,7 @@ def _do_ue_delete(context, ue_id, delete_validations=False, REQUEST=None, force=
if not ue:
raise ScoValueError("UE inexistante !")
ue = ue[0]
if context.ue_is_locked(ue["ue_id"]):
if sco_edit_ue.ue_is_locked(context, ue["ue_id"]):
raise ScoLockedFormError()
# Il y a-t-il des etudiants ayant validé cette UE ?
# si oui, propose de supprimer les validations
@ -718,7 +651,8 @@ def _do_ue_delete(context, ue_id, delete_validations=False, REQUEST=None, force=
)
cnx = context.GetDBConnexion()
context._ueEditor.delete(cnx, ue_id)
context._inval_cache() # > UE delete + supr. validations associées etudiants (cas compliqué, mais rarement utilisé: acceptable de tout invalider ?)
# > UE delete + supr. validations associées etudiants (cas compliqué, mais rarement utilisé: acceptable de tout invalider ?):
sco_core.inval_cache(context)
# news
F = context.formation_list(args={"formation_id": ue["formation_id"]})[0]
sco_news.add(
@ -788,7 +722,7 @@ def do_matiere_delete(context, oid, REQUEST):
# check
mat = context.do_matiere_list({"matiere_id": oid})[0]
ue = context.do_ue_list({"ue_id": mat["ue_id"]})[0]
locked = context.matiere_is_locked(mat["matiere_id"])
locked = sco_edit_matiere.matiere_is_locked(context, mat["matiere_id"])
if locked:
log("do_matiere_delete: mat=%s" % mat)
log("do_matiere_delete: ue=%s" % ue)
@ -829,11 +763,11 @@ def do_matiere_edit(context, *args, **kw):
cnx = context.GetDBConnexion()
# check
mat = context.do_matiere_list({"matiere_id": args[0]["matiere_id"]})[0]
if context.matiere_is_locked(mat["matiere_id"]):
if sco_edit_matiere.matiere_is_locked(context, mat["matiere_id"]):
raise ScoLockedFormError()
# edit
context._matiereEditor.edit(cnx, *args, **kw)
context._inval_cache() # > modif matiere
sco_core.inval_cache(context) # > modif matiere
@bp.route("/do_matiere_formation_id")
@ -913,7 +847,7 @@ def do_module_create(context, args, REQUEST):
def do_module_delete(context, oid, REQUEST):
"delete module"
mod = context.do_module_list({"module_id": oid})[0]
if context.module_is_locked(mod["module_id"]):
if sco_edit_module.module_is_locked(context, mod["module_id"]):
raise ScoLockedFormError()
# S'il y a des moduleimpls, on ne peut pas detruire le module !
@ -959,7 +893,7 @@ def do_module_edit(context, val):
"edit a module"
# check
mod = context.do_module_list({"module_id": val["module_id"]})[0]
if context.module_is_locked(mod["module_id"]):
if sco_edit_module.module_is_locked(context, mod["module_id"]):
# formation verrouillée: empeche de modifier certains champs:
protected_fields = ("coefficient", "ue_id", "matiere_id", "semestre_id")
for f in protected_fields:
@ -973,8 +907,8 @@ def do_module_edit(context, val):
context, args={"formation_id": mod["formation_id"]}
)
if sems:
context._inval_cache(
formsemestre_id_list=[s["formsemestre_id"] for s in sems]
sco_core.inval_cache(
context, formsemestre_id_list=[s["formsemestre_id"] for s in sems]
) # > modif module
@ -1001,68 +935,17 @@ def formation_count_sems(context, formation_id):
return len(sems)
@bp.route("/module_count_moduleimpls")
@permission_required(Permission.ScoView)
@scodoc7func(context)
def module_count_moduleimpls(context, module_id):
"Number of moduleimpls using this module"
mods = sco_moduleimpl.do_moduleimpl_list(context, module_id=module_id)
return len(mods)
sco_publish(
"/module_count_moduleimpls",
sco_edit_module.module_count_moduleimpls,
Permission.ScoView,
)
sco_publish("/module_is_locked", sco_edit_module.module_is_locked, Permission.ScoView)
@bp.route("/module_is_locked")
@permission_required(Permission.ScoView)
@scodoc7func(context)
def module_is_locked(context, module_id):
"""True if UE should not be modified
(used in a locked formsemestre)
"""
r = ndb.SimpleDictFetch(
context,
"""SELECT mi.* from notes_modules mod, notes_formsemestre sem, notes_moduleimpl mi
WHERE mi.module_id = mod.module_id AND mi.formsemestre_id = sem.formsemestre_id
AND mi.module_id = %(module_id)s AND sem.etat = 0
""",
{"module_id": module_id},
)
return len(r) > 0
@bp.route("/matiere_is_locked")
@permission_required(Permission.ScoView)
@scodoc7func(context)
def matiere_is_locked(context, matiere_id):
"""True if matiere should not be modified
(contains modules used in a locked formsemestre)
"""
r = ndb.SimpleDictFetch(
context,
"""SELECT ma.* from notes_matieres ma, notes_modules mod, notes_formsemestre sem, notes_moduleimpl mi
WHERE ma.matiere_id = mod.matiere_id AND mi.module_id = mod.module_id AND mi.formsemestre_id = sem.formsemestre_id
AND ma.matiere_id = %(matiere_id)s AND sem.etat = 0
""",
{"matiere_id": matiere_id},
)
return len(r) > 0
@bp.route("/ue_is_locked")
@permission_required(Permission.ScoView)
@scodoc7func(context)
def ue_is_locked(context, ue_id):
"""True if module should not be modified
(contains modules used in a locked formsemestre)
"""
r = ndb.SimpleDictFetch(
context,
"""SELECT ue.* FROM notes_ue ue, notes_modules mod, notes_formsemestre sem, notes_moduleimpl mi
WHERE ue.ue_id = mod.ue_id
AND mi.module_id = mod.module_id AND mi.formsemestre_id = sem.formsemestre_id
AND ue.ue_id = %(ue_id)s AND sem.etat = 0
""",
{"ue_id": ue_id},
)
return len(r) > 0
sco_publish(
"/matiere_is_locked", sco_edit_matiere.matiere_is_locked, Permission.ScoView
)
@bp.route("/module_move")
@ -1261,7 +1144,9 @@ def _check_access_diretud(
"""
authuser = REQUEST.AUTHENTICATED_USER
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
header = context.sco_header(page_title="Accès interdit", REQUEST=REQUEST)
header = html_sco_header.sco_header(
context, page_title="Accès interdit", REQUEST=REQUEST
)
footer = context.sco_footer(REQUEST)
if (str(authuser) not in sem["responsables"]) and not authuser.has_permission(
required_permission, context
@ -1299,32 +1184,6 @@ sco_publish(
Permission.ScoView,
)
@bp.route("/html_sem_header")
@permission_required(Permission.ScoView)
@scodoc7func(context)
def html_sem_header(
context,
REQUEST,
title,
sem=None,
with_page_header=True,
with_h2=True,
page_title=None,
**args
):
"Titre d'une page semestre avec lien vers tableau de bord"
# sem now unused and thus optional...
if with_page_header:
h = context.sco_header(REQUEST, page_title="%s" % (page_title or title), **args)
else:
h = ""
if with_h2:
return h + """<h2 class="formsemestre">%s</h2>""" % (title)
else:
return h
# --- dialogue modif enseignants/moduleimpl
@bp.route("/edit_enseignants_form")
@permission_required(Permission.ScoView)
@ -1333,7 +1192,8 @@ def edit_enseignants_form(context, REQUEST, moduleimpl_id):
"modif liste enseignants/moduleimpl"
M, sem = sco_moduleimpl.can_change_ens(context, REQUEST, moduleimpl_id)
# --
header = context.html_sem_header(
header = html_sco_header.html_sem_header(
context,
REQUEST,
'Enseignants du <a href="moduleimpl_status?moduleimpl_id=%s">module %s</a>'
% (moduleimpl_id, M["module"]["titre"]),
@ -1443,7 +1303,8 @@ def edit_moduleimpl_resp(context, REQUEST, moduleimpl_id):
"""
M, sem = sco_moduleimpl.can_change_module_resp(context, REQUEST, moduleimpl_id)
H = [
context.html_sem_header(
html_sco_header.html_sem_header(
context,
REQUEST,
'Modification du responsable du <a href="moduleimpl_status?moduleimpl_id=%s">module %s</a>'
% (moduleimpl_id, M["module"]["titre"]),
@ -1552,7 +1413,8 @@ def edit_moduleimpl_expr(context, REQUEST, moduleimpl_id):
"""
M, sem = sco_moduleimpl.can_change_ens(context, REQUEST, moduleimpl_id)
H = [
context.html_sem_header(
html_sco_header.html_sem_header(
context,
REQUEST,
'Modification règle de calcul du <a href="moduleimpl_status?moduleimpl_id=%s">module %s</a>'
% (moduleimpl_id, M["module"]["titre"]),
@ -1602,8 +1464,8 @@ def edit_moduleimpl_expr(context, REQUEST, moduleimpl_id):
},
formsemestre_id=sem["formsemestre_id"],
)
context._inval_cache(
formsemestre_id=sem["formsemestre_id"]
sco_core.inval_cache(
context, formsemestre_id=sem["formsemestre_id"]
) # > modif regle calcul
return REQUEST.RESPONSE.redirect(
"moduleimpl_status?moduleimpl_id="
@ -1649,7 +1511,8 @@ def view_module_abs(context, REQUEST, moduleimpl_id, format="html"):
)
H = [
context.html_sem_header(
html_sco_header.html_sem_header(
context,
REQUEST,
'Absences du <a href="moduleimpl_status?moduleimpl_id=%s">module %s</a>'
% (moduleimpl_id, M["module"]["titre"]),
@ -1677,7 +1540,9 @@ def view_module_abs(context, REQUEST, moduleimpl_id, format="html"):
base_url="%s?moduleimpl_id=%s" % (REQUEST.URL0, moduleimpl_id),
filename="absmodule_" + scu.make_filename(M["module"]["titre"]),
caption="Absences dans le module %s" % M["module"]["titre"],
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
if format != "html":
@ -1699,7 +1564,8 @@ def edit_ue_expr(context, REQUEST, formsemestre_id, ue_id):
#
ue = context.do_ue_list({"ue_id": ue_id})[0]
H = [
context.html_sem_header(
html_sco_header.html_sem_header(
context,
REQUEST,
"Modification règle de calcul de l'UE %s (%s)"
% (ue["acronyme"], ue["titre"]),
@ -1749,7 +1615,9 @@ def edit_ue_expr(context, REQUEST, formsemestre_id, ue_id):
else:
sco_compute_moy.formsemestre_ue_computation_expr_create(cnx, tf[2])
context._inval_cache(formsemestre_id=formsemestre_id) # > modif regle calcul
sco_core.inval_cache(
context, formsemestre_id=formsemestre_id
) # > modif regle calcul
return REQUEST.RESPONSE.redirect(
"formsemestre_status?formsemestre_id="
+ formsemestre_id
@ -1829,12 +1697,12 @@ def formsemestre_enseignants_list(context, REQUEST, formsemestre_id, format="htm
html_sortable=True,
html_class="table_leftalign",
filename=scu.make_filename("Enseignants-" + sem["titreannee"]),
html_title=context.html_sem_header(
REQUEST, "Enseignants du semestre", sem, with_page_header=False
html_title=html_sco_header.html_sem_header(
context, REQUEST, "Enseignants du semestre", sem, with_page_header=False
),
base_url="%s?formsemestre_id=%s" % (REQUEST.URL0, formsemestre_id),
caption="Tous les enseignants (responsables ou associés aux modules de ce semestre) apparaissent. Le nombre de saisies d'absences est le nombre d'opérations d'ajout effectuées sur ce semestre, sans tenir compte des annulations ou double saisies.",
preferences=context.get_preferences(formsemestre_id),
preferences=sco_preferences.SemPreferences(context, formsemestre_id),
)
return T.make_page(
context, page_title=title, title=title, REQUEST=REQUEST, format=format
@ -1908,8 +1776,8 @@ def do_formsemestre_inscription_create(context, args, REQUEST, method=None):
commit=False,
)
#
context._inval_cache(
formsemestre_id=args["formsemestre_id"]
sco_core.inval_cache(
context, formsemestre_id=args["formsemestre_id"]
) # > inscription au semestre
return r
@ -1922,8 +1790,8 @@ def do_formsemestre_inscription_delete(context, oid, formsemestre_id=None):
cnx = context.GetDBConnexion()
context._formsemestre_inscriptionEditor.delete(cnx, oid)
context._inval_cache(
formsemestre_id=formsemestre_id
sco_core.inval_cache(
context, formsemestre_id=formsemestre_id
) # > desinscription du semestre
@ -1943,7 +1811,7 @@ 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 = context.get_formsemestre_inscription_cache()
cache = sco_core.get_formsemestre_inscription_cache(context, )
r = cache.get(formsemestre_id)
if r is None:
# retreive list
@ -1961,8 +1829,8 @@ def do_formsemestre_inscription_edit(context, args=None, formsemestre_id=None):
"edit a formsemestre_inscription"
cnx = context.GetDBConnexion()
context._formsemestre_inscriptionEditor.edit(cnx, args)
context._inval_cache(
formsemestre_id=formsemestre_id
sco_core.inval_cache(
context, formsemestre_id=formsemestre_id
) # > modif inscription semestre (demission ?)
@ -1994,7 +1862,7 @@ def formsemestre_desinscription(
raise ScoValueError("desinscription impossible: semestre verrouille")
# -- Si décisions de jury, désinscription interdite
nt = context._getNotesCache().get_NotesTable(context, formsemestre_id)
nt = sco_core.get_notes_cache(context).get_NotesTable(context, formsemestre_id)
if nt.etud_has_decision(etudid):
raise ScoValueError(
"""Désinscription impossible: l'étudiant a une décision de jury
@ -2049,7 +1917,7 @@ def formsemestre_desinscription(
context.do_formsemestre_desinscription(etudid, formsemestre_id, REQUEST=REQUEST)
return (
context.sco_header(REQUEST)
html_sco_header.sco_header(context, REQUEST)
+ '<p>Etudiant désinscrit !</p><p><a class="stdlink" href="%s/ficheEtud?etudid=%s">retour à la fiche</a>'
% (context.ScoURL(), etudid)
+ context.sco_footer(REQUEST)
@ -2069,7 +1937,7 @@ def do_formsemestre_desinscription(context, etudid, formsemestre_id, REQUEST=Non
raise ScoValueError("desinscription impossible: semestre verrouille")
# -- Si decisions de jury, desinscription interdite
nt = context._getNotesCache().get_NotesTable(context, formsemestre_id)
nt = sco_core.get_notes_cache(context).get_NotesTable(context, formsemestre_id)
if nt.etud_has_decision(etudid):
raise ScoValueError(
"desinscription impossible: l'étudiant a une décision de jury (la supprimer avant si nécessaire)"
@ -2247,7 +2115,7 @@ def _evaluation_check_write_access(context, REQUEST, moduleimpl_id=None):
sem = sco_formsemestre.get_formsemestre(context, M["formsemestre_id"])
if (
(not authuser.has_permission(ScoEditAllEvals, context))
(not authuser.has_permission(Permission.ScoEditAllEvals, context))
and uid != M["responsable_id"]
and uid not in sem["responsables"]
):
@ -2409,7 +2277,7 @@ def evaluation_delete(context, REQUEST, evaluation_id):
tit = "Suppression de l'évaluation %(description)s (%(jour)s)" % E
etat = sco_evaluations.do_evaluation_etat(context, evaluation_id)
H = [
context.html_sem_header(REQUEST, tit, with_h2=False),
html_sco_header.html_sem_header(context, REQUEST, tit, with_h2=False),
"""<h2 class="formsemestre">Module <tt>%(code)s</tt> %(titre)s</h2>""" % Mod,
"""<h3>%s</h3>""" % tit,
"""<p class="help">Opération <span class="redboldtext">irréversible</span>. Si vous supprimez l'évaluation, vous ne pourrez pas retrouver les notes associées.</p>""",
@ -2553,8 +2421,8 @@ def do_evaluation_edit(context, REQUEST, args):
context._evaluationEditor.edit(cnx, args)
# inval cache pour ce semestre
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0]
context._inval_cache(
formsemestre_id=M["formsemestre_id"]
sco_core.inval_cache(
context, formsemestre_id=M["formsemestre_id"]
) # > evaluation_edit (coef, ...)
@ -2584,7 +2452,8 @@ def evaluation_create(context, moduleimpl_id, REQUEST):
def evaluation_listenotes(context, REQUEST=None):
"""Affichage des notes d'une évaluation"""
if REQUEST.form.get("format", "html") == "html":
H = context.sco_header(
H = html_sco_header.sco_header(
context,
REQUEST,
cssstyles=["css/verticalhisto.css"],
javascripts=["js/etud_info.js"],
@ -2651,17 +2520,6 @@ sco_publish(
)
# cache notes evaluations
def get_evaluations_cache(context):
u = context.GetDBConnexionString()
if CACHE_evaluations.has_key(u):
return CACHE_evaluations[u]
else:
log("get_evaluations_cache: new simpleCache")
CACHE_evaluations[u] = sco_cache.simpleCache()
return CACHE_evaluations[u]
def _notes_getall(
context, evaluation_id, table="notes_notes", filter_suppressed=True, by_uid=None
):
@ -2673,7 +2531,7 @@ def _notes_getall(
filter_suppressed and table == "notes_notes" and (by_uid is None)
) # pas de cache pour (rares) appels via undo_notes ou specifiant un enseignant
if do_cache:
cache = context.get_evaluations_cache()
cache = sco_core.get_evaluations_cache(context)
r = cache.get(evaluation_id)
if r != None:
return r
@ -2751,7 +2609,7 @@ def formsemestre_bulletins_mailetuds(
):
"envoi a chaque etudiant (inscrit et ayant un mail) son bulletin"
prefer_mail_perso = int(prefer_mail_perso)
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etudids
etudids = nt.get_etudids()
@ -2790,7 +2648,7 @@ def formsemestre_bulletins_mailetuds(
nb_send += 1
#
return (
context.sco_header(REQUEST)
html_sco_header.sco_header(context, REQUEST)
+ '<p>%d bulletins sur %d envoyés par mail !</p><p><a class="stdlink" href="formsemestre_status?formsemestre_id=%s">continuer</a></p>'
% (nb_send, len(etudids), formsemestre_id)
+ context.sco_footer(REQUEST)
@ -2834,7 +2692,7 @@ def appreciation_add_form(
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
# check custom access permission
can_edit_app = (str(authuser) in sem["responsables"]) or (
authuser.has_permission(ScoEtudInscrit, context)
authuser.has_permission(Permission.ScoEtudInscrit, context)
)
if not can_edit_app:
raise AccessDenied("vous n'avez pas le droit d'ajouter une appreciation")
@ -2854,7 +2712,7 @@ def appreciation_add_form(
else:
a = "Ajout"
H = [
context.sco_header(REQUEST)
html_sco_header.sco_header(context, REQUEST)
+ "<h2>%s d'une appréciation sur %s</h2>" % (a, etud["nomprenom"])
]
F = context.sco_footer(REQUEST)
@ -2908,8 +2766,8 @@ def appreciation_add_form(
msg=tf[2]["comment"],
)
# ennuyeux mais necessaire (pour le PDF seulement)
context._inval_cache(
pdfonly=True, formsemestre_id=formsemestre_id
sco_core.inval_cache(
context, pdfonly=True, formsemestre_id=formsemestre_id
) # > appreciation_add
return REQUEST.RESPONSE.redirect(bull_url)
@ -2923,7 +2781,7 @@ def _can_edit_pv(context, REQUEST, formsemestre_id):
# Autorise les secrétariats, repérés via la permission ScoEtudChangeAdr
# (ceci nous évite d'ajouter une permission Zope aux installations existantes)
authuser = REQUEST.AUTHENTICATED_USER
return authuser.has_permission(ScoEtudChangeAdr, context)
return authuser.has_permission(Permission.ScoEtudChangeAdr, context)
# --- FORMULAIRE POUR VALIDATION DES UE ET SEMESTRES
@ -2939,7 +2797,7 @@ def _can_validate_sem(context, REQUEST, formsemestre_id):
def _is_chef_or_diretud(context, REQUEST, sem):
"Vrai si utilisateur est admin, chef dept ou responsable du semestre"
authuser = REQUEST.AUTHENTICATED_USER
if authuser.has_permission(ScoImplement, context):
if authuser.has_permission(Permission.ScoImplement, context):
return True # admin, chef dept
uid = str(authuser)
if uid in sem["responsables"]:
@ -3195,7 +3053,7 @@ def formsemestre_validation_suppress_etud(
if not dialog_confirmed:
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
etud = context.getEtudInfo(etudid=etudid, filled=1)[0]
nt = context._getNotesCache().get_NotesTable(
nt = sco_core.get_notes_cache(context).get_NotesTable(
context, formsemestre_id
) # > get_etud_decision_sem
decision_jury = nt.get_etud_decision_sem(etudid)
@ -3414,7 +3272,7 @@ def check_sem_integrity(context, formsemestre_id, REQUEST):
modimpl["mod"] = mod
return (
context.sco_header(REQUEST=REQUEST)
html_sco_header.sco_header(context, REQUEST=REQUEST)
+ "<p>formation_id=%s" % sem["formation_id"]
+ "<h2>Inconsistent UE/MOD:</h2>"
+ "<br/>".join([str(x) for x in bad_ue])
@ -3458,7 +3316,11 @@ def check_form_integrity(context, formation_id, fix=False, REQUEST=None):
else:
txth = "OK"
log("ok")
return context.sco_header(REQUEST=REQUEST) + txth + context.sco_footer(REQUEST)
return (
html_sco_header.sco_header(context, REQUEST=REQUEST)
+ txth
+ context.sco_footer(REQUEST)
)
@bp.route("/check_formsemestre_integrity")
@ -3507,7 +3369,7 @@ def check_formsemestre_integrity(context, formsemestre_id, REQUEST=None):
diag = ["OK"]
log("ok")
return (
context.sco_header(REQUEST=REQUEST)
html_sco_header.sco_header(context, REQUEST=REQUEST)
+ "<br/>".join(diag)
+ context.sco_footer(REQUEST)
)
@ -3525,7 +3387,7 @@ def check_integrity_all(context, REQUEST=None):
for sem in sco_formsemestre.do_formsemestre_list(context):
context.check_formsemestre_integrity(sem["formsemestre_id"], REQUEST=REQUEST)
return (
context.sco_header(REQUEST=REQUEST)
html_sco_header.sco_header(context, REQUEST=REQUEST)
+ "<p>empty page: see logs and mails</p>"
+ context.sco_footer(REQUEST)
)

View File

@ -88,7 +88,6 @@ from app.scodoc.sco_permissions import (
ScoEditApo,
ScoSuperAdmin,
)
import app.scodoc.sco_permissions
from app.scodoc.sco_exceptions import (
AccessDenied,
ScoException,
@ -99,10 +98,9 @@ from app.scodoc.sco_exceptions import (
ScoInvalidDept,
)
from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
import app.scodoc.scolars
import app.scodoc.sco_codes_parcours
import app.scodoc.sco_preferences
import app.scodoc.sco_formations
from app.scodoc.sco_news import NEWS_INSCR, NEWS_NOTE, NEWS_FORM, NEWS_SEM, NEWS_MISC
from app.scodoc.VERSION import SCOVERSION, SCONEWS
from app.scodoc.scolars import (
format_nom,
format_prenom,
@ -111,40 +109,50 @@ from app.scodoc.scolars import (
format_lycee_from_code,
)
from app.scodoc.scolars import format_telephone, format_pays, make_etud_args
import app.scodoc.sco_find_etud
import app.scodoc.sco_photos
import app.scodoc.sco_formsemestre
import app.scodoc.sco_formsemestre_edit
import app.scodoc.sco_news
from app.scodoc.sco_news import NEWS_INSCR, NEWS_NOTE, NEWS_FORM, NEWS_SEM, NEWS_MISC
import app.scodoc.html_sco_header
import app.scodoc.html_sidebar
from app.scodoc.gen_tables import GenTable
import app.scodoc.sco_excel
import app.scodoc.imageresize
import app.scodoc.ImportScolars
import app.scodoc.sco_abs
import app.scodoc.sco_portal_apogee
import app.scodoc.sco_synchro_etuds
import app.scodoc.sco_page_etud
import app.scodoc.sco_groups
import app.scodoc.sco_trombino
import app.scodoc.sco_groups_view
import app.scodoc.sco_trombino_tours
import app.scodoc.sco_parcours_dut
import app.scodoc.sco_report
import app.scodoc.sco_archives_etud
import app.scodoc.sco_debouche
import app.scodoc.sco_groups_edit
import app.scodoc.sco_up_to_date
import app.scodoc.sco_edt_cal
import app.scodoc.sco_dept
import app.scodoc.sco_dump_db
from app.scodoc import scolars
from app.scodoc import sco_codes_parcours
from app.scodoc import sco_preferences
from app.scodoc import sco_formations
from app.scodoc import sco_permissions
from app.scodoc import sco_find_etud
from app.scodoc import sco_photos
from app.scodoc import sco_formsemestre
from app.scodoc import sco_formsemestre_edit
from app.scodoc import sco_news
from app.scodoc import html_sco_header
from app.scodoc import html_sidebar
from app.scodoc import sco_excel
from app.scodoc import imageresize
from app.scodoc import ImportScolars
from app.scodoc import sco_abs
from app.scodoc import sco_portal_apogee
from app.scodoc import sco_synchro_etuds
from app.scodoc import sco_page_etud
from app.scodoc import sco_groups
from app.scodoc import sco_trombino
from app.scodoc import sco_groups_view
from app.scodoc import sco_trombino_tours
from app.scodoc import sco_parcours_dut
from app.scodoc import sco_report
from app.scodoc import sco_archives_etud
from app.scodoc import sco_debouche
from app.scodoc import sco_groups_edit
from app.scodoc import sco_up_to_date
from app.scodoc import sco_edt_cal
from app.scodoc import sco_dept
from app.scodoc import sco_dump_db
from app.scodoc.VERSION import SCOVERSION, SCONEWS
context = ScoDoc7Context(globals())
def sco_publish(route, function, permission):
"""Declare a route for a python function,
protected by permission and called following ScoDoc 7 Zope standards.
"""
bp.route(route)(permission_required(permission)(scodoc7func(context)(function)))
log.set_log_directory(Config.INSTANCE_HOME + "/log")
@ -156,22 +164,12 @@ log("ScoDoc8 restarting...")
#
# --------------------------------------------------------------------
# ? à déplacer ?
def DeptId():
if g.scodoc_dept in sco_mgr.get_dept_ids():
return g.scodoc_dept
raise ScoInvalidDept("département invalide: %s" % g.scodoc_dept)
# sco_publish(
# "/formsemestre_evaluations_delai_correction",
# sco_evaluations.formsemestre_evaluations_delai_correction,
# Permission.ScoView,
# )
sco_publish("/sco_header", html_sco_header.sco_header, Permission.ScoView)
sco_publish("/sco_footer", html_sco_header.sco_footer, Permission.ScoView)
@bp.route("/about")
@permission_required(Permission.ScoView)
@ -195,7 +193,12 @@ def about(context, REQUEST):
+ " <em>Au pays des aveugles...</em></div>"
)
d = ""
return context.sco_header(REQUEST) + "\n".join(H) + d + context.sco_footer(REQUEST)
return (
html_sco_header.sco_header(context, REQUEST)
+ "\n".join(H)
+ d
+ context.sco_footer(REQUEST)
)
# --------------------------------------------------------------------
@ -221,13 +224,13 @@ def formsemestre_edit_preferences(context, formsemestre_id, REQUEST):
authuser = REQUEST.AUTHENTICATED_USER
sem = sco_formsemestre.get_formsemestre(context.Notes, formsemestre_id)
ok = (
authuser.has_permission(ScoImplement, context)
authuser.has_permission(Permission.ScoImplement, context)
or ((str(authuser) in sem["responsables"]) and sem["resp_can_edit"])
) and (sem["etat"] == "1")
if ok:
return context.get_preferences(formsemestre_id=formsemestre_id).edit(
REQUEST=REQUEST
)
return sco_preferences.SemPreferences(
context, formsemestre_id=formsemestre_id
).edit(REQUEST=REQUEST)
else:
raise AccessDenied("Modification impossible pour %s" % authuser)
@ -247,10 +250,6 @@ def doc_preferences(context, REQUEST):
#
# --------------------------------------------------------------------
# ----------------- BANDEAUX -------------------
sco_publish("/sidebar", html_sidebar.sidebar, Permission.ScoView)
sco_publish("/sidebar_dept", html_sidebar.sidebar_dept, Permission.ScoView)
@bp.route("/showEtudLog")
@permission_required(Permission.ScoView)
@ -279,7 +278,9 @@ def showEtudLog(context, etudid, format="html", REQUEST=None):
filename="log_" + scu.make_filename(etud["nomprenom"]),
html_next_section='<ul><li><a href="ficheEtud?etudid=%(etudid)s">fiche de %(nomprenom)s</a></li></ul>'
% etud,
preferences=context.get_preferences(),
preferences=sco_preferences.SemPreferences(
context,
),
)
return tab.make_page(context, format=format, REQUEST=REQUEST)
@ -296,7 +297,9 @@ def rssnews(context, REQUEST=None):
"rss feed"
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
return sco_news.scolar_news_summary_rss(
context, "Nouvelles de " + context.get_preference("DeptName"), context.ScoURL()
context,
"Nouvelles de " + sco_preferences.get_preference(context, "DeptName"),
context.ScoURL(),
)
@ -361,7 +364,8 @@ sco_publish(
# XMLgetEtudInfos était le nom dans l'ancienne API ScoDoc 6
@bp.route("/etud_info", "/XMLgetEtudInfos")
@bp.route("/etud_info")
@bp.route("/XMLgetEtudInfos")
@permission_required(Permission.ScoView)
@scodoc7func(context)
def etud_info(context, etudid=None, format="xml", REQUEST=None):
@ -494,7 +498,7 @@ sco_publish(
# vrai si l'utilisateur peut modifier les informations de suivi sur la page etud"
def can_edit_suivi(context, REQUEST=None):
authuser = REQUEST.AUTHENTICATED_USER
return authuser.has_permission(ScoEtudChangeAdr, context)
return authuser.has_permission(Permission.ScoEtudChangeAdr, context)
sco_publish(
@ -561,8 +565,8 @@ def canSuppressAnnotation(context, annotation_id, REQUEST):
# c'est pourquoi on teste aussi ScoEtudInscrit (normalement détenue par le chef)
return (
(str(authuser) == anno["zope_authenticated_user"])
or authuser.has_permission(ScoEtudSupprAnnotations, context)
or authuser.has_permission(ScoEtudInscrit, context)
or authuser.has_permission(Permission.ScoEtudSupprAnnotations, context)
or authuser.has_permission(Permission.ScoEtudInscrit, context)
)
@ -604,8 +608,8 @@ def formChangeCoordonnees(context, etudid, REQUEST):
'<h2><font color="#FF0000">Changement des coordonnées de </font> %(nomprenom)s</h2><p>'
% etud
]
header = context.sco_header(
REQUEST, page_title="Changement adresse de %(nomprenom)s" % etud
header = html_sco_header.sco_header(
context, REQUEST, page_title="Changement adresse de %(nomprenom)s" % etud
)
tf = TrivialFormulator(
@ -714,7 +718,7 @@ def etud_photo_orig_page(context, etudid=None, REQUEST=None):
"Page with photo in orig. size"
etud = context.getEtudInfo(etudid=etudid, filled=1, REQUEST=REQUEST)[0]
H = [
context.sco_header(REQUEST, page_title=etud["nomprenom"]),
html_sco_header.sco_header(context, REQUEST, page_title=etud["nomprenom"]),
"<h2>%s</h2>" % etud["nomprenom"],
'<div><a href="ficheEtud?etudid=%s">' % etudid,
sco_photos.etud_photo_orig_html(context, etud),
@ -735,7 +739,7 @@ def formChangePhoto(context, etudid=None, REQUEST=None):
else:
etud["photoloc"] = "externe"
H = [
context.sco_header(REQUEST, page_title="Changement de photo"),
html_sco_header.sco_header(context, REQUEST, page_title="Changement de photo"),
"""<h2>Changement de la photo de %(nomprenom)s</h2>
<p>Photo actuelle (%(photoloc)s):
"""
@ -852,7 +856,8 @@ def _formDem_of_Def(
etud["nowdmy"] = time.strftime("%d/%m/%Y")
etud["operation_name"] = operation_name
#
header = context.sco_header(
header = html_sco_header.sco_header(
context,
REQUEST,
page_title="%(operation_name)s de %(nomprenom)s (du semestre %(semtitre)s)"
% etud,
@ -1075,7 +1080,7 @@ def etudident_edit_form(context, REQUEST=None):
def _etudident_create_or_edit_form(context, REQUEST, edit):
"Le formulaire HTML"
H = [context.sco_header(REQUEST, init_jquery_ui=True)]
H = [html_sco_header.sco_header(context, REQUEST, init_jquery_ui=True)]
F = context.sco_footer(REQUEST)
etudid = REQUEST.form.get("etudid", None)
cnx = context.GetDBConnexion()
@ -1173,7 +1178,7 @@ def _etudident_create_or_edit_form(context, REQUEST, edit):
else:
A = """<div class="infoapogee"><p>Pas d'informations d'Apogée</p></div>"""
require_ine = context.get_preference("always_require_ine")
require_ine = sco_preferences.get_preference(context, "always_require_ine")
descr += [
("adm_id", {"input_type": "hidden"}),
@ -1692,7 +1697,7 @@ def form_students_import_excel(context, REQUEST, formsemestre_id=None):
if sem and sem["etat"] != "1":
raise ScoValueError("Modification impossible: semestre verrouille")
H = [
context.sco_header(REQUEST, page_title="Import etudiants"),
html_sco_header.sco_header(context, REQUEST, page_title="Import etudiants"),
"""<h2 class="formsemestre">Téléchargement d\'une nouvelle liste d\'etudiants</h2>
<div style="color: red">
<p>A utiliser pour importer de <b>nouveaux</b> étudiants (typiquement au
@ -1861,10 +1866,11 @@ def form_students_import_infos_admissions(context, REQUEST, formsemestre_id=None
"formulaire import xls"
authuser = REQUEST.AUTHENTICATED_USER
F = context.sco_footer(REQUEST)
if not authuser.has_permission(ScoEtudInscrit, context):
if not authuser.has_permission(Permission.ScoEtudInscrit, context):
# autorise juste l'export
H = [
context.sco_header(
html_sco_header.sco_header(
context,
REQUEST,
page_title="Export données admissions (Parcoursup ou autre)",
),
@ -1880,7 +1886,9 @@ def form_students_import_infos_admissions(context, REQUEST, formsemestre_id=None
# On a le droit d'importer:
H = [
context.sco_header(REQUEST, page_title="Import données admissions Parcoursup"),
html_sco_header.sco_header(
context, REQUEST, page_title="Import données admissions Parcoursup"
),
"""<h2 class="formsemestre">Téléchargement des informations sur l'admission des étudiants depuis feuilles import Parcoursup</h2>
<div style="color: red">
<p>A utiliser pour renseigner les informations sur l'origine des étudiants (lycées, bac, etc). Ces informations sont facultatives mais souvent utiles pour mieux connaitre les étudiants et aussi pour effectuer des statistiques (résultats suivant le type de bac...). Les données sont affichées sur les fiches individuelles des étudiants.</p>
@ -1972,7 +1980,11 @@ def _students_import_admission(
type_admission=type_admission,
)
if REQUEST:
H = [context.sco_header(REQUEST, page_title="Import données admissions")]
H = [
html_sco_header.sco_header(
context, REQUEST, page_title="Import données admissions"
)
]
H.append("<p>Import terminé !</p>")
H.append(
'<p><a class="stdlink" href="%s">Continuer</a></p>'

View File

@ -1,8 +1,18 @@
#!/usr/bin/env python
# -*- coding: UTF-8 -*
"""Outil pour migration ScoDoc 7 => ScoDoc 8
- Liste des appels de la forme context.xxx
./refactor.py showcontextcalls app/scodoc/*.p
- remplace context.xxx par module.xxx
./refactor.py refactor method module app/scodoc/*.py
Pour chaque module dans views:
- construire la liste des fonctions définies dans ce module:
get_module_functions
@ -16,21 +26,21 @@ Pour chaque module dans views et dans scodoc:
from __future__ import print_function
import re
from pprint import pprint as pp
import os
import sys
import types
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
# import flask
from config import Config
# import app
# from app import create_app, cli, db
# from app.auth.models import User, Role, UserRole
from app.views import notes
# from app.views import notes
TYPES_TO_SCAN = {
types.FunctionType,
@ -61,6 +71,8 @@ def scan_views_symbols():
"""Scan modules in app.views and returns
{ }
"""
import app
views_modules = [
getattr(app.views, mod_name)
for mod_name in dir(app.views)
@ -102,6 +114,83 @@ def replace_context_calls(sourcefilename, sym2mod):
return source2, undefined_list
sym2mod = scan_views_symbols()
# sym2mod = scan_views_symbols()
source2, undefined_list = replace_context_calls("app/scodoc/sco_core.py", sym2mod)
# source2, undefined_list = replace_context_calls("app/scodoc/sco_core.py", sym2mod)
def list_context_calls(sourcefilename):
"""List of methods called on context in this file"""
source = open(sourcefilename).read()
exp = re.compile(r"context\.([a-zA-Z0-9_]+)")
return sorted(set(exp.findall(source)))
def get_context_calls(src_filenames):
"""returns { method_name : [ list of module names in which it is called ] }"""
S = {}
for sourcefilename in src_filenames:
l = list_context_calls(sourcefilename)
module_name = os.path.splitext(os.path.split(sourcefilename)[1])[0]
for m in l:
if m in S:
S[m].append(module_name)
else:
S[m] = [module_name]
return S
@click.group()
def cli():
pass
@cli.command()
@click.argument("src_filenames", nargs=-1)
def showcontextcalls(src_filenames):
click.echo("Appels de méthodes sur l'object context")
S = get_context_calls(src_filenames)
#
for method in sorted(S.keys()):
print(method + ":\t" + ", ".join(S[method]))
@cli.command()
@click.argument("modulemethod", nargs=1)
@click.argument("src_filenames", nargs=-1)
def refactor(modulemethod, src_filenames):
"""Replace call context.method(...)
by module.method(context, ...)
in all given source filenames
"""
modulemethod = str(modulemethod) # avoid unicode in Python2
frags = modulemethod.split(".")
if len(frags) < 2:
raise click.BadParameter("must be module.method", param_hint="modulemethod")
module = ".".join(frags[:-1])
method = frags[-1]
backup = tempfile.mkdtemp(dir="/tmp")
for sourcefilename in src_filenames:
source_module_name = os.path.splitext(os.path.split(sourcefilename)[1])[0]
is_local = source_module_name == module
source = open(sourcefilename).read()
if not is_local:
source2 = source.replace(
"context." + method + "(", module + "." + method + "(context, "
)
else:
# call in the same module:
source2 = source.replace("context." + method + "(", method + "(context, ")
if source2 != source:
print("changed %s" % sourcefilename)
shutil.move(sourcefilename, backup)
open(sourcefilename, "w").write(source2)
print("Done.\noriginal files saved in %s\n" % backup)
if __name__ == "__main__":
try:
cli(obj={})
except SystemExit as e:
if e.code != 0:
raise

View File

@ -25,7 +25,9 @@ for sem in sems:
formsemestre_id = sem["formsemestre_id"]
nt = context.Notes._getNotesCache().get_NotesTable(context.Notes, formsemestre_id)
etudids = nt.get_etudids()
use_ue_coef = context.get_preference("use_ue_coefs", formsemestre_id)
use_ue_coef = sco_preferences.get_preference(
context, "use_ue_coefs", formsemestre_id
)
n += 1
print("%d %s (%d) use_ue_coef=%s" % (n, formsemestre_id, len(etudids), use_ue_coef))
for etudid in etudids: