forked from ScoDoc/ScoDoc
Merge ScoDoc 7.23
Merge branch 'master' of https://scodoc.org/git/viennet/ScoDoc into ScoDoc8
This commit is contained in:
commit
dc4bfe4d2e
@ -28,10 +28,16 @@
|
|||||||
""" Importation des etudiants à partir de fichiers CSV
|
""" Importation des etudiants à partir de fichiers CSV
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os, sys, time, pdb
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import pdb
|
||||||
|
import collections
|
||||||
|
import types
|
||||||
|
import re
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import scolars
|
import scolars
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
@ -42,6 +48,15 @@ import sco_news
|
|||||||
from sco_news import NEWS_INSCR, NEWS_NOTE, NEWS_FORM, NEWS_SEM, NEWS_MISC
|
from sco_news import NEWS_INSCR, NEWS_NOTE, NEWS_FORM, NEWS_SEM, NEWS_MISC
|
||||||
from sco_formsemestre_inscriptions import do_formsemestre_inscription_with_modules
|
from sco_formsemestre_inscriptions import do_formsemestre_inscription_with_modules
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
|
from sco_exceptions import (
|
||||||
|
AccessDenied,
|
||||||
|
FormatError,
|
||||||
|
ScoException,
|
||||||
|
ScoValueError,
|
||||||
|
ScoInvalidDateError,
|
||||||
|
ScoLockedFormError,
|
||||||
|
ScoGenError,
|
||||||
|
)
|
||||||
|
|
||||||
# format description (relative to Product directory))
|
# format description (relative to Product directory))
|
||||||
FORMAT_FILE = "misc/format_import_etudiants.txt"
|
FORMAT_FILE = "misc/format_import_etudiants.txt"
|
||||||
@ -93,7 +108,7 @@ ADMISSION_MODIFIABLE_FIELDS = (
|
|||||||
def sco_import_format(with_codesemestre=True):
|
def sco_import_format(with_codesemestre=True):
|
||||||
"returns tuples (Attribut, Type, Table, AllowNulls, Description)"
|
"returns tuples (Attribut, Type, Table, AllowNulls, Description)"
|
||||||
r = []
|
r = []
|
||||||
for l in open(SCO_SRC_DIR + "/" + FORMAT_FILE):
|
for l in open(scu.SCO_SRC_DIR + "/" + FORMAT_FILE):
|
||||||
l = l.strip()
|
l = l.strip()
|
||||||
if l and l[0] != "#":
|
if l and l[0] != "#":
|
||||||
fs = l.split(";")
|
fs = l.split(";")
|
||||||
@ -152,10 +167,10 @@ def sco_import_generate_excel_sample(
|
|||||||
titles = []
|
titles = []
|
||||||
titlesStyles = []
|
titlesStyles = []
|
||||||
for l in fmt:
|
for l in fmt:
|
||||||
name = strlower(l[0])
|
name = scu.strlower(l[0])
|
||||||
if (not with_codesemestre) and name == "codesemestre":
|
if (not with_codesemestre) and name == "codesemestre":
|
||||||
continue # pas de colonne codesemestre
|
continue # pas de colonne codesemestre
|
||||||
if only_tables is not None and strlower(l[2]) not in only_tables:
|
if only_tables is not None and scu.strlower(l[2]) not in only_tables:
|
||||||
continue # table non demandée
|
continue # table non demandée
|
||||||
if name in exclude_cols:
|
if name in exclude_cols:
|
||||||
continue # colonne exclue
|
continue # colonne exclue
|
||||||
@ -192,7 +207,7 @@ def sco_import_generate_excel_sample(
|
|||||||
)
|
)
|
||||||
l.append(etud["partitionsgroupes"])
|
l.append(etud["partitionsgroupes"])
|
||||||
else:
|
else:
|
||||||
key = strlower(field).split()[0]
|
key = scu.strlower(field).split()[0]
|
||||||
l.append(etud.get(key, ""))
|
l.append(etud.get(key, ""))
|
||||||
lines.append(l)
|
lines.append(l)
|
||||||
else:
|
else:
|
||||||
@ -224,7 +239,7 @@ def students_import_excel(
|
|||||||
if formsemestre_id:
|
if formsemestre_id:
|
||||||
dest = "formsemestre_status?formsemestre_id=%s" % formsemestre_id
|
dest = "formsemestre_status?formsemestre_id=%s" % formsemestre_id
|
||||||
else:
|
else:
|
||||||
dest = REQUEST.URL1
|
dest = context.NotesURL()
|
||||||
H = [context.sco_header(REQUEST, page_title="Import etudiants")]
|
H = [context.sco_header(REQUEST, page_title="Import etudiants")]
|
||||||
H.append("<ul>")
|
H.append("<ul>")
|
||||||
for d in diag:
|
for d in diag:
|
||||||
@ -249,7 +264,7 @@ def scolars_import_excel_file(
|
|||||||
"""
|
"""
|
||||||
log("scolars_import_excel_file: formsemestre_id=%s" % formsemestre_id)
|
log("scolars_import_excel_file: formsemestre_id=%s" % formsemestre_id)
|
||||||
cnx = context.GetDBConnexion(autocommit=False)
|
cnx = context.GetDBConnexion(autocommit=False)
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
annee_courante = time.localtime()[0]
|
annee_courante = time.localtime()[0]
|
||||||
always_require_ine = context.get_preference("always_require_ine")
|
always_require_ine = context.get_preference("always_require_ine")
|
||||||
exceldata = datafile.read()
|
exceldata = datafile.read()
|
||||||
@ -265,7 +280,7 @@ def scolars_import_excel_file(
|
|||||||
titles = {}
|
titles = {}
|
||||||
fmt = sco_import_format()
|
fmt = sco_import_format()
|
||||||
for l in fmt:
|
for l in fmt:
|
||||||
tit = strlower(l[0]).split()[0] # titles in lowercase, and take 1st word
|
tit = scu.strlower(l[0]).split()[0] # titles in lowercase, and take 1st word
|
||||||
if (
|
if (
|
||||||
(not formsemestre_id) or (tit != "codesemestre")
|
(not formsemestre_id) or (tit != "codesemestre")
|
||||||
) and tit not in exclude_cols:
|
) and tit not in exclude_cols:
|
||||||
@ -274,7 +289,7 @@ def scolars_import_excel_file(
|
|||||||
# log("titles=%s" % titles)
|
# log("titles=%s" % titles)
|
||||||
# remove quotes, downcase and keep only 1st word
|
# remove quotes, downcase and keep only 1st word
|
||||||
try:
|
try:
|
||||||
fs = [strlower(stripquotes(s)).split()[0] for s in data[0]]
|
fs = [scu.strlower(scu.stripquotes(s)).split()[0] for s in data[0]]
|
||||||
except:
|
except:
|
||||||
raise ScoValueError("Titres de colonnes invalides (ou vides ?)")
|
raise ScoValueError("Titres de colonnes invalides (ou vides ?)")
|
||||||
# log("excel: fs='%s'\ndata=%s" % (str(fs), str(data)))
|
# log("excel: fs='%s'\ndata=%s" % (str(fs), str(data)))
|
||||||
@ -351,22 +366,22 @@ def scolars_import_excel_file(
|
|||||||
% (val, linenum, titleslist[i])
|
% (val, linenum, titleslist[i])
|
||||||
)
|
)
|
||||||
# xxx Ad-hoc checks (should be in format description)
|
# xxx Ad-hoc checks (should be in format description)
|
||||||
if strlower(titleslist[i]) == "sexe":
|
if scu.strlower(titleslist[i]) == "sexe":
|
||||||
try:
|
try:
|
||||||
val = scolars.normalize_sexe(val)
|
val = scolars.input_civilite(val)
|
||||||
except:
|
except:
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
"valeur invalide pour 'SEXE' (doit etre 'M' ou 'MME' ou 'H' ou 'F', pas '%s') ligne %d, colonne %s"
|
"valeur invalide pour 'SEXE' (doit etre 'M', 'F', ou 'MME', 'H', 'X' ou vide, mais pas '%s') ligne %d, colonne %s"
|
||||||
% (val, linenum, titleslist[i])
|
% (val, linenum, titleslist[i])
|
||||||
)
|
)
|
||||||
# Excel date conversion:
|
# Excel date conversion:
|
||||||
if strlower(titleslist[i]) == "date_naissance":
|
if scu.strlower(titleslist[i]) == "date_naissance":
|
||||||
if val:
|
if val:
|
||||||
if re.match("^[0-9]*\.?[0-9]*$", str(val)):
|
if re.match(r"^[0-9]*\.?[0-9]*$", str(val)):
|
||||||
val = sco_excel.xldate_as_datetime(float(val))
|
val = sco_excel.xldate_as_datetime(float(val))
|
||||||
# INE
|
# INE
|
||||||
if (
|
if (
|
||||||
strlower(titleslist[i]) == "code_ine"
|
scu.strlower(titleslist[i]) == "code_ine"
|
||||||
and always_require_ine
|
and always_require_ine
|
||||||
and not val
|
and not val
|
||||||
):
|
):
|
||||||
@ -423,7 +438,7 @@ def scolars_import_excel_file(
|
|||||||
log("scolars_import_excel_file: aborting transaction !")
|
log("scolars_import_excel_file: aborting transaction !")
|
||||||
# Nota: db transaction is sometimes partly commited...
|
# Nota: db transaction is sometimes partly commited...
|
||||||
# here we try to remove all created students
|
# here we try to remove all created students
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
for etudid in created_etudids:
|
for etudid in created_etudids:
|
||||||
log("scolars_import_excel_file: deleting etudid=%s" % etudid)
|
log("scolars_import_excel_file: deleting etudid=%s" % etudid)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
@ -500,11 +515,11 @@ def _import_one_student(
|
|||||||
# Admissions
|
# Admissions
|
||||||
args["etudid"] = etudid
|
args["etudid"] = etudid
|
||||||
args["annee"] = annee_courante
|
args["annee"] = annee_courante
|
||||||
adm_id = scolars.admission_create(cnx, args)
|
_ = scolars.admission_create(cnx, args)
|
||||||
# Adresse
|
# Adresse
|
||||||
args["typeadresse"] = "domicile"
|
args["typeadresse"] = "domicile"
|
||||||
args["description"] = "(infos admission)"
|
args["description"] = "(infos admission)"
|
||||||
adresse_id = scolars.adresse_create(cnx, args)
|
_ = scolars.adresse_create(cnx, args)
|
||||||
# Inscription au semestre
|
# Inscription au semestre
|
||||||
args["etat"] = "I" # etat insc. semestre
|
args["etat"] = "I" # etat insc. semestre
|
||||||
if formsemestre_id:
|
if formsemestre_id:
|
||||||
@ -689,7 +704,7 @@ _ADM_PATTERN = re.compile(r"[\W]+", re.UNICODE) # supprime tout sauf alphanum
|
|||||||
|
|
||||||
|
|
||||||
def adm_normalize_string(s): # normalize unicode title
|
def adm_normalize_string(s): # normalize unicode title
|
||||||
return suppression_diacritics(_ADM_PATTERN.sub("", s.strip().lower())).replace(
|
return scu.suppression_diacritics(_ADM_PATTERN.sub("", s.strip().lower())).replace(
|
||||||
"_", ""
|
"_", ""
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -729,19 +744,19 @@ def adm_get_fields(titles, formsemestre_id):
|
|||||||
|
|
||||||
|
|
||||||
def adm_convert_text(v):
|
def adm_convert_text(v):
|
||||||
if type(v) == FloatType:
|
if type(v) == types.FloatType:
|
||||||
return "{:g}".format(v) # evite "1.0"
|
return "{:g}".format(v) # evite "1.0"
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def adm_convert_int(v):
|
def adm_convert_int(v):
|
||||||
if type(v) != IntType and not v:
|
if type(v) != types.IntType and not v:
|
||||||
return None
|
return None
|
||||||
return int(float(v)) # accept "10.0"
|
return int(float(v)) # accept "10.0"
|
||||||
|
|
||||||
|
|
||||||
def adm_convert_real(v):
|
def adm_convert_real(v):
|
||||||
if type(v) != FloatType and not v:
|
if type(v) != types.FloatType and not v:
|
||||||
return None
|
return None
|
||||||
return float(v)
|
return float(v)
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
v 1.2
|
v 1.2
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from types import *
|
from types import BooleanType, StringType
|
||||||
|
|
||||||
|
|
||||||
def TrivialFormulator(
|
def TrivialFormulator(
|
||||||
@ -368,9 +368,6 @@ class TF:
|
|||||||
idx = 0
|
idx = 0
|
||||||
for idx in range(len(self.formdescription)):
|
for idx in range(len(self.formdescription)):
|
||||||
(field, descr) = self.formdescription[idx]
|
(field, descr) = self.formdescription[idx]
|
||||||
nextitemname = None
|
|
||||||
if idx < len(self.formdescription) - 2:
|
|
||||||
nextitemname = self.formdescription[idx + 1][0]
|
|
||||||
if descr.get("readonly", False):
|
if descr.get("readonly", False):
|
||||||
R.append(self._ReadOnlyElement(field, descr))
|
R.append(self._ReadOnlyElement(field, descr))
|
||||||
continue
|
continue
|
||||||
@ -682,7 +679,6 @@ class TF:
|
|||||||
"Generate HTML for an element, read-only"
|
"Generate HTML for an element, read-only"
|
||||||
R = []
|
R = []
|
||||||
title = descr.get("title", field.capitalize())
|
title = descr.get("title", field.capitalize())
|
||||||
withcheckbox = descr.get("withcheckbox", False)
|
|
||||||
input_type = descr.get("input_type", "text")
|
input_type = descr.get("input_type", "text")
|
||||||
klass = descr.get("cssclass", "")
|
klass = descr.get("cssclass", "")
|
||||||
klass = " " + klass
|
klass = " " + klass
|
||||||
|
@ -6,10 +6,16 @@ SCOVERSION = "8.00a"
|
|||||||
SCONAME = "ScoDoc"
|
SCONAME = "ScoDoc"
|
||||||
|
|
||||||
SCONEWS = """
|
SCONEWS = """
|
||||||
|
<h4>Année 2021</h4>
|
||||||
|
<ul>
|
||||||
|
<li>Gestion du genre neutre (pas d'affichage de la civilité)</li>
|
||||||
|
<li>Diverses corrections (PV de jurys, ...)</li>
|
||||||
|
<li>Modernisation du code Python</li>
|
||||||
|
</ul>
|
||||||
<h4>Année 2020</h4>
|
<h4>Année 2020</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Corrections d'erreurs, améliorations saise absences< et affichage bulletins</li>
|
<li>Corrections d'erreurs, améliorations saise absences< et affichage bulletins</li>
|
||||||
<li>Nouveau site <a href="https://scodoc.org">scodoc.org</a> pour la documentation.</li>
|
<li>Nouveau site <a href="https://scodoc.org">scodoc.org</a> pour la documentation</li>
|
||||||
<li>Enregistrement de semestres extérieurs</li>
|
<li>Enregistrement de semestres extérieurs</li>
|
||||||
<li>Améliorations PV de Jury</li>
|
<li>Améliorations PV de Jury</li>
|
||||||
<li>Contributions J.-M. Place: aide au diagnostic problèmes export Apogée
|
<li>Contributions J.-M. Place: aide au diagnostic problèmes export Apogée
|
||||||
|
23
ZAbsences.py
23
ZAbsences.py
@ -44,20 +44,19 @@ L'API de plus bas niveau est en gros:
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import urllib
|
|
||||||
import datetime
|
|
||||||
import jaxml
|
|
||||||
import cgi
|
|
||||||
import string
|
import string
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
|
import datetime
|
||||||
|
import dateutil
|
||||||
|
import dateutil.parser
|
||||||
import calendar
|
import calendar
|
||||||
|
import urllib
|
||||||
from mx.DateTime import DateTime as mxDateTime
|
import cgi
|
||||||
from mx.DateTime.ISO import ParseDateTimeUTC
|
import jaxml
|
||||||
|
|
||||||
# ---------------
|
# ---------------
|
||||||
from sco_zope import *
|
from sco_zope import * # pylint: disable=unused-wildcard-import
|
||||||
|
|
||||||
# ---------------
|
# ---------------
|
||||||
import sco_utils as scu
|
import sco_utils as scu
|
||||||
@ -1542,8 +1541,8 @@ ou entrez une date pour visualiser les absents un jour donné :
|
|||||||
return scu.log_unknown_etud(self, REQUEST=REQUEST)
|
return scu.log_unknown_etud(self, REQUEST=REQUEST)
|
||||||
etud = etuds[0]
|
etud = etuds[0]
|
||||||
# check dates
|
# check dates
|
||||||
begin_date = ParseDateTimeUTC(begin) # may raises ValueError
|
begin_date = dateutil.parser.isoparse(begin) # may raises ValueError
|
||||||
end_date = ParseDateTimeUTC(end)
|
end_date = dateutil.parser.isoparse(end)
|
||||||
if begin_date > end_date:
|
if begin_date > end_date:
|
||||||
raise ValueError("invalid dates")
|
raise ValueError("invalid dates")
|
||||||
#
|
#
|
||||||
@ -1605,7 +1604,7 @@ ou entrez une date pour visualiser les absents un jour donné :
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + self.sco_footer(REQUEST)
|
return "\n".join(H) + tf[1] + self.sco_footer(REQUEST)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.ScoURL())
|
||||||
else:
|
else:
|
||||||
e = tf[2]["begin"].split("/")
|
e = tf[2]["begin"].split("/")
|
||||||
begin = e[2] + "-" + e[1] + "-" + e[0] + " 00:00:00"
|
begin = e[2] + "-" + e[1] + "-" + e[0] + " 00:00:00"
|
||||||
@ -1866,7 +1865,7 @@ ou entrez une date pour visualiser les absents un jour donné :
|
|||||||
|
|
||||||
return "\n".join(H) + "<br/>" + tf[1] + F + self.sco_footer(REQUEST)
|
return "\n".join(H) + "<br/>" + tf[1] + F + self.sco_footer(REQUEST)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.ScoURL())
|
||||||
else:
|
else:
|
||||||
n = self._ProcessBilletAbsence(
|
n = self._ProcessBilletAbsence(
|
||||||
billet, tf[2]["estjust"], tf[2]["description"], REQUEST
|
billet, tf[2]["estjust"], tf[2]["description"], REQUEST
|
||||||
|
@ -296,7 +296,7 @@ class ZEntreprises(
|
|||||||
c[
|
c[
|
||||||
"_date_target"
|
"_date_target"
|
||||||
] = "%s/entreprise_contact_edit?entreprise_contact_id=%s" % (
|
] = "%s/entreprise_contact_edit?entreprise_contact_id=%s" % (
|
||||||
REQUEST.URL1,
|
self.EntreprisesURL(),
|
||||||
c["entreprise_contact_id"],
|
c["entreprise_contact_id"],
|
||||||
)
|
)
|
||||||
c["entreprise"] = sco_entreprises.do_entreprise_list(
|
c["entreprise"] = sco_entreprises.do_entreprise_list(
|
||||||
@ -306,7 +306,7 @@ class ZEntreprises(
|
|||||||
c["etud"] = self.getEtudInfo(etudid=c["etudid"], filled=1)[0]
|
c["etud"] = self.getEtudInfo(etudid=c["etudid"], filled=1)[0]
|
||||||
c["etudnom"] = c["etud"]["nomprenom"]
|
c["etudnom"] = c["etud"]["nomprenom"]
|
||||||
c["_etudnom_target"] = "%s/ficheEtud?etudid=%s" % (
|
c["_etudnom_target"] = "%s/ficheEtud?etudid=%s" % (
|
||||||
REQUEST.URL1,
|
self.ScoURL(),
|
||||||
c["etudid"],
|
c["etudid"],
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -374,7 +374,7 @@ class ZEntreprises(
|
|||||||
c[
|
c[
|
||||||
"_nomprenom_target"
|
"_nomprenom_target"
|
||||||
] = "%s/entreprise_correspondant_edit?entreprise_corresp_id=%s" % (
|
] = "%s/entreprise_correspondant_edit?entreprise_corresp_id=%s" % (
|
||||||
REQUEST.URL1,
|
self.EntreprisesURL(),
|
||||||
c["entreprise_corresp_id"],
|
c["entreprise_corresp_id"],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -462,7 +462,7 @@ class ZEntreprises(
|
|||||||
)[0]
|
)[0]
|
||||||
link_create_corr = (
|
link_create_corr = (
|
||||||
'<a href="%s/entreprise_correspondant_create?entreprise_id=%s">créer un nouveau correspondant</a>'
|
'<a href="%s/entreprise_correspondant_create?entreprise_id=%s">créer un nouveau correspondant</a>'
|
||||||
% (REQUEST.URL1, c["entreprise_id"])
|
% (self.EntreprisesURL(), c["entreprise_id"])
|
||||||
)
|
)
|
||||||
E = sco_entreprises.do_entreprise_list(
|
E = sco_entreprises.do_entreprise_list(
|
||||||
self, args={"entreprise_id": c["entreprise_id"]}
|
self, args={"entreprise_id": c["entreprise_id"]}
|
||||||
@ -562,7 +562,7 @@ class ZEntreprises(
|
|||||||
% entreprise_contact_id
|
% entreprise_contact_id
|
||||||
)
|
)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.EntreprisesURL())
|
||||||
else:
|
else:
|
||||||
etudok = sco_entreprises.do_entreprise_check_etudiant(
|
etudok = sco_entreprises.do_entreprise_check_etudiant(
|
||||||
self, tf[2]["etudiant"]
|
self, tf[2]["etudiant"]
|
||||||
@ -572,8 +572,8 @@ class ZEntreprises(
|
|||||||
else:
|
else:
|
||||||
tf[2].update({"etudid": etudok[1]})
|
tf[2].update({"etudid": etudok[1]})
|
||||||
sco_entreprises.do_entreprise_contact_edit(self, tf[2])
|
sco_entreprises.do_entreprise_contact_edit(self, tf[2])
|
||||||
REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
REQUEST.URL1
|
self.EntreprisesURL()
|
||||||
+ "/entreprise_contact_list?entreprise_id="
|
+ "/entreprise_contact_list?entreprise_id="
|
||||||
+ str(c["entreprise_id"])
|
+ str(c["entreprise_id"])
|
||||||
)
|
)
|
||||||
@ -680,15 +680,15 @@ class ZEntreprises(
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
H.append(tf[1])
|
H.append(tf[1])
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
"%s/entreprise_correspondant_list?entreprise_id=%s"
|
"%s/entreprise_correspondant_list?entreprise_id=%s"
|
||||||
% (REQUEST.URL1, c["entreprise_id"])
|
% (self.EntreprisesURL(), c["entreprise_id"])
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
sco_entreprises.do_entreprise_correspondant_edit(self, tf[2])
|
sco_entreprises.do_entreprise_correspondant_edit(self, tf[2])
|
||||||
REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
"%s/entreprise_correspondant_list?entreprise_id=%s"
|
"%s/entreprise_correspondant_list?entreprise_id=%s"
|
||||||
% (REQUEST.URL1, c["entreprise_id"])
|
% (self.EntreprisesURL(), c["entreprise_id"])
|
||||||
)
|
)
|
||||||
H.append(entreprise_footer(self, REQUEST))
|
H.append(entreprise_footer(self, REQUEST))
|
||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
@ -708,7 +708,7 @@ class ZEntreprises(
|
|||||||
curtime = time.strftime("%d/%m/%Y")
|
curtime = time.strftime("%d/%m/%Y")
|
||||||
link_create_corr = (
|
link_create_corr = (
|
||||||
'<a href="%s/entreprise_correspondant_create?entreprise_id=%s">créer un nouveau correspondant</a>'
|
'<a href="%s/entreprise_correspondant_create?entreprise_id=%s">créer un nouveau correspondant</a>'
|
||||||
% (REQUEST.URL1, entreprise_id)
|
% (self.EntreprisesURL(), entreprise_id)
|
||||||
)
|
)
|
||||||
H = [
|
H = [
|
||||||
entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"),
|
entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"),
|
||||||
@ -789,7 +789,7 @@ class ZEntreprises(
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
H.append(tf[1])
|
H.append(tf[1])
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.EntreprisesURL())
|
||||||
else:
|
else:
|
||||||
etudok = sco_entreprises.do_entreprise_check_etudiant(
|
etudok = sco_entreprises.do_entreprise_check_etudiant(
|
||||||
self, tf[2]["etudiant"]
|
self, tf[2]["etudiant"]
|
||||||
@ -799,7 +799,7 @@ class ZEntreprises(
|
|||||||
else:
|
else:
|
||||||
tf[2].update({"etudid": etudok[1]})
|
tf[2].update({"etudid": etudok[1]})
|
||||||
sco_entreprises.do_entreprise_contact_create(self, tf[2])
|
sco_entreprises.do_entreprise_contact_create(self, tf[2])
|
||||||
REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.EntreprisesURL())
|
||||||
H.append(entreprise_footer(self, REQUEST))
|
H.append(entreprise_footer(self, REQUEST))
|
||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
@ -828,12 +828,12 @@ class ZEntreprises(
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
H.append(tf[1])
|
H.append(tf[1])
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.EntreprisesURL())
|
||||||
else:
|
else:
|
||||||
sco_entreprises.do_entreprise_contact_delete(
|
sco_entreprises.do_entreprise_contact_delete(
|
||||||
self, c["entreprise_contact_id"]
|
self, c["entreprise_contact_id"]
|
||||||
)
|
)
|
||||||
REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.EntreprisesURL())
|
||||||
H.append(entreprise_footer(self, REQUEST))
|
H.append(entreprise_footer(self, REQUEST))
|
||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
@ -935,10 +935,10 @@ class ZEntreprises(
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
H.append(tf[1])
|
H.append(tf[1])
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.EntreprisesURL())
|
||||||
else:
|
else:
|
||||||
sco_entreprises.do_entreprise_correspondant_create(self, tf[2])
|
sco_entreprises.do_entreprise_correspondant_create(self, tf[2])
|
||||||
REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.EntreprisesURL())
|
||||||
H.append(entreprise_footer(self, REQUEST))
|
H.append(entreprise_footer(self, REQUEST))
|
||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
@ -967,12 +967,12 @@ class ZEntreprises(
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
H.append(tf[1])
|
H.append(tf[1])
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.EntreprisesURL())
|
||||||
else:
|
else:
|
||||||
sco_entreprises.do_entreprise_correspondant_delete(
|
sco_entreprises.do_entreprise_correspondant_delete(
|
||||||
self, c["entreprise_corresp_id"]
|
self, c["entreprise_corresp_id"]
|
||||||
)
|
)
|
||||||
REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.EntreprisesURL())
|
||||||
H.append(entreprise_footer(self, REQUEST))
|
H.append(entreprise_footer(self, REQUEST))
|
||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
@ -1025,10 +1025,10 @@ class ZEntreprises(
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
H.append(tf[1])
|
H.append(tf[1])
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.EntreprisesURL())
|
||||||
else:
|
else:
|
||||||
sco_entreprises.do_entreprise_delete(self, E["entreprise_id"])
|
sco_entreprises.do_entreprise_delete(self, E["entreprise_id"])
|
||||||
REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.EntreprisesURL())
|
||||||
H.append(entreprise_footer(self, REQUEST))
|
H.append(entreprise_footer(self, REQUEST))
|
||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
@ -1120,10 +1120,10 @@ class ZEntreprises(
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + entreprise_footer(self, REQUEST)
|
return "\n".join(H) + tf[1] + entreprise_footer(self, REQUEST)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.EntreprisesURL())
|
||||||
else:
|
else:
|
||||||
sco_entreprises.do_entreprise_create(self, tf[2])
|
sco_entreprises.do_entreprise_create(self, tf[2])
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.EntreprisesURL())
|
||||||
|
|
||||||
security.declareProtected(ScoEntrepriseView, "entreprise_edit")
|
security.declareProtected(ScoEntrepriseView, "entreprise_edit")
|
||||||
|
|
||||||
@ -1295,7 +1295,7 @@ class ZEntreprises(
|
|||||||
H.append("</ul>")
|
H.append("</ul>")
|
||||||
return "\n".join(H) + entreprise_footer(self, REQUEST)
|
return "\n".join(H) + entreprise_footer(self, REQUEST)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "?start=" + start)
|
return REQUEST.RESPONSE.redirect(self.EntreprisesURL() + "?start=" + start)
|
||||||
else:
|
else:
|
||||||
sco_entreprises.do_entreprise_edit(self, tf[2])
|
sco_entreprises.do_entreprise_edit(self, tf[2])
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "?start=" + start)
|
return REQUEST.RESPONSE.redirect(self.EntreprisesURL() + "?start=" + start)
|
||||||
|
13
ZNotes.py
13
ZNotes.py
@ -35,7 +35,6 @@ import pprint
|
|||||||
from sco_zope import * # pylint: disable=unused-wildcard-import
|
from sco_zope import * # pylint: disable=unused-wildcard-import
|
||||||
|
|
||||||
# ---------------
|
# ---------------
|
||||||
# from sco_utils import *
|
|
||||||
import sco_utils as scu
|
import sco_utils as scu
|
||||||
import notesdb as ndb
|
import notesdb as ndb
|
||||||
from notes_log import log, sendAlarm
|
from notes_log import log, sendAlarm
|
||||||
@ -170,7 +169,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
|
|||||||
"Changes the instance values"
|
"Changes the instance values"
|
||||||
self.title = title
|
self.title = title
|
||||||
self._p_changed = 1
|
self._p_changed = 1
|
||||||
RESPONSE.redirect("manage_editForm")
|
return RESPONSE.redirect("manage_editForm")
|
||||||
|
|
||||||
def _getNotesCache(self):
|
def _getNotesCache(self):
|
||||||
"returns CacheNotesTable instance for us"
|
"returns CacheNotesTable instance for us"
|
||||||
@ -267,10 +266,12 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
|
|||||||
sco_formsemestre_edit.formsemestre_createwithmodules
|
sco_formsemestre_edit.formsemestre_createwithmodules
|
||||||
)
|
)
|
||||||
|
|
||||||
security.declareProtected(ScoView, "formsemestre_editwithmodules")
|
security.declareProtected(
|
||||||
|
ScoView, "formsemestre_editwithmodules"
|
||||||
|
) # controle d'acces specifique pour dir. etud
|
||||||
formsemestre_editwithmodules = sco_formsemestre_edit.formsemestre_editwithmodules
|
formsemestre_editwithmodules = sco_formsemestre_edit.formsemestre_editwithmodules
|
||||||
|
|
||||||
security.declareProtected(ScoView, "formsemestre_clone")
|
security.declareProtected(ScoImplement, "formsemestre_clone")
|
||||||
formsemestre_clone = sco_formsemestre_edit.formsemestre_clone
|
formsemestre_clone = sco_formsemestre_edit.formsemestre_clone
|
||||||
|
|
||||||
security.declareProtected(ScoChangeFormation, "formsemestre_associate_new_version")
|
security.declareProtected(ScoChangeFormation, "formsemestre_associate_new_version")
|
||||||
@ -531,7 +532,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + footer
|
return "\n".join(H) + tf[1] + footer
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.NotesURL())
|
||||||
else:
|
else:
|
||||||
formation_id, _, _ = self.formation_import_xml(tf[2]["xmlfile"], REQUEST)
|
formation_id, _, _ = self.formation_import_xml(tf[2]["xmlfile"], REQUEST)
|
||||||
|
|
||||||
@ -685,7 +686,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
|
|||||||
#
|
#
|
||||||
if not force:
|
if not force:
|
||||||
return REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
REQUEST.URL1 + "/ue_list?formation_id=" + str(ue["formation_id"])
|
self.NotesURL() + "/ue_list?formation_id=" + str(ue["formation_id"])
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
@ -345,8 +345,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
|
|||||||
return (
|
return (
|
||||||
"<p>Département "
|
"<p>Département "
|
||||||
+ DeptId
|
+ DeptId
|
||||||
+ """ supprimé du serveur web (la base de données n'est pas affectée)!</p><p><a href="%s">Continuer</a></p>"""
|
+ """ supprimé du serveur web (la base de données n'est pas affectée)!</p><p><a href="/ScoDoc">Continuer</a></p>"""
|
||||||
% REQUEST.URL1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
_top_level_css = """
|
_top_level_css = """
|
||||||
@ -410,7 +409,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
|
|||||||
except:
|
except:
|
||||||
admin_password_initialized = "0"
|
admin_password_initialized = "0"
|
||||||
if isAdmin and admin_password_initialized != "1":
|
if isAdmin and admin_password_initialized != "1":
|
||||||
REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
"ScoDoc/change_admin_user_form?message=Le%20mot%20de%20passe%20administrateur%20doit%20etre%20change%20!"
|
"ScoDoc/change_admin_user_form?message=Le%20mot%20de%20passe%20administrateur%20doit%20etre%20change%20!"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -980,5 +979,5 @@ def manage_addZScoDoc(self, id="ScoDoc", title="Site ScoDoc", REQUEST=None):
|
|||||||
) # ne cree (presque rien), tout se passe lors du 1er accès
|
) # ne cree (presque rien), tout se passe lors du 1er accès
|
||||||
self._setObject(id, zscodoc)
|
self._setObject(id, zscodoc)
|
||||||
if REQUEST is not None:
|
if REQUEST is not None:
|
||||||
REQUEST.RESPONSE.redirect("%s/manage_workspace" % REQUEST.URL1)
|
REQUEST.RESPONSE.redirect("/ScoDoc/manage_workspace")
|
||||||
return id
|
return id
|
||||||
|
114
ZScoUsers.py
114
ZScoUsers.py
@ -27,28 +27,45 @@
|
|||||||
|
|
||||||
""" Gestion des utilisateurs (table SQL pour Zope User Folder)
|
""" Gestion des utilisateurs (table SQL pour Zope User Folder)
|
||||||
"""
|
"""
|
||||||
import string, re
|
import string
|
||||||
|
import re
|
||||||
import time
|
import time
|
||||||
import md5, base64
|
import md5
|
||||||
|
import base64
|
||||||
|
import jaxml
|
||||||
|
|
||||||
|
from sco_zope import * # pylint: disable=unused-wildcard-import
|
||||||
from sco_zope import *
|
|
||||||
|
|
||||||
# ---------------
|
# ---------------
|
||||||
|
import sco_utils as scu
|
||||||
import notesdb
|
import notesdb as ndb
|
||||||
from notesdb import *
|
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from scolog import logdb
|
from scolog import logdb
|
||||||
from sco_utils import *
|
|
||||||
from scolars import format_prenom, format_nom
|
from scolars import format_prenom, format_nom
|
||||||
import sco_import_users, sco_excel
|
import sco_import_users
|
||||||
from TrivialFormulator import TrivialFormulator, TF
|
import sco_excel
|
||||||
|
from TrivialFormulator import TrivialFormulator, TF, tf_error_message
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
import scolars
|
import scolars
|
||||||
import sco_cache
|
import sco_cache
|
||||||
import sco_users
|
import sco_users
|
||||||
|
from sco_permissions import (
|
||||||
|
ScoEditAllEvals,
|
||||||
|
ScoEditAllNotes,
|
||||||
|
ScoImplement,
|
||||||
|
ScoSuperAdmin,
|
||||||
|
ScoUsersAdmin,
|
||||||
|
ScoUsersView,
|
||||||
|
ScoView,
|
||||||
|
)
|
||||||
|
from sco_exceptions import (
|
||||||
|
AccessDenied,
|
||||||
|
ScoException,
|
||||||
|
ScoValueError,
|
||||||
|
ScoInvalidDateError,
|
||||||
|
ScoLockedFormError,
|
||||||
|
ScoGenError,
|
||||||
|
)
|
||||||
|
|
||||||
# ---------------
|
# ---------------
|
||||||
# cache global: chaque instance, repérée par son URL, a un cache
|
# cache global: chaque instance, repérée par son URL, a un cache
|
||||||
@ -93,7 +110,7 @@ class ZScoUsers(
|
|||||||
# Ugly but necessary during transition out of Zope:
|
# Ugly but necessary during transition out of Zope:
|
||||||
_db_cnx_string = "dbname=SCOUSERS port=5432"
|
_db_cnx_string = "dbname=SCOUSERS port=5432"
|
||||||
security.declareProtected("Change DTML Documents", "GetUsersDBConnexion")
|
security.declareProtected("Change DTML Documents", "GetUsersDBConnexion")
|
||||||
GetUsersDBConnexion = notesdb.GetUsersDBConnexion
|
GetUsersDBConnexion = ndb.GetUsersDBConnexion
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -162,7 +179,7 @@ class ZScoUsers(
|
|||||||
F = self.sco_footer(REQUEST)
|
F = self.sco_footer(REQUEST)
|
||||||
return "\n".join(H) + F
|
return "\n".join(H) + F
|
||||||
|
|
||||||
_userEditor = EditableTable(
|
_userEditor = ndb.EditableTable(
|
||||||
"sco_users",
|
"sco_users",
|
||||||
"user_id",
|
"user_id",
|
||||||
(
|
(
|
||||||
@ -180,12 +197,12 @@ class ZScoUsers(
|
|||||||
"date_expiration",
|
"date_expiration",
|
||||||
),
|
),
|
||||||
output_formators={
|
output_formators={
|
||||||
"date_modif_passwd": DateISOtoDMY,
|
"date_modif_passwd": ndb.DateISOtoDMY,
|
||||||
"date_expiration": DateISOtoDMY,
|
"date_expiration": ndb.DateISOtoDMY,
|
||||||
},
|
},
|
||||||
input_formators={
|
input_formators={
|
||||||
"date_modif_passwd": DateDMYtoISO,
|
"date_modif_passwd": ndb.DateDMYtoISO,
|
||||||
"date_expiration": DateDMYtoISO,
|
"date_expiration": ndb.DateDMYtoISO,
|
||||||
},
|
},
|
||||||
sortkey="nom",
|
sortkey="nom",
|
||||||
filter_nulls=False,
|
filter_nulls=False,
|
||||||
@ -217,12 +234,12 @@ class ZScoUsers(
|
|||||||
u = self._user_list(args={"user_name": user_name})[0]
|
u = self._user_list(args={"user_name": user_name})[0]
|
||||||
if u["status"] == "old" and u["roles"] and u["roles"][0] != "-":
|
if u["status"] == "old" and u["roles"] and u["roles"][0] != "-":
|
||||||
roles = ["-" + r for r in u["roles"].split(",")]
|
roles = ["-" + r for r in u["roles"].split(",")]
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
self.acl_users.scodoc_editUser(cursor, user_name, roles=roles)
|
self.acl_users.scodoc_editUser(cursor, user_name, roles=roles)
|
||||||
self.get_userlist_cache().inval_cache()
|
self.get_userlist_cache().inval_cache()
|
||||||
elif not u["status"] and u["roles"] and u["roles"][0] == "-":
|
elif not u["status"] and u["roles"] and u["roles"][0] == "-":
|
||||||
roles = [r[1:] for r in u["roles"].split(",") if (r and r[0] == "-")]
|
roles = [r[1:] for r in u["roles"].split(",") if (r and r[0] == "-")]
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
self.acl_users.scodoc_editUser(cursor, user_name, roles=roles)
|
self.acl_users.scodoc_editUser(cursor, user_name, roles=roles)
|
||||||
self.get_userlist_cache().inval_cache()
|
self.get_userlist_cache().inval_cache()
|
||||||
|
|
||||||
@ -268,7 +285,7 @@ class ZScoUsers(
|
|||||||
"nom_fmt": user_name,
|
"nom_fmt": user_name,
|
||||||
"nomcomplet": user_name,
|
"nomcomplet": user_name,
|
||||||
"nomplogin": user_name,
|
"nomplogin": user_name,
|
||||||
"nomnoacc": suppress_accents(user_name),
|
"nomnoacc": scu.suppress_accents(user_name),
|
||||||
"passwd_temp": 0,
|
"passwd_temp": 0,
|
||||||
"status": "",
|
"status": "",
|
||||||
"date_expiration": None,
|
"date_expiration": None,
|
||||||
@ -289,7 +306,7 @@ class ZScoUsers(
|
|||||||
else:
|
else:
|
||||||
n = user_name
|
n = user_name
|
||||||
|
|
||||||
prenom_abbrv = abbrev_prenom(p)
|
prenom_abbrv = scu.abbrev_prenom(p)
|
||||||
# nomprenom est le nom capitalisé suivi de l'initiale du prénom
|
# nomprenom est le nom capitalisé suivi de l'initiale du prénom
|
||||||
info["nomprenom"] = (n + " " + prenom_abbrv).strip()
|
info["nomprenom"] = (n + " " + prenom_abbrv).strip()
|
||||||
# prenomnom est l'initiale du prénom suivie du nom
|
# prenomnom est l'initiale du prénom suivie du nom
|
||||||
@ -301,9 +318,9 @@ class ZScoUsers(
|
|||||||
info["nomcomplet"] = info["prenom_fmt"] + " " + info["nom_fmt"]
|
info["nomcomplet"] = info["prenom_fmt"] + " " + info["nom_fmt"]
|
||||||
# nomplogin est le nom en majuscules suivi du prénom et du login
|
# nomplogin est le nom en majuscules suivi du prénom et du login
|
||||||
# e.g. Dupont Pierre (dupont)
|
# e.g. Dupont Pierre (dupont)
|
||||||
info["nomplogin"] = "%s %s (%s)" % (strupper(n), p, info["user_name"])
|
info["nomplogin"] = "%s %s (%s)" % (scu.strupper(n), p, info["user_name"])
|
||||||
# nomnoacc est le nom en minuscules sans accents
|
# nomnoacc est le nom en minuscules sans accents
|
||||||
info["nomnoacc"] = suppress_accents(strlower(info["nom"]))
|
info["nomnoacc"] = scu.suppress_accents(scu.strlower(info["nom"]))
|
||||||
|
|
||||||
return info
|
return info
|
||||||
|
|
||||||
@ -346,7 +363,7 @@ class ZScoUsers(
|
|||||||
assert len(user) == 1, "database inconsistency: len(user)=%d" % len(user)
|
assert len(user) == 1, "database inconsistency: len(user)=%d" % len(user)
|
||||||
# should not occur, already tested in _can_handle_passwd
|
# should not occur, already tested in _can_handle_passwd
|
||||||
cnx = self.GetUsersDBConnexion() # en mode autocommit
|
cnx = self.GetUsersDBConnexion() # en mode autocommit
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"update sco_users set date_modif_passwd=now(), passwd_temp=0 where user_name=%(user_name)s",
|
"update sco_users set date_modif_passwd=now(), passwd_temp=0 where user_name=%(user_name)s",
|
||||||
{"user_name": user_name},
|
{"user_name": user_name},
|
||||||
@ -417,7 +434,7 @@ class ZScoUsers(
|
|||||||
<meta http-equiv="Content-Type" content="text/html; charset=%s" />
|
<meta http-equiv="Content-Type" content="text/html; charset=%s" />
|
||||||
<body><h1>Mot de passe changé !</h1>
|
<body><h1>Mot de passe changé !</h1>
|
||||||
"""
|
"""
|
||||||
% (SCO_ENCODING, SCO_ENCODING)
|
% (scu.SCO_ENCODING, scu.SCO_ENCODING)
|
||||||
+ "\n".join(H)
|
+ "\n".join(H)
|
||||||
+ '<a href="%s" class="stdlink">Continuer</a></body></html>'
|
+ '<a href="%s" class="stdlink">Continuer</a></body></html>'
|
||||||
% self.ScoURL()
|
% self.ScoURL()
|
||||||
@ -536,7 +553,7 @@ class ZScoUsers(
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
for p in scoperms:
|
for p in scoperms:
|
||||||
permname, value = p[:2]
|
permname, _ = p[:2]
|
||||||
if thisuser.has_permission(permname, self):
|
if thisuser.has_permission(permname, self):
|
||||||
b = "oui"
|
b = "oui"
|
||||||
else:
|
else:
|
||||||
@ -775,11 +792,12 @@ class ZScoUsers(
|
|||||||
descr,
|
descr,
|
||||||
initvalues=initvalues,
|
initvalues=initvalues,
|
||||||
submitlabel=submitlabel,
|
submitlabel=submitlabel,
|
||||||
|
cancelbutton="Annuler",
|
||||||
)
|
)
|
||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + "\n" + tf[1] + F
|
return "\n".join(H) + "\n" + tf[1] + F
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.UsersURL())
|
||||||
else:
|
else:
|
||||||
vals = tf[2]
|
vals = tf[2]
|
||||||
roles = set(vals["roles"]).intersection(editable_roles)
|
roles = set(vals["roles"]).intersection(editable_roles)
|
||||||
@ -903,7 +921,7 @@ class ZScoUsers(
|
|||||||
|
|
||||||
# Des noms/prénoms semblables existent ?
|
# Des noms/prénoms semblables existent ?
|
||||||
cnx = self.GetUsersDBConnexion()
|
cnx = self.GetUsersDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"select * from sco_users where lower(nom) ~ %(nom)s and lower(prenom) ~ %(prenom)s;",
|
"select * from sco_users where lower(nom) ~ %(nom)s and lower(prenom) ~ %(prenom)s;",
|
||||||
{"nom": nom.lower().strip(), "prenom": prenom.lower().strip()},
|
{"nom": nom.lower().strip(), "prenom": prenom.lower().strip()},
|
||||||
@ -980,7 +998,7 @@ class ZScoUsers(
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + "</li></ol>" + help + F
|
return "\n".join(H) + tf[1] + "</li></ol>" + help + F
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.UsersURL())
|
||||||
else:
|
else:
|
||||||
# IMPORT
|
# IMPORT
|
||||||
diag = sco_import_users.import_excel_file(
|
diag = sco_import_users.import_excel_file(
|
||||||
@ -989,7 +1007,9 @@ class ZScoUsers(
|
|||||||
H = [head]
|
H = [head]
|
||||||
H.append("<p>Import excel: %s</p>" % diag)
|
H.append("<p>Import excel: %s</p>" % diag)
|
||||||
H.append("<p>OK, import terminé !</p>")
|
H.append("<p>OK, import terminé !</p>")
|
||||||
H.append('<p><a class="stdlink" href="%s">Continuer</a></p>' % REQUEST.URL1)
|
H.append(
|
||||||
|
'<p><a class="stdlink" href="%s">Continuer</a></p>' % self.UsersURL()
|
||||||
|
)
|
||||||
return "\n".join(H) + help + F
|
return "\n".join(H) + help + F
|
||||||
|
|
||||||
security.declareProtected(ScoUsersAdmin, "import_users_generate_excel_sample")
|
security.declareProtected(ScoUsersAdmin, "import_users_generate_excel_sample")
|
||||||
@ -1004,13 +1024,13 @@ class ZScoUsers(
|
|||||||
def create_user(self, args, REQUEST=None):
|
def create_user(self, args, REQUEST=None):
|
||||||
"creation utilisateur zope"
|
"creation utilisateur zope"
|
||||||
cnx = self.GetUsersDBConnexion()
|
cnx = self.GetUsersDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
passwd = args["passwd"]
|
passwd = args["passwd"]
|
||||||
args["passwd"] = "undefined"
|
args["passwd"] = "undefined"
|
||||||
if "passwd2" in args:
|
if "passwd2" in args:
|
||||||
del args["passwd2"]
|
del args["passwd2"]
|
||||||
log("create_user: args=%s" % args) # log apres supr. du mot de passe !
|
log("create_user: args=%s" % args) # log apres supr. du mot de passe !
|
||||||
r = self._userEditor.create(cnx, args)
|
_ = self._userEditor.create(cnx, args)
|
||||||
self.get_userlist_cache().inval_cache() # >
|
self.get_userlist_cache().inval_cache() # >
|
||||||
|
|
||||||
# call exUserFolder to set passwd
|
# call exUserFolder to set passwd
|
||||||
@ -1020,7 +1040,7 @@ class ZScoUsers(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if REQUEST:
|
if REQUEST:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(self.UsersURL())
|
||||||
|
|
||||||
security.declareProtected(ScoUsersAdmin, "delete_user_form")
|
security.declareProtected(ScoUsersAdmin, "delete_user_form")
|
||||||
|
|
||||||
@ -1048,11 +1068,13 @@ class ZScoUsers(
|
|||||||
% user_name,
|
% user_name,
|
||||||
dest_url="",
|
dest_url="",
|
||||||
REQUEST=REQUEST,
|
REQUEST=REQUEST,
|
||||||
cancel_url=REQUEST.URL1,
|
cancel_url=self.UsersURL(),
|
||||||
parameters={"user_name": user_name},
|
parameters={"user_name": user_name},
|
||||||
)
|
)
|
||||||
self._user_delete(user_name)
|
self._user_delete(user_name)
|
||||||
REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(
|
||||||
|
self.UsersURL() + r"?head_message=Utilisateur%20supprimé"
|
||||||
|
)
|
||||||
|
|
||||||
security.declareProtected(ScoView, "list_users")
|
security.declareProtected(ScoView, "list_users")
|
||||||
|
|
||||||
@ -1100,15 +1122,15 @@ class ZScoUsers(
|
|||||||
|
|
||||||
# Convert dates to ISO if XML output
|
# Convert dates to ISO if XML output
|
||||||
if format == "xml" and u["date_modif_passwd"] != "NA":
|
if format == "xml" and u["date_modif_passwd"] != "NA":
|
||||||
u["date_modif_passwd"] = DateDMYtoISO(u["date_modif_passwd"]) or ""
|
u["date_modif_passwd"] = ndb.DateDMYtoISO(u["date_modif_passwd"]) or ""
|
||||||
|
|
||||||
# Convert date_expiration and date_modif_passwd to ISO to ease sorting
|
# Convert date_expiration and date_modif_passwd to ISO to ease sorting
|
||||||
if u["date_expiration"]:
|
if u["date_expiration"]:
|
||||||
u["date_expiration_iso"] = DateDMYtoISO(u["date_expiration"])
|
u["date_expiration_iso"] = ndb.DateDMYtoISO(u["date_expiration"])
|
||||||
else:
|
else:
|
||||||
u["date_expiration_iso"] = ""
|
u["date_expiration_iso"] = ""
|
||||||
if u["date_modif_passwd"]:
|
if u["date_modif_passwd"]:
|
||||||
u["date_modif_passwd_iso"] = DateDMYtoISO(u["date_expiration"])
|
u["date_modif_passwd_iso"] = ndb.DateDMYtoISO(u["date_expiration"])
|
||||||
else:
|
else:
|
||||||
u["date_modif_passwd_iso"] = ""
|
u["date_modif_passwd_iso"] = ""
|
||||||
|
|
||||||
@ -1202,13 +1224,13 @@ class ZScoUsers(
|
|||||||
"""Returns XML list of users with name (nomplogin) starting with start.
|
"""Returns XML list of users with name (nomplogin) starting with start.
|
||||||
Used for forms auto-completion."""
|
Used for forms auto-completion."""
|
||||||
userlist = self.get_userlist(dept=dept)
|
userlist = self.get_userlist(dept=dept)
|
||||||
start = suppression_diacritics(unicode(start, "utf-8"))
|
start = scu.suppression_diacritics(unicode(start, "utf-8"))
|
||||||
start = strlower(str(start))
|
start = scu.strlower(str(start))
|
||||||
|
|
||||||
userlist = [user for user in userlist if user["nomnoacc"].startswith(start)]
|
userlist = [user for user in userlist if user["nomnoacc"].startswith(start)]
|
||||||
if REQUEST:
|
if REQUEST:
|
||||||
REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE)
|
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
|
||||||
doc = jaxml.XML_document(encoding=SCO_ENCODING)
|
doc = jaxml.XML_document(encoding=scu.SCO_ENCODING)
|
||||||
doc.results()
|
doc.results()
|
||||||
for user in userlist[:limit]:
|
for user in userlist[:limit]:
|
||||||
doc._push()
|
doc._push()
|
||||||
@ -1243,8 +1265,8 @@ Il devra ensuite se connecter et le changer.
|
|||||||
)
|
)
|
||||||
self.reset_password(user_name=user_name, REQUEST=REQUEST)
|
self.reset_password(user_name=user_name, REQUEST=REQUEST)
|
||||||
return REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
REQUEST.URL1
|
self.UsersURL()
|
||||||
+ "?head_message=mot%20de%20passe%20de%20"
|
+ r"?head_message=mot%20de%20passe%20de%20"
|
||||||
+ user_name
|
+ user_name
|
||||||
+ "%20reinitialise"
|
+ "%20reinitialise"
|
||||||
)
|
)
|
||||||
@ -1269,14 +1291,14 @@ Il devra ensuite se connecter et le changer.
|
|||||||
log("reset_password: %s" % user_name)
|
log("reset_password: %s" % user_name)
|
||||||
# Check that user has valid mail
|
# Check that user has valid mail
|
||||||
info = self.user_info(user_name=user_name)
|
info = self.user_info(user_name=user_name)
|
||||||
if not is_valid_mail(info["email"]):
|
if not scu.is_valid_mail(info["email"]):
|
||||||
raise Exception("pas de mail valide associé à l'utilisateur")
|
raise Exception("pas de mail valide associé à l'utilisateur")
|
||||||
# Generate random password
|
# Generate random password
|
||||||
password = sco_import_users.generate_password()
|
password = sco_import_users.generate_password()
|
||||||
self.do_change_password(user_name, password)
|
self.do_change_password(user_name, password)
|
||||||
# Flag it as temporary:
|
# Flag it as temporary:
|
||||||
cnx = self.GetUsersDBConnexion()
|
cnx = self.GetUsersDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
ui = {"user_name": user_name}
|
ui = {"user_name": user_name}
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"update sco_users set passwd_temp=1 where user_name='%(user_name)s'" % ui
|
"update sco_users set passwd_temp=1 where user_name='%(user_name)s'" % ui
|
||||||
|
335
ZScolar.py
335
ZScolar.py
@ -30,8 +30,15 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
import time, string, glob, re
|
import time
|
||||||
import urllib, urllib2, cgi, xml
|
import string
|
||||||
|
import glob
|
||||||
|
import re
|
||||||
|
import urllib
|
||||||
|
import urllib2
|
||||||
|
import cgi
|
||||||
|
import xml
|
||||||
|
import jaxml
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
@ -41,7 +48,7 @@ from zipfile import ZipFile
|
|||||||
import thread
|
import thread
|
||||||
import psycopg2
|
import psycopg2
|
||||||
|
|
||||||
from sco_zope import *
|
from sco_zope import * # pylint: disable=unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
# ---------------
|
# ---------------
|
||||||
@ -52,19 +59,47 @@ log("restarting...")
|
|||||||
|
|
||||||
log("ZScolar home=%s" % file_path)
|
log("ZScolar home=%s" % file_path)
|
||||||
|
|
||||||
import sco_utils
|
|
||||||
from sco_utils import *
|
|
||||||
import notesdb
|
|
||||||
from notesdb import *
|
|
||||||
from scolog import logdb
|
|
||||||
|
|
||||||
|
import sco_utils as scu
|
||||||
|
import notesdb as ndb
|
||||||
|
from scolog import logdb
|
||||||
|
from sco_permissions import (
|
||||||
|
ScoAbsChange,
|
||||||
|
ScoView,
|
||||||
|
ScoEnsView,
|
||||||
|
ScoImplement,
|
||||||
|
ScoChangeFormation,
|
||||||
|
ScoChangePreferences,
|
||||||
|
ScoObservateur,
|
||||||
|
ScoEtudAddAnnotations,
|
||||||
|
ScoEtudInscrit,
|
||||||
|
ScoEtudChangeGroups,
|
||||||
|
ScoEtudChangeAdr,
|
||||||
|
ScoEtudSupprAnnotations,
|
||||||
|
ScoEditAllEvals,
|
||||||
|
ScoEditAllNotes,
|
||||||
|
ScoEditFormationTags,
|
||||||
|
ScoEditApo,
|
||||||
|
ScoSuperAdmin,
|
||||||
|
)
|
||||||
|
import sco_permissions
|
||||||
|
from sco_exceptions import (
|
||||||
|
AccessDenied,
|
||||||
|
ScoException,
|
||||||
|
ScoValueError,
|
||||||
|
ScoInvalidDateError,
|
||||||
|
ScoLockedFormError,
|
||||||
|
ScoGenError,
|
||||||
|
)
|
||||||
|
from TrivialFormulator import TrivialFormulator, tf_error_message
|
||||||
import scolars
|
import scolars
|
||||||
|
import sco_codes_parcours
|
||||||
import sco_preferences
|
import sco_preferences
|
||||||
import sco_formations
|
import sco_formations
|
||||||
from scolars import (
|
from scolars import (
|
||||||
format_nom,
|
format_nom,
|
||||||
format_prenom,
|
format_prenom,
|
||||||
format_sexe,
|
format_civilite,
|
||||||
format_lycee,
|
format_lycee,
|
||||||
format_lycee_from_code,
|
format_lycee_from_code,
|
||||||
)
|
)
|
||||||
@ -110,9 +145,9 @@ import sco_dump_db
|
|||||||
|
|
||||||
from VERSION import SCOVERSION, SCONEWS
|
from VERSION import SCOVERSION, SCONEWS
|
||||||
|
|
||||||
if hasattr(CONFIG, "ABSOLUTE_URL") and CONFIG.ABSOLUTE_URL:
|
if hasattr(scu.CONFIG, "ABSOLUTE_URL") and scu.CONFIG.ABSOLUTE_URL:
|
||||||
log("ScoDoc: ABSOLUTE_URL='%s'" % CONFIG.ABSOLUTE_URL)
|
log("ScoDoc: ABSOLUTE_URL='%s'" % scu.CONFIG.ABSOLUTE_URL)
|
||||||
log("ScoDoc: using encoding %s" % SCO_ENCODING)
|
log("ScoDoc: using encoding %s" % scu.SCO_ENCODING)
|
||||||
|
|
||||||
# import essai_cas
|
# import essai_cas
|
||||||
|
|
||||||
@ -171,11 +206,11 @@ class ZScolar(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
|
|||||||
# The for used to edit this object
|
# The for used to edit this object
|
||||||
security.declareProtected(ScoView, "manage_editZScolar")
|
security.declareProtected(ScoView, "manage_editZScolar")
|
||||||
|
|
||||||
def manage_editZScolar(self, title, RESPONSE=None):
|
def manage_editZScolar(self, title, REQUEST=None):
|
||||||
"Changes the instance values"
|
"Changes the instance values"
|
||||||
self.title = title
|
self.title = title
|
||||||
self._p_changed = 1
|
self._p_changed = 1
|
||||||
RESPONSE.redirect("manage_editForm")
|
return REQUEST.RESPONSE.redirect("manage_editForm")
|
||||||
|
|
||||||
def _setup_initial_roles_and_permissions(self):
|
def _setup_initial_roles_and_permissions(self):
|
||||||
"""Initialize roles and permissions
|
"""Initialize roles and permissions
|
||||||
@ -197,8 +232,10 @@ class ZScolar(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
|
|||||||
H.append(r)
|
H.append(r)
|
||||||
ok = False
|
ok = False
|
||||||
|
|
||||||
for permission in Sco_Default_Permissions.keys():
|
for permission in sco_permissions.Sco_Default_Permissions.keys():
|
||||||
roles = [r + DeptId for r in Sco_Default_Permissions[permission]]
|
roles = [
|
||||||
|
r + DeptId for r in sco_permissions.Sco_Default_Permissions[permission]
|
||||||
|
]
|
||||||
roles.append("Manager")
|
roles.append("Manager")
|
||||||
log("granting '%s' to %s" % (permission, roles))
|
log("granting '%s' to %s" % (permission, roles))
|
||||||
try:
|
try:
|
||||||
@ -257,11 +294,16 @@ class ZScolar(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<p>
|
<p>
|
||||||
UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span class="span_ue_apo" style="display: inline" id="toto">VRTU11</span>)</span>
|
<tt>
|
||||||
<span class="locked">[verrouillé]</span>
|
REQUEST.URL=%s<br/>
|
||||||
|
REQUEST.URL0=%s<br/>
|
||||||
|
</tt>
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
"""
|
""" % (
|
||||||
|
REQUEST.URL,
|
||||||
|
REQUEST.URL0,
|
||||||
|
)
|
||||||
# return (
|
# return (
|
||||||
# self.sco_header(REQUEST)
|
# self.sco_header(REQUEST)
|
||||||
# + """<div class="xp">%s</div>""" % x
|
# + """<div class="xp">%s</div>""" % x
|
||||||
@ -271,51 +313,51 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
# raise ValueError("essai exception")
|
# raise ValueError("essai exception")
|
||||||
# raise ScoValueError('essai exception !', dest_url='totoro', REQUEST=REQUEST)
|
# raise ScoValueError('essai exception !', dest_url='totoro', REQUEST=REQUEST)
|
||||||
|
|
||||||
# cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
# cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
# cursor.execute("select * from notes_formations")
|
# cursor.execute("select * from notes_formations")
|
||||||
# b += str(cursor.fetchall())
|
# b += str(cursor.fetchall())
|
||||||
# b = self.Notes.gloups()
|
# b = self.Notes.gloups()
|
||||||
# raise NoteProcessError('test exception !')
|
# raise NoteProcessError('test exception !')
|
||||||
|
|
||||||
# essai: liste des permissions
|
# essai: liste des permissions
|
||||||
from AccessControl import getSecurityManager # pylint: disable=import-error
|
# from AccessControl import getSecurityManager # pylint: disable=import-error
|
||||||
from AccessControl.Permission import Permission # pylint: disable=import-error
|
# from AccessControl.Permission import Permission # pylint: disable=import-error
|
||||||
|
|
||||||
permissions = self.ac_inherited_permissions(1)
|
# permissions = self.ac_inherited_permissions(1)
|
||||||
scoperms = [p for p in permissions if p[0][:3] == "Sco"]
|
# scoperms = [p for p in permissions if p[0][:3] == "Sco"]
|
||||||
# H.append( str(self.aq_parent.aq_parent.permission_settings()) )
|
# # H.append( str(self.aq_parent.aq_parent.permission_settings()) )
|
||||||
# H.append('<p>perms: %s</p>'%str(scoperms))
|
# # H.append('<p>perms: %s</p>'%str(scoperms))
|
||||||
# H.append('<p>valid_roles: %s</p>'%str(self.valid_roles()))
|
# # H.append('<p>valid_roles: %s</p>'%str(self.valid_roles()))
|
||||||
# H.append('<p>ac_inherited_permissions=%s</p>'%str(self.ac_inherited_permissions(1)))
|
# # H.append('<p>ac_inherited_permissions=%s</p>'%str(self.ac_inherited_permissions(1)))
|
||||||
def collect_roles(context, rd):
|
# def collect_roles(context, rd):
|
||||||
for p in scoperms:
|
# for p in scoperms:
|
||||||
name, value = p[:2]
|
# name, value = p[:2]
|
||||||
P = Permission(name, value, context)
|
# P = Permission(name, value, context)
|
||||||
roles = list(P.getRoles())
|
# roles = list(P.getRoles())
|
||||||
if rd.has_key(name):
|
# if rd.has_key(name):
|
||||||
rd[name] += roles
|
# rd[name] += roles
|
||||||
else:
|
# else:
|
||||||
rd[name] = roles
|
# rd[name] = roles
|
||||||
if hasattr(context, "aq_parent"):
|
# if hasattr(context, "aq_parent"):
|
||||||
collect_roles(context.aq_parent, rd)
|
# collect_roles(context.aq_parent, rd)
|
||||||
|
|
||||||
b = ""
|
# b = ""
|
||||||
rd = {}
|
# rd = {}
|
||||||
collect_roles(self, rd)
|
# collect_roles(self, rd)
|
||||||
b = "<p>" + str(rd) + "</p>"
|
# b = "<p>" + str(rd) + "</p>"
|
||||||
|
|
||||||
authuser = REQUEST.AUTHENTICATED_USER
|
# authuser = REQUEST.AUTHENTICATED_USER
|
||||||
for p in scoperms:
|
# for p in scoperms:
|
||||||
permname, value = p[:2]
|
# permname, _ = p[:2]
|
||||||
b += "<p>" + permname + " : "
|
# b += "<p>" + permname + " : "
|
||||||
if authuser.has_permission(permname, self):
|
# if authuser.has_permission(permname, self):
|
||||||
b += "yes"
|
# b += "yes"
|
||||||
else:
|
# else:
|
||||||
b += "no"
|
# b += "no"
|
||||||
b += "</p>"
|
# b += "</p>"
|
||||||
b += "<p>xxx</p><hr><p>" + str(self.aq_parent.aq_parent)
|
# b += "<p>xxx</p><hr><p>" + str(self.aq_parent.aq_parent)
|
||||||
|
|
||||||
return self.sco_header(REQUEST) + str(b) + self.sco_footer(REQUEST)
|
# return self.sco_header(REQUEST) + str(b) + self.sco_footer(REQUEST)
|
||||||
|
|
||||||
# essais calendriers:
|
# essais calendriers:
|
||||||
security.declareProtected(ScoView, "experimental_calendar")
|
security.declareProtected(ScoView, "experimental_calendar")
|
||||||
@ -326,11 +368,39 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
security.declareProtected(ScoView, "ScoURL")
|
security.declareProtected(ScoView, "ScoURL")
|
||||||
|
|
||||||
def ScoURL(self):
|
def ScoURL(self):
|
||||||
"base URL for this sco instance"
|
"""base URL for this sco instance.
|
||||||
|
e.g. https://scodoc.xxx.fr/ScoDoc/DEPT/Scolarite
|
||||||
|
= page accueil département
|
||||||
|
"""
|
||||||
# absolute_url is the classic Zope method
|
# absolute_url is the classic Zope method
|
||||||
# The avoid the burden of configuring a proxy zope object, we offer
|
# The avoid the burden of configuring a proxy zope object, we offer
|
||||||
# a custom configuration via scodoc_config
|
# a custom configuration via scodoc_config
|
||||||
return CONFIG.ABSOLUTE_URL or self.absolute_url()
|
# XXX ne devrait pas marcher car l'URL dépend du département !!!
|
||||||
|
return scu.CONFIG.ABSOLUTE_URL or self.absolute_url()
|
||||||
|
|
||||||
|
def NotesURL(self):
|
||||||
|
"""URL of Notes
|
||||||
|
e.g. https://scodoc.xxx.fr/ScoDoc/DEPT/Scolarite/Notes
|
||||||
|
= url de base des requêtes de ZNotes
|
||||||
|
et page accueil programmes.
|
||||||
|
"""
|
||||||
|
return self.ScoURL() + "/Notes"
|
||||||
|
|
||||||
|
def EntreprisesURL(self):
|
||||||
|
"""URL of Enterprises
|
||||||
|
e.g. https://scodoc.xxx.fr/ScoDoc/DEPT/Scolarite/Entreprises
|
||||||
|
= url de base des requêtes de ZEntreprises
|
||||||
|
et page accueil Entreprises
|
||||||
|
"""
|
||||||
|
return self.ScoURL() + "/Entreprises"
|
||||||
|
|
||||||
|
def UsersURL(self):
|
||||||
|
"""URL of Users
|
||||||
|
e.g. https://scodoc.xxx.fr/ScoDoc/DEPT/Scolarite/Users
|
||||||
|
= url de base des requêtes ZScoUsers
|
||||||
|
et page accueil users
|
||||||
|
"""
|
||||||
|
return self.ScoURL() + "/Users"
|
||||||
|
|
||||||
security.declareProtected(ScoView, "sco_header")
|
security.declareProtected(ScoView, "sco_header")
|
||||||
sco_header = html_sco_header.sco_header
|
sco_header = html_sco_header.sco_header
|
||||||
@ -349,7 +419,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
return self._db_cnx_string
|
return self._db_cnx_string
|
||||||
|
|
||||||
security.declareProtected(ScoSuperAdmin, "GetDBConnexion")
|
security.declareProtected(ScoSuperAdmin, "GetDBConnexion")
|
||||||
GetDBConnexion = notesdb.GetDBConnexion
|
GetDBConnexion = ndb.GetDBConnexion
|
||||||
|
|
||||||
# A enlever après re-ecriture de ZEntreprises.py
|
# A enlever après re-ecriture de ZEntreprises.py
|
||||||
security.declareProtected(ScoView, "TrivialFormulator")
|
security.declareProtected(ScoView, "TrivialFormulator")
|
||||||
@ -392,10 +462,10 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
"version info"
|
"version info"
|
||||||
H = [
|
H = [
|
||||||
"""<h2>Système de gestion scolarité</h2>
|
"""<h2>Système de gestion scolarité</h2>
|
||||||
<p>© Emmanuel Viennet 1997-2020</p>
|
<p>© Emmanuel Viennet 1997-2021</p>
|
||||||
<p>Version %s</p>
|
<p>Version %s</p>
|
||||||
"""
|
"""
|
||||||
% (sco_utils.get_scodoc_version())
|
% (scu.get_scodoc_version())
|
||||||
]
|
]
|
||||||
H.append(
|
H.append(
|
||||||
'<p>Logiciel libre écrit en <a href="http://www.python.org">Python</a>.</p><p>Utilise <a href="http://www.reportlab.org/">ReportLab</a> pour générer les documents PDF, et <a href="http://sourceforge.net/projects/pyexcelerator">pyExcelerator</a> pour le traitement des documents Excel.</p>'
|
'<p>Logiciel libre écrit en <a href="http://www.python.org">Python</a>.</p><p>Utilise <a href="http://www.reportlab.org/">ReportLab</a> pour générer les documents PDF, et <a href="http://sourceforge.net/projects/pyexcelerator">pyExcelerator</a> pour le traitement des documents Excel.</p>'
|
||||||
@ -403,7 +473,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
H.append("<h2>Dernières évolutions</h2>" + SCONEWS)
|
H.append("<h2>Dernières évolutions</h2>" + SCONEWS)
|
||||||
H.append(
|
H.append(
|
||||||
'<div class="about-logo">'
|
'<div class="about-logo">'
|
||||||
+ icontag("borgne_img")
|
+ scu.icontag("borgne_img")
|
||||||
+ " <em>Au pays des aveugles...</em></div>"
|
+ " <em>Au pays des aveugles...</em></div>"
|
||||||
)
|
)
|
||||||
d = ""
|
d = ""
|
||||||
@ -417,12 +487,12 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
if format == "html" or format == "pdf":
|
if format == "html" or format == "pdf":
|
||||||
raise ScoValueError(msg)
|
raise ScoValueError(msg)
|
||||||
elif format == "xml":
|
elif format == "xml":
|
||||||
REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE)
|
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
|
||||||
doc = jaxml.XML_document(encoding=SCO_ENCODING)
|
doc = jaxml.XML_document(encoding=scu.SCO_ENCODING)
|
||||||
doc.error(msg=msg)
|
doc.error(msg=msg)
|
||||||
return repr(doc)
|
return repr(doc)
|
||||||
elif format == "json":
|
elif format == "json":
|
||||||
REQUEST.RESPONSE.setHeader("content-type", JSON_MIMETYPE)
|
REQUEST.RESPONSE.setHeader("content-type", scu.JSON_MIMETYPE)
|
||||||
return "undefined" # XXX voir quoi faire en cas d'erreur json
|
return "undefined" # XXX voir quoi faire en cas d'erreur json
|
||||||
else:
|
else:
|
||||||
raise ValueError("ScoErrorResponse: invalid format")
|
raise ValueError("ScoErrorResponse: invalid format")
|
||||||
@ -517,7 +587,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
page_title="Opérations sur %(nomprenom)s" % etud,
|
page_title="Opérations sur %(nomprenom)s" % etud,
|
||||||
html_title="<h2>Opérations effectuées sur l'étudiant %(nomprenom)s</h2>"
|
html_title="<h2>Opérations effectuées sur l'étudiant %(nomprenom)s</h2>"
|
||||||
% etud,
|
% etud,
|
||||||
filename="log_" + make_filename(etud["nomprenom"]),
|
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>'
|
html_next_section='<ul><li><a href="ficheEtud?etudid=%(etudid)s">fiche de %(nomprenom)s</a></li></ul>'
|
||||||
% etud,
|
% etud,
|
||||||
preferences=self.get_preferences(),
|
preferences=self.get_preferences(),
|
||||||
@ -530,7 +600,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
def listScoLog(self, etudid):
|
def listScoLog(self, etudid):
|
||||||
"liste des operations effectuees sur cet etudiant"
|
"liste des operations effectuees sur cet etudiant"
|
||||||
cnx = self.GetDBConnexion()
|
cnx = self.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"select * from scolog where etudid=%(etudid)s ORDER BY DATE DESC",
|
"select * from scolog where etudid=%(etudid)s ORDER BY DATE DESC",
|
||||||
{"etudid": etudid},
|
{"etudid": etudid},
|
||||||
@ -545,7 +615,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
|
|
||||||
def rssnews(self, REQUEST=None):
|
def rssnews(self, REQUEST=None):
|
||||||
"rss feed"
|
"rss feed"
|
||||||
REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE)
|
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
|
||||||
return sco_news.scolar_news_summary_rss(
|
return sco_news.scolar_news_summary_rss(
|
||||||
self, "Nouvelles de " + self.get_preference("DeptName"), self.ScoURL()
|
self, "Nouvelles de " + self.get_preference("DeptName"), self.ScoURL()
|
||||||
)
|
)
|
||||||
@ -846,18 +916,19 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
"nom": "?",
|
"nom": "?",
|
||||||
"nom_usuel": "",
|
"nom_usuel": "",
|
||||||
"prenom": "?",
|
"prenom": "?",
|
||||||
"sexe": "?",
|
"civilite": "?",
|
||||||
|
"sexe": "?", # for backward compat
|
||||||
"email": "?",
|
"email": "?",
|
||||||
"emailperso": "",
|
"emailperso": "",
|
||||||
"error": "code etudiant inconnu",
|
"error": "code etudiant inconnu",
|
||||||
}
|
}
|
||||||
return sendResult(
|
return scu.sendResult(
|
||||||
REQUEST, d, name="etudiant", format=format, force_outer_xml_tag=False
|
REQUEST, d, name="etudiant", format=format, force_outer_xml_tag=False
|
||||||
)
|
)
|
||||||
d = {}
|
d = {}
|
||||||
etud = etuds[0]
|
etud = etuds[0]
|
||||||
self.fillEtudsInfo([etud])
|
self.fillEtudsInfo([etud])
|
||||||
etud["date_naissance_iso"] = DateDMYtoISO(etud["date_naissance"])
|
etud["date_naissance_iso"] = ndb.DateDMYtoISO(etud["date_naissance"])
|
||||||
for a in (
|
for a in (
|
||||||
"etudid",
|
"etudid",
|
||||||
"code_nip",
|
"code_nip",
|
||||||
@ -865,7 +936,6 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
"nom",
|
"nom",
|
||||||
"nom_usuel",
|
"nom_usuel",
|
||||||
"prenom",
|
"prenom",
|
||||||
"sexe",
|
|
||||||
"nomprenom",
|
"nomprenom",
|
||||||
"email",
|
"email",
|
||||||
"emailperso",
|
"emailperso",
|
||||||
@ -885,8 +955,12 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
"codelycee",
|
"codelycee",
|
||||||
"date_naissance_iso",
|
"date_naissance_iso",
|
||||||
):
|
):
|
||||||
d[a] = quote_xml_attr(etud[a])
|
d[a] = scu.quote_xml_attr(etud[a])
|
||||||
d["photo_url"] = quote_xml_attr(sco_photos.etud_photo_url(self, etud))
|
d["civilite"] = scu.quote_xml_attr(
|
||||||
|
etud["civilite_str"]
|
||||||
|
) # exception: ne sort pas la civilite brute
|
||||||
|
d["sexe"] = d["civilite"] # backward compat pour anciens clients
|
||||||
|
d["photo_url"] = scu.quote_xml_attr(sco_photos.etud_photo_url(self, etud))
|
||||||
|
|
||||||
sem = etud["cursem"]
|
sem = etud["cursem"]
|
||||||
if sem:
|
if sem:
|
||||||
@ -895,10 +969,10 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
{
|
{
|
||||||
"current": "1",
|
"current": "1",
|
||||||
"formsemestre_id": sem["formsemestre_id"],
|
"formsemestre_id": sem["formsemestre_id"],
|
||||||
"date_debut": DateDMYtoISO(sem["date_debut"]),
|
"date_debut": ndb.DateDMYtoISO(sem["date_debut"]),
|
||||||
"date_fin": DateDMYtoISO(sem["date_fin"]),
|
"date_fin": ndb.DateDMYtoISO(sem["date_fin"]),
|
||||||
"etat": quote_xml_attr(sem["ins"]["etat"]),
|
"etat": scu.quote_xml_attr(sem["ins"]["etat"]),
|
||||||
"groupes": quote_xml_attr(
|
"groupes": scu.quote_xml_attr(
|
||||||
etud["groupes"]
|
etud["groupes"]
|
||||||
), # slt pour semestre courant
|
), # slt pour semestre courant
|
||||||
}
|
}
|
||||||
@ -910,14 +984,14 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
d["insemestre"].append(
|
d["insemestre"].append(
|
||||||
{
|
{
|
||||||
"formsemestre_id": sem["formsemestre_id"],
|
"formsemestre_id": sem["formsemestre_id"],
|
||||||
"date_debut": DateDMYtoISO(sem["date_debut"]),
|
"date_debut": ndb.DateDMYtoISO(sem["date_debut"]),
|
||||||
"date_fin": DateDMYtoISO(sem["date_fin"]),
|
"date_fin": ndb.DateDMYtoISO(sem["date_fin"]),
|
||||||
"etat": quote_xml_attr(sem["ins"]["etat"]),
|
"etat": scu.quote_xml_attr(sem["ins"]["etat"]),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
log("etud_info (%gs)" % (time.time() - t0))
|
log("etud_info (%gs)" % (time.time() - t0))
|
||||||
return sendResult(
|
return scu.sendResult(
|
||||||
REQUEST, d, name="etudiant", format=format, force_outer_xml_tag=False
|
REQUEST, d, name="etudiant", format=format, force_outer_xml_tag=False
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -960,7 +1034,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
def _descr_situation_etud(self, etudid, ne=""):
|
def _descr_situation_etud(self, etudid, ne=""):
|
||||||
"""chaine decrivant la situation actuelle de l'etudiant"""
|
"""chaine decrivant la situation actuelle de l'etudiant"""
|
||||||
cnx = self.GetDBConnexion()
|
cnx = self.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"select I.formsemestre_id, I.etat from notes_formsemestre_inscription I, notes_formsemestre S where etudid=%(etudid)s and S.formsemestre_id = I.formsemestre_id and date_debut < now() and date_fin > now() order by S.date_debut desc;",
|
"select I.formsemestre_id, I.etat from notes_formsemestre_inscription I, notes_formsemestre S where etudid=%(etudid)s and S.formsemestre_id = I.formsemestre_id and date_debut < now() and date_fin > now() order by S.date_debut desc;",
|
||||||
{"etudid": etudid},
|
{"etudid": etudid},
|
||||||
@ -1052,7 +1126,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
logdb(REQUEST, cnx, method="addAnnotation", etudid=etudid)
|
logdb(REQUEST, cnx, method="addAnnotation", etudid=etudid)
|
||||||
REQUEST.RESPONSE.redirect("ficheEtud?etudid=" + etudid)
|
return REQUEST.RESPONSE.redirect("ficheEtud?etudid=" + etudid)
|
||||||
|
|
||||||
security.declareProtected(ScoView, "canSuppressAnnotation")
|
security.declareProtected(ScoView, "canSuppressAnnotation")
|
||||||
|
|
||||||
@ -1091,7 +1165,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
logdb(REQUEST, cnx, method="SuppressAnnotation", etudid=etudid)
|
logdb(REQUEST, cnx, method="SuppressAnnotation", etudid=etudid)
|
||||||
scolars.etud_annotations_delete(cnx, annotation_id)
|
scolars.etud_annotations_delete(cnx, annotation_id)
|
||||||
|
|
||||||
REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
"ficheEtud?etudid=%s&head_message=Annotation%%20supprimée" % (etudid)
|
"ficheEtud?etudid=%s&head_message=Annotation%%20supprimée" % (etudid)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1150,17 +1224,18 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
initvalues=adr,
|
initvalues=adr,
|
||||||
submitlabel="Valider le formulaire",
|
submitlabel="Valider le formulaire",
|
||||||
)
|
)
|
||||||
|
dest_url = self.ScoURL() + "/ficheEtud?etudid=" + etudid
|
||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return header + "\n".join(H) + tf[1] + self.sco_footer(REQUEST)
|
return header + "\n".join(H) + tf[1] + self.sco_footer(REQUEST)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(dest_url)
|
||||||
else:
|
else:
|
||||||
if adrs:
|
if adrs:
|
||||||
scolars.adresse_edit(cnx, args=tf[2], context=self)
|
scolars.adresse_edit(cnx, args=tf[2], context=self)
|
||||||
else:
|
else:
|
||||||
scolars.adresse_create(cnx, args=tf[2])
|
scolars.adresse_create(cnx, args=tf[2])
|
||||||
logdb(REQUEST, cnx, method="changeCoordonnees", etudid=etudid)
|
logdb(REQUEST, cnx, method="changeCoordonnees", etudid=etudid)
|
||||||
REQUEST.RESPONSE.redirect("ficheEtud?etudid=" + etudid)
|
return REQUEST.RESPONSE.redirect(dest_url)
|
||||||
|
|
||||||
# --- Gestion des groupes:
|
# --- Gestion des groupes:
|
||||||
security.declareProtected(ScoView, "affectGroups")
|
security.declareProtected(ScoView, "affectGroups")
|
||||||
@ -1273,6 +1348,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
submitlabel="Valider",
|
submitlabel="Valider",
|
||||||
cancelbutton="Annuler",
|
cancelbutton="Annuler",
|
||||||
)
|
)
|
||||||
|
dest_url = self.ScoURL() + "/ficheEtud?etudid=" + etud["etudid"]
|
||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return (
|
return (
|
||||||
"\n".join(H)
|
"\n".join(H)
|
||||||
@ -1282,16 +1358,12 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
+ self.sco_footer(REQUEST)
|
+ self.sco_footer(REQUEST)
|
||||||
)
|
)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(dest_url)
|
||||||
REQUEST.URL1 + "/ficheEtud?etudid=" + etud["etudid"]
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
data = tf[2]["photofile"].read()
|
data = tf[2]["photofile"].read()
|
||||||
status, diag = sco_photos.store_photo(self, etud, data, REQUEST=REQUEST)
|
status, diag = sco_photos.store_photo(self, etud, data, REQUEST=REQUEST)
|
||||||
if status != 0:
|
if status != 0:
|
||||||
return REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(dest_url)
|
||||||
self.ScoURL() + "/ficheEtud?etudid=" + etud["etudid"]
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
H.append('<p class="warning">Erreur:' + diag + "</p>")
|
H.append('<p class="warning">Erreur:' + diag + "</p>")
|
||||||
return "\n".join(H) + self.sco_footer(REQUEST)
|
return "\n".join(H) + self.sco_footer(REQUEST)
|
||||||
@ -1313,7 +1385,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
sco_photos.suppress_photo(self, etud, REQUEST=REQUEST)
|
sco_photos.suppress_photo(self, etud, REQUEST=REQUEST)
|
||||||
|
|
||||||
return REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
REQUEST.URL1 + "/ficheEtud?etudid=" + etud["etudid"]
|
self.ScoURL() + "/ficheEtud?etudid=" + etud["etudid"]
|
||||||
)
|
)
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -1350,7 +1422,6 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
operation_method="",
|
operation_method="",
|
||||||
):
|
):
|
||||||
"Formulaire démission ou défaillance Etudiant"
|
"Formulaire démission ou défaillance Etudiant"
|
||||||
cnx = self.GetDBConnexion()
|
|
||||||
etud = self.getEtudInfo(etudid=etudid, filled=1, REQUEST=REQUEST)[0]
|
etud = self.getEtudInfo(etudid=etudid, filled=1, REQUEST=REQUEST)[0]
|
||||||
sem = sco_formsemestre.get_formsemestre(self, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(self, formsemestre_id)
|
||||||
if sem["etat"] != "1":
|
if sem["etat"] != "1":
|
||||||
@ -1374,7 +1445,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
"""<form action="%s" method="get">
|
"""<form action="%s" method="get">
|
||||||
<b>Date de la %s (J/M/AAAA): </b>
|
<b>Date de la %s (J/M/AAAA): </b>
|
||||||
"""
|
"""
|
||||||
% (operation_method, strlower(operation_name))
|
% (operation_method, scu.strlower(operation_name))
|
||||||
)
|
)
|
||||||
H.append(
|
H.append(
|
||||||
"""
|
"""
|
||||||
@ -1410,7 +1481,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
etudid,
|
etudid,
|
||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
event_date=event_date,
|
event_date=event_date,
|
||||||
etat_new=DEF,
|
etat_new=sco_codes_parcours.DEF,
|
||||||
operation_method="defailleEtudiant",
|
operation_method="defailleEtudiant",
|
||||||
event_type="DEFAILLANCE",
|
event_type="DEFAILLANCE",
|
||||||
REQUEST=REQUEST,
|
REQUEST=REQUEST,
|
||||||
@ -1488,7 +1559,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
dialog_confirmed=dialog_confirmed,
|
dialog_confirmed=dialog_confirmed,
|
||||||
args=args,
|
args=args,
|
||||||
operation_name="défaillance",
|
operation_name="défaillance",
|
||||||
etat_current=DEF,
|
etat_current=sco_codes_parcours.DEF,
|
||||||
etat_new="I",
|
etat_new="I",
|
||||||
operation_method="cancelDef",
|
operation_method="cancelDef",
|
||||||
event_type="DEFAILLANCE",
|
event_type="DEFAILLANCE",
|
||||||
@ -1544,7 +1615,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
args=ins, formsemestre_id=formsemestre_id
|
args=ins, formsemestre_id=formsemestre_id
|
||||||
)
|
)
|
||||||
logdb(REQUEST, cnx, method=operation_method, etudid=etudid)
|
logdb(REQUEST, cnx, method=operation_method, etudid=etudid)
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"delete from scolar_events where etudid=%(etudid)s and formsemestre_id=%(formsemestre_id)s and event_type='"
|
"delete from scolar_events where etudid=%(etudid)s and formsemestre_id=%(formsemestre_id)s and event_type='"
|
||||||
+ event_type
|
+ event_type
|
||||||
@ -1572,7 +1643,6 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
"Le formulaire HTML"
|
"Le formulaire HTML"
|
||||||
H = [self.sco_header(REQUEST, init_jquery_ui=True)]
|
H = [self.sco_header(REQUEST, init_jquery_ui=True)]
|
||||||
F = self.sco_footer(REQUEST)
|
F = self.sco_footer(REQUEST)
|
||||||
AUTHENTICATED_USER = REQUEST.AUTHENTICATED_USER
|
|
||||||
etudid = REQUEST.form.get("etudid", None)
|
etudid = REQUEST.form.get("etudid", None)
|
||||||
cnx = self.GetDBConnexion()
|
cnx = self.GetDBConnexion()
|
||||||
descr = []
|
descr = []
|
||||||
@ -1607,12 +1677,14 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
# recuperation infos Apogee
|
# recuperation infos Apogee
|
||||||
# Si on a le code NIP, fait juste une requete, sinon tente de rechercher par nom
|
# Si on a le code NIP, fait juste une requete, sinon tente de rechercher par nom
|
||||||
# (la recherche par nom ne fonctionne plus à Paris 13)
|
# (la recherche par nom ne fonctionne plus à Paris 13)
|
||||||
code_nip = initvalues.get("code_nip", "")
|
# XXX A terminer
|
||||||
if code_nip:
|
# code_nip = initvalues.get("code_nip", "")
|
||||||
try:
|
# if code_nip:
|
||||||
info = sco_portal_apogee.get_etud_apogee(self, code_nip)
|
# try:
|
||||||
except ValueError:
|
# infos = sco_portal_apogee.get_etud_apogee(self, code_nip)
|
||||||
pass # XXX a terminer
|
# except ValueError:
|
||||||
|
# infos = None
|
||||||
|
# pass # XXX a terminer
|
||||||
nom = REQUEST.form.get("nom", None)
|
nom = REQUEST.form.get("nom", None)
|
||||||
if nom is None:
|
if nom is None:
|
||||||
nom = initvalues.get("nom", None)
|
nom = initvalues.get("nom", None)
|
||||||
@ -1675,15 +1747,19 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
("nom_usuel", {"size": 25, "title": "Nom usuel", "allow_null": True}),
|
("nom_usuel", {"size": 25, "title": "Nom usuel", "allow_null": True}),
|
||||||
(
|
(
|
||||||
"prenom",
|
"prenom",
|
||||||
{"size": 25, "title": "Prénom", "allow_null": CONFIG.ALLOW_NULL_PRENOM},
|
{
|
||||||
|
"size": 25,
|
||||||
|
"title": "Prénom",
|
||||||
|
"allow_null": scu.CONFIG.ALLOW_NULL_PRENOM,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"sexe",
|
"civilite",
|
||||||
{
|
{
|
||||||
"input_type": "menu",
|
"input_type": "menu",
|
||||||
"labels": ["H", "F"],
|
"labels": ["Homme", "Femme", "Autre/neutre"],
|
||||||
"allowed_values": ["MR", "MME"],
|
"allowed_values": ["M", "F", "X"],
|
||||||
"title": "Genre",
|
"title": "Civilité",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
@ -1776,7 +1852,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
{
|
{
|
||||||
"input_type": "menu",
|
"input_type": "menu",
|
||||||
"title": "Voie d'admission",
|
"title": "Voie d'admission",
|
||||||
"allowed_values": TYPES_ADMISSION,
|
"allowed_values": scu.TYPES_ADMISSION,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
@ -2009,7 +2085,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
"billet_absence",
|
"billet_absence",
|
||||||
"identite",
|
"identite",
|
||||||
]
|
]
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
for table in tables:
|
for table in tables:
|
||||||
cursor.execute("delete from %s where etudid=%%(etudid)s" % table, etud)
|
cursor.execute("delete from %s where etudid=%%(etudid)s" % table, etud)
|
||||||
cnx.commit()
|
cnx.commit()
|
||||||
@ -2017,7 +2093,9 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
to_inval = [s["formsemestre_id"] for s in etud["sems"]]
|
to_inval = [s["formsemestre_id"] for s in etud["sems"]]
|
||||||
if to_inval:
|
if to_inval:
|
||||||
self.Notes._inval_cache(formsemestre_id_list=to_inval) # >
|
self.Notes._inval_cache(formsemestre_id_list=to_inval) # >
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(
|
||||||
|
self.ScoURL() + r"?head_message=Etudiant%20supprimé"
|
||||||
|
)
|
||||||
|
|
||||||
security.declareProtected(ScoEtudInscrit, "check_group_apogee")
|
security.declareProtected(ScoEtudInscrit, "check_group_apogee")
|
||||||
|
|
||||||
@ -2030,7 +2108,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
XXX A re-écrire pour API 2: prendre liste dans l'étape et vérifier à partir de cela.
|
XXX A re-écrire pour API 2: prendre liste dans l'étape et vérifier à partir de cela.
|
||||||
"""
|
"""
|
||||||
etat = etat or None
|
etat = etat or None
|
||||||
members, group, group_tit, sem, nbdem = sco_groups.get_group_infos(
|
members, group, _, sem, _ = sco_groups.get_group_infos(
|
||||||
self, group_id, etat=etat
|
self, group_id, etat=etat
|
||||||
)
|
)
|
||||||
formsemestre_id = group["formsemestre_id"]
|
formsemestre_id = group["formsemestre_id"]
|
||||||
@ -2136,8 +2214,8 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
% (
|
% (
|
||||||
REQUEST.URL0,
|
REQUEST.URL0,
|
||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
strnone(group_id),
|
scu.strnone(group_id),
|
||||||
strnone(etat),
|
scu.strnone(etat),
|
||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -2155,8 +2233,8 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
% (
|
% (
|
||||||
REQUEST.URL0,
|
REQUEST.URL0,
|
||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
strnone(group_id),
|
scu.strnone(group_id),
|
||||||
strnone(etat),
|
scu.strnone(etat),
|
||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -2169,8 +2247,13 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
|
|||||||
"formulaire import xls"
|
"formulaire import xls"
|
||||||
if formsemestre_id:
|
if formsemestre_id:
|
||||||
sem = sco_formsemestre.get_formsemestre(self.Notes, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(self.Notes, formsemestre_id)
|
||||||
|
dest_url = (
|
||||||
|
self.ScoURL()
|
||||||
|
+ "/formsemestre_status?formsemestre_id=%s" % formsemestre_id
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
sem = None
|
sem = None
|
||||||
|
dest_url = self.ScoURL()
|
||||||
if sem and sem["etat"] != "1":
|
if sem and sem["etat"] != "1":
|
||||||
raise ScoValueError("Modification impossible: semestre verrouille")
|
raise ScoValueError("Modification impossible: semestre verrouille")
|
||||||
H = [
|
H = [
|
||||||
@ -2286,7 +2369,7 @@ Les champs avec un astérisque (*) doivent être présents (nulls non autorisés
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + "</li></ol>" + "\n".join(S) + F
|
return "\n".join(H) + tf[1] + "</li></ol>" + "\n".join(S) + F
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(dest_url)
|
||||||
else:
|
else:
|
||||||
return ImportScolars.students_import_excel(
|
return ImportScolars.students_import_excel(
|
||||||
self,
|
self,
|
||||||
@ -2335,7 +2418,6 @@ Les champs avec un astérisque (*) doivent être présents (nulls non autorisés
|
|||||||
|
|
||||||
def form_students_import_infos_admissions(self, REQUEST, formsemestre_id=None):
|
def form_students_import_infos_admissions(self, REQUEST, formsemestre_id=None):
|
||||||
"formulaire import xls"
|
"formulaire import xls"
|
||||||
sem = sco_formsemestre.get_formsemestre(self.Notes, formsemestre_id)
|
|
||||||
authuser = REQUEST.AUTHENTICATED_USER
|
authuser = REQUEST.AUTHENTICATED_USER
|
||||||
F = self.sco_footer(REQUEST)
|
F = self.sco_footer(REQUEST)
|
||||||
if not authuser.has_permission(ScoEtudInscrit, self):
|
if not authuser.has_permission(ScoEtudInscrit, self):
|
||||||
@ -2424,7 +2506,11 @@ Les champs avec un astérisque (*) doivent être présents (nulls non autorisés
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + help_text + F
|
return "\n".join(H) + tf[1] + help_text + F
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(
|
||||||
|
self.ScoURL()
|
||||||
|
+ "/formsemestre_status?formsemestre_id="
|
||||||
|
+ formsemestre_id
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return self._students_import_admission(
|
return self._students_import_admission(
|
||||||
tf[2]["csvfile"],
|
tf[2]["csvfile"],
|
||||||
@ -2505,7 +2591,6 @@ Les champs avec un astérisque (*) doivent être présents (nulls non autorisés
|
|||||||
def stat_bac(self, formsemestre_id):
|
def stat_bac(self, formsemestre_id):
|
||||||
"Renvoie statistisques sur nb d'etudiants par bac"
|
"Renvoie statistisques sur nb d'etudiants par bac"
|
||||||
cnx = self.GetDBConnexion()
|
cnx = self.GetDBConnexion()
|
||||||
sem = sco_formsemestre.get_formsemestre(self, formsemestre_id)
|
|
||||||
ins = self.Notes.do_formsemestre_inscription_list(
|
ins = self.Notes.do_formsemestre_inscription_list(
|
||||||
args={"formsemestre_id": formsemestre_id}
|
args={"formsemestre_id": formsemestre_id}
|
||||||
)
|
)
|
||||||
@ -2634,23 +2719,23 @@ def manage_addZScolarForm(context, DeptId, REQUEST=None):
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + context.standard_html_footer(context)
|
return "\n".join(H) + tf[1] + context.standard_html_footer(context)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect("/ScoDoc")
|
||||||
else:
|
else:
|
||||||
DeptId = tf[2]["DeptId"].strip()
|
DeptId = tf[2]["DeptId"].strip()
|
||||||
db_cnx_string = tf[2]["db_cnx_string"].strip()
|
db_cnx_string = tf[2]["db_cnx_string"].strip()
|
||||||
# default connexion string
|
# default connexion string
|
||||||
if not db_cnx_string:
|
if not db_cnx_string:
|
||||||
db_name = "SCO" + DeptId.upper()
|
db_name = "SCO" + DeptId.upper()
|
||||||
db_user = SCO_DEFAULT_SQL_USER
|
db_user = scu.SCO_DEFAULT_SQL_USER
|
||||||
db_cnx_string = "user=%s dbname=%s port=%s" % (
|
db_cnx_string = "user=%s dbname=%s port=%s" % (
|
||||||
db_user,
|
db_user,
|
||||||
db_name,
|
db_name,
|
||||||
SCO_DEFAULT_SQL_PORT,
|
scu.SCO_DEFAULT_SQL_PORT,
|
||||||
)
|
)
|
||||||
# vérifie que la bd existe et possede le meme nom de dept.
|
# vérifie que la bd existe et possede le meme nom de dept.
|
||||||
try:
|
try:
|
||||||
cnx = psycopg2.connect(db_cnx_string)
|
cnx = psycopg2.connect(db_cnx_string)
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute("select * from sco_prefs where name='DeptName'")
|
cursor.execute("select * from sco_prefs where name='DeptName'")
|
||||||
except:
|
except:
|
||||||
return _simple_error_page(
|
return _simple_error_page(
|
||||||
|
@ -95,9 +95,6 @@ apt-get -y install python-cracklib # was python-crack
|
|||||||
apt-get -y install python-icalendar
|
apt-get -y install python-icalendar
|
||||||
apt-get -y install python-requests
|
apt-get -y install python-requests
|
||||||
|
|
||||||
# XXX to fix: mx not needed anymore !
|
|
||||||
apt-get -y install python-egenix-mxtools python-egenix-mxdatetime
|
|
||||||
|
|
||||||
|
|
||||||
# ------------
|
# ------------
|
||||||
SVNVERSION=$(cd ..; svnversion)
|
SVNVERSION=$(cd ..; svnversion)
|
||||||
|
@ -1070,6 +1070,21 @@ for dept in get_depts():
|
|||||||
"etape",
|
"etape",
|
||||||
["alter table notes_formsemestre_inscription add column etape text"],
|
["alter table notes_formsemestre_inscription add column etape text"],
|
||||||
)
|
)
|
||||||
|
# Migre identite.sexe vers identite.civilite: normalise valeurs: M, F, X
|
||||||
|
check_field(
|
||||||
|
cnx,
|
||||||
|
"identite",
|
||||||
|
"civilite",
|
||||||
|
[
|
||||||
|
"UPDATE identite set sexe='M' where upper(sexe) = 'M' or upper(sexe) = 'M.' or upper(sexe) = 'MR' or upper(sexe) = 'H'",
|
||||||
|
"UPDATE identite set sexe='F' where upper(sexe) = 'F' or upper(sexe) = 'MME' or upper(sexe) = 'MLLE' or upper(sexe) = 'MELLE' or upper(sexe) = 'MLLE.' or upper(sexe) = 'F'",
|
||||||
|
"UPDATE identite set sexe='X' where sexe is NULL",
|
||||||
|
"ALTER TABLE identite RENAME COLUMN sexe TO civilite",
|
||||||
|
"ALTER TABLE identite ALTER COLUMN civilite SET NOT NULL",
|
||||||
|
"ALTER TABLE identite ADD CONSTRAINT civchk CHECK (civilite IN ('M', 'F', 'X'))",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
# Add here actions to performs after upgrades:
|
# Add here actions to performs after upgrades:
|
||||||
cnx.commit()
|
cnx.commit()
|
||||||
cnx.close()
|
cnx.close()
|
||||||
|
28
csv2rules.py
28
csv2rules.py
@ -45,7 +45,27 @@ HEAD = """# -*- coding: utf-8 -*-
|
|||||||
#
|
#
|
||||||
# Command: %s %s
|
# Command: %s %s
|
||||||
#
|
#
|
||||||
from sco_codes_parcours import *
|
from sco_codes_parcours import (
|
||||||
|
DUTRule,
|
||||||
|
ADC,
|
||||||
|
ADJ,
|
||||||
|
ADM,
|
||||||
|
AJ,
|
||||||
|
ALL,
|
||||||
|
ATB,
|
||||||
|
ATJ,
|
||||||
|
ATT,
|
||||||
|
CMP,
|
||||||
|
NAR,
|
||||||
|
NEXT,
|
||||||
|
RA_OR_NEXT,
|
||||||
|
RA_OR_RS,
|
||||||
|
RAT,
|
||||||
|
REO,
|
||||||
|
REDOANNEE,
|
||||||
|
REDOSEM,
|
||||||
|
RS_OR_NEXT,
|
||||||
|
)
|
||||||
|
|
||||||
rules_source_file='%s'
|
rules_source_file='%s'
|
||||||
|
|
||||||
@ -55,15 +75,15 @@ rules_source_file='%s'
|
|||||||
sourcefile,
|
sourcefile,
|
||||||
)
|
)
|
||||||
|
|
||||||
from sco_codes_parcours import *
|
import sco_utils as scu
|
||||||
|
|
||||||
|
|
||||||
def _fmt(s):
|
def _fmt(s):
|
||||||
if not s:
|
if not s:
|
||||||
return None
|
return None
|
||||||
if strlower(s) in ("ok", "oui", "o", "y", "yes"):
|
if scu.strlower(s) in ("ok", "oui", "o", "y", "yes"):
|
||||||
return True
|
return True
|
||||||
if strlower(s) in ("no", "non"):
|
if scu.strlower(s) in ("no", "non"):
|
||||||
return False
|
return False
|
||||||
if s == "*":
|
if s == "*":
|
||||||
return ALL
|
return ALL
|
||||||
|
8
debug.py
8
debug.py
@ -32,10 +32,13 @@ nt = context.Notes._getNotesCache().get_NotesTable(context.Notes, formsemestre_i
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
import pdb
|
import pdb
|
||||||
|
import pprint
|
||||||
|
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
|
from notesdb import * # pylint: disable=unused-wildcard-import
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
|
from sco_utils import * # pylint: disable=unused-wildcard-import
|
||||||
|
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
import sco_archives
|
import sco_archives
|
||||||
@ -106,7 +109,6 @@ class DummyRequest:
|
|||||||
self.AUTHENTICATED_USER = FakeUser("admin")
|
self.AUTHENTICATED_USER = FakeUser("admin")
|
||||||
self.form = {}
|
self.form = {}
|
||||||
self.URL = "http://scodoc/"
|
self.URL = "http://scodoc/"
|
||||||
self.URL1 = self.URL
|
|
||||||
self.URL0 = self.URL
|
self.URL0 = self.URL
|
||||||
self.BASE0 = "localhost"
|
self.BASE0 = "localhost"
|
||||||
self.REMOTE_HOST = "localhost"
|
self.REMOTE_HOST = "localhost"
|
||||||
|
@ -25,7 +25,9 @@
|
|||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from sco_utils import *
|
import cgi
|
||||||
|
|
||||||
|
import sco_utils as scu
|
||||||
from sco_formsemestre_status import formsemestre_page_title
|
from sco_formsemestre_status import formsemestre_page_title
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -95,7 +97,7 @@ def sco_header(
|
|||||||
"page_title": page_title or context.title_or_id(),
|
"page_title": page_title or context.title_or_id(),
|
||||||
"no_side_bar": no_side_bar,
|
"no_side_bar": no_side_bar,
|
||||||
"ScoURL": context.ScoURL(),
|
"ScoURL": context.ScoURL(),
|
||||||
"encoding": SCO_ENCODING,
|
"encoding": scu.SCO_ENCODING,
|
||||||
"titrebandeau_mkup": "<td>" + titrebandeau + "</td>",
|
"titrebandeau_mkup": "<td>" + titrebandeau + "</td>",
|
||||||
"authuser": str(REQUEST.AUTHENTICATED_USER),
|
"authuser": str(REQUEST.AUTHENTICATED_USER),
|
||||||
}
|
}
|
||||||
@ -224,7 +226,7 @@ def sco_header(
|
|||||||
|
|
||||||
# Body et bandeau haut:
|
# Body et bandeau haut:
|
||||||
H.append("""<body %(bodyOnLoad_mkup)s>""" % params)
|
H.append("""<body %(bodyOnLoad_mkup)s>""" % params)
|
||||||
H.append(CUSTOM_HTML_HEADER)
|
H.append(scu.CUSTOM_HTML_HEADER)
|
||||||
#
|
#
|
||||||
if not no_side_bar:
|
if not no_side_bar:
|
||||||
H.append(context.sidebar(REQUEST))
|
H.append(context.sidebar(REQUEST))
|
||||||
@ -258,4 +260,6 @@ def sco_header(
|
|||||||
|
|
||||||
def sco_footer(context, REQUEST=None):
|
def sco_footer(context, REQUEST=None):
|
||||||
"""Main HTMl pages footer"""
|
"""Main HTMl pages footer"""
|
||||||
return """</div><!-- /gtrcontent -->""" + CUSTOM_HTML_FOOTER + """</body></html>"""
|
return (
|
||||||
|
"""</div><!-- /gtrcontent -->""" + scu.CUSTOM_HTML_FOOTER + """</body></html>"""
|
||||||
|
)
|
||||||
|
@ -25,8 +25,14 @@
|
|||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from sco_abs import getAbsSemEtud
|
from sco_abs import getAbsSemEtud
|
||||||
|
from sco_permissions import (
|
||||||
|
ScoUsersAdmin,
|
||||||
|
ScoUsersView,
|
||||||
|
ScoChangePreferences,
|
||||||
|
ScoAbsChange,
|
||||||
|
)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Génération de la "sidebar" (marge gauche des pages HTML)
|
Génération de la "sidebar" (marge gauche des pages HTML)
|
||||||
@ -76,7 +82,7 @@ def sidebar_common(context, REQUEST=None):
|
|||||||
def sidebar(context, REQUEST=None):
|
def sidebar(context, REQUEST=None):
|
||||||
"Main HTML page sidebar"
|
"Main HTML page sidebar"
|
||||||
# rewritten from legacy DTML code
|
# rewritten from legacy DTML code
|
||||||
params = {"ScoURL": context.ScoURL(), "SCO_USER_MANUAL": SCO_USER_MANUAL}
|
params = {"ScoURL": context.ScoURL(), "SCO_USER_MANUAL": scu.SCO_USER_MANUAL}
|
||||||
|
|
||||||
H = ['<div class="sidebar">', sidebar_common(context, REQUEST)]
|
H = ['<div class="sidebar">', sidebar_common(context, REQUEST)]
|
||||||
|
|
||||||
@ -97,7 +103,7 @@ def sidebar(context, REQUEST=None):
|
|||||||
# compte les absences du semestre en cours
|
# compte les absences du semestre en cours
|
||||||
H.append(
|
H.append(
|
||||||
"""<h2 id="insidebar-etud"><a href="%(ScoURL)s/ficheEtud?etudid=%(etudid)s" class="sidebar">
|
"""<h2 id="insidebar-etud"><a href="%(ScoURL)s/ficheEtud?etudid=%(etudid)s" class="sidebar">
|
||||||
<font color="#FF0000">%(sexe)s %(nom_disp)s</font></a>
|
<font color="#FF0000">%(civilite_str)s %(nom_disp)s</font></a>
|
||||||
</h2>
|
</h2>
|
||||||
<b>Absences</b>"""
|
<b>Absences</b>"""
|
||||||
% params
|
% params
|
||||||
@ -142,7 +148,7 @@ def sidebar(context, REQUEST=None):
|
|||||||
# ---------
|
# ---------
|
||||||
H.append("</div><br/> ") # /etud-insidebar
|
H.append("</div><br/> ") # /etud-insidebar
|
||||||
# Logo
|
# Logo
|
||||||
scologo_img = icontag("scologo_img")
|
scologo_img = scu.icontag("scologo_img")
|
||||||
H.append('<div class="logo-insidebar"><div class="logo-logo">%s<br/>' % scologo_img)
|
H.append('<div class="logo-insidebar"><div class="logo-logo">%s<br/>' % scologo_img)
|
||||||
H.append(
|
H.append(
|
||||||
"""<a href="%(ScoURL)s/about" class="sidebar">A propos</a><br/>
|
"""<a href="%(ScoURL)s/about" class="sidebar">A propos</a><br/>
|
||||||
|
16
intervals.py
16
intervals.py
@ -173,17 +173,17 @@ if __name__ == "__main__":
|
|||||||
repr(i)
|
repr(i)
|
||||||
== "{[None, 3] => 'My,', [3, 5] => 'Hello', [6, 7] => 'World', [8, 10] => '(Test)', [10, None] => '!'}"
|
== "{[None, 3] => 'My,', [3, 5] => 'Hello', [6, 7] => 'World', [8, 10] => '(Test)', [10, None] => '!'}"
|
||||||
)
|
)
|
||||||
i[5.5:6] = "Cruel"
|
i[5.5:6] = "Cruel" # pylint: disable=invalid-slice-index
|
||||||
assert (
|
assert (
|
||||||
repr(i)
|
repr(i)
|
||||||
== "{[None, 3] => 'My,', [3, 5] => 'Hello', [5.5, 6] => 'Cruel', [6, 7] => 'World', [8, 10] => '(Test)', [10, None] => '!'}"
|
== "{[None, 3] => 'My,', [3, 5] => 'Hello', [5.5, 6] => 'Cruel', [6, 7] => 'World', [8, 10] => '(Test)', [10, None] => '!'}"
|
||||||
)
|
)
|
||||||
i[6:6.5] = "And Harsh"
|
i[6:6.5] = "And Harsh" # pylint: disable=invalid-slice-index
|
||||||
assert (
|
assert (
|
||||||
repr(i)
|
repr(i)
|
||||||
== "{[None, 3] => 'My,', [3, 5] => 'Hello', [5.5, 6] => 'Cruel', [6, 6.5] => 'And Harsh', [6.5, 7] => 'World', [8, 10] => '(Test)', [10, None] => '!'}"
|
== "{[None, 3] => 'My,', [3, 5] => 'Hello', [5.5, 6] => 'Cruel', [6, 6.5] => 'And Harsh', [6.5, 7] => 'World', [8, 10] => '(Test)', [10, None] => '!'}"
|
||||||
)
|
)
|
||||||
i[5.9:6.6] = None
|
i[5.9:6.6] = None # pylint: disable=invalid-slice-index
|
||||||
assert (
|
assert (
|
||||||
repr(i)
|
repr(i)
|
||||||
== "{[None, 3] => 'My,', [3, 5] => 'Hello', [5.5, 5.9000000000000004] => 'Cruel', [6.5999999999999996, 7] => 'World', [8, 10] => '(Test)', [10, None] => '!'}"
|
== "{[None, 3] => 'My,', [3, 5] => 'Hello', [5.5, 5.9000000000000004] => 'Cruel', [6.5999999999999996, 7] => 'World', [8, 10] => '(Test)', [10, None] => '!'}"
|
||||||
@ -222,9 +222,13 @@ if __name__ == "__main__":
|
|||||||
print("Test 3 skipped")
|
print("Test 3 skipped")
|
||||||
else:
|
else:
|
||||||
i = intervalmap()
|
i = intervalmap()
|
||||||
i[: datetime(2005, 10, 24)] = "A"
|
i[: datetime(2005, 10, 24)] = "A" # pylint: disable=invalid-slice-index
|
||||||
i[datetime(2005, 11, 11) : datetime(2005, 11, 17)] = "B"
|
i[
|
||||||
i[datetime(2005, 11, 30) :] = "C"
|
datetime(2005, 11, 11) : datetime( # pylint: disable=invalid-slice-index
|
||||||
|
2005, 11, 17
|
||||||
|
)
|
||||||
|
] = "B"
|
||||||
|
i[datetime(2005, 11, 30) :] = "C" # pylint: disable=invalid-slice-index
|
||||||
assert i[datetime(2005, 9, 25)] == "A"
|
assert i[datetime(2005, 9, 25)] == "A"
|
||||||
assert i[datetime(2005, 10, 23)] == "A"
|
assert i[datetime(2005, 10, 23)] == "A"
|
||||||
assert i[datetime(2005, 10, 26)] == None
|
assert i[datetime(2005, 10, 26)] == None
|
||||||
|
@ -49,7 +49,7 @@ CREATE TABLE identite (
|
|||||||
etudid text DEFAULT notes_newid_etud('EID'::text) UNIQUE NOT NULL,
|
etudid text DEFAULT notes_newid_etud('EID'::text) UNIQUE NOT NULL,
|
||||||
nom text,
|
nom text,
|
||||||
prenom text,
|
prenom text,
|
||||||
sexe text,
|
civilite text NOT NULL CHECK (civilite IN ('M', 'F', 'X')),
|
||||||
date_naissance date, -- new: date en texte
|
date_naissance date, -- new: date en texte
|
||||||
lieu_naissance text,
|
lieu_naissance text,
|
||||||
dept_naissance text,
|
dept_naissance text,
|
||||||
|
@ -8,7 +8,7 @@ Code_INE; text; identite; 1; code INE;INE
|
|||||||
nom; text; identite; 0; nom de l'etudiant;
|
nom; text; identite; 0; nom de l'etudiant;
|
||||||
nom_usuel; text; identite; 1; nom usuel (si different);
|
nom_usuel; text; identite; 1; nom usuel (si different);
|
||||||
prenom; text; identite; 0; prenom de l'etudiant
|
prenom; text; identite; 0; prenom de l'etudiant
|
||||||
sexe (H ou F); text; identite; 0; sexe ('H' ou 'F');sexe;genre
|
civilite; text; identite; 1; sexe ('M', 'F', 'X');sexe;genre
|
||||||
date_naissance;text;identite; 1; date de naissance (jj/mm/aaaa)
|
date_naissance;text;identite; 1; date de naissance (jj/mm/aaaa)
|
||||||
lieu_naissance;text;identite; 1; lieu de naissance
|
lieu_naissance;text;identite; 1; lieu de naissance
|
||||||
nationalite; text; identite; 1; nationalite
|
nationalite; text; identite; 1; nationalite
|
||||||
|
15
notes_log.py
15
notes_log.py
@ -1,13 +1,26 @@
|
|||||||
# -*- mode: python -*-
|
# -*- mode: python -*-
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import pdb, os, sys, time, re, inspect
|
import pdb
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import inspect
|
||||||
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
from email.mime.base import MIMEBase
|
from email.mime.base import MIMEBase
|
||||||
from email.header import Header
|
from email.header import Header
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
# Simple & stupid file logguer, used only to debug
|
# Simple & stupid file logguer, used only to debug
|
||||||
# (logging to SQL is done in scolog)
|
# (logging to SQL is done in scolog)
|
||||||
|
|
||||||
|
@ -27,16 +27,19 @@
|
|||||||
|
|
||||||
"""Calculs sur les notes et cache des resultats
|
"""Calculs sur les notes et cache des resultats
|
||||||
"""
|
"""
|
||||||
from types import StringType
|
from types import StringType, FloatType
|
||||||
|
import time
|
||||||
import pdb
|
import pdb
|
||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
|
|
||||||
import scolars
|
import scolars
|
||||||
import sco_groups
|
import sco_groups
|
||||||
from notes_log import log, logCallStack
|
from notes_log import log, logCallStack
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
import sco_codes_parcours
|
import sco_codes_parcours
|
||||||
|
from sco_codes_parcours import DEF, UE_SPORT, UE_is_fondamentale, UE_is_professionnelle
|
||||||
from sco_parcours_dut import formsemestre_get_etud_capitalisation
|
from sco_parcours_dut import formsemestre_get_etud_capitalisation
|
||||||
from sco_parcours_dut import list_formsemestre_utilisateurs_uecap
|
from sco_parcours_dut import list_formsemestre_utilisateurs_uecap
|
||||||
import sco_parcours_dut
|
import sco_parcours_dut
|
||||||
@ -46,9 +49,15 @@ import sco_moduleimpl
|
|||||||
import sco_evaluations
|
import sco_evaluations
|
||||||
import sco_compute_moy
|
import sco_compute_moy
|
||||||
from sco_formulas import NoteVector
|
from sco_formulas import NoteVector
|
||||||
|
from sco_exceptions import (
|
||||||
|
AccessDenied,
|
||||||
|
NoteProcessError,
|
||||||
|
ScoException,
|
||||||
|
ScoValueError,
|
||||||
|
)
|
||||||
|
|
||||||
# Support for old user-written "bonus" functions with 2 args:
|
# Support for old user-written "bonus" functions with 2 args:
|
||||||
BONUS_TWO_ARGS = len(inspect.getargspec(CONFIG.compute_bonus)[0]) == 2
|
BONUS_TWO_ARGS = len(inspect.getargspec(scu.CONFIG.compute_bonus)[0]) == 2
|
||||||
|
|
||||||
|
|
||||||
def comp_ranks(T):
|
def comp_ranks(T):
|
||||||
@ -107,7 +116,7 @@ def comp_etud_sum_coef_modules_ue(context, formsemestre_id, etudid, ue_id):
|
|||||||
|
|
||||||
(nécessaire pour éviter appels récursifs de nt, qui peuvent boucler)
|
(nécessaire pour éviter appels récursifs de nt, qui peuvent boucler)
|
||||||
"""
|
"""
|
||||||
infos = SimpleDictFetch(
|
infos = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"""SELECT mod.coefficient
|
"""SELECT mod.coefficient
|
||||||
FROM notes_modules mod, notes_moduleimpl mi, notes_moduleimpl_inscription ins
|
FROM notes_modules mod, notes_moduleimpl mi, notes_moduleimpl_inscription ins
|
||||||
@ -187,7 +196,7 @@ class NotesTable:
|
|||||||
for i in range(len(self.inscrlist)):
|
for i in range(len(self.inscrlist)):
|
||||||
rangalpha[self.inscrlist[i]["etudid"]] = i
|
rangalpha[self.inscrlist[i]["etudid"]] = i
|
||||||
|
|
||||||
self.bonus = DictDefault(defaultvalue=0)
|
self.bonus = scu.DictDefault(defaultvalue=0)
|
||||||
# Notes dans les modules { moduleimpl_id : { etudid: note_moyenne_dans_ce_module } }
|
# Notes dans les modules { moduleimpl_id : { etudid: note_moyenne_dans_ce_module } }
|
||||||
(
|
(
|
||||||
self._modmoys,
|
self._modmoys,
|
||||||
@ -363,29 +372,28 @@ class NotesTable:
|
|||||||
def get_sexnom(self, etudid):
|
def get_sexnom(self, etudid):
|
||||||
"M. DUPONT"
|
"M. DUPONT"
|
||||||
etud = self.identdict[etudid]
|
etud = self.identdict[etudid]
|
||||||
return etud["sexe"] + " " + strupper(etud["nom_usuel"] or etud["nom"])
|
return (
|
||||||
|
etud["civilite_str"] + " " + scu.strupper(etud["nom_usuel"] or etud["nom"])
|
||||||
|
)
|
||||||
|
|
||||||
def get_nom_short(self, etudid):
|
def get_nom_short(self, etudid):
|
||||||
"formatte nom d'un etud (pour table recap)"
|
"formatte nom d'un etud (pour table recap)"
|
||||||
etud = self.identdict[etudid]
|
etud = self.identdict[etudid]
|
||||||
# Attention aux caracteres multibytes pour decouper les 2 premiers:
|
# Attention aux caracteres multibytes pour decouper les 2 premiers:
|
||||||
return (
|
return (
|
||||||
strupper(etud["nom_usuel"] or etud["nom"])
|
scu.strupper(etud["nom_usuel"] or etud["nom"])
|
||||||
+ " "
|
+ " "
|
||||||
+ etud["prenom"].decode(SCO_ENCODING).capitalize()[:2].encode(SCO_ENCODING)
|
+ etud["prenom"]
|
||||||
|
.decode(scu.SCO_ENCODING)
|
||||||
|
.capitalize()[:2]
|
||||||
|
.encode(scu.SCO_ENCODING)
|
||||||
+ "."
|
+ "."
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_nom_long(self, etudid):
|
def get_nom_long(self, etudid):
|
||||||
"formatte nom d'un etud: M. Pierre DUPONT"
|
"formatte nom d'un etud: M. Pierre DUPONT"
|
||||||
etud = self.identdict[etudid]
|
etud = self.identdict[etudid]
|
||||||
return " ".join(
|
return scolars.format_nomprenom(etud)
|
||||||
[
|
|
||||||
scolars.format_sexe(etud["sexe"]),
|
|
||||||
scolars.format_prenom(etud["prenom"]),
|
|
||||||
scolars.format_nom(etud["nom_usuel"] or etud["nom"]),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_displayed_etud_code(self, etudid):
|
def get_displayed_etud_code(self, etudid):
|
||||||
'code à afficher sur les listings "anonymes"'
|
'code à afficher sur les listings "anonymes"'
|
||||||
@ -616,7 +624,7 @@ class NotesTable:
|
|||||||
# si 'NI', etudiant non inscrit a ce module
|
# si 'NI', etudiant non inscrit a ce module
|
||||||
if val != "NI":
|
if val != "NI":
|
||||||
est_inscrit = True
|
est_inscrit = True
|
||||||
if modimpl["module"]["module_type"] == MODULE_STANDARD:
|
if modimpl["module"]["module_type"] == scu.MODULE_STANDARD:
|
||||||
coef = modimpl["module"]["coefficient"]
|
coef = modimpl["module"]["coefficient"]
|
||||||
if modimpl["ue"]["type"] != UE_SPORT:
|
if modimpl["ue"]["type"] != UE_SPORT:
|
||||||
notes.append(val, name=modimpl["module"]["code"])
|
notes.append(val, name=modimpl["module"]["code"])
|
||||||
@ -652,7 +660,7 @@ class NotesTable:
|
|||||||
except:
|
except:
|
||||||
# log('comp_etud_moy_ue: exception: val=%s coef=%s' % (val,coef))
|
# log('comp_etud_moy_ue: exception: val=%s coef=%s' % (val,coef))
|
||||||
pass
|
pass
|
||||||
elif modimpl["module"]["module_type"] == MODULE_MALUS:
|
elif modimpl["module"]["module_type"] == scu.MODULE_MALUS:
|
||||||
try:
|
try:
|
||||||
ue_malus += val
|
ue_malus += val
|
||||||
except:
|
except:
|
||||||
@ -672,7 +680,7 @@ class NotesTable:
|
|||||||
moy = sum_notes / sum_coefs
|
moy = sum_notes / sum_coefs
|
||||||
if ue_malus:
|
if ue_malus:
|
||||||
moy -= ue_malus
|
moy -= ue_malus
|
||||||
moy = max(NOTES_MIN, min(moy, 20.0))
|
moy = max(scu.NOTES_MIN, min(moy, 20.0))
|
||||||
moy_valid = True
|
moy_valid = True
|
||||||
else:
|
else:
|
||||||
moy = "NA"
|
moy = "NA"
|
||||||
@ -898,7 +906,7 @@ class NotesTable:
|
|||||||
# mu["moy"] can be a number, or "NA", or "ERR" (user-defined UE formulas)
|
# mu["moy"] can be a number, or "NA", or "ERR" (user-defined UE formulas)
|
||||||
if (
|
if (
|
||||||
(mu["ue"]["type"] != UE_SPORT)
|
(mu["ue"]["type"] != UE_SPORT)
|
||||||
and isnumber(mu["moy"])
|
and scu.isnumber(mu["moy"])
|
||||||
and (mu["est_inscrit"] or mu["is_capitalized"])
|
and (mu["est_inscrit"] or mu["is_capitalized"])
|
||||||
):
|
):
|
||||||
coef_ue = mu["ue"]["coefficient"]
|
coef_ue = mu["ue"]["coefficient"]
|
||||||
@ -931,9 +939,11 @@ class NotesTable:
|
|||||||
|
|
||||||
if BONUS_TWO_ARGS:
|
if BONUS_TWO_ARGS:
|
||||||
# backward compat: compute_bonus took only 2 args
|
# backward compat: compute_bonus took only 2 args
|
||||||
bonus = CONFIG.compute_bonus(notes_bonus_gen, coefs_bonus_gen)
|
bonus = scu.CONFIG.compute_bonus(
|
||||||
|
notes_bonus_gen, coefs_bonus_gen
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
bonus = CONFIG.compute_bonus(
|
bonus = scu.CONFIG.compute_bonus(
|
||||||
notes_bonus_gen, coefs_bonus_gen, infos=infos
|
notes_bonus_gen, coefs_bonus_gen, infos=infos
|
||||||
)
|
)
|
||||||
self.bonus[etudid] = bonus
|
self.bonus[etudid] = bonus
|
||||||
@ -1023,7 +1033,7 @@ class NotesTable:
|
|||||||
Si l'étudiant est défaillant, met un code DEF sur toutes les UE
|
Si l'étudiant est défaillant, met un code DEF sur toutes les UE
|
||||||
"""
|
"""
|
||||||
cnx = self.context.GetDBConnexion()
|
cnx = self.context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"select etudid, code, assidu, compense_formsemestre_id, event_date from scolar_formsemestre_validation where formsemestre_id=%(formsemestre_id)s and ue_id is NULL;",
|
"select etudid, code, assidu, compense_formsemestre_id, event_date from scolar_formsemestre_validation where formsemestre_id=%(formsemestre_id)s and ue_id is NULL;",
|
||||||
{"formsemestre_id": self.formsemestre_id},
|
{"formsemestre_id": self.formsemestre_id},
|
||||||
@ -1040,7 +1050,7 @@ class NotesTable:
|
|||||||
"code": code,
|
"code": code,
|
||||||
"assidu": assidu,
|
"assidu": assidu,
|
||||||
"compense_formsemestre_id": compense_formsemestre_id,
|
"compense_formsemestre_id": compense_formsemestre_id,
|
||||||
"event_date": DateISOtoDMY(event_date),
|
"event_date": ndb.DateISOtoDMY(event_date),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.decisions_jury = decisions_jury
|
self.decisions_jury = decisions_jury
|
||||||
@ -1089,7 +1099,7 @@ class NotesTable:
|
|||||||
decisions_jury_ues[etudid][ue_id] = {
|
decisions_jury_ues[etudid][ue_id] = {
|
||||||
"code": code,
|
"code": code,
|
||||||
"ects": ects, # 0. si non UE validée ou si mode de calcul different (?)
|
"ects": ects, # 0. si non UE validée ou si mode de calcul different (?)
|
||||||
"event_date": DateISOtoDMY(event_date),
|
"event_date": ndb.DateISOtoDMY(event_date),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.decisions_jury_ues = decisions_jury_ues
|
self.decisions_jury_ues = decisions_jury_ues
|
||||||
@ -1146,7 +1156,7 @@ class NotesTable:
|
|||||||
ue_capitalisees = { etudid :
|
ue_capitalisees = { etudid :
|
||||||
[{ 'moy':, 'event_date' : ,'formsemestre_id' : }, ...] }
|
[{ 'moy':, 'event_date' : ,'formsemestre_id' : }, ...] }
|
||||||
"""
|
"""
|
||||||
self.ue_capitalisees = DictDefault(defaultvalue=[])
|
self.ue_capitalisees = scu.DictDefault(defaultvalue=[])
|
||||||
cnx = None
|
cnx = None
|
||||||
for etudid in self.get_etudids():
|
for etudid in self.get_etudids():
|
||||||
capital = formsemestre_get_etud_capitalisation(
|
capital = formsemestre_get_etud_capitalisation(
|
||||||
@ -1281,13 +1291,13 @@ class NotesTable:
|
|||||||
(ne compte que les notes en attente dans des évaluation avec coef. non nul).
|
(ne compte que les notes en attente dans des évaluation avec coef. non nul).
|
||||||
"""
|
"""
|
||||||
cnx = self.context.GetDBConnexion()
|
cnx = self.context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"select n.* from notes_notes n, notes_evaluation e, notes_moduleimpl m, notes_moduleimpl_inscription i where n.etudid = %(etudid)s and n.value = %(code_attente)s and n.evaluation_id=e.evaluation_id and e.moduleimpl_id=m.moduleimpl_id and m.formsemestre_id=%(formsemestre_id)s and e.coefficient != 0 and m.moduleimpl_id=i.moduleimpl_id and i.etudid=%(etudid)s",
|
"select n.* from notes_notes n, notes_evaluation e, notes_moduleimpl m, notes_moduleimpl_inscription i where n.etudid = %(etudid)s and n.value = %(code_attente)s and n.evaluation_id=e.evaluation_id and e.moduleimpl_id=m.moduleimpl_id and m.formsemestre_id=%(formsemestre_id)s and e.coefficient != 0 and m.moduleimpl_id=i.moduleimpl_id and i.etudid=%(etudid)s",
|
||||||
{
|
{
|
||||||
"formsemestre_id": self.formsemestre_id,
|
"formsemestre_id": self.formsemestre_id,
|
||||||
"etudid": etudid,
|
"etudid": etudid,
|
||||||
"code_attente": NOTES_ATTENTE,
|
"code_attente": scu.NOTES_ATTENTE,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
return len(cursor.fetchall()) > 0
|
return len(cursor.fetchall()) > 0
|
||||||
@ -1331,7 +1341,7 @@ class CacheNotesTable:
|
|||||||
# Cache des classeur PDF (bulletins)
|
# Cache des classeur PDF (bulletins)
|
||||||
self.pdfcache = {} # { formsemestre_id : (filename, pdfdoc) }
|
self.pdfcache = {} # { formsemestre_id : (filename, pdfdoc) }
|
||||||
# Listeners:
|
# Listeners:
|
||||||
self.listeners = DictDefault(
|
self.listeners = scu.DictDefault(
|
||||||
defaultvalue={}
|
defaultvalue={}
|
||||||
) # {formsemestre_id : {listener_id : callback }}
|
) # {formsemestre_id : {listener_id : callback }}
|
||||||
|
|
||||||
|
20
notesdb.py
20
notesdb.py
@ -5,10 +5,11 @@ import pdb, os, sys, string
|
|||||||
import traceback
|
import traceback
|
||||||
import psycopg2
|
import psycopg2
|
||||||
import psycopg2.pool
|
import psycopg2.pool
|
||||||
|
import psycopg2.extras
|
||||||
import thread
|
import thread
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from sco_exceptions import *
|
from sco_exceptions import ScoException, ScoValueError, NoteProcessError
|
||||||
from types import *
|
from types import StringType
|
||||||
from cgi import escape
|
from cgi import escape
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
@ -67,16 +68,17 @@ def GetUsersDBConnexion(context, autocommit=True):
|
|||||||
return cnx
|
return cnx
|
||||||
|
|
||||||
|
|
||||||
|
# Nota: on pourrait maintenant utiliser psycopg2.extras.DictCursor
|
||||||
class ScoDocCursor(psycopg2.extensions.cursor):
|
class ScoDocCursor(psycopg2.extensions.cursor):
|
||||||
"""A database cursor emulating some methods of psycopg v1 cursors"""
|
"""A database cursor emulating some methods of psycopg v1 cursors"""
|
||||||
|
|
||||||
def dictfetchall(cursor):
|
def dictfetchall(self):
|
||||||
col_names = [d[0] for d in cursor.description]
|
col_names = [d[0] for d in self.description]
|
||||||
return [dict(zip(col_names, row)) for row in cursor.fetchall()]
|
return [dict(zip(col_names, row)) for row in self.fetchall()]
|
||||||
|
|
||||||
def dictfetchone(cursor):
|
def dictfetchone(self):
|
||||||
col_names = [d[0] for d in cursor.description]
|
col_names = [d[0] for d in self.description]
|
||||||
row = cursor.fetchone()
|
row = self.fetchone()
|
||||||
if row:
|
if row:
|
||||||
return dict(zip(col_names, row))
|
return dict(zip(col_names, row))
|
||||||
else:
|
else:
|
||||||
@ -173,7 +175,7 @@ def DBSelectArgs(
|
|||||||
cond = ""
|
cond = ""
|
||||||
i = 1
|
i = 1
|
||||||
cl = []
|
cl = []
|
||||||
for (aux_tab, aux_id) in aux_tables:
|
for (_, aux_id) in aux_tables:
|
||||||
cl.append("T0.%s = T%d.%s" % (id_name, i, aux_id))
|
cl.append("T0.%s = T%d.%s" % (id_name, i, aux_id))
|
||||||
i = i + 1
|
i = i + 1
|
||||||
cond += " and ".join(cl)
|
cond += " and ".join(cl)
|
||||||
|
@ -30,12 +30,14 @@
|
|||||||
# conçu et développé par Cléo Baras (IUT de Grenoble)
|
# conçu et développé par Cléo Baras (IUT de Grenoble)
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
|
import os
|
||||||
import codecs
|
import codecs
|
||||||
import re
|
import re
|
||||||
import scolars
|
import scolars
|
||||||
import pe_jurype, pe_tagtable, pe_tools
|
import pe_jurype, pe_tagtable, pe_tools
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
|
from notes_log import log
|
||||||
import scolars
|
import scolars
|
||||||
|
|
||||||
import pe_jurype, pe_tagtable, pe_tools
|
import pe_jurype, pe_tagtable, pe_tools
|
||||||
@ -55,7 +57,7 @@ def get_code_latex_from_modele(fichier):
|
|||||||
vers le modele : attention pas de vérification du format d'encodage
|
vers le modele : attention pas de vérification du format d'encodage
|
||||||
Le fichier doit donc etre enregistré avec le même codage que ScoDoc (utf-8)
|
Le fichier doit donc etre enregistré avec le même codage que ScoDoc (utf-8)
|
||||||
"""
|
"""
|
||||||
fid_latex = codecs.open(fichier, "r", encoding=SCO_ENCODING)
|
fid_latex = codecs.open(fichier, "r", encoding=scu.SCO_ENCODING)
|
||||||
un_avis_latex = fid_latex.read()
|
un_avis_latex = fid_latex.read()
|
||||||
fid_latex.close()
|
fid_latex.close()
|
||||||
return un_avis_latex
|
return un_avis_latex
|
||||||
@ -72,7 +74,7 @@ def get_code_latex_from_scodoc_preference(
|
|||||||
template_latex = context.get_preference(champ, formsemestre_id)
|
template_latex = context.get_preference(champ, formsemestre_id)
|
||||||
# Conversion du template en unicode:
|
# Conversion du template en unicode:
|
||||||
if template_latex:
|
if template_latex:
|
||||||
template_latex = template_latex.decode(SCO_ENCODING)
|
template_latex = template_latex.decode(scu.SCO_ENCODING)
|
||||||
else:
|
else:
|
||||||
template_latex = u"" # EV: preference non définie (None)
|
template_latex = u"" # EV: preference non définie (None)
|
||||||
|
|
||||||
@ -119,10 +121,14 @@ def comp_latex_parcourstimeline(etudiant, promo, taille=17):
|
|||||||
\\end{parcourstimeline}
|
\\end{parcourstimeline}
|
||||||
"""
|
"""
|
||||||
reslatex = codelatexDebut
|
reslatex = codelatexDebut
|
||||||
reslatex = reslatex.replace("**debut**", etudiant["entree"].decode(SCO_ENCODING))
|
|
||||||
reslatex = reslatex.replace("**fin**", str(etudiant["promo"]).decode(SCO_ENCODING))
|
|
||||||
reslatex = reslatex.replace(
|
reslatex = reslatex.replace(
|
||||||
"**nbreSemestres**", str(etudiant["nbSemestres"]).decode(SCO_ENCODING)
|
"**debut**", etudiant["entree"].decode(scu.SCO_ENCODING)
|
||||||
|
)
|
||||||
|
reslatex = reslatex.replace(
|
||||||
|
"**fin**", str(etudiant["promo"]).decode(scu.SCO_ENCODING)
|
||||||
|
)
|
||||||
|
reslatex = reslatex.replace(
|
||||||
|
"**nbreSemestres**", str(etudiant["nbSemestres"]).decode(scu.SCO_ENCODING)
|
||||||
)
|
)
|
||||||
# Tri du parcours par ordre croissant : de la forme descr, nom sem date-date
|
# Tri du parcours par ordre croissant : de la forme descr, nom sem date-date
|
||||||
parcours = etudiant["parcours"][::-1] # EV: XXX je ne comprend pas ce commentaire ?
|
parcours = etudiant["parcours"][::-1] # EV: XXX je ne comprend pas ce commentaire ?
|
||||||
@ -179,7 +185,7 @@ def get_code_latex_avis_etudiant(
|
|||||||
# Recherche des tags dans le fichier
|
# Recherche des tags dans le fichier
|
||||||
tags_latex = get_tags_latex(code)
|
tags_latex = get_tags_latex(code)
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
print("Les tags" + str(tags_latex))
|
log("Les tags" + str(tags_latex))
|
||||||
|
|
||||||
# Interprète et remplace chaque tags latex par les données numériques de l'étudiant (y compris les
|
# Interprète et remplace chaque tags latex par les données numériques de l'étudiant (y compris les
|
||||||
# tags "macros" tels que parcourstimeline
|
# tags "macros" tels que parcourstimeline
|
||||||
@ -207,17 +213,16 @@ def get_code_latex_avis_etudiant(
|
|||||||
elif tag_latex == u"bilanParTag":
|
elif tag_latex == u"bilanParTag":
|
||||||
valeur = get_bilanParTag(donnees_etudiant)
|
valeur = get_bilanParTag(donnees_etudiant)
|
||||||
|
|
||||||
# Les tags "simples": par ex. nom, prenom, sexe, ...
|
# Les tags "simples": par ex. nom, prenom, civilite, ...
|
||||||
else:
|
else:
|
||||||
if tag_latex in donnees_etudiant:
|
if tag_latex in donnees_etudiant:
|
||||||
valeur = donnees_etudiant[tag_latex].decode(SCO_ENCODING)
|
valeur = donnees_etudiant[tag_latex].decode(scu.SCO_ENCODING)
|
||||||
elif tag_latex in prefs: # les champs **NomResponsablePE**, ...
|
elif tag_latex in prefs: # les champs **NomResponsablePE**, ...
|
||||||
valeur = pe_tools.escape_for_latex(prefs[tag_latex]).decode(
|
valeur = pe_tools.escape_for_latex(prefs[tag_latex]).decode(
|
||||||
SCO_ENCODING
|
scu.SCO_ENCODING
|
||||||
)
|
)
|
||||||
|
|
||||||
# Gestion des pb d'encodage XXX debug
|
# Gestion des pb d'encodage XXX debug
|
||||||
# print(tag_latex, valeur)
|
|
||||||
assert isinstance(tag_latex, unicode)
|
assert isinstance(tag_latex, unicode)
|
||||||
assert isinstance(valeur, unicode)
|
assert isinstance(valeur, unicode)
|
||||||
|
|
||||||
@ -244,7 +249,7 @@ def get_annotation_PE(context, etudid, tag_annotation_pe):
|
|||||||
exp = re.compile(r"^" + tag_annotation_pe)
|
exp = re.compile(r"^" + tag_annotation_pe)
|
||||||
|
|
||||||
for a in annotations:
|
for a in annotations:
|
||||||
commentaire = unescape_html(a["comment"]).decode(SCO_ENCODING)
|
commentaire = scu.unescape_html(a["comment"]).decode(scu.SCO_ENCODING)
|
||||||
if exp.match(commentaire): # tag en début de commentaire ?
|
if exp.match(commentaire): # tag en début de commentaire ?
|
||||||
a["comment_u"] = commentaire # unicode, HTML non quoté
|
a["comment_u"] = commentaire # unicode, HTML non quoté
|
||||||
annotationsPE.append(
|
annotationsPE.append(
|
||||||
@ -282,7 +287,6 @@ def str_from_syntheseJury(donnees_etudiant, aggregat, groupe, tag_scodoc, champ)
|
|||||||
for chp in champ
|
for chp in champ
|
||||||
]
|
]
|
||||||
else: # champ = str à priori
|
else: # champ = str à priori
|
||||||
# print(champ)
|
|
||||||
valeur = DONNEE_MANQUANTE
|
valeur = DONNEE_MANQUANTE
|
||||||
if (
|
if (
|
||||||
(aggregat in donnees_etudiant)
|
(aggregat in donnees_etudiant)
|
||||||
@ -316,7 +320,6 @@ def str_from_syntheseJury(donnees_etudiant, aggregat, groupe, tag_scodoc, champ)
|
|||||||
else:
|
else:
|
||||||
valeur = u"%s" % donnees_numeriques[indice_champ]
|
valeur = u"%s" % donnees_numeriques[indice_champ]
|
||||||
|
|
||||||
# print(valeur)
|
|
||||||
return valeur
|
return valeur
|
||||||
|
|
||||||
|
|
||||||
@ -339,7 +342,7 @@ def get_bilanParTag(donnees_etudiant, groupe="groupe"):
|
|||||||
|
|
||||||
lignes = []
|
lignes = []
|
||||||
valeurs = {"note": [], "rang": []}
|
valeurs = {"note": [], "rang": []}
|
||||||
for (indice_aggregat, (aggregat, intitule, ordre)) in enumerate(entete):
|
for (indice_aggregat, (aggregat, intitule, _)) in enumerate(entete):
|
||||||
# print("> " + aggregat)
|
# print("> " + aggregat)
|
||||||
# listeTags = jury.get_allTagForAggregat(aggregat) # les tags de l'aggrégat
|
# listeTags = jury.get_allTagForAggregat(aggregat) # les tags de l'aggrégat
|
||||||
listeTags = [
|
listeTags = [
|
||||||
@ -366,25 +369,20 @@ def get_bilanParTag(donnees_etudiant, groupe="groupe"):
|
|||||||
("\\textit{" + rang + "}") if note else ""
|
("\\textit{" + rang + "}") if note else ""
|
||||||
) # rang masqué si pas de notes
|
) # rang masqué si pas de notes
|
||||||
|
|
||||||
# pprint.pprint(valeurs)
|
|
||||||
# print(len(entete))
|
|
||||||
code_latex = u"\\begin{tabular}{|c|" + "|c" * (len(entete)) + "|}\n"
|
code_latex = u"\\begin{tabular}{|c|" + "|c" * (len(entete)) + "|}\n"
|
||||||
code_latex += u"\\hline \n"
|
code_latex += u"\\hline \n"
|
||||||
code_latex += (
|
code_latex += (
|
||||||
u" & "
|
u" & "
|
||||||
+ " & ".join(
|
+ " & ".join(["\\textbf{" + intitule + "}" for (agg, intitule, _) in entete])
|
||||||
["\\textbf{" + intitule + "}" for (agg, intitule, ordre) in entete]
|
|
||||||
)
|
|
||||||
+ " \\\\ \n"
|
+ " \\\\ \n"
|
||||||
)
|
)
|
||||||
code_latex += u"\\hline"
|
code_latex += u"\\hline"
|
||||||
code_latex += u"\\hline \n"
|
code_latex += u"\\hline \n"
|
||||||
for (i, ligne_val) in enumerate(valeurs["note"]):
|
for (i, ligne_val) in enumerate(valeurs["note"]):
|
||||||
titre = lignes[i] # règle le pb d'encodage
|
titre = lignes[i] # règle le pb d'encodage
|
||||||
# print titre, ligne_val
|
|
||||||
code_latex += (
|
code_latex += (
|
||||||
u"\\textbf{"
|
u"\\textbf{"
|
||||||
+ titre.decode(SCO_ENCODING)
|
+ titre.decode(scu.SCO_ENCODING)
|
||||||
+ u"} & "
|
+ u"} & "
|
||||||
+ " & ".join(ligne_val)
|
+ " & ".join(ligne_val)
|
||||||
+ u"\\\\ \n"
|
+ u"\\\\ \n"
|
||||||
@ -412,9 +410,11 @@ def get_avis_poursuite_par_etudiant(
|
|||||||
if pe_tools.PE_DEBUG:
|
if pe_tools.PE_DEBUG:
|
||||||
pe_tools.pe_print(jury.syntheseJury[etudid]["nom"] + " " + etudid)
|
pe_tools.pe_print(jury.syntheseJury[etudid]["nom"] + " " + etudid)
|
||||||
|
|
||||||
sexe = jury.syntheseJury[etudid]["sexe"].decode(SCO_ENCODING)
|
civilite_str = jury.syntheseJury[etudid]["civilite_str"].decode(scu.SCO_ENCODING)
|
||||||
nom = jury.syntheseJury[etudid]["nom"].replace(" ", "-").decode(SCO_ENCODING)
|
nom = jury.syntheseJury[etudid]["nom"].replace(" ", "-").decode(scu.SCO_ENCODING)
|
||||||
prenom = jury.syntheseJury[etudid]["prenom"].replace(" ", "-").decode(SCO_ENCODING)
|
prenom = (
|
||||||
|
jury.syntheseJury[etudid]["prenom"].replace(" ", "-").decode(scu.SCO_ENCODING)
|
||||||
|
)
|
||||||
|
|
||||||
nom_fichier = (
|
nom_fichier = (
|
||||||
u"avis_poursuite_"
|
u"avis_poursuite_"
|
||||||
@ -429,7 +429,9 @@ def get_avis_poursuite_par_etudiant(
|
|||||||
|
|
||||||
# Entete (commentaire)
|
# Entete (commentaire)
|
||||||
|
|
||||||
contenu_latex = u"%% ---- Etudiant: " + sexe + " " + nom + " " + prenom + u"\n"
|
contenu_latex = (
|
||||||
|
u"%% ---- Etudiant: " + civilite_str + " " + nom + " " + prenom + u"\n"
|
||||||
|
)
|
||||||
|
|
||||||
# les annnotations
|
# les annnotations
|
||||||
annotationPE = get_annotation_PE(
|
annotationPE = get_annotation_PE(
|
||||||
@ -460,11 +462,11 @@ def get_templates_from_distrib(template="avis"):
|
|||||||
|
|
||||||
if template in ["avis", "footer"]:
|
if template in ["avis", "footer"]:
|
||||||
# pas de preference pour le template: utilise fichier du serveur
|
# pas de preference pour le template: utilise fichier du serveur
|
||||||
p = os.path.join(SCO_SRC_DIR, pe_local_tmpl)
|
p = os.path.join(scu.SCO_SRC_DIR, pe_local_tmpl)
|
||||||
if os.path.exists(p):
|
if os.path.exists(p):
|
||||||
template_latex = get_code_latex_from_modele(p)
|
template_latex = get_code_latex_from_modele(p)
|
||||||
else:
|
else:
|
||||||
p = os.path.join(SCO_SRC_DIR, pe_default_tmpl)
|
p = os.path.join(scu.SCO_SRC_DIR, pe_default_tmpl)
|
||||||
if os.path.exists(p):
|
if os.path.exists(p):
|
||||||
template_latex = get_code_latex_from_modele(p)
|
template_latex = get_code_latex_from_modele(p)
|
||||||
else:
|
else:
|
||||||
@ -502,7 +504,7 @@ def table_syntheseAnnotationPE(context, syntheseJury, tag_annotation_pe):
|
|||||||
[syntheseJury[etudid]["nbSemestres"] for etudid in etudids]
|
[syntheseJury[etudid]["nbSemestres"] for etudid in etudids]
|
||||||
) # le nombre de semestre le + grand
|
) # le nombre de semestre le + grand
|
||||||
|
|
||||||
infos = ["sexe", "nom", "prenom", "age", "nbSemestres"]
|
infos = ["civilite", "nom", "prenom", "age", "nbSemestres"]
|
||||||
entete = ["etudid"]
|
entete = ["etudid"]
|
||||||
entete.extend(infos)
|
entete.extend(infos)
|
||||||
entete.extend(["P%d" % i for i in range(1, maxParcours + 1)]) # ajout du parcours
|
entete.extend(["P%d" % i for i in range(1, maxParcours + 1)]) # ajout du parcours
|
||||||
@ -518,7 +520,7 @@ def table_syntheseAnnotationPE(context, syntheseJury, tag_annotation_pe):
|
|||||||
# Les info générales:
|
# Les info générales:
|
||||||
row = {
|
row = {
|
||||||
"etudid": etudid,
|
"etudid": etudid,
|
||||||
"sexe": e["sexe"],
|
"civilite": e["civilite"],
|
||||||
"nom": e["nom"],
|
"nom": e["nom"],
|
||||||
"prenom": e["prenom"],
|
"prenom": e["prenom"],
|
||||||
"age": e["age"],
|
"age": e["age"],
|
||||||
@ -534,7 +536,9 @@ def table_syntheseAnnotationPE(context, syntheseJury, tag_annotation_pe):
|
|||||||
annotationPE = get_annotation_PE(
|
annotationPE = get_annotation_PE(
|
||||||
context, etudid, tag_annotation_pe=tag_annotation_pe
|
context, etudid, tag_annotation_pe=tag_annotation_pe
|
||||||
)
|
)
|
||||||
row["Annotation PE"] = annotationPE.encode(SCO_ENCODING) if annotationPE else ""
|
row["Annotation PE"] = (
|
||||||
|
annotationPE.encode(scu.SCO_ENCODING) if annotationPE else ""
|
||||||
|
)
|
||||||
rows.append(row)
|
rows.append(row)
|
||||||
|
|
||||||
T = GenTable(
|
T = GenTable(
|
||||||
|
29
pe_jurype.py
29
pe_jurype.py
@ -42,6 +42,7 @@ Created on Fri Sep 9 09:15:05 2016
|
|||||||
# a l'edition d'un jury de poursuites d'etudes
|
# a l'edition d'un jury de poursuites d'etudes
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
@ -54,10 +55,9 @@ from zipfile import ZipFile, BadZipfile
|
|||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
from gen_tables import GenTable, SeqGenTable
|
from gen_tables import GenTable, SeqGenTable
|
||||||
|
import sco_utils as scu
|
||||||
import sco_codes_parcours # sco_codes_parcours.NEXT -> sem suivant
|
import sco_codes_parcours # sco_codes_parcours.NEXT -> sem suivant
|
||||||
import sco_report
|
import sco_report
|
||||||
from sco_utils import *
|
|
||||||
|
|
||||||
import pe_tagtable, pe_tools, pe_avislatex, pe_semestretag, pe_settag
|
import pe_tagtable, pe_tools, pe_avislatex, pe_semestretag, pe_settag
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ class JuryPE:
|
|||||||
- context : le contexte Zope
|
- context : le contexte Zope
|
||||||
- juryEtudDict : dictionnaire récapitulant les étudiants participant au jury PE (données administratives +
|
- juryEtudDict : dictionnaire récapitulant les étudiants participant au jury PE (données administratives +
|
||||||
celles des semestres valides à prendre en compte permettant le calcul des moyennes ...
|
celles des semestres valides à prendre en compte permettant le calcul des moyennes ...
|
||||||
{'etudid : { 'nom', 'prenom', 'sexe', 'diplome', '', }}
|
{'etudid : { 'nom', 'prenom', 'civilite', 'diplome', '', }}
|
||||||
Rq: il contient à la fois les étudiants qui vont être diplomés à la date prévue
|
Rq: il contient à la fois les étudiants qui vont être diplomés à la date prévue
|
||||||
et ceux qui sont éliminés (abandon, redoublement, ...) pour affichage alternatif
|
et ceux qui sont éliminés (abandon, redoublement, ...) pour affichage alternatif
|
||||||
|
|
||||||
@ -450,15 +450,15 @@ class JuryPE:
|
|||||||
end="",
|
end="",
|
||||||
)
|
)
|
||||||
|
|
||||||
if pe_tools.PE_DEBUG and pe_tools.PE_DEBUG >= 2:
|
# if pe_tools.PE_DEBUG and pe_tools.PE_DEBUG >= 2:
|
||||||
print
|
# print
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------------------------------------------
|
||||||
def est_un_etudiant_reoriente_ou_demissionnaire(self, etudid):
|
def est_un_etudiant_reoriente_ou_demissionnaire(self, etudid):
|
||||||
"""Renvoie True si l'étudiant est réorienté (NAR) ou démissionnaire (DEM)"""
|
"""Renvoie True si l'étudiant est réorienté (NAR) ou démissionnaire (DEM)"""
|
||||||
reponse = False
|
reponse = False
|
||||||
etud = self.get_cache_etudInfo_d_un_etudiant(self.context, etudid)
|
etud = self.get_cache_etudInfo_d_un_etudiant(self.context, etudid)
|
||||||
(code, parcours) = sco_report.get_codeparcoursetud(self.context.Notes, etud)
|
(_, parcours) = sco_report.get_codeparcoursetud(self.context.Notes, etud)
|
||||||
if (
|
if (
|
||||||
len(set(sco_codes_parcours.CODES_SEM_REO.keys()) & set(parcours.values()))
|
len(set(sco_codes_parcours.CODES_SEM_REO.keys()) & set(parcours.values()))
|
||||||
> 0
|
> 0
|
||||||
@ -812,7 +812,7 @@ class JuryPE:
|
|||||||
self.syntheseJury[etudid] = {
|
self.syntheseJury[etudid] = {
|
||||||
"nom": etudinfo["nom"],
|
"nom": etudinfo["nom"],
|
||||||
"prenom": etudinfo["prenom"],
|
"prenom": etudinfo["prenom"],
|
||||||
"sexe": etudinfo["sexe"],
|
"civilite": etudinfo["civilite"],
|
||||||
"age": str(pe_tools.calcul_age(etudinfo["date_naissance"])),
|
"age": str(pe_tools.calcul_age(etudinfo["date_naissance"])),
|
||||||
"lycee": etudinfo["nomlycee"]
|
"lycee": etudinfo["nomlycee"]
|
||||||
+ (
|
+ (
|
||||||
@ -862,13 +862,13 @@ class JuryPE:
|
|||||||
|
|
||||||
def get_dateEntree(self, etudid):
|
def get_dateEntree(self, etudid):
|
||||||
"""Renvoie l'année d'entrée de l'étudiant à l'IUT"""
|
"""Renvoie l'année d'entrée de l'étudiant à l'IUT"""
|
||||||
etudinfo = self.ETUDINFO_DICT[etudid]
|
# etudinfo = self.ETUDINFO_DICT[etudid]
|
||||||
semDeb = self.get_semestresDUT_d_un_etudiant(etudid)[-1] # le 1er sem à l'IUT
|
semDeb = self.get_semestresDUT_d_un_etudiant(etudid)[-1] # le 1er sem à l'IUT
|
||||||
return semDeb["annee_debut"]
|
return semDeb["annee_debut"]
|
||||||
|
|
||||||
def get_parcoursIUT(self, etudid):
|
def get_parcoursIUT(self, etudid):
|
||||||
"""Renvoie une liste d'infos sur les semestres du parcours d'un étudiant"""
|
"""Renvoie une liste d'infos sur les semestres du parcours d'un étudiant"""
|
||||||
etudinfo = self.ETUDINFO_DICT[etudid]
|
# etudinfo = self.ETUDINFO_DICT[etudid]
|
||||||
sems = self.get_semestresDUT_d_un_etudiant(etudid)
|
sems = self.get_semestresDUT_d_un_etudiant(etudid)
|
||||||
|
|
||||||
infos = []
|
infos = []
|
||||||
@ -985,7 +985,7 @@ class JuryPE:
|
|||||||
[self.syntheseJury[etudid]["nbSemestres"] for etudid in etudids]
|
[self.syntheseJury[etudid]["nbSemestres"] for etudid in etudids]
|
||||||
)
|
)
|
||||||
|
|
||||||
infos = ["sexe", "nom", "prenom", "age", "nbSemestres"]
|
infos = ["civilite", "nom", "prenom", "age", "nbSemestres"]
|
||||||
entete = ["etudid"]
|
entete = ["etudid"]
|
||||||
entete.extend(infos)
|
entete.extend(infos)
|
||||||
entete.extend(["P%d" % i for i in range(1, maxParcours + 1)])
|
entete.extend(["P%d" % i for i in range(1, maxParcours + 1)])
|
||||||
@ -1036,7 +1036,7 @@ class JuryPE:
|
|||||||
# Les info générales:
|
# Les info générales:
|
||||||
row = {
|
row = {
|
||||||
"etudid": etudid,
|
"etudid": etudid,
|
||||||
"sexe": e["sexe"],
|
"civilite": e["civilite"],
|
||||||
"nom": e["nom"],
|
"nom": e["nom"],
|
||||||
"prenom": e["prenom"],
|
"prenom": e["prenom"],
|
||||||
"age": e["age"],
|
"age": e["age"],
|
||||||
@ -1073,7 +1073,7 @@ class JuryPE:
|
|||||||
if mode == "singlesheet"
|
if mode == "singlesheet"
|
||||||
else "%s " % (sem)
|
else "%s " % (sem)
|
||||||
)
|
)
|
||||||
row[champ + "note"] = fmt_note(resgroupe[0])
|
row[champ + "note"] = scu.fmt_note(resgroupe[0])
|
||||||
row[champ + "class groupe"] = "%s / %s" % (
|
row[champ + "class groupe"] = "%s / %s" % (
|
||||||
resgroupe[2],
|
resgroupe[2],
|
||||||
resgroupe[3],
|
resgroupe[3],
|
||||||
@ -1083,11 +1083,12 @@ class JuryPE:
|
|||||||
respromo[3],
|
respromo[3],
|
||||||
)
|
)
|
||||||
row[champ + "min/moy/max groupe"] = "%s / %s / %s" % tuple(
|
row[champ + "min/moy/max groupe"] = "%s / %s / %s" % tuple(
|
||||||
fmt_note(x)
|
scu.fmt_note(x)
|
||||||
for x in (resgroupe[6], resgroupe[4], resgroupe[5])
|
for x in (resgroupe[6], resgroupe[4], resgroupe[5])
|
||||||
)
|
)
|
||||||
row[champ + "min/moy/max promo"] = "%s / %s / %s" % tuple(
|
row[champ + "min/moy/max promo"] = "%s / %s / %s" % tuple(
|
||||||
fmt_note(x) for x in (respromo[6], respromo[4], respromo[5])
|
scu.fmt_note(x)
|
||||||
|
for x in (respromo[6], respromo[4], respromo[5])
|
||||||
)
|
)
|
||||||
rows.append(row)
|
rows.append(row)
|
||||||
|
|
||||||
|
@ -35,8 +35,10 @@ Created on Fri Sep 9 09:15:05 2016
|
|||||||
|
|
||||||
@author: barasc
|
@author: barasc
|
||||||
"""
|
"""
|
||||||
import notes_table
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
from notes_log import log
|
||||||
|
import notes_table
|
||||||
import sco_codes_parcours
|
import sco_codes_parcours
|
||||||
import sco_tag_module
|
import sco_tag_module
|
||||||
import sco_utils
|
import sco_utils
|
||||||
@ -57,7 +59,7 @@ class SemestreTag(pe_tagtable.TableTag):
|
|||||||
Attributs supplémentaires :
|
Attributs supplémentaires :
|
||||||
- inscrlist/identdict: étudiants inscrits hors démissionnaires ou défaillants
|
- inscrlist/identdict: étudiants inscrits hors démissionnaires ou défaillants
|
||||||
- _tagdict : Dictionnaire résumant les tags et les modules du semestre auxquels ils sont liés
|
- _tagdict : Dictionnaire résumant les tags et les modules du semestre auxquels ils sont liés
|
||||||
- _sum_coeff_semestre : la somme des coeffs du semestre
|
|
||||||
|
|
||||||
Attributs hérités de TableTag :
|
Attributs hérités de TableTag :
|
||||||
- nom :
|
- nom :
|
||||||
@ -111,7 +113,7 @@ class SemestreTag(pe_tagtable.TableTag):
|
|||||||
self.modimpls = [
|
self.modimpls = [
|
||||||
modimpl
|
modimpl
|
||||||
for modimpl in self.nt._modimpls
|
for modimpl in self.nt._modimpls
|
||||||
if modimpl["ue"]["type"] == sco_utils.UE_STANDARD
|
if modimpl["ue"]["type"] == sco_codes_parcours.UE_STANDARD
|
||||||
] # la liste des modules (objet modimpl)
|
] # la liste des modules (objet modimpl)
|
||||||
# self._modimpl_ids = [modimpl['moduleimpl_id'] for modimpl in self._modimpls] # la liste de id des modules (modimpl_id)
|
# self._modimpl_ids = [modimpl['moduleimpl_id'] for modimpl in self._modimpls] # la liste de id des modules (modimpl_id)
|
||||||
self.somme_coeffs = sum(
|
self.somme_coeffs = sum(
|
||||||
@ -136,8 +138,7 @@ class SemestreTag(pe_tagtable.TableTag):
|
|||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
def get_etudids(self):
|
def get_etudids(self):
|
||||||
"""Renvoie la liste des etud_id des étudiants inscrits au semestre
|
"""Renvoie la liste des etud_id des étudiants inscrits au semestre"""
|
||||||
"""
|
|
||||||
return [etud["etudid"] for etud in self.inscrlist]
|
return [etud["etudid"] for etud in self.inscrlist]
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
@ -382,7 +383,7 @@ class SemestreTag(pe_tagtable.TableTag):
|
|||||||
+ (
|
+ (
|
||||||
"%1.5f" % (coeff * self.somme_coeffs)
|
"%1.5f" % (coeff * self.somme_coeffs)
|
||||||
if coeff != None and isinstance(coeff, float)
|
if coeff != None and isinstance(coeff, float)
|
||||||
else str(coeff * self._sum_coeff_semestre)
|
else "???" # str(coeff * self._sum_coeff_semestre) # voir avec Cléo
|
||||||
)
|
)
|
||||||
+ delim
|
+ delim
|
||||||
)
|
)
|
||||||
@ -477,8 +478,9 @@ def get_moduleimpl(nt, modimpl_id):
|
|||||||
] # la liste de id des modules (modimpl_id)
|
] # la liste de id des modules (modimpl_id)
|
||||||
if modimpl_id not in modimplids:
|
if modimpl_id not in modimplids:
|
||||||
if SemestreTag.DEBUG:
|
if SemestreTag.DEBUG:
|
||||||
print "SemestreTag.get_moduleimpl( %s ) : le modimpl recherche n'existe pas" % (
|
log(
|
||||||
modimpl_id
|
"SemestreTag.get_moduleimpl( %s ) : le modimpl recherche n'existe pas"
|
||||||
|
% (modimpl_id)
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
return nt._modimpls[modimplids.index(modimpl_id)]
|
return nt._modimpls[modimplids.index(modimpl_id)]
|
||||||
|
@ -36,7 +36,7 @@ Created on Fri Sep 9 09:15:05 2016
|
|||||||
@author: barasc
|
@author: barasc
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from pe_tools import *
|
from pe_tools import pe_print, PE_DEBUG
|
||||||
|
|
||||||
import pe_tagtable
|
import pe_tagtable
|
||||||
import pe_semestretag
|
import pe_semestretag
|
||||||
|
@ -210,7 +210,7 @@ class TableTag:
|
|||||||
]
|
]
|
||||||
nb_notes_valides = len(notes_valides)
|
nb_notes_valides = len(notes_valides)
|
||||||
if nb_notes_valides > 0:
|
if nb_notes_valides > 0:
|
||||||
(moy, coeff) = moyenne_ponderee_terme_a_terme(notes_valides, force=True)
|
(moy, _) = moyenne_ponderee_terme_a_terme(notes_valides, force=True)
|
||||||
self.statistiques[tag] = (moy, max(notes_valides), min(notes_valides))
|
self.statistiques[tag] = (moy, max(notes_valides), min(notes_valides))
|
||||||
|
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
|
10
pe_tools.py
10
pe_tools.py
@ -37,12 +37,14 @@ Created on Thu Sep 8 09:36:33 2016
|
|||||||
"""
|
"""
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import os
|
||||||
import datetime
|
import datetime
|
||||||
import operator
|
import operator
|
||||||
import re
|
import re
|
||||||
import unicodedata
|
import unicodedata
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
|
from notes_log import log
|
||||||
import notes_table
|
import notes_table
|
||||||
|
|
||||||
PE_DEBUG = 0
|
PE_DEBUG = 0
|
||||||
@ -175,7 +177,7 @@ def add_pe_stuff_to_zip(context, zipfile, ziproot):
|
|||||||
|
|
||||||
Also copy logos
|
Also copy logos
|
||||||
"""
|
"""
|
||||||
PE_AUX_DIR = os.path.join(SCO_SRC_DIR, "config/doc_poursuites_etudes")
|
PE_AUX_DIR = os.path.join(scu.SCO_SRC_DIR, "config/doc_poursuites_etudes")
|
||||||
distrib_dir = os.path.join(PE_AUX_DIR, "distrib")
|
distrib_dir = os.path.join(PE_AUX_DIR, "distrib")
|
||||||
distrib_pathnames = list_directory_filenames(
|
distrib_pathnames = list_directory_filenames(
|
||||||
distrib_dir
|
distrib_dir
|
||||||
@ -204,7 +206,7 @@ def add_pe_stuff_to_zip(context, zipfile, ziproot):
|
|||||||
# Logos: (add to logos/ directory in zip)
|
# Logos: (add to logos/ directory in zip)
|
||||||
logos_names = ["logo_header.jpg", "logo_footer.jpg"]
|
logos_names = ["logo_header.jpg", "logo_footer.jpg"]
|
||||||
for f in logos_names:
|
for f in logos_names:
|
||||||
logo = os.path.join(SCODOC_LOGOS_DIR, f)
|
logo = os.path.join(scu.SCODOC_LOGOS_DIR, f)
|
||||||
if os.path.isfile(logo):
|
if os.path.isfile(logo):
|
||||||
add_local_file_to_zip(zipfile, ziproot, logo, "avis/logos/" + f)
|
add_local_file_to_zip(zipfile, ziproot, logo, "avis/logos/" + f)
|
||||||
|
|
||||||
@ -215,7 +217,7 @@ JURY_SYNTHESE_POUR_DEBUG = {
|
|||||||
"EID1810": {
|
"EID1810": {
|
||||||
"nom": "ROUX",
|
"nom": "ROUX",
|
||||||
"entree": "2016",
|
"entree": "2016",
|
||||||
"sexe": "M.",
|
"civilite_str": "M.",
|
||||||
"promo": 2016,
|
"promo": 2016,
|
||||||
"S2": {
|
"S2": {
|
||||||
"groupe": {
|
"groupe": {
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_formsemestre_status
|
import sco_formsemestre_status
|
||||||
@ -44,7 +44,7 @@ from gen_tables import GenTable
|
|||||||
import sco_codes_parcours
|
import sco_codes_parcours
|
||||||
|
|
||||||
import pe_tools
|
import pe_tools
|
||||||
from pe_tools import *
|
from pe_tools import PE_LATEX_ENCODING
|
||||||
import pe_tagtable
|
import pe_tagtable
|
||||||
import pe_semestretag
|
import pe_semestretag
|
||||||
import pe_settag
|
import pe_settag
|
||||||
@ -110,7 +110,7 @@ def pe_view_sem_recap(
|
|||||||
# template fourni via le formulaire Web
|
# template fourni via le formulaire Web
|
||||||
if avis_tmpl_file:
|
if avis_tmpl_file:
|
||||||
template_latex = avis_tmpl_file.read()
|
template_latex = avis_tmpl_file.read()
|
||||||
template_latex = template_latex.decode(SCO_ENCODING)
|
template_latex = template_latex.decode(scu.SCO_ENCODING)
|
||||||
else:
|
else:
|
||||||
# template indiqué dans préférences ScoDoc ?
|
# template indiqué dans préférences ScoDoc ?
|
||||||
template_latex = pe_avislatex.get_code_latex_from_scodoc_preference(
|
template_latex = pe_avislatex.get_code_latex_from_scodoc_preference(
|
||||||
@ -127,7 +127,7 @@ def pe_view_sem_recap(
|
|||||||
# template fourni via le formulaire Web
|
# template fourni via le formulaire Web
|
||||||
if footer_tmpl_file:
|
if footer_tmpl_file:
|
||||||
footer_latex = footer_tmpl_file.read()
|
footer_latex = footer_tmpl_file.read()
|
||||||
footer_latex = footer_latex.decode(SCO_ENCODING)
|
footer_latex = footer_latex.decode(scu.SCO_ENCODING)
|
||||||
else:
|
else:
|
||||||
footer_latex = pe_avislatex.get_code_latex_from_scodoc_preference(
|
footer_latex = pe_avislatex.get_code_latex_from_scodoc_preference(
|
||||||
context, formsemestre_id, champ="pe_avis_latex_footer"
|
context, formsemestre_id, champ="pe_avis_latex_footer"
|
||||||
|
@ -31,13 +31,15 @@
|
|||||||
|
|
||||||
Il suffit d'appeler abs_notify() après chaque ajout d'absence.
|
Il suffit d'appeler abs_notify() après chaque ajout d'absence.
|
||||||
"""
|
"""
|
||||||
|
import datetime
|
||||||
|
|
||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
from email.header import Header
|
from email.header import Header
|
||||||
|
|
||||||
from notesdb import *
|
|
||||||
from sco_utils import *
|
import notesdb as ndb
|
||||||
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from scolog import logdb
|
from scolog import logdb
|
||||||
import sco_bulletins
|
import sco_bulletins
|
||||||
@ -54,8 +56,8 @@ def abs_notify(context, etudid, date):
|
|||||||
if not sem:
|
if not sem:
|
||||||
return # non inscrit a la date, pas de notification
|
return # non inscrit a la date, pas de notification
|
||||||
|
|
||||||
debut_sem = DateDMYtoISO(sem["date_debut"])
|
debut_sem = ndb.DateDMYtoISO(sem["date_debut"])
|
||||||
fin_sem = DateDMYtoISO(sem["date_fin"])
|
fin_sem = ndb.DateDMYtoISO(sem["date_fin"])
|
||||||
nbabs = context.CountAbs(etudid, debut=debut_sem, fin=fin_sem)
|
nbabs = context.CountAbs(etudid, debut=debut_sem, fin=fin_sem)
|
||||||
nbabsjust = context.CountAbsJust(etudid, debut=debut_sem, fin=fin_sem)
|
nbabsjust = context.CountAbsJust(etudid, debut=debut_sem, fin=fin_sem)
|
||||||
|
|
||||||
@ -108,12 +110,12 @@ def abs_notify_send(
|
|||||||
"""Actually send the notification by email, and register it in database"""
|
"""Actually send the notification by email, and register it in database"""
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
log("abs_notify: sending notification to %s" % destinations)
|
log("abs_notify: sending notification to %s" % destinations)
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
for email in destinations:
|
for email in destinations:
|
||||||
del msg["To"]
|
del msg["To"]
|
||||||
msg["To"] = email
|
msg["To"] = email
|
||||||
context.sendEmail(msg)
|
context.sendEmail(msg)
|
||||||
SimpleQuery(
|
ndb.SimpleQuery(
|
||||||
context,
|
context,
|
||||||
"""insert into absences_notifications (etudid, email, nbabs, nbabsjust, formsemestre_id) values (%(etudid)s, %(email)s, %(nbabs)s, %(nbabsjust)s, %(formsemestre_id)s)""",
|
"""insert into absences_notifications (etudid, email, nbabs, nbabsjust, formsemestre_id) values (%(etudid)s, %(email)s, %(nbabs)s, %(nbabsjust)s, %(formsemestre_id)s)""",
|
||||||
vars(),
|
vars(),
|
||||||
@ -200,7 +202,7 @@ def etud_nbabs_last_notified(context, etudid, formsemestre_id=None):
|
|||||||
"""nbabs lors de la dernière notification envoyée pour cet étudiant dans ce semestre
|
"""nbabs lors de la dernière notification envoyée pour cet étudiant dans ce semestre
|
||||||
ou sans semestre (ce dernier cas est nécessaire pour la transition au nouveau code)"""
|
ou sans semestre (ce dernier cas est nécessaire pour la transition au nouveau code)"""
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""select * from absences_notifications where etudid = %(etudid)s and (formsemestre_id = %(formsemestre_id)s or formsemestre_id is NULL) order by notification_date desc""",
|
"""select * from absences_notifications where etudid = %(etudid)s and (formsemestre_id = %(formsemestre_id)s or formsemestre_id is NULL) order by notification_date desc""",
|
||||||
vars(),
|
vars(),
|
||||||
@ -215,17 +217,15 @@ def etud_nbabs_last_notified(context, etudid, formsemestre_id=None):
|
|||||||
def user_nbdays_since_last_notif(context, email_addr, etudid):
|
def user_nbdays_since_last_notif(context, email_addr, etudid):
|
||||||
"""nb days since last notification to this email, or None if no previous notification"""
|
"""nb days since last notification to this email, or None if no previous notification"""
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""select * from absences_notifications where email = %(email_addr)s and etudid=%(etudid)s order by notification_date desc""",
|
"""select * from absences_notifications where email = %(email_addr)s and etudid=%(etudid)s order by notification_date desc""",
|
||||||
{"email_addr": email_addr, "etudid": etudid},
|
{"email_addr": email_addr, "etudid": etudid},
|
||||||
)
|
)
|
||||||
res = cursor.dictfetchone()
|
res = cursor.dictfetchone()
|
||||||
if res:
|
if res:
|
||||||
mxd = res["notification_date"] # mx.DateTime instance
|
now = datetime.datetime.now(res["notification_date"].tzinfo)
|
||||||
lastdate = datetime.datetime(mxd.year, mxd.month, mxd.day)
|
return (now - res["notification_date"]).days
|
||||||
now = datetime.datetime.now()
|
|
||||||
return (now - lastdate).days
|
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -254,10 +254,10 @@ def abs_notification_message(context, sem, prefs, etudid, nbabs, nbabsjust):
|
|||||||
subject = """Trop d'absences pour %(nomprenom)s""" % etud
|
subject = """Trop d'absences pour %(nomprenom)s""" % etud
|
||||||
#
|
#
|
||||||
msg = MIMEMultipart()
|
msg = MIMEMultipart()
|
||||||
subj = Header("[ScoDoc] " + subject, SCO_ENCODING)
|
subj = Header("[ScoDoc] " + subject, scu.SCO_ENCODING)
|
||||||
msg["Subject"] = subj
|
msg["Subject"] = subj
|
||||||
msg["From"] = prefs["email_from_addr"]
|
msg["From"] = prefs["email_from_addr"]
|
||||||
txt = MIMEText(txt, "plain", SCO_ENCODING)
|
txt = MIMEText(txt, "plain", scu.SCO_ENCODING)
|
||||||
msg.attach(txt)
|
msg.attach(txt)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@ -270,7 +270,7 @@ def retreive_current_formsemestre(context, etudid, cur_date):
|
|||||||
WHERE sem.formsemestre_id = i.formsemestre_id AND i.etudid=%(etudid)s
|
WHERE sem.formsemestre_id = i.formsemestre_id AND i.etudid=%(etudid)s
|
||||||
AND (%(cur_date)s >= sem.date_debut) AND (%(cur_date)s <= sem.date_fin)"""
|
AND (%(cur_date)s >= sem.date_debut) AND (%(cur_date)s <= sem.date_fin)"""
|
||||||
|
|
||||||
r = SimpleDictFetch(context, req, {"etudid": etudid, "cur_date": cur_date})
|
r = ndb.SimpleDictFetch(context, req, {"etudid": etudid, "cur_date": cur_date})
|
||||||
if not r:
|
if not r:
|
||||||
return None
|
return None
|
||||||
# s'il y a plusieurs semestres, prend le premier (rarissime et non significatif):
|
# s'il y a plusieurs semestres, prend le premier (rarissime et non significatif):
|
||||||
@ -283,5 +283,5 @@ def mod_with_evals_at_date(context, date_abs, etudid):
|
|||||||
req = """SELECT m.* FROM notes_moduleimpl m, notes_evaluation e, notes_moduleimpl_inscription i
|
req = """SELECT m.* FROM notes_moduleimpl m, notes_evaluation e, notes_moduleimpl_inscription i
|
||||||
WHERE m.moduleimpl_id = e.moduleimpl_id AND e.moduleimpl_id = i.moduleimpl_id
|
WHERE m.moduleimpl_id = e.moduleimpl_id AND e.moduleimpl_id = i.moduleimpl_id
|
||||||
AND i.etudid = %(etudid)s AND e.jour = %(date_abs)s"""
|
AND i.etudid = %(etudid)s AND e.jour = %(date_abs)s"""
|
||||||
r = SimpleDictFetch(context, req, {"etudid": etudid, "date_abs": date_abs})
|
r = ndb.SimpleDictFetch(context, req, {"etudid": etudid, "date_abs": date_abs})
|
||||||
return r
|
return r
|
||||||
|
@ -56,10 +56,21 @@ def doSignaleAbsence(
|
|||||||
demijournee=2,
|
demijournee=2,
|
||||||
estjust=False,
|
estjust=False,
|
||||||
description=None,
|
description=None,
|
||||||
|
etudid=False,
|
||||||
REQUEST=None,
|
REQUEST=None,
|
||||||
): # etudid implied
|
): # etudid implied
|
||||||
"""Signalement d'une absence"""
|
"""Signalement d'une absence.
|
||||||
etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0]
|
|
||||||
|
Args:
|
||||||
|
datedebut: dd/mm/yyyy
|
||||||
|
datefin: dd/mm/yyyy (non incluse)
|
||||||
|
moduleimpl_id: module auquel imputer les absences
|
||||||
|
demijournee: 2 si journée complète, 1 matin, 0 après-midi
|
||||||
|
estjust: absence justifiée
|
||||||
|
description: str
|
||||||
|
etudid: etudiant concerné. Si non spécifié, cherche dans REQUEST.form
|
||||||
|
"""
|
||||||
|
etud = context.getEtudInfo(filled=1, etudid=etudid, REQUEST=REQUEST)[0]
|
||||||
etudid = etud["etudid"]
|
etudid = etud["etudid"]
|
||||||
|
|
||||||
description_abs = description
|
description_abs = description
|
||||||
@ -247,10 +258,25 @@ Raison: <input type="text" name="description" size="42"/> (optionnel)
|
|||||||
|
|
||||||
|
|
||||||
def doJustifAbsence(
|
def doJustifAbsence(
|
||||||
context, datedebut, datefin, demijournee, description=None, REQUEST=None
|
context,
|
||||||
|
datedebut,
|
||||||
|
datefin,
|
||||||
|
demijournee,
|
||||||
|
description=None,
|
||||||
|
etudid=False,
|
||||||
|
REQUEST=None,
|
||||||
): # etudid implied
|
): # etudid implied
|
||||||
"""Justification d'une absence"""
|
"""Justification d'une absence
|
||||||
etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0]
|
|
||||||
|
Args:
|
||||||
|
datedebut: dd/mm/yyyy
|
||||||
|
datefin: dd/mm/yyyy (non incluse)
|
||||||
|
demijournee: 2 si journée complète, 1 matin, 0 après-midi
|
||||||
|
estjust: absence justifiée
|
||||||
|
description: str
|
||||||
|
etudid: etudiant concerné. Si non spécifié, cherche dans REQUEST.form
|
||||||
|
"""
|
||||||
|
etud = context.getEtudInfo(filled=1, etudid=etudid, REQUEST=REQUEST)[0]
|
||||||
etudid = etud["etudid"]
|
etudid = etud["etudid"]
|
||||||
description_abs = description
|
description_abs = description
|
||||||
dates = sco_abs.DateRangeISO(context, datedebut, datefin)
|
dates = sco_abs.DateRangeISO(context, datedebut, datefin)
|
||||||
@ -370,10 +396,10 @@ Raison: <input type="text" name="description" size="42"/> (optionnel)
|
|||||||
|
|
||||||
|
|
||||||
def doAnnuleAbsence(
|
def doAnnuleAbsence(
|
||||||
context, datedebut, datefin, demijournee, REQUEST=None
|
context, datedebut, datefin, demijournee, etudid=False, REQUEST=None
|
||||||
): # etudid implied
|
): # etudid implied
|
||||||
"""Annulation des absences pour une demi journée"""
|
"""Annulation des absences pour une demi journée"""
|
||||||
etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0]
|
etud = context.getEtudInfo(filled=1, etudid=etudid, REQUEST=REQUEST)[0]
|
||||||
etudid = etud["etudid"]
|
etudid = etud["etudid"]
|
||||||
|
|
||||||
dates = sco_abs.DateRangeISO(context, datedebut, datefin)
|
dates = sco_abs.DateRangeISO(context, datedebut, datefin)
|
||||||
|
@ -46,10 +46,11 @@ Pour chaque étudiant commun:
|
|||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import sco_apogee_csv
|
import sco_apogee_csv
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
|
||||||
_help_txt = """
|
_help_txt = """
|
||||||
<div class="help">
|
<div class="help">
|
||||||
|
@ -27,9 +27,7 @@
|
|||||||
|
|
||||||
"""Exportation des résultats des étudiants vers Apogée.
|
"""Exportation des résultats des étudiants vers Apogée.
|
||||||
|
|
||||||
EXPERIMENTAL / PRECAUTIONS !
|
Ce code a été au départ inspiré par les travaux de Damien Mascré, scodoc2apogee (en Java).
|
||||||
|
|
||||||
Code inspiré par les travaux de Damien Mascré, scodoc2apogee (en Java).
|
|
||||||
|
|
||||||
A utiliser en fin de semestre, après les jury.
|
A utiliser en fin de semestre, après les jury.
|
||||||
|
|
||||||
@ -81,6 +79,13 @@ XXX A vérifier:
|
|||||||
AJAC car 1 sem. validé et pas de NAR
|
AJAC car 1 sem. validé et pas de NAR
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import collections
|
||||||
|
from types import FloatType
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import datetime
|
||||||
|
import os
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
import pprint
|
import pprint
|
||||||
@ -90,6 +95,10 @@ try:
|
|||||||
except:
|
except:
|
||||||
chardet_detect = None
|
chardet_detect = None
|
||||||
|
|
||||||
|
import sco_utils as scu
|
||||||
|
import notesdb as ndb
|
||||||
|
from notes_log import log
|
||||||
|
from sco_exceptions import ScoValueError, FormatError
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
from sco_formsemestre import ApoEtapeVDI
|
from sco_formsemestre import ApoEtapeVDI
|
||||||
import sco_formsemestre_status
|
import sco_formsemestre_status
|
||||||
@ -98,8 +107,6 @@ import sco_codes_parcours
|
|||||||
from sco_codes_parcours import code_semestre_validant
|
from sco_codes_parcours import code_semestre_validant
|
||||||
from sco_codes_parcours import ATT, ATB, ADM, ADC, ADJ, ATJ, ATB, AJ, CMP, NAR, RAT, DEF
|
from sco_codes_parcours import ATT, ATB, ADM, ADC, ADJ, ATJ, ATB, AJ, CMP, NAR, RAT, DEF
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
from notesdb import *
|
|
||||||
from sco_utils import *
|
|
||||||
|
|
||||||
APO_PORTAL_ENCODING = (
|
APO_PORTAL_ENCODING = (
|
||||||
"utf8" # encodage du fichier CSV Apogée (était 'ISO-8859-1' avant jul. 2016)
|
"utf8" # encodage du fichier CSV Apogée (était 'ISO-8859-1' avant jul. 2016)
|
||||||
@ -347,10 +354,10 @@ class ApoEtud(dict):
|
|||||||
for col_id in apo_data.col_ids[:4]:
|
for col_id in apo_data.col_ids[:4]:
|
||||||
self.new_cols[col_id] = self.cols[col_id]
|
self.new_cols[col_id] = self.cols[col_id]
|
||||||
|
|
||||||
def unassociated_codes(self, apo_data):
|
# def unassociated_codes(self, apo_data):
|
||||||
"list of apo elements for this student without a value in ScoDoc"
|
# "list of apo elements for this student without a value in ScoDoc"
|
||||||
codes = set([apo_data.cols[col_id].code for col_id in apo_data.col_ids])
|
# codes = set([apo_data.cols[col_id].code for col_id in apo_data.col_ids])
|
||||||
return codes - set(sco_elts)
|
# return codes - set(sco_elts)
|
||||||
|
|
||||||
def search_elt_in_sem(self, context, code, sem, cur_sem, autre_sem):
|
def search_elt_in_sem(self, context, code, sem, cur_sem, autre_sem):
|
||||||
"""
|
"""
|
||||||
@ -749,7 +756,7 @@ class ApoData:
|
|||||||
if not data:
|
if not data:
|
||||||
raise FormatError("Fichier Apogée vide !")
|
raise FormatError("Fichier Apogée vide !")
|
||||||
|
|
||||||
data_utf8 = data.decode(APO_INPUT_ENCODING).encode(SCO_ENCODING)
|
data_utf8 = data.decode(APO_INPUT_ENCODING).encode(scu.SCO_ENCODING)
|
||||||
f = StringIOFileLineWrapper(data_utf8) # pour traiter comme un fichier
|
f = StringIOFileLineWrapper(data_utf8) # pour traiter comme un fichier
|
||||||
# check that we are at the begining of Apogee CSV
|
# check that we are at the begining of Apogee CSV
|
||||||
line = f.readline().strip()
|
line = f.readline().strip()
|
||||||
@ -1023,7 +1030,7 @@ def _apo_read_cols(f):
|
|||||||
line = f.readline().strip(" " + APO_NEWLINE)
|
line = f.readline().strip(" " + APO_NEWLINE)
|
||||||
fs = line.split(APO_SEP)
|
fs = line.split(APO_SEP)
|
||||||
if fs[0] != "apoL_a01_code":
|
if fs[0] != "apoL_a01_code":
|
||||||
raise FormatError("invalid line: %s (expecting apoL_a01_code)"(line, i))
|
raise FormatError("invalid line: %s (expecting apoL_a01_code)" % line)
|
||||||
col_keys = fs
|
col_keys = fs
|
||||||
|
|
||||||
while True: # skip premiere partie (apoL_a02_nom, ...)
|
while True: # skip premiere partie (apoL_a02_nom, ...)
|
||||||
@ -1046,7 +1053,9 @@ def _apo_read_cols(f):
|
|||||||
raise FormatError("duplicate column definition: %s" % col_id)
|
raise FormatError("duplicate column definition: %s" % col_id)
|
||||||
m = re.match(r"^apoL_c([0-9]{4})$", col_id)
|
m = re.match(r"^apoL_c([0-9]{4})$", col_id)
|
||||||
if not m:
|
if not m:
|
||||||
raise FormatError("invalid column id: %s (expecting apoL_c%04d)"(line, i))
|
raise FormatError(
|
||||||
|
"invalid column id: %s (expecting apoL_c%04d)" % (line, col_id)
|
||||||
|
)
|
||||||
if int(m.group(1)) != i:
|
if int(m.group(1)) != i:
|
||||||
raise FormatError("invalid column id: %s for index %s" % (col_id, i))
|
raise FormatError("invalid column id: %s for index %s" % (col_id, i))
|
||||||
|
|
||||||
@ -1281,7 +1290,7 @@ def export_csv_to_apogee(
|
|||||||
)
|
)
|
||||||
log(logf.getvalue()) # sortie aussi sur le log ScoDoc
|
log(logf.getvalue()) # sortie aussi sur le log ScoDoc
|
||||||
|
|
||||||
csv_data = f.getvalue().decode(SCO_ENCODING).encode(APO_OUTPUT_ENCODING)
|
csv_data = f.getvalue().decode(scu.SCO_ENCODING).encode(APO_OUTPUT_ENCODING)
|
||||||
|
|
||||||
# Write data to ZIP
|
# Write data to ZIP
|
||||||
dest_zip.writestr(csv_filename, csv_data)
|
dest_zip.writestr(csv_filename, csv_data)
|
||||||
|
@ -45,15 +45,16 @@
|
|||||||
qui est une description (humaine, format libre) de l'archive.
|
qui est une description (humaine, format libre) de l'archive.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import os
|
||||||
from mx.DateTime import DateTime as mxDateTime
|
import time
|
||||||
import mx.DateTime
|
import datetime
|
||||||
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import glob
|
import glob
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
|
from notes_log import log
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_pvjury
|
import sco_pvjury
|
||||||
import sco_excel
|
import sco_excel
|
||||||
@ -62,6 +63,10 @@ import sco_groups
|
|||||||
import sco_groups_view
|
import sco_groups_view
|
||||||
from sco_recapcomplet import make_formsemestre_recapcomplet
|
from sco_recapcomplet import make_formsemestre_recapcomplet
|
||||||
import sco_bulletins_pdf
|
import sco_bulletins_pdf
|
||||||
|
from TrivialFormulator import TrivialFormulator
|
||||||
|
from sco_exceptions import (
|
||||||
|
AccessDenied,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BaseArchiver:
|
class BaseArchiver:
|
||||||
@ -75,12 +80,12 @@ class BaseArchiver:
|
|||||||
for dir in dirs[1:]:
|
for dir in dirs[1:]:
|
||||||
path = os.path.join(path, dir)
|
path = os.path.join(path, dir)
|
||||||
try:
|
try:
|
||||||
GSL.acquire()
|
scu.GSL.acquire()
|
||||||
if not os.path.isdir(path):
|
if not os.path.isdir(path):
|
||||||
log("creating directory %s" % path)
|
log("creating directory %s" % path)
|
||||||
os.mkdir(path)
|
os.mkdir(path)
|
||||||
finally:
|
finally:
|
||||||
GSL.release()
|
scu.GSL.release()
|
||||||
|
|
||||||
def get_obj_dir(self, context, oid):
|
def get_obj_dir(self, context, oid):
|
||||||
"""
|
"""
|
||||||
@ -89,7 +94,7 @@ class BaseArchiver:
|
|||||||
"""
|
"""
|
||||||
dept_dir = os.path.join(self.root, context.DeptId())
|
dept_dir = os.path.join(self.root, context.DeptId())
|
||||||
try:
|
try:
|
||||||
GSL.acquire()
|
scu.GSL.acquire()
|
||||||
if not os.path.isdir(dept_dir):
|
if not os.path.isdir(dept_dir):
|
||||||
log("creating directory %s" % dept_dir)
|
log("creating directory %s" % dept_dir)
|
||||||
os.mkdir(dept_dir)
|
os.mkdir(dept_dir)
|
||||||
@ -98,7 +103,7 @@ class BaseArchiver:
|
|||||||
log("creating directory %s" % obj_dir)
|
log("creating directory %s" % obj_dir)
|
||||||
os.mkdir(obj_dir)
|
os.mkdir(obj_dir)
|
||||||
finally:
|
finally:
|
||||||
GSL.release()
|
scu.GSL.release()
|
||||||
return obj_dir
|
return obj_dir
|
||||||
|
|
||||||
def list_oids(self, context):
|
def list_oids(self, context):
|
||||||
@ -126,23 +131,23 @@ class BaseArchiver:
|
|||||||
def delete_archive(self, archive_id):
|
def delete_archive(self, archive_id):
|
||||||
"""Delete (forever) this archive"""
|
"""Delete (forever) this archive"""
|
||||||
try:
|
try:
|
||||||
GSL.acquire()
|
scu.GSL.acquire()
|
||||||
shutil.rmtree(archive_id, ignore_errors=True)
|
shutil.rmtree(archive_id, ignore_errors=True)
|
||||||
finally:
|
finally:
|
||||||
GSL.release()
|
scu.GSL.release()
|
||||||
|
|
||||||
def get_archive_date(self, archive_id):
|
def get_archive_date(self, archive_id):
|
||||||
"""Returns date (as a DateTime object) of an archive"""
|
"""Returns date (as a DateTime object) of an archive"""
|
||||||
dt = [int(x) for x in os.path.split(archive_id)[1].split("-")]
|
dt = [int(x) for x in os.path.split(archive_id)[1].split("-")]
|
||||||
return mxDateTime(*dt)
|
return datetime.datetime(*dt)
|
||||||
|
|
||||||
def list_archive(self, archive_id):
|
def list_archive(self, archive_id):
|
||||||
"""Return list of filenames (without path) in archive"""
|
"""Return list of filenames (without path) in archive"""
|
||||||
try:
|
try:
|
||||||
GSL.acquire()
|
scu.GSL.acquire()
|
||||||
files = os.listdir(archive_id)
|
files = os.listdir(archive_id)
|
||||||
finally:
|
finally:
|
||||||
GSL.release()
|
scu.GSL.release()
|
||||||
files.sort()
|
files.sort()
|
||||||
return [f for f in files if f and f[0] != "_"]
|
return [f for f in files if f and f[0] != "_"]
|
||||||
|
|
||||||
@ -182,10 +187,10 @@ class BaseArchiver:
|
|||||||
)
|
)
|
||||||
log("creating archive: %s" % archive_id)
|
log("creating archive: %s" % archive_id)
|
||||||
try:
|
try:
|
||||||
GSL.acquire()
|
scu.GSL.acquire()
|
||||||
os.mkdir(archive_id) # if exists, raises an OSError
|
os.mkdir(archive_id) # if exists, raises an OSError
|
||||||
finally:
|
finally:
|
||||||
GSL.release()
|
scu.GSL.release()
|
||||||
self.store(archive_id, "_description.txt", description)
|
self.store(archive_id, "_description.txt", description)
|
||||||
return archive_id
|
return archive_id
|
||||||
|
|
||||||
@ -194,21 +199,21 @@ class BaseArchiver:
|
|||||||
Filename may be modified (sanitized): return used filename
|
Filename may be modified (sanitized): return used filename
|
||||||
The file is created or replaced.
|
The file is created or replaced.
|
||||||
"""
|
"""
|
||||||
filename = sanitize_filename(filename)
|
filename = scu.sanitize_filename(filename)
|
||||||
log("storing %s (%d bytes) in %s" % (filename, len(data), archive_id))
|
log("storing %s (%d bytes) in %s" % (filename, len(data), archive_id))
|
||||||
try:
|
try:
|
||||||
GSL.acquire()
|
scu.GSL.acquire()
|
||||||
fname = os.path.join(archive_id, filename)
|
fname = os.path.join(archive_id, filename)
|
||||||
f = open(fname, "w")
|
f = open(fname, "w")
|
||||||
f.write(data)
|
f.write(data)
|
||||||
f.close()
|
f.close()
|
||||||
finally:
|
finally:
|
||||||
GSL.release()
|
scu.GSL.release()
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
def get(self, archive_id, filename):
|
def get(self, archive_id, filename):
|
||||||
"""Retreive data"""
|
"""Retreive data"""
|
||||||
if not is_valid_filename(filename):
|
if not scu.is_valid_filename(filename):
|
||||||
log('Archiver.get: invalid filename "%s"' % filename)
|
log('Archiver.get: invalid filename "%s"' % filename)
|
||||||
raise ValueError("invalid filename")
|
raise ValueError("invalid filename")
|
||||||
fname = os.path.join(archive_id, filename)
|
fname = os.path.join(archive_id, filename)
|
||||||
@ -220,18 +225,18 @@ class BaseArchiver:
|
|||||||
# XXX très incomplet: devrait inférer et assigner un type MIME
|
# XXX très incomplet: devrait inférer et assigner un type MIME
|
||||||
archive_id = self.get_id_from_name(context, oid, archive_name)
|
archive_id = self.get_id_from_name(context, oid, archive_name)
|
||||||
data = self.get(archive_id, filename)
|
data = self.get(archive_id, filename)
|
||||||
ext = os.path.splitext(strlower(filename))[1]
|
ext = os.path.splitext(scu.strlower(filename))[1]
|
||||||
if ext == ".html" or ext == ".htm":
|
if ext == ".html" or ext == ".htm":
|
||||||
return data
|
return data
|
||||||
elif ext == ".xml":
|
elif ext == ".xml":
|
||||||
REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE)
|
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
|
||||||
return data
|
return data
|
||||||
elif ext == ".xls":
|
elif ext == ".xls":
|
||||||
return sco_excel.sendExcelFile(REQUEST, data, filename)
|
return sco_excel.sendExcelFile(REQUEST, data, filename)
|
||||||
elif ext == ".csv":
|
elif ext == ".csv":
|
||||||
return sendCSVFile(REQUEST, data, filename)
|
return scu.sendCSVFile(REQUEST, data, filename)
|
||||||
elif ext == ".pdf":
|
elif ext == ".pdf":
|
||||||
return sendPDFFile(REQUEST, data, filename)
|
return scu.sendPDFFile(REQUEST, data, filename)
|
||||||
|
|
||||||
return data # should set mimetype...
|
return data # should set mimetype...
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
les dossiers d'admission et autres pièces utiles.
|
les dossiers d'admission et autres pièces utiles.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import ImportScolars
|
import ImportScolars
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
@ -38,6 +38,9 @@ import sco_groups
|
|||||||
import sco_trombino
|
import sco_trombino
|
||||||
import sco_excel
|
import sco_excel
|
||||||
import sco_archives
|
import sco_archives
|
||||||
|
from sco_permissions import ScoEtudAddAnnotations
|
||||||
|
from sco_exceptions import AccessDenied
|
||||||
|
from TrivialFormulator import TrivialFormulator
|
||||||
|
|
||||||
|
|
||||||
class EtudsArchiver(sco_archives.BaseArchiver):
|
class EtudsArchiver(sco_archives.BaseArchiver):
|
||||||
@ -65,10 +68,10 @@ def etud_list_archives_html(context, REQUEST, etudid):
|
|||||||
"content": EtudsArchive.list_archive(archive_id),
|
"content": EtudsArchive.list_archive(archive_id),
|
||||||
}
|
}
|
||||||
L.append(a)
|
L.append(a)
|
||||||
delete_icon = icontag(
|
delete_icon = scu.icontag(
|
||||||
"delete_small_img", title="Supprimer fichier", alt="supprimer"
|
"delete_small_img", title="Supprimer fichier", alt="supprimer"
|
||||||
)
|
)
|
||||||
delete_disabled_icon = icontag(
|
delete_disabled_icon = scu.icontag(
|
||||||
"delete_small_dis_img", title="Suppression non autorisée"
|
"delete_small_dis_img", title="Suppression non autorisée"
|
||||||
)
|
)
|
||||||
H = ['<div class="etudarchive"><ul>']
|
H = ['<div class="etudarchive"><ul>']
|
||||||
@ -137,7 +140,7 @@ def etud_upload_file_form(context, REQUEST, etudid):
|
|||||||
% etud,
|
% etud,
|
||||||
"""<p>Le fichier ne doit pas dépasser %sMo.</p>
|
"""<p>Le fichier ne doit pas dépasser %sMo.</p>
|
||||||
"""
|
"""
|
||||||
% (CONFIG.ETUD_MAX_FILE_SIZE / (1024 * 1024)),
|
% (scu.CONFIG.ETUD_MAX_FILE_SIZE / (1024 * 1024)),
|
||||||
]
|
]
|
||||||
tf = TrivialFormulator(
|
tf = TrivialFormulator(
|
||||||
REQUEST.URL0,
|
REQUEST.URL0,
|
||||||
@ -161,7 +164,9 @@ def etud_upload_file_form(context, REQUEST, etudid):
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
|
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "/ficheEtud?etudid=" + etudid)
|
return REQUEST.RESPONSE.redirect(
|
||||||
|
context.NotesURL() + "/ficheEtud?etudid=" + etudid
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
data = tf[2]["datafile"].read()
|
data = tf[2]["datafile"].read()
|
||||||
descr = tf[2]["description"]
|
descr = tf[2]["description"]
|
||||||
@ -169,7 +174,9 @@ def etud_upload_file_form(context, REQUEST, etudid):
|
|||||||
_store_etud_file_to_new_archive(
|
_store_etud_file_to_new_archive(
|
||||||
context, REQUEST, etudid, data, filename, description=descr
|
context, REQUEST, etudid, data, filename, description=descr
|
||||||
)
|
)
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "/ficheEtud?etudid=" + etudid)
|
return REQUEST.RESPONSE.redirect(
|
||||||
|
context.NotesURL() + "/ficheEtud?etudid=" + etudid
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _store_etud_file_to_new_archive(
|
def _store_etud_file_to_new_archive(
|
||||||
@ -177,7 +184,7 @@ def _store_etud_file_to_new_archive(
|
|||||||
):
|
):
|
||||||
"""Store data to new archive."""
|
"""Store data to new archive."""
|
||||||
filesize = len(data)
|
filesize = len(data)
|
||||||
if filesize < 10 or filesize > CONFIG.ETUD_MAX_FILE_SIZE:
|
if filesize < 10 or filesize > scu.CONFIG.ETUD_MAX_FILE_SIZE:
|
||||||
return 0, "Fichier image de taille invalide ! (%d)" % filesize
|
return 0, "Fichier image de taille invalide ! (%d)" % filesize
|
||||||
archive_id = EtudsArchive.create_obj_archive(context, etudid, description)
|
archive_id = EtudsArchive.create_obj_archive(context, etudid, description)
|
||||||
EtudsArchive.store(archive_id, filename, data)
|
EtudsArchive.store(archive_id, filename, data)
|
||||||
|
105
sco_bulletins.py
105
sco_bulletins.py
@ -28,18 +28,26 @@
|
|||||||
"""Génération des bulletins de notes
|
"""Génération des bulletins de notes
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import time
|
||||||
|
from types import StringType
|
||||||
|
import pprint
|
||||||
|
import urllib
|
||||||
|
import htmlutils
|
||||||
import email
|
import email
|
||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
from email.mime.base import MIMEBase
|
from email.mime.base import MIMEBase
|
||||||
from email.header import Header
|
from email.header import Header
|
||||||
|
|
||||||
import time
|
|
||||||
from reportlab.lib.colors import Color
|
from reportlab.lib.colors import Color
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notes_table import *
|
import notesdb as ndb
|
||||||
import htmlutils
|
from notes_log import log
|
||||||
|
import scolars
|
||||||
|
from sco_permissions import ScoImplement, ScoEtudInscrit
|
||||||
|
from sco_exceptions import AccessDenied
|
||||||
|
import sco_codes_parcours
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_groups
|
import sco_groups
|
||||||
import sco_pvjury
|
import sco_pvjury
|
||||||
@ -112,7 +120,7 @@ def formsemestre_bulletinetud_dict(
|
|||||||
context, formsemestre_id
|
context, formsemestre_id
|
||||||
) # > toutes notes
|
) # > toutes notes
|
||||||
|
|
||||||
I = DictDefault(defaultvalue="")
|
I = scu.DictDefault(defaultvalue="")
|
||||||
I["etudid"] = etudid
|
I["etudid"] = etudid
|
||||||
I["formsemestre_id"] = formsemestre_id
|
I["formsemestre_id"] = formsemestre_id
|
||||||
I["sem"] = nt.sem
|
I["sem"] = nt.sem
|
||||||
@ -180,7 +188,7 @@ def formsemestre_bulletinetud_dict(
|
|||||||
if I["etud_etat"] == "D":
|
if I["etud_etat"] == "D":
|
||||||
I["demission"] = "(Démission)"
|
I["demission"] = "(Démission)"
|
||||||
I["filigranne"] = "Démission"
|
I["filigranne"] = "Démission"
|
||||||
elif I["etud_etat"] == DEF:
|
elif I["etud_etat"] == sco_codes_parcours.DEF:
|
||||||
I["demission"] = "(Défaillant)"
|
I["demission"] = "(Défaillant)"
|
||||||
I["filigranne"] = "Défaillant"
|
I["filigranne"] = "Défaillant"
|
||||||
elif (prefs["bul_show_temporary"] and not I["decision_sem"]) or prefs[
|
elif (prefs["bul_show_temporary"] and not I["decision_sem"]) or prefs[
|
||||||
@ -204,16 +212,16 @@ def formsemestre_bulletinetud_dict(
|
|||||||
modimpls = nt.get_modimpls()
|
modimpls = nt.get_modimpls()
|
||||||
moy_gen = nt.get_etud_moy_gen(etudid)
|
moy_gen = nt.get_etud_moy_gen(etudid)
|
||||||
I["nb_inscrits"] = len(nt.rangs)
|
I["nb_inscrits"] = len(nt.rangs)
|
||||||
I["moy_gen"] = fmt_note(moy_gen)
|
I["moy_gen"] = scu.fmt_note(moy_gen)
|
||||||
I["moy_min"] = fmt_note(nt.moy_min)
|
I["moy_min"] = scu.fmt_note(nt.moy_min)
|
||||||
I["moy_max"] = fmt_note(nt.moy_max)
|
I["moy_max"] = scu.fmt_note(nt.moy_max)
|
||||||
I["mention"] = ""
|
I["mention"] = ""
|
||||||
if dpv:
|
if dpv:
|
||||||
decision_sem = dpv["decisions"][0]["decision_sem"]
|
decision_sem = dpv["decisions"][0]["decision_sem"]
|
||||||
if decision_sem and sco_codes_parcours.code_semestre_validant(
|
if decision_sem and sco_codes_parcours.code_semestre_validant(
|
||||||
decision_sem["code"]
|
decision_sem["code"]
|
||||||
):
|
):
|
||||||
I["mention"] = get_mention(moy_gen)
|
I["mention"] = scu.get_mention(moy_gen)
|
||||||
|
|
||||||
if dpv and dpv["decisions"][0]:
|
if dpv and dpv["decisions"][0]:
|
||||||
I["sum_ects"] = dpv["decisions"][0]["sum_ects"]
|
I["sum_ects"] = dpv["decisions"][0]["sum_ects"]
|
||||||
@ -221,7 +229,7 @@ def formsemestre_bulletinetud_dict(
|
|||||||
else:
|
else:
|
||||||
I["sum_ects"] = 0
|
I["sum_ects"] = 0
|
||||||
I["sum_ects_capitalises"] = 0
|
I["sum_ects_capitalises"] = 0
|
||||||
I["moy_moy"] = fmt_note(nt.moy_moy) # moyenne des moyennes generales
|
I["moy_moy"] = scu.fmt_note(nt.moy_moy) # moyenne des moyennes generales
|
||||||
if type(moy_gen) != StringType and type(nt.moy_moy) != StringType:
|
if type(moy_gen) != StringType and type(nt.moy_moy) != StringType:
|
||||||
I["moy_gen_bargraph_html"] = " " + htmlutils.horizontal_bargraph(
|
I["moy_gen_bargraph_html"] = " " + htmlutils.horizontal_bargraph(
|
||||||
moy_gen * 5, nt.moy_moy * 5
|
moy_gen * 5, nt.moy_moy * 5
|
||||||
@ -241,8 +249,8 @@ def formsemestre_bulletinetud_dict(
|
|||||||
if nt.get_moduleimpls_attente():
|
if nt.get_moduleimpls_attente():
|
||||||
# n'affiche pas le rang sur le bulletin s'il y a des
|
# n'affiche pas le rang sur le bulletin s'il y a des
|
||||||
# notes en attente dans ce semestre
|
# notes en attente dans ce semestre
|
||||||
rang = RANG_ATTENTE_STR
|
rang = scu.RANG_ATTENTE_STR
|
||||||
rang_gr = DictDefault(defaultvalue=RANG_ATTENTE_STR)
|
rang_gr = scu.DictDefault(defaultvalue=scu.RANG_ATTENTE_STR)
|
||||||
I["rang"] = rang
|
I["rang"] = rang
|
||||||
I["rang_gr"] = rang_gr
|
I["rang_gr"] = rang_gr
|
||||||
I["gr_name"] = gr_name
|
I["gr_name"] = gr_name
|
||||||
@ -268,17 +276,17 @@ def formsemestre_bulletinetud_dict(
|
|||||||
u = ue.copy()
|
u = ue.copy()
|
||||||
ue_status = nt.get_etud_ue_status(etudid, ue["ue_id"])
|
ue_status = nt.get_etud_ue_status(etudid, ue["ue_id"])
|
||||||
u["ue_status"] = ue_status # { 'moy', 'coef_ue', ...}
|
u["ue_status"] = ue_status # { 'moy', 'coef_ue', ...}
|
||||||
if ue["type"] != UE_SPORT:
|
if ue["type"] != sco_codes_parcours.UE_SPORT:
|
||||||
u["cur_moy_ue_txt"] = fmt_note(ue_status["cur_moy_ue"])
|
u["cur_moy_ue_txt"] = scu.fmt_note(ue_status["cur_moy_ue"])
|
||||||
else:
|
else:
|
||||||
x = fmt_note(nt.bonus[etudid], keep_numeric=True)
|
x = scu.fmt_note(nt.bonus[etudid], keep_numeric=True)
|
||||||
if type(x) == StringType:
|
if type(x) == StringType:
|
||||||
u["cur_moy_ue_txt"] = "pas de bonus"
|
u["cur_moy_ue_txt"] = "pas de bonus"
|
||||||
else:
|
else:
|
||||||
u["cur_moy_ue_txt"] = "bonus de %.3g points" % x
|
u["cur_moy_ue_txt"] = "bonus de %.3g points" % x
|
||||||
u["moy_ue_txt"] = fmt_note(ue_status["moy"])
|
u["moy_ue_txt"] = scu.fmt_note(ue_status["moy"])
|
||||||
if ue_status["coef_ue"] != None:
|
if ue_status["coef_ue"] != None:
|
||||||
u["coef_ue_txt"] = fmt_coef(ue_status["coef_ue"])
|
u["coef_ue_txt"] = scu.fmt_coef(ue_status["coef_ue"])
|
||||||
else:
|
else:
|
||||||
# C'est un bug:
|
# C'est un bug:
|
||||||
log("u=" + pprint.pformat(u))
|
log("u=" + pprint.pformat(u))
|
||||||
@ -290,7 +298,7 @@ def formsemestre_bulletinetud_dict(
|
|||||||
and ue["ue_id"] in dpv["decisions"][0]["decisions_ue"]
|
and ue["ue_id"] in dpv["decisions"][0]["decisions_ue"]
|
||||||
):
|
):
|
||||||
u["ects"] = dpv["decisions"][0]["decisions_ue"][ue["ue_id"]]["ects"]
|
u["ects"] = dpv["decisions"][0]["decisions_ue"][ue["ue_id"]]["ects"]
|
||||||
if ue["type"] == UE_ELECTIVE:
|
if ue["type"] == sco_codes_parcours.UE_ELECTIVE:
|
||||||
u["ects"] = (
|
u["ects"] = (
|
||||||
"%g+" % u["ects"]
|
"%g+" % u["ects"]
|
||||||
) # ajoute un "+" pour indiquer ECTS d'une UE élective
|
) # ajoute un "+" pour indiquer ECTS d'une UE élective
|
||||||
@ -314,7 +322,7 @@ def formsemestre_bulletinetud_dict(
|
|||||||
sem_origin = sco_formsemestre.get_formsemestre(
|
sem_origin = sco_formsemestre.get_formsemestre(
|
||||||
context, ue_status["formsemestre_id"]
|
context, ue_status["formsemestre_id"]
|
||||||
)
|
)
|
||||||
u["ue_descr_txt"] = "Capitalisée le %s" % DateISOtoDMY(
|
u["ue_descr_txt"] = "Capitalisée le %s" % ndb.DateISOtoDMY(
|
||||||
ue_status["event_date"]
|
ue_status["event_date"]
|
||||||
)
|
)
|
||||||
u[
|
u[
|
||||||
@ -345,10 +353,10 @@ def formsemestre_bulletinetud_dict(
|
|||||||
_sort_mod_by_matiere(u["modules_capitalized"], nt_cap, etudid)
|
_sort_mod_by_matiere(u["modules_capitalized"], nt_cap, etudid)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if prefs["bul_show_ue_rangs"] and ue["type"] != UE_SPORT:
|
if prefs["bul_show_ue_rangs"] and ue["type"] != sco_codes_parcours.UE_SPORT:
|
||||||
if ue_attente: # nt.get_moduleimpls_attente():
|
if ue_attente: # nt.get_moduleimpls_attente():
|
||||||
u["ue_descr_txt"] = "%s/%s" % (
|
u["ue_descr_txt"] = "%s/%s" % (
|
||||||
RANG_ATTENTE_STR,
|
scu.RANG_ATTENTE_STR,
|
||||||
nt.ue_rangs[ue["ue_id"]][1],
|
nt.ue_rangs[ue["ue_id"]][1],
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -384,7 +392,7 @@ def _sort_mod_by_matiere(modlist, nt, etudid):
|
|||||||
"titre": mod["mat"]["titre"],
|
"titre": mod["mat"]["titre"],
|
||||||
"modules": mod,
|
"modules": mod,
|
||||||
"moy": moy,
|
"moy": moy,
|
||||||
"moy_txt": fmt_note(moy),
|
"moy_txt": scu.fmt_note(moy),
|
||||||
}
|
}
|
||||||
return matmod
|
return matmod
|
||||||
|
|
||||||
@ -400,8 +408,8 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
|
|||||||
)
|
)
|
||||||
if bul_show_abs_modules:
|
if bul_show_abs_modules:
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||||
debut_sem = DateDMYtoISO(sem["date_debut"])
|
debut_sem = ndb.DateDMYtoISO(sem["date_debut"])
|
||||||
fin_sem = DateDMYtoISO(sem["date_fin"])
|
fin_sem = ndb.DateDMYtoISO(sem["date_fin"])
|
||||||
|
|
||||||
ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue_id]
|
ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue_id]
|
||||||
mods = [] # result
|
mods = [] # result
|
||||||
@ -412,7 +420,7 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
|
|||||||
mod_moy = nt.get_etud_mod_moy(
|
mod_moy = nt.get_etud_mod_moy(
|
||||||
modimpl["moduleimpl_id"], etudid
|
modimpl["moduleimpl_id"], etudid
|
||||||
) # peut etre 'NI'
|
) # peut etre 'NI'
|
||||||
is_malus = mod["module"]["module_type"] == MODULE_MALUS
|
is_malus = mod["module"]["module_type"] == scu.MODULE_MALUS
|
||||||
if bul_show_abs_modules:
|
if bul_show_abs_modules:
|
||||||
mod_abs = [
|
mod_abs = [
|
||||||
context.Absences.CountAbs(
|
context.Absences.CountAbs(
|
||||||
@ -428,25 +436,25 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
|
|||||||
moduleimpl_id=modimpl["moduleimpl_id"],
|
moduleimpl_id=modimpl["moduleimpl_id"],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
mod["mod_abs_txt"] = fmt_abs(mod_abs)
|
mod["mod_abs_txt"] = scu.fmt_abs(mod_abs)
|
||||||
else:
|
else:
|
||||||
mod["mod_abs_txt"] = ""
|
mod["mod_abs_txt"] = ""
|
||||||
|
|
||||||
mod["mod_moy_txt"] = fmt_note(mod_moy)
|
mod["mod_moy_txt"] = scu.fmt_note(mod_moy)
|
||||||
if mod["mod_moy_txt"][:2] == "NA":
|
if mod["mod_moy_txt"][:2] == "NA":
|
||||||
mod["mod_moy_txt"] = "-"
|
mod["mod_moy_txt"] = "-"
|
||||||
if is_malus:
|
if is_malus:
|
||||||
if mod_moy > 0:
|
if mod_moy > 0:
|
||||||
mod["mod_moy_txt"] = fmt_note(mod_moy)
|
mod["mod_moy_txt"] = scu.fmt_note(mod_moy)
|
||||||
mod["mod_coef_txt"] = "Malus"
|
mod["mod_coef_txt"] = "Malus"
|
||||||
elif mod_moy < 0:
|
elif mod_moy < 0:
|
||||||
mod["mod_moy_txt"] = fmt_note(-mod_moy)
|
mod["mod_moy_txt"] = scu.fmt_note(-mod_moy)
|
||||||
mod["mod_coef_txt"] = "Bonus"
|
mod["mod_coef_txt"] = "Bonus"
|
||||||
else:
|
else:
|
||||||
mod["mod_moy_txt"] = "-"
|
mod["mod_moy_txt"] = "-"
|
||||||
mod["mod_coef_txt"] = "-"
|
mod["mod_coef_txt"] = "-"
|
||||||
else:
|
else:
|
||||||
mod["mod_coef_txt"] = fmt_coef(modimpl["module"]["coefficient"])
|
mod["mod_coef_txt"] = scu.fmt_coef(modimpl["module"]["coefficient"])
|
||||||
if mod["mod_moy_txt"] != "NI": # ne montre pas les modules 'non inscrit'
|
if mod["mod_moy_txt"] != "NI": # ne montre pas les modules 'non inscrit'
|
||||||
mods.append(mod)
|
mods.append(mod)
|
||||||
if is_malus: # n'affiche pas les statistiques sur les modules malus
|
if is_malus: # n'affiche pas les statistiques sur les modules malus
|
||||||
@ -462,7 +470,7 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
|
|||||||
mod["stats"] = nt.get_mod_stats(modimpl["moduleimpl_id"])
|
mod["stats"] = nt.get_mod_stats(modimpl["moduleimpl_id"])
|
||||||
mod["mod_descr_txt"] = "Module %s, coef. %s (%s)" % (
|
mod["mod_descr_txt"] = "Module %s, coef. %s (%s)" % (
|
||||||
modimpl["module"]["titre"],
|
modimpl["module"]["titre"],
|
||||||
fmt_coef(modimpl["module"]["coefficient"]),
|
scu.fmt_coef(modimpl["module"]["coefficient"]),
|
||||||
context.Users.user_info(modimpl["responsable_id"])["nomcomplet"],
|
context.Users.user_info(modimpl["responsable_id"])["nomcomplet"],
|
||||||
)
|
)
|
||||||
link_mod = (
|
link_mod = (
|
||||||
@ -481,7 +489,7 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
|
|||||||
|
|
||||||
mod_descr = "Module %s, coef. %s (%s)" % (
|
mod_descr = "Module %s, coef. %s (%s)" % (
|
||||||
modimpl["module"]["titre"],
|
modimpl["module"]["titre"],
|
||||||
fmt_coef(modimpl["module"]["coefficient"]),
|
scu.fmt_coef(modimpl["module"]["coefficient"]),
|
||||||
context.Users.user_info(modimpl["responsable_id"])["nomcomplet"],
|
context.Users.user_info(modimpl["responsable_id"])["nomcomplet"],
|
||||||
)
|
)
|
||||||
link_mod = (
|
link_mod = (
|
||||||
@ -525,18 +533,18 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
|
|||||||
if val == "NP":
|
if val == "NP":
|
||||||
e["note_txt"] = "nd"
|
e["note_txt"] = "nd"
|
||||||
e["note_html"] = '<span class="note_nd">nd</span>'
|
e["note_html"] = '<span class="note_nd">nd</span>'
|
||||||
e["coef_txt"] = fmt_coef(e["coefficient"])
|
e["coef_txt"] = scu.fmt_coef(e["coefficient"])
|
||||||
else:
|
else:
|
||||||
# (-0.15) s'affiche "bonus de 0.15"
|
# (-0.15) s'affiche "bonus de 0.15"
|
||||||
if is_malus:
|
if is_malus:
|
||||||
val = abs(val)
|
val = abs(val)
|
||||||
e["note_txt"] = fmt_note(val, note_max=e["note_max"])
|
e["note_txt"] = scu.fmt_note(val, note_max=e["note_max"])
|
||||||
e["note_html"] = e["note_txt"]
|
e["note_html"] = e["note_txt"]
|
||||||
if is_malus:
|
if is_malus:
|
||||||
e["coef_txt"] = ""
|
e["coef_txt"] = ""
|
||||||
else:
|
else:
|
||||||
e["coef_txt"] = fmt_coef(e["coefficient"])
|
e["coef_txt"] = scu.fmt_coef(e["coefficient"])
|
||||||
if e["evaluation_type"] == EVALUATION_RATTRAPAGE:
|
if e["evaluation_type"] == scu.EVALUATION_RATTRAPAGE:
|
||||||
e["coef_txt"] = "rat."
|
e["coef_txt"] = "rat."
|
||||||
if e["etat"]["evalattente"]:
|
if e["etat"]["evalattente"]:
|
||||||
mod_attente = True # une eval en attente dans ce module
|
mod_attente = True # une eval en attente dans ce module
|
||||||
@ -567,12 +575,12 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
|
|||||||
e["name"],
|
e["name"],
|
||||||
)
|
)
|
||||||
e["note_txt"] = e["note_html"] = ""
|
e["note_txt"] = e["note_html"] = ""
|
||||||
e["coef_txt"] = fmt_coef(e["coefficient"])
|
e["coef_txt"] = scu.fmt_coef(e["coefficient"])
|
||||||
# Classement
|
# Classement
|
||||||
if bul_show_mod_rangs and mod["mod_moy_txt"] != "-" and not is_malus:
|
if bul_show_mod_rangs and mod["mod_moy_txt"] != "-" and not is_malus:
|
||||||
rg = nt.mod_rangs[modimpl["moduleimpl_id"]]
|
rg = nt.mod_rangs[modimpl["moduleimpl_id"]]
|
||||||
if mod_attente: # nt.get_moduleimpls_attente():
|
if mod_attente: # nt.get_moduleimpls_attente():
|
||||||
mod["mod_rang"] = RANG_ATTENTE_STR
|
mod["mod_rang"] = scu.RANG_ATTENTE_STR
|
||||||
else:
|
else:
|
||||||
mod["mod_rang"] = rg[0][etudid]
|
mod["mod_rang"] = rg[0][etudid]
|
||||||
mod["mod_eff"] = rg[1] # effectif dans ce module
|
mod["mod_eff"] = rg[1] # effectif dans ce module
|
||||||
@ -637,7 +645,7 @@ def etud_descr_situation_semestre(
|
|||||||
descr_mention : 'Mention Bien', ou vide si pas de mention ou si pas show_mention
|
descr_mention : 'Mention Bien', ou vide si pas de mention ou si pas show_mention
|
||||||
"""
|
"""
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
infos = DictDefault(defaultvalue="")
|
infos = scu.DictDefault(defaultvalue="")
|
||||||
|
|
||||||
# --- Situation et décisions jury
|
# --- Situation et décisions jury
|
||||||
|
|
||||||
@ -648,7 +656,6 @@ def etud_descr_situation_semestre(
|
|||||||
date_inscr = None
|
date_inscr = None
|
||||||
date_dem = None
|
date_dem = None
|
||||||
date_def = None
|
date_def = None
|
||||||
date_echec = None
|
|
||||||
for event in events:
|
for event in events:
|
||||||
event_type = event["event_type"]
|
event_type = event["event_type"]
|
||||||
if event_type == "INSCRIPTION":
|
if event_type == "INSCRIPTION":
|
||||||
@ -765,7 +772,7 @@ def formsemestre_bulletinetud(
|
|||||||
etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0]
|
etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0]
|
||||||
etudid = etud["etudid"]
|
etudid = etud["etudid"]
|
||||||
except:
|
except:
|
||||||
return log_unknown_etud(context, REQUEST, format=format)
|
return scu.log_unknown_etud(context, REQUEST, format=format)
|
||||||
|
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||||
|
|
||||||
@ -887,7 +894,7 @@ def do_formsemestre_bulletinetud(
|
|||||||
etud = I["etud"]
|
etud = I["etud"]
|
||||||
|
|
||||||
if format == "html":
|
if format == "html":
|
||||||
htm, junk = sco_bulletins_generator.make_formsemestre_bulletinetud(
|
htm, _ = sco_bulletins_generator.make_formsemestre_bulletinetud(
|
||||||
context, I, version=version, format="html", REQUEST=REQUEST
|
context, I, version=version, format="html", REQUEST=REQUEST
|
||||||
)
|
)
|
||||||
return htm, I["filigranne"]
|
return htm, I["filigranne"]
|
||||||
@ -903,7 +910,7 @@ def do_formsemestre_bulletinetud(
|
|||||||
)
|
)
|
||||||
if format == "pdf":
|
if format == "pdf":
|
||||||
return (
|
return (
|
||||||
sendPDFFile(REQUEST, bul, filename),
|
scu.sendPDFFile(REQUEST, bul, filename),
|
||||||
I["filigranne"],
|
I["filigranne"],
|
||||||
) # unused ret. value
|
) # unused ret. value
|
||||||
else:
|
else:
|
||||||
@ -918,7 +925,7 @@ def do_formsemestre_bulletinetud(
|
|||||||
if nohtml:
|
if nohtml:
|
||||||
htm = "" # speed up if html version not needed
|
htm = "" # speed up if html version not needed
|
||||||
else:
|
else:
|
||||||
htm, junk = sco_bulletins_generator.make_formsemestre_bulletinetud(
|
htm, _ = sco_bulletins_generator.make_formsemestre_bulletinetud(
|
||||||
context, I, version=version, format="html", REQUEST=REQUEST
|
context, I, version=version, format="html", REQUEST=REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -962,7 +969,7 @@ def mail_bulletin(context, formsemestre_id, I, pdfdata, filename, recipient_addr
|
|||||||
"""
|
"""
|
||||||
etud = I["etud"]
|
etud = I["etud"]
|
||||||
webmaster = context.get_preference("bul_mail_contact_addr", formsemestre_id)
|
webmaster = context.get_preference("bul_mail_contact_addr", formsemestre_id)
|
||||||
dept = unescape_html(context.get_preference("DeptName", formsemestre_id))
|
dept = scu.unescape_html(context.get_preference("DeptName", formsemestre_id))
|
||||||
copy_addr = context.get_preference("email_copy_bulletins", formsemestre_id)
|
copy_addr = context.get_preference("email_copy_bulletins", formsemestre_id)
|
||||||
intro_mail = context.get_preference("bul_intro_mail", formsemestre_id)
|
intro_mail = context.get_preference("bul_intro_mail", formsemestre_id)
|
||||||
|
|
||||||
@ -981,7 +988,7 @@ def mail_bulletin(context, formsemestre_id, I, pdfdata, filename, recipient_addr
|
|||||||
)
|
)
|
||||||
|
|
||||||
msg = MIMEMultipart()
|
msg = MIMEMultipart()
|
||||||
subj = Header("Relevé de notes de %s" % etud["nomprenom"], SCO_ENCODING)
|
subj = Header("Relevé de notes de %s" % etud["nomprenom"], scu.SCO_ENCODING)
|
||||||
recipients = [recipient_addr]
|
recipients = [recipient_addr]
|
||||||
msg["Subject"] = subj
|
msg["Subject"] = subj
|
||||||
msg["From"] = context.get_preference("email_from_addr", formsemestre_id)
|
msg["From"] = context.get_preference("email_from_addr", formsemestre_id)
|
||||||
@ -991,7 +998,7 @@ def mail_bulletin(context, formsemestre_id, I, pdfdata, filename, recipient_addr
|
|||||||
# Guarantees the message ends in a newline
|
# Guarantees the message ends in a newline
|
||||||
msg.epilogue = ""
|
msg.epilogue = ""
|
||||||
# Text
|
# Text
|
||||||
txt = MIMEText(hea, "plain", SCO_ENCODING)
|
txt = MIMEText(hea, "plain", scu.SCO_ENCODING)
|
||||||
# log('hea:\n' + hea)
|
# log('hea:\n' + hea)
|
||||||
msg.attach(txt)
|
msg.attach(txt)
|
||||||
# Attach pdf
|
# Attach pdf
|
||||||
@ -1155,7 +1162,7 @@ def _formsemestre_bulletinetud_header_html(
|
|||||||
url
|
url
|
||||||
+ "?formsemestre_id=%s&etudid=%s&format=pdf&version=%s"
|
+ "?formsemestre_id=%s&etudid=%s&format=pdf&version=%s"
|
||||||
% (formsemestre_id, etudid, version),
|
% (formsemestre_id, etudid, version),
|
||||||
ICON_PDF,
|
scu.ICON_PDF,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
H.append("""</tr></table>""")
|
H.append("""</tr></table>""")
|
||||||
|
@ -28,12 +28,14 @@
|
|||||||
"""Generation bulletins de notes: exemple minimal pour les programmeurs
|
"""Generation bulletins de notes: exemple minimal pour les programmeurs
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Quelques modules ScoDoc utiles:
|
import VERSION
|
||||||
from sco_pdf import *
|
import sco_utils as scu
|
||||||
|
import sco_pdf
|
||||||
import sco_preferences
|
import sco_preferences
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import sco_bulletins_generator
|
import sco_bulletins_generator
|
||||||
import sco_bulletins_standard
|
import sco_bulletins_standard
|
||||||
|
from reportlab.platypus import Paragraph
|
||||||
|
|
||||||
|
|
||||||
class BulletinGeneratorExample(sco_bulletins_standard.BulletinGeneratorStandard):
|
class BulletinGeneratorExample(sco_bulletins_standard.BulletinGeneratorStandard):
|
||||||
@ -59,7 +61,7 @@ class BulletinGeneratorExample(sco_bulletins_standard.BulletinGeneratorStandard)
|
|||||||
assert format == "pdf" # garde fou
|
assert format == "pdf" # garde fou
|
||||||
return [
|
return [
|
||||||
Paragraph(
|
Paragraph(
|
||||||
SU(
|
sco_pdf.SU(
|
||||||
"L'étudiant %(nomprenom)s a une moyenne générale de %(moy_gen)s"
|
"L'étudiant %(nomprenom)s a une moyenne générale de %(moy_gen)s"
|
||||||
% self.infos
|
% self.infos
|
||||||
),
|
),
|
||||||
|
@ -28,9 +28,12 @@
|
|||||||
"""Génération du bulletin en format JSON (beta, non completement testé)
|
"""Génération du bulletin en format JSON (beta, non completement testé)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import datetime
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from notes_table import *
|
import sco_utils as scu
|
||||||
|
import notesdb as ndb
|
||||||
|
import scolars
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_groups
|
import sco_groups
|
||||||
import sco_photos
|
import sco_photos
|
||||||
@ -62,9 +65,9 @@ def make_json_formsemestre_bulletinetud(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if REQUEST:
|
if REQUEST:
|
||||||
REQUEST.RESPONSE.setHeader("content-type", JSON_MIMETYPE)
|
REQUEST.RESPONSE.setHeader("content-type", scu.JSON_MIMETYPE)
|
||||||
|
|
||||||
return json.dumps(d, cls=ScoDocJSONEncoder, encoding=SCO_ENCODING)
|
return json.dumps(d, cls=scu.ScoDocJSONEncoder, encoding=scu.SCO_ENCODING)
|
||||||
|
|
||||||
|
|
||||||
# (fonction séparée: n'utilise pas formsemestre_bulletinetud_dict()
|
# (fonction séparée: n'utilise pas formsemestre_bulletinetud_dict()
|
||||||
@ -119,16 +122,16 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
etudid=etudid,
|
etudid=etudid,
|
||||||
code_nip=etudinfo["code_nip"],
|
code_nip=etudinfo["code_nip"],
|
||||||
code_ine=etudinfo["code_ine"],
|
code_ine=etudinfo["code_ine"],
|
||||||
nom=quote_xml_attr(etudinfo["nom"]),
|
nom=scu.quote_xml_attr(etudinfo["nom"]),
|
||||||
prenom=quote_xml_attr(etudinfo["prenom"]),
|
prenom=scu.quote_xml_attr(etudinfo["prenom"]),
|
||||||
sexe=quote_xml_attr(etudinfo["sexe"]),
|
civilite=scu.quote_xml_attr(etudinfo["civilite_str"]),
|
||||||
photo_url=quote_xml_attr(
|
photo_url=scu.quote_xml_attr(
|
||||||
sco_photos.etud_photo_url(context, etudinfo, fast=True)
|
sco_photos.etud_photo_url(context, etudinfo, fast=True)
|
||||||
),
|
),
|
||||||
email=quote_xml_attr(etudinfo["email"]),
|
email=scu.quote_xml_attr(etudinfo["email"]),
|
||||||
emailperso=quote_xml_attr(etudinfo["emailperso"]),
|
emailperso=scu.quote_xml_attr(etudinfo["emailperso"]),
|
||||||
)
|
)
|
||||||
|
d["etudiant"]["sexe"] = d["etudiant"]["civilite"] # backward compat for our clients
|
||||||
# Disponible pour publication ?
|
# Disponible pour publication ?
|
||||||
if not published:
|
if not published:
|
||||||
return d # stop !
|
return d # stop !
|
||||||
@ -150,7 +153,7 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
ues = nt.get_ues()
|
ues = nt.get_ues()
|
||||||
modimpls = nt.get_modimpls()
|
modimpls = nt.get_modimpls()
|
||||||
nbetuds = len(nt.rangs)
|
nbetuds = len(nt.rangs)
|
||||||
mg = fmt_note(nt.get_etud_moy_gen(etudid))
|
mg = scu.fmt_note(nt.get_etud_moy_gen(etudid))
|
||||||
if (
|
if (
|
||||||
nt.get_moduleimpls_attente()
|
nt.get_moduleimpls_attente()
|
||||||
or context.get_preference("bul_show_rangs", formsemestre_id) == 0
|
or context.get_preference("bul_show_rangs", formsemestre_id) == 0
|
||||||
@ -168,9 +171,9 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
|
|
||||||
d["note"] = dict(
|
d["note"] = dict(
|
||||||
value=mg,
|
value=mg,
|
||||||
min=fmt_note(nt.moy_min),
|
min=scu.fmt_note(nt.moy_min),
|
||||||
max=fmt_note(nt.moy_max),
|
max=scu.fmt_note(nt.moy_max),
|
||||||
moy=fmt_note(nt.moy_moy),
|
moy=scu.fmt_note(nt.moy_moy),
|
||||||
)
|
)
|
||||||
d["rang"] = dict(value=rang, ninscrits=nbetuds)
|
d["rang"] = dict(value=rang, ninscrits=nbetuds)
|
||||||
d["rang_group"] = []
|
d["rang_group"] = []
|
||||||
@ -199,25 +202,27 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
ects_txt = ""
|
ects_txt = ""
|
||||||
u = dict(
|
u = dict(
|
||||||
id=ue["ue_id"],
|
id=ue["ue_id"],
|
||||||
numero=quote_xml_attr(ue["numero"]),
|
numero=scu.quote_xml_attr(ue["numero"]),
|
||||||
acronyme=quote_xml_attr(ue["acronyme"]),
|
acronyme=scu.quote_xml_attr(ue["acronyme"]),
|
||||||
titre=quote_xml_attr(ue["titre"]),
|
titre=scu.quote_xml_attr(ue["titre"]),
|
||||||
note=dict(
|
note=dict(
|
||||||
value=fmt_note(ue_status["cur_moy_ue"]),
|
value=scu.fmt_note(ue_status["cur_moy_ue"]),
|
||||||
min=fmt_note(ue["min"]),
|
min=scu.fmt_note(ue["min"]),
|
||||||
max=fmt_note(ue["max"]),
|
max=scu.fmt_note(ue["max"]),
|
||||||
),
|
),
|
||||||
rang=str(nt.ue_rangs[ue["ue_id"]][0][etudid]),
|
rang=str(nt.ue_rangs[ue["ue_id"]][0][etudid]),
|
||||||
effectif=str(nt.ue_rangs[ue["ue_id"]][1]),
|
effectif=str(nt.ue_rangs[ue["ue_id"]][1]),
|
||||||
ects=ects_txt,
|
ects=ects_txt,
|
||||||
code_apogee=quote_xml_attr(ue["code_apogee"]),
|
code_apogee=scu.quote_xml_attr(ue["code_apogee"]),
|
||||||
)
|
)
|
||||||
d["ue"].append(u)
|
d["ue"].append(u)
|
||||||
u["module"] = []
|
u["module"] = []
|
||||||
# Liste les modules de l'UE
|
# Liste les modules de l'UE
|
||||||
ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue["ue_id"]]
|
ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue["ue_id"]]
|
||||||
for modimpl in ue_modimpls:
|
for modimpl in ue_modimpls:
|
||||||
mod_moy = fmt_note(nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid))
|
mod_moy = scu.fmt_note(
|
||||||
|
nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid)
|
||||||
|
)
|
||||||
if mod_moy == "NI": # ne mentionne pas les modules ou n'est pas inscrit
|
if mod_moy == "NI": # ne mentionne pas les modules ou n'est pas inscrit
|
||||||
continue
|
continue
|
||||||
mod = modimpl["module"]
|
mod = modimpl["module"]
|
||||||
@ -232,15 +237,15 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
code=mod["code"],
|
code=mod["code"],
|
||||||
coefficient=mod["coefficient"],
|
coefficient=mod["coefficient"],
|
||||||
numero=mod["numero"],
|
numero=mod["numero"],
|
||||||
titre=quote_xml_attr(mod["titre"]),
|
titre=scu.quote_xml_attr(mod["titre"]),
|
||||||
abbrev=quote_xml_attr(mod["abbrev"]),
|
abbrev=scu.quote_xml_attr(mod["abbrev"]),
|
||||||
# ects=ects, ects des modules maintenant inutilisés
|
# ects=ects, ects des modules maintenant inutilisés
|
||||||
note=dict(value=mod_moy),
|
note=dict(value=mod_moy),
|
||||||
code_apogee=quote_xml_attr(mod["code_apogee"]),
|
code_apogee=scu.quote_xml_attr(mod["code_apogee"]),
|
||||||
)
|
)
|
||||||
m["note"].update(modstat)
|
m["note"].update(modstat)
|
||||||
for k in ("min", "max", "moy"): # formatte toutes les notes
|
for k in ("min", "max", "moy"): # formatte toutes les notes
|
||||||
m["note"][k] = fmt_note(m["note"][k])
|
m["note"][k] = scu.fmt_note(m["note"][k])
|
||||||
|
|
||||||
u["module"].append(m)
|
u["module"].append(m)
|
||||||
if context.get_preference("bul_show_mod_rangs", formsemestre_id):
|
if context.get_preference("bul_show_mod_rangs", formsemestre_id):
|
||||||
@ -258,19 +263,19 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
val = e["notes"].get(etudid, {"value": "NP"})[
|
val = e["notes"].get(etudid, {"value": "NP"})[
|
||||||
"value"
|
"value"
|
||||||
] # NA si etud demissionnaire
|
] # NA si etud demissionnaire
|
||||||
val = fmt_note(val, note_max=e["note_max"])
|
val = scu.fmt_note(val, note_max=e["note_max"])
|
||||||
m["evaluation"].append(
|
m["evaluation"].append(
|
||||||
dict(
|
dict(
|
||||||
jour=DateDMYtoISO(e["jour"], null_is_empty=True),
|
jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True),
|
||||||
heure_debut=TimetoISO8601(
|
heure_debut=ndb.TimetoISO8601(
|
||||||
e["heure_debut"], null_is_empty=True
|
e["heure_debut"], null_is_empty=True
|
||||||
),
|
),
|
||||||
heure_fin=TimetoISO8601(
|
heure_fin=ndb.TimetoISO8601(
|
||||||
e["heure_fin"], null_is_empty=True
|
e["heure_fin"], null_is_empty=True
|
||||||
),
|
),
|
||||||
coefficient=e["coefficient"],
|
coefficient=e["coefficient"],
|
||||||
evaluation_type=e["evaluation_type"],
|
evaluation_type=e["evaluation_type"],
|
||||||
description=quote_xml_attr(e["description"]),
|
description=scu.quote_xml_attr(e["description"]),
|
||||||
note=val,
|
note=val,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -285,15 +290,17 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
if e["evaluation_id"] not in complete_eval_ids:
|
if e["evaluation_id"] not in complete_eval_ids:
|
||||||
m["evaluation"].append(
|
m["evaluation"].append(
|
||||||
dict(
|
dict(
|
||||||
jour=DateDMYtoISO(e["jour"], null_is_empty=True),
|
jour=ndb.DateDMYtoISO(
|
||||||
heure_debut=TimetoISO8601(
|
e["jour"], null_is_empty=True
|
||||||
|
),
|
||||||
|
heure_debut=ndb.TimetoISO8601(
|
||||||
e["heure_debut"], null_is_empty=True
|
e["heure_debut"], null_is_empty=True
|
||||||
),
|
),
|
||||||
heure_fin=TimetoISO8601(
|
heure_fin=ndb.TimetoISO8601(
|
||||||
e["heure_fin"], null_is_empty=True
|
e["heure_fin"], null_is_empty=True
|
||||||
),
|
),
|
||||||
coefficient=e["coefficient"],
|
coefficient=e["coefficient"],
|
||||||
description=quote_xml_attr(e["description"]),
|
description=scu.quote_xml_attr(e["description"]),
|
||||||
incomplete="1",
|
incomplete="1",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -307,20 +314,18 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
d["ue_capitalisee"].append(
|
d["ue_capitalisee"].append(
|
||||||
dict(
|
dict(
|
||||||
id=ue["ue_id"],
|
id=ue["ue_id"],
|
||||||
numero=quote_xml_attr(ue["numero"]),
|
numero=scu.quote_xml_attr(ue["numero"]),
|
||||||
acronyme=quote_xml_attr(ue["acronyme"]),
|
acronyme=scu.quote_xml_attr(ue["acronyme"]),
|
||||||
titre=quote_xml_attr(ue["titre"]),
|
titre=scu.quote_xml_attr(ue["titre"]),
|
||||||
note=fmt_note(ue_status["moy"]),
|
note=scu.fmt_note(ue_status["moy"]),
|
||||||
coefficient_ue=fmt_note(ue_status["coef_ue"]),
|
coefficient_ue=scu.fmt_note(ue_status["coef_ue"]),
|
||||||
date_capitalisation=DateDMYtoISO(ue_status["event_date"]),
|
date_capitalisation=ndb.DateDMYtoISO(ue_status["event_date"]),
|
||||||
ects=ects_txt,
|
ects=ects_txt,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- Absences
|
# --- Absences
|
||||||
if context.get_preference("bul_show_abs", formsemestre_id):
|
if context.get_preference("bul_show_abs", formsemestre_id):
|
||||||
debut_sem = DateDMYtoISO(sem["date_debut"])
|
|
||||||
fin_sem = DateDMYtoISO(sem["date_fin"])
|
|
||||||
AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid)
|
AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid)
|
||||||
nbabs = AbsEtudSem.CountAbs()
|
nbabs = AbsEtudSem.CountAbs()
|
||||||
nbabsjust = AbsEtudSem.CountAbsJust()
|
nbabsjust = AbsEtudSem.CountAbsJust()
|
||||||
@ -339,7 +344,7 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
format="xml",
|
format="xml",
|
||||||
show_uevalid=context.get_preference("bul_show_uevalid", formsemestre_id),
|
show_uevalid=context.get_preference("bul_show_uevalid", formsemestre_id),
|
||||||
)
|
)
|
||||||
d["situation"] = quote_xml_attr(infos["situation"])
|
d["situation"] = scu.quote_xml_attr(infos["situation"])
|
||||||
if dpv:
|
if dpv:
|
||||||
decision = dpv["decisions"][0]
|
decision = dpv["decisions"][0]
|
||||||
etat = decision["etat"]
|
etat = decision["etat"]
|
||||||
@ -366,11 +371,11 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
d["decision_ue"].append(
|
d["decision_ue"].append(
|
||||||
dict(
|
dict(
|
||||||
ue_id=ue["ue_id"],
|
ue_id=ue["ue_id"],
|
||||||
numero=quote_xml_attr(ue["numero"]),
|
numero=scu.quote_xml_attr(ue["numero"]),
|
||||||
acronyme=quote_xml_attr(ue["acronyme"]),
|
acronyme=scu.quote_xml_attr(ue["acronyme"]),
|
||||||
titre=quote_xml_attr(ue["titre"]),
|
titre=scu.quote_xml_attr(ue["titre"]),
|
||||||
code=decision["decisions_ue"][ue_id]["code"],
|
code=decision["decisions_ue"][ue_id]["code"],
|
||||||
ects=quote_xml_attr(ue["ects"] or ""),
|
ects=scu.quote_xml_attr(ue["ects"] or ""),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
d["autorisation_inscription"] = []
|
d["autorisation_inscription"] = []
|
||||||
@ -389,7 +394,10 @@ def formsemestre_bulletinetud_published_dict(
|
|||||||
d["appreciation"] = []
|
d["appreciation"] = []
|
||||||
for app in apprecs:
|
for app in apprecs:
|
||||||
d["appreciation"].append(
|
d["appreciation"].append(
|
||||||
dict(comment=quote_xml_attr(app["comment"]), date=DateDMYtoISO(app["date"]))
|
dict(
|
||||||
|
comment=scu.quote_xml_attr(app["comment"]),
|
||||||
|
date=ndb.DateDMYtoISO(app["date"]),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -37,8 +37,13 @@
|
|||||||
|
|
||||||
import traceback, re
|
import traceback, re
|
||||||
|
|
||||||
|
import sco_utils as scu
|
||||||
|
from sco_permissions import ScoEtudInscrit
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
from sco_pdf import *
|
import sco_pdf
|
||||||
|
from sco_pdf import Color, Paragraph, Spacer, Table
|
||||||
|
from sco_pdf import blue, cm, mm
|
||||||
|
from sco_pdf import SU
|
||||||
import sco_preferences
|
import sco_preferences
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import sco_bulletins_generator
|
import sco_bulletins_generator
|
||||||
@ -81,9 +86,7 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
|
|||||||
|
|
||||||
def bul_table_html(self):
|
def bul_table_html(self):
|
||||||
"""Génère la table centrale du bulletin de notes: chaine HTML"""
|
"""Génère la table centrale du bulletin de notes: chaine HTML"""
|
||||||
format = "html"
|
|
||||||
I = self.infos
|
I = self.infos
|
||||||
authuser = self.authuser
|
|
||||||
formsemestre_id = self.infos["formsemestre_id"]
|
formsemestre_id = self.infos["formsemestre_id"]
|
||||||
context = self.context
|
context = self.context
|
||||||
|
|
||||||
@ -98,8 +101,8 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
|
|||||||
bgcolor = "background-color: rgb(255,255,240)"
|
bgcolor = "background-color: rgb(255,255,240)"
|
||||||
|
|
||||||
linktmpl = '<span onclick="toggle_vis_ue(this);" class="toggle_ue">%s</span>'
|
linktmpl = '<span onclick="toggle_vis_ue(this);" class="toggle_ue">%s</span>'
|
||||||
minuslink = linktmpl % icontag("minus_img", border="0", alt="-")
|
minuslink = linktmpl % scu.icontag("minus_img", border="0", alt="-")
|
||||||
pluslink = linktmpl % icontag("plus_img", border="0", alt="+")
|
pluslink = linktmpl % scu.icontag("plus_img", border="0", alt="+")
|
||||||
|
|
||||||
H = ['<table class="notes_bulletin" style="background-color: %s;">' % bgcolor]
|
H = ['<table class="notes_bulletin" style="background-color: %s;">' % bgcolor]
|
||||||
|
|
||||||
@ -131,8 +134,8 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
|
|||||||
if context.get_preference("bul_show_minmax_mod", formsemestre_id):
|
if context.get_preference("bul_show_minmax_mod", formsemestre_id):
|
||||||
rang_minmax = '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' % (
|
rang_minmax = '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' % (
|
||||||
mod["mod_rang_txt"],
|
mod["mod_rang_txt"],
|
||||||
fmt_note(mod["stats"]["min"]),
|
scu.fmt_note(mod["stats"]["min"]),
|
||||||
fmt_note(mod["stats"]["max"]),
|
scu.fmt_note(mod["stats"]["max"]),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
rang_minmax = mod["mod_rang_txt"] # vide si pas option rang
|
rang_minmax = mod["mod_rang_txt"] # vide si pas option rang
|
||||||
@ -209,9 +212,9 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
|
|||||||
moy_txt = (
|
moy_txt = (
|
||||||
'%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>'
|
'%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>'
|
||||||
% (
|
% (
|
||||||
fmt_note(ue["cur_moy_ue_txt"]),
|
scu.fmt_note(ue["cur_moy_ue_txt"]),
|
||||||
fmt_note(ue["min"]),
|
scu.fmt_note(ue["min"]),
|
||||||
fmt_note(ue["max"]),
|
scu.fmt_note(ue["max"]),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -441,7 +444,6 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
|
|||||||
S = BulTableStyle()
|
S = BulTableStyle()
|
||||||
P = [] # elems pour gen. pdf
|
P = [] # elems pour gen. pdf
|
||||||
formsemestre_id = I["formsemestre_id"]
|
formsemestre_id = I["formsemestre_id"]
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
|
||||||
bul_show_abs_modules = context.get_preference(
|
bul_show_abs_modules = context.get_preference(
|
||||||
"bul_show_abs_modules", formsemestre_id
|
"bul_show_abs_modules", formsemestre_id
|
||||||
)
|
)
|
||||||
@ -460,7 +462,7 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
|
|||||||
]
|
]
|
||||||
if bul_show_abs_modules:
|
if bul_show_abs_modules:
|
||||||
t.append("Abs (J. / N.J.)")
|
t.append("Abs (J. / N.J.)")
|
||||||
P.append(bold_paras(t))
|
P.append(sco_pdf.bold_paras(t))
|
||||||
|
|
||||||
def list_modules(ue_modules, ue_type=None):
|
def list_modules(ue_modules, ue_type=None):
|
||||||
"ajoute les lignes decrivant les modules d'une UE, avec eventuellement les évaluations de chacun"
|
"ajoute les lignes decrivant les modules d'une UE, avec eventuellement les évaluations de chacun"
|
||||||
@ -471,8 +473,8 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
|
|||||||
if context.get_preference("bul_show_minmax_mod", formsemestre_id):
|
if context.get_preference("bul_show_minmax_mod", formsemestre_id):
|
||||||
rang_minmax = '%s <font size="8">[%s, %s]</font>' % (
|
rang_minmax = '%s <font size="8">[%s, %s]</font>' % (
|
||||||
mod["mod_rang_txt"],
|
mod["mod_rang_txt"],
|
||||||
fmt_note(mod["stats"]["min"]),
|
scu.fmt_note(mod["stats"]["min"]),
|
||||||
fmt_note(mod["stats"]["max"]),
|
scu.fmt_note(mod["stats"]["max"]),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
rang_minmax = mod["mod_rang_txt"] # vide si pas option rang
|
rang_minmax = mod["mod_rang_txt"] # vide si pas option rang
|
||||||
@ -504,7 +506,7 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
|
|||||||
t = [ue["acronyme"], ue["moy_ue_txt"], ue_descr, "", coef_ue]
|
t = [ue["acronyme"], ue["moy_ue_txt"], ue_descr, "", coef_ue]
|
||||||
if bul_show_abs_modules:
|
if bul_show_abs_modules:
|
||||||
t.append("")
|
t.append("")
|
||||||
P.append(bold_paras(t))
|
P.append(sco_pdf.bold_paras(t))
|
||||||
coef_ue = ""
|
coef_ue = ""
|
||||||
ue_descr = "(en cours, non prise en compte)"
|
ue_descr = "(en cours, non prise en compte)"
|
||||||
S.ueline()
|
S.ueline()
|
||||||
@ -523,7 +525,7 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
|
|||||||
t = [ue["acronyme"], moy_txt, ue_descr, "", coef_ue]
|
t = [ue["acronyme"], moy_txt, ue_descr, "", coef_ue]
|
||||||
if bul_show_abs_modules:
|
if bul_show_abs_modules:
|
||||||
t.append("")
|
t.append("")
|
||||||
P.append(bold_paras(t))
|
P.append(sco_pdf.bold_paras(t))
|
||||||
S.ueline()
|
S.ueline()
|
||||||
list_modules(ue["modules"], ue_type=ue_type)
|
list_modules(ue["modules"], ue_type=ue_type)
|
||||||
|
|
||||||
|
@ -50,13 +50,21 @@ Pour définir un nouveau type de bulletin:
|
|||||||
Chaque semestre peut si nécessaire utiliser un type de bulletin différent.
|
Chaque semestre peut si nécessaire utiliser un type de bulletin différent.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import htmlutils, time
|
import htmlutils
|
||||||
import pprint, traceback
|
import time
|
||||||
|
import pprint
|
||||||
|
import traceback
|
||||||
|
import re
|
||||||
|
import cStringIO
|
||||||
|
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
|
||||||
|
|
||||||
from notes_table import *
|
import VERSION
|
||||||
|
import sco_utils as scu
|
||||||
|
from notes_log import log
|
||||||
|
import sco_formsemestre
|
||||||
import sco_bulletins
|
import sco_bulletins
|
||||||
|
|
||||||
from sco_pdf import *
|
import sco_pdf
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
@ -84,10 +92,10 @@ def pdfassemblebulletins(
|
|||||||
report = cStringIO.StringIO() # in-memory document, no disk file
|
report = cStringIO.StringIO() # in-memory document, no disk file
|
||||||
document = BaseDocTemplate(report)
|
document = BaseDocTemplate(report)
|
||||||
document.addPageTemplates(
|
document.addPageTemplates(
|
||||||
ScolarsPageTemplate(
|
sco_pdf.ScolarsPageTemplate(
|
||||||
document,
|
document,
|
||||||
context=context,
|
context=context,
|
||||||
author="%s %s (E. Viennet)" % (SCONAME, SCOVERSION),
|
author="%s %s (E. Viennet)" % (VERSION.SCONAME, VERSION.SCOVERSION),
|
||||||
title="Bulletin %s" % bul_title,
|
title="Bulletin %s" % bul_title,
|
||||||
subject="Bulletin de note",
|
subject="Bulletin de note",
|
||||||
server_name=server_name,
|
server_name=server_name,
|
||||||
@ -117,7 +125,7 @@ def process_field(
|
|||||||
If format = 'html', replaces <para> by <p>. HTML does not allow logos.
|
If format = 'html', replaces <para> by <p>. HTML does not allow logos.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
text = (field or "") % WrapDict(
|
text = (field or "") % scu.WrapDict(
|
||||||
cdict
|
cdict
|
||||||
) # note that None values are mapped to empty strings
|
) # note that None values are mapped to empty strings
|
||||||
except:
|
except:
|
||||||
@ -135,9 +143,9 @@ def process_field(
|
|||||||
return text
|
return text
|
||||||
# --- PDF format:
|
# --- PDF format:
|
||||||
# handle logos:
|
# handle logos:
|
||||||
image_dir = SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/"
|
image_dir = scu.SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/"
|
||||||
if not os.path.exists(image_dir):
|
if not os.path.exists(image_dir):
|
||||||
image_dir = SCODOC_LOGOS_DIR + "/" # use global logos
|
image_dir = scu.SCODOC_LOGOS_DIR + "/" # use global logos
|
||||||
text = re.sub(
|
text = re.sub(
|
||||||
r"<(\s*)logo(.*?)src\s*=\s*(.*?)>", r"<\1logo\2\3>", text
|
r"<(\s*)logo(.*?)src\s*=\s*(.*?)>", r"<\1logo\2\3>", text
|
||||||
) # remove forbidden src attribute
|
) # remove forbidden src attribute
|
||||||
@ -150,7 +158,7 @@ def process_field(
|
|||||||
# tentatives d'acceder à d'autres fichiers !
|
# tentatives d'acceder à d'autres fichiers !
|
||||||
|
|
||||||
# log('field: %s' % (text))
|
# log('field: %s' % (text))
|
||||||
return makeParas(text, style, suppress_empty=suppress_empty_pars)
|
return sco_pdf.makeParas(text, style, suppress_empty=suppress_empty_pars)
|
||||||
|
|
||||||
|
|
||||||
def get_formsemestre_bulletins_pdf(
|
def get_formsemestre_bulletins_pdf(
|
||||||
@ -180,7 +188,7 @@ def get_formsemestre_bulletins_pdf(
|
|||||||
)
|
)
|
||||||
fragments += frag
|
fragments += frag
|
||||||
filigrannes[i] = filigranne
|
filigrannes[i] = filigranne
|
||||||
bookmarks[i] = suppress_accents(nt.get_sexnom(etudid))
|
bookmarks[i] = scu.suppress_accents(nt.get_sexnom(etudid))
|
||||||
i = i + 1
|
i = i + 1
|
||||||
#
|
#
|
||||||
infos = {"DeptName": context.get_preference("DeptName", formsemestre_id)}
|
infos = {"DeptName": context.get_preference("DeptName", formsemestre_id)}
|
||||||
@ -189,7 +197,7 @@ def get_formsemestre_bulletins_pdf(
|
|||||||
else:
|
else:
|
||||||
server_name = ""
|
server_name = ""
|
||||||
try:
|
try:
|
||||||
PDFLOCK.acquire()
|
sco_pdf.PDFLOCK.acquire()
|
||||||
pdfdoc = pdfassemblebulletins(
|
pdfdoc = pdfassemblebulletins(
|
||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
fragments,
|
fragments,
|
||||||
@ -201,11 +209,11 @@ def get_formsemestre_bulletins_pdf(
|
|||||||
context=context,
|
context=context,
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
PDFLOCK.release()
|
sco_pdf.PDFLOCK.release()
|
||||||
#
|
#
|
||||||
dt = time.strftime("%Y-%m-%d")
|
dt = time.strftime("%Y-%m-%d")
|
||||||
filename = "bul-%s-%s.pdf" % (sem["titre_num"], dt)
|
filename = "bul-%s-%s.pdf" % (sem["titre_num"], dt)
|
||||||
filename = unescape_html(filename).replace(" ", "_").replace("&", "")
|
filename = scu.unescape_html(filename).replace(" ", "_").replace("&", "")
|
||||||
# fill cache
|
# fill cache
|
||||||
context._getNotesCache().store_bulletins_pdf(
|
context._getNotesCache().store_bulletins_pdf(
|
||||||
formsemestre_id, version, filename, pdfdoc
|
formsemestre_id, version, filename, pdfdoc
|
||||||
@ -239,7 +247,7 @@ def get_etud_bulletins_pdf(context, etudid, REQUEST, version="selectedevals"):
|
|||||||
else:
|
else:
|
||||||
server_name = ""
|
server_name = ""
|
||||||
try:
|
try:
|
||||||
PDFLOCK.acquire()
|
sco_pdf.PDFLOCK.acquire()
|
||||||
pdfdoc = pdfassemblebulletins(
|
pdfdoc = pdfassemblebulletins(
|
||||||
None,
|
None,
|
||||||
fragments,
|
fragments,
|
||||||
@ -251,11 +259,11 @@ def get_etud_bulletins_pdf(context, etudid, REQUEST, version="selectedevals"):
|
|||||||
context=context,
|
context=context,
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
PDFLOCK.release()
|
sco_pdf.PDFLOCK.release()
|
||||||
#
|
#
|
||||||
filename = "bul-%s" % (etud["nomprenom"])
|
filename = "bul-%s" % (etud["nomprenom"])
|
||||||
filename = (
|
filename = (
|
||||||
unescape_html(filename).replace(" ", "_").replace("&", "").replace(".", "")
|
scu.unescape_html(filename).replace(" ", "_").replace("&", "").replace(".", "")
|
||||||
+ ".pdf"
|
+ ".pdf"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -53,53 +53,53 @@ Lien sur Scolarite/edit_preferences (sans formsemestre_id)
|
|||||||
et sur page "réglages bulletin" (avec formsemestre_id)
|
et sur page "réglages bulletin" (avec formsemestre_id)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import os
|
# import os
|
||||||
|
|
||||||
|
|
||||||
def form_change_bul_sig(context, side, formsemestre_id=None, REQUEST=None):
|
# def form_change_bul_sig(context, side, formsemestre_id=None, REQUEST=None):
|
||||||
"""Change pdf signature"""
|
# """Change pdf signature"""
|
||||||
filename = _get_sig_existing_filename(
|
# filename = _get_sig_existing_filename(
|
||||||
context, side, formsemestre_id=formsemestre_id
|
# context, side, formsemestre_id=formsemestre_id
|
||||||
)
|
# )
|
||||||
if side == "left":
|
# if side == "left":
|
||||||
sidetxt = "gauche"
|
# sidetxt = "gauche"
|
||||||
elif side == "right":
|
# elif side == "right":
|
||||||
sidetxt = "droite"
|
# sidetxt = "droite"
|
||||||
else:
|
# else:
|
||||||
raise ValueError("invalid value for 'side' parameter")
|
# raise ValueError("invalid value for 'side' parameter")
|
||||||
signatureloc = get_bul_sig_img()
|
# signatureloc = get_bul_sig_img()
|
||||||
H = [
|
# H = [
|
||||||
self.sco_header(REQUEST, page_title="Changement de signature"),
|
# self.sco_header(REQUEST, page_title="Changement de signature"),
|
||||||
"""<h2>Changement de la signature bulletin de %(sidetxt)s</h2>
|
# """<h2>Changement de la signature bulletin de %(sidetxt)s</h2>
|
||||||
"""
|
# """
|
||||||
% (sidetxt,),
|
# % (sidetxt,),
|
||||||
]
|
# ]
|
||||||
"<p>Photo actuelle (%(signatureloc)s): "
|
# "<p>Photo actuelle (%(signatureloc)s): "
|
||||||
|
|
||||||
|
|
||||||
def get_bul_sig_img(context, side, formsemestre_id=None):
|
# def get_bul_sig_img(context, side, formsemestre_id=None):
|
||||||
"send back signature image data"
|
# "send back signature image data"
|
||||||
# slow, not cached, used for unfrequent access (do not bypass python)
|
# # slow, not cached, used for unfrequent access (do not bypass python)
|
||||||
|
|
||||||
|
|
||||||
def _sig_filename(context, side, formsemestre_id=None):
|
# def _sig_filename(context, side, formsemestre_id=None):
|
||||||
if not side in ("left", "right"):
|
# if not side in ("left", "right"):
|
||||||
raise ValueError("side must be left or right")
|
# raise ValueError("side must be left or right")
|
||||||
dirs = [SCODOC_LOGOS_DIR, context.DeptId()]
|
# dirs = [SCODOC_LOGOS_DIR, context.DeptId()]
|
||||||
if formsemestre_id:
|
# if formsemestre_id:
|
||||||
dirs.append(formsemestre_id)
|
# dirs.append(formsemestre_id)
|
||||||
dirs.append("bul_sig_{}".format(side))
|
# dirs.append("bul_sig_{}".format(side))
|
||||||
return os.path.join(*dirs)
|
# return os.path.join(*dirs)
|
||||||
|
|
||||||
|
|
||||||
def _get_sig_existing_filename(context, side, formsemestre_id=None):
|
# def _get_sig_existing_filename(context, side, formsemestre_id=None):
|
||||||
"full path to signature to use, or None if no signature available"
|
# "full path to signature to use, or None if no signature available"
|
||||||
if formsemestre_id:
|
# if formsemestre_id:
|
||||||
filename = _sig_filename(context, side, formsemestre_id=formsemestre_id)
|
# filename = _sig_filename(context, side, formsemestre_id=formsemestre_id)
|
||||||
if os.path.exists(filename):
|
# if os.path.exists(filename):
|
||||||
return filename
|
# return filename
|
||||||
filename = _sig_filename(context, side)
|
# filename = _sig_filename(context, side)
|
||||||
if os.path.exists(filename):
|
# if os.path.exists(filename):
|
||||||
return filename
|
# return filename
|
||||||
else:
|
# else:
|
||||||
return None
|
# return None
|
||||||
|
@ -46,7 +46,10 @@ de la forme %(XXX)s sont remplacées par la valeur de XXX, pour XXX dans:
|
|||||||
Balises img: actuellement interdites.
|
Balises img: actuellement interdites.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import traceback, re
|
import datetime
|
||||||
|
import traceback
|
||||||
|
import re
|
||||||
|
import jaxml
|
||||||
|
|
||||||
import sco_utils as scu
|
import sco_utils as scu
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
|
@ -34,8 +34,12 @@ E. Viennet, juillet 2011
|
|||||||
"""
|
"""
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
import sco_utils as scu
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
from sco_pdf import *
|
import sco_pdf
|
||||||
|
from sco_pdf import blue, cm, mm
|
||||||
|
from sco_pdf import Color, Paragraph, Spacer, Table
|
||||||
|
|
||||||
import sco_preferences
|
import sco_preferences
|
||||||
|
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
@ -72,7 +76,6 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard):
|
|||||||
I = self.infos
|
I = self.infos
|
||||||
context = self.context
|
context = self.context
|
||||||
formsemestre_id = I["formsemestre_id"]
|
formsemestre_id = I["formsemestre_id"]
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
|
||||||
prefs = context.get_preferences(formsemestre_id)
|
prefs = context.get_preferences(formsemestre_id)
|
||||||
|
|
||||||
P = [] # elems pour générer table avec gen_table (liste de dicts)
|
P = [] # elems pour générer table avec gen_table (liste de dicts)
|
||||||
@ -134,7 +137,7 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard):
|
|||||||
total_pt_ue_v = (
|
total_pt_ue_v = (
|
||||||
ue["ue_status"]["cur_moy_ue"] * ue["ue_status"]["coef_ue"]
|
ue["ue_status"]["cur_moy_ue"] * ue["ue_status"]["coef_ue"]
|
||||||
)
|
)
|
||||||
total_pt_ue = fmt_note(total_pt_ue_v)
|
total_pt_ue = scu.fmt_note(total_pt_ue_v)
|
||||||
# log('total_pt_ue = %s' % total_pt_ue)
|
# log('total_pt_ue = %s' % total_pt_ue)
|
||||||
except:
|
except:
|
||||||
# log("ue['ue_status']['cur_moy_ue'] = %s" % ue['ue_status']['cur_moy_ue'] )
|
# log("ue['ue_status']['cur_moy_ue'] = %s" % ue['ue_status']['cur_moy_ue'] )
|
||||||
@ -212,7 +215,6 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard):
|
|||||||
|
|
||||||
ue_descr = "(en cours, non prise en compte)"
|
ue_descr = "(en cours, non prise en compte)"
|
||||||
ue_type = "cur"
|
ue_type = "cur"
|
||||||
rowstyle = " bul_ucac_row_ue_cur"
|
|
||||||
|
|
||||||
# --- UE ordinaire
|
# --- UE ordinaire
|
||||||
pt = list_ue(ue, ue_descr)
|
pt = list_ue(ue, ue_descr)
|
||||||
@ -228,8 +230,8 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard):
|
|||||||
{
|
{
|
||||||
"code_ue": "Total",
|
"code_ue": "Total",
|
||||||
"moyenne_ue": I["moy_gen"],
|
"moyenne_ue": I["moy_gen"],
|
||||||
"coef": fmt_note(sum_coef_ues),
|
"coef": scu.fmt_note(sum_coef_ues),
|
||||||
"total": fmt_note(sum_pt_sem),
|
"total": scu.fmt_note(sum_pt_sem),
|
||||||
"_code_ue_colspan": 4,
|
"_code_ue_colspan": 4,
|
||||||
"_css_row_class": "bul_ucac_row_total",
|
"_css_row_class": "bul_ucac_row_total",
|
||||||
"_pdf_row_markup": ["b"],
|
"_pdf_row_markup": ["b"],
|
||||||
|
@ -37,7 +37,14 @@ Malheureusement, le code de génération JSON et XML sont séparés, ce qui est
|
|||||||
Je propose de considérer le XMl comme "deprecated" et de ne plus le modifier, sauf nécessité.
|
Je propose de considérer le XMl comme "deprecated" et de ne plus le modifier, sauf nécessité.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from notes_table import *
|
import datetime
|
||||||
|
import jaxml
|
||||||
|
|
||||||
|
import sco_utils as scu
|
||||||
|
import notesdb as ndb
|
||||||
|
from notes_log import log
|
||||||
|
import scolars
|
||||||
|
import sco_codes_parcours
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_groups
|
import sco_groups
|
||||||
import sco_photos
|
import sco_photos
|
||||||
@ -62,9 +69,9 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
"bulletin au format XML"
|
"bulletin au format XML"
|
||||||
log("xml_bulletin( formsemestre_id=%s, etudid=%s )" % (formsemestre_id, etudid))
|
log("xml_bulletin( formsemestre_id=%s, etudid=%s )" % (formsemestre_id, etudid))
|
||||||
if REQUEST:
|
if REQUEST:
|
||||||
REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE)
|
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
|
||||||
if not doc:
|
if not doc:
|
||||||
doc = jaxml.XML_document(encoding=SCO_ENCODING)
|
doc = jaxml.XML_document(encoding=scu.SCO_ENCODING)
|
||||||
|
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||||
if sem["bul_hide_xml"] == "0" or force_publishing:
|
if sem["bul_hide_xml"] == "0" or force_publishing:
|
||||||
@ -98,12 +105,13 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
etudid=etudid,
|
etudid=etudid,
|
||||||
code_nip=etudinfo["code_nip"],
|
code_nip=etudinfo["code_nip"],
|
||||||
code_ine=etudinfo["code_ine"],
|
code_ine=etudinfo["code_ine"],
|
||||||
nom=quote_xml_attr(etudinfo["nom"]),
|
nom=scu.quote_xml_attr(etudinfo["nom"]),
|
||||||
prenom=quote_xml_attr(etudinfo["prenom"]),
|
prenom=scu.quote_xml_attr(etudinfo["prenom"]),
|
||||||
sexe=quote_xml_attr(etudinfo["sexe"]),
|
civilite=scu.quote_xml_attr(etudinfo["civilite_str"]),
|
||||||
photo_url=quote_xml_attr(sco_photos.etud_photo_url(context, etudinfo)),
|
sexe=scu.quote_xml_attr(etudinfo["civilite_str"]), # compat
|
||||||
email=quote_xml_attr(etudinfo["email"]),
|
photo_url=scu.quote_xml_attr(sco_photos.etud_photo_url(context, etudinfo)),
|
||||||
emailperso=quote_xml_attr(etudinfo["emailperso"]),
|
email=scu.quote_xml_attr(etudinfo["email"]),
|
||||||
|
emailperso=scu.quote_xml_attr(etudinfo["emailperso"]),
|
||||||
)
|
)
|
||||||
doc._pop()
|
doc._pop()
|
||||||
|
|
||||||
@ -128,7 +136,7 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
ues = nt.get_ues()
|
ues = nt.get_ues()
|
||||||
modimpls = nt.get_modimpls()
|
modimpls = nt.get_modimpls()
|
||||||
nbetuds = len(nt.rangs)
|
nbetuds = len(nt.rangs)
|
||||||
mg = fmt_note(nt.get_etud_moy_gen(etudid))
|
mg = scu.fmt_note(nt.get_etud_moy_gen(etudid))
|
||||||
if (
|
if (
|
||||||
nt.get_moduleimpls_attente()
|
nt.get_moduleimpls_attente()
|
||||||
or context.get_preference("bul_show_rangs", formsemestre_id) == 0
|
or context.get_preference("bul_show_rangs", formsemestre_id) == 0
|
||||||
@ -147,9 +155,9 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
doc._push()
|
doc._push()
|
||||||
doc.note(
|
doc.note(
|
||||||
value=mg,
|
value=mg,
|
||||||
min=fmt_note(nt.moy_min),
|
min=scu.fmt_note(nt.moy_min),
|
||||||
max=fmt_note(nt.moy_max),
|
max=scu.fmt_note(nt.moy_max),
|
||||||
moy=fmt_note(nt.moy_moy),
|
moy=scu.fmt_note(nt.moy_moy),
|
||||||
)
|
)
|
||||||
doc._pop()
|
doc._pop()
|
||||||
doc._push()
|
doc._push()
|
||||||
@ -177,17 +185,21 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
doc._push()
|
doc._push()
|
||||||
doc.ue(
|
doc.ue(
|
||||||
id=ue["ue_id"],
|
id=ue["ue_id"],
|
||||||
numero=quote_xml_attr(ue["numero"]),
|
numero=scu.quote_xml_attr(ue["numero"]),
|
||||||
acronyme=quote_xml_attr(ue["acronyme"]),
|
acronyme=scu.quote_xml_attr(ue["acronyme"]),
|
||||||
titre=quote_xml_attr(ue["titre"]),
|
titre=scu.quote_xml_attr(ue["titre"]),
|
||||||
code_apogee=quote_xml_attr(ue["code_apogee"]),
|
code_apogee=scu.quote_xml_attr(ue["code_apogee"]),
|
||||||
)
|
)
|
||||||
doc._push()
|
doc._push()
|
||||||
if ue["type"] != UE_SPORT:
|
if ue["type"] != sco_codes_parcours.UE_SPORT:
|
||||||
v = ue_status["cur_moy_ue"]
|
v = ue_status["cur_moy_ue"]
|
||||||
else:
|
else:
|
||||||
v = nt.bonus[etudid]
|
v = nt.bonus[etudid]
|
||||||
doc.note(value=fmt_note(v), min=fmt_note(ue["min"]), max=fmt_note(ue["max"]))
|
doc.note(
|
||||||
|
value=scu.fmt_note(v),
|
||||||
|
min=scu.fmt_note(ue["min"]),
|
||||||
|
max=scu.fmt_note(ue["max"]),
|
||||||
|
)
|
||||||
doc._pop()
|
doc._pop()
|
||||||
try:
|
try:
|
||||||
ects_txt = str(int(ue["ects"]))
|
ects_txt = str(int(ue["ects"]))
|
||||||
@ -205,7 +217,9 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
# Liste les modules de l'UE
|
# Liste les modules de l'UE
|
||||||
ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue["ue_id"]]
|
ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue["ue_id"]]
|
||||||
for modimpl in ue_modimpls:
|
for modimpl in ue_modimpls:
|
||||||
mod_moy = fmt_note(nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid))
|
mod_moy = scu.fmt_note(
|
||||||
|
nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid)
|
||||||
|
)
|
||||||
if mod_moy == "NI": # ne mentionne pas les modules ou n'est pas inscrit
|
if mod_moy == "NI": # ne mentionne pas les modules ou n'est pas inscrit
|
||||||
continue
|
continue
|
||||||
mod = modimpl["module"]
|
mod = modimpl["module"]
|
||||||
@ -219,18 +233,18 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
code=mod["code"],
|
code=mod["code"],
|
||||||
coefficient=mod["coefficient"],
|
coefficient=mod["coefficient"],
|
||||||
numero=mod["numero"],
|
numero=mod["numero"],
|
||||||
titre=quote_xml_attr(mod["titre"]),
|
titre=scu.quote_xml_attr(mod["titre"]),
|
||||||
abbrev=quote_xml_attr(mod["abbrev"]),
|
abbrev=scu.quote_xml_attr(mod["abbrev"]),
|
||||||
code_apogee=quote_xml_attr(mod["code_apogee"])
|
code_apogee=scu.quote_xml_attr(mod["code_apogee"])
|
||||||
# ects=ects ects des modules maintenant inutilisés
|
# ects=ects ects des modules maintenant inutilisés
|
||||||
)
|
)
|
||||||
doc._push()
|
doc._push()
|
||||||
modstat = nt.get_mod_stats(modimpl["moduleimpl_id"])
|
modstat = nt.get_mod_stats(modimpl["moduleimpl_id"])
|
||||||
doc.note(
|
doc.note(
|
||||||
value=mod_moy,
|
value=mod_moy,
|
||||||
min=fmt_note(modstat["min"]),
|
min=scu.fmt_note(modstat["min"]),
|
||||||
max=fmt_note(modstat["max"]),
|
max=scu.fmt_note(modstat["max"]),
|
||||||
moy=fmt_note(modstat["moy"]),
|
moy=scu.fmt_note(modstat["moy"]),
|
||||||
)
|
)
|
||||||
doc._pop()
|
doc._pop()
|
||||||
if context.get_preference("bul_show_mod_rangs", formsemestre_id):
|
if context.get_preference("bul_show_mod_rangs", formsemestre_id):
|
||||||
@ -247,14 +261,16 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
if int(e["visibulletin"]) == 1 or version == "long":
|
if int(e["visibulletin"]) == 1 or version == "long":
|
||||||
doc._push()
|
doc._push()
|
||||||
doc.evaluation(
|
doc.evaluation(
|
||||||
jour=DateDMYtoISO(e["jour"], null_is_empty=True),
|
jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True),
|
||||||
heure_debut=TimetoISO8601(
|
heure_debut=ndb.TimetoISO8601(
|
||||||
e["heure_debut"], null_is_empty=True
|
e["heure_debut"], null_is_empty=True
|
||||||
),
|
),
|
||||||
heure_fin=TimetoISO8601(e["heure_fin"], null_is_empty=True),
|
heure_fin=ndb.TimetoISO8601(
|
||||||
|
e["heure_fin"], null_is_empty=True
|
||||||
|
),
|
||||||
coefficient=e["coefficient"],
|
coefficient=e["coefficient"],
|
||||||
evaluation_type=e["evaluation_type"],
|
evaluation_type=e["evaluation_type"],
|
||||||
description=quote_xml_attr(e["description"]),
|
description=scu.quote_xml_attr(e["description"]),
|
||||||
note_max_origin=e[
|
note_max_origin=e[
|
||||||
"note_max"
|
"note_max"
|
||||||
], # notes envoyées sur 20, ceci juste pour garder trace
|
], # notes envoyées sur 20, ceci juste pour garder trace
|
||||||
@ -262,7 +278,7 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
val = e["notes"].get(etudid, {"value": "NP"})[
|
val = e["notes"].get(etudid, {"value": "NP"})[
|
||||||
"value"
|
"value"
|
||||||
] # NA si etud demissionnaire
|
] # NA si etud demissionnaire
|
||||||
val = fmt_note(val, note_max=e["note_max"])
|
val = scu.fmt_note(val, note_max=e["note_max"])
|
||||||
doc.note(value=val)
|
doc.note(value=val)
|
||||||
doc._pop()
|
doc._pop()
|
||||||
# Evaluations incomplètes ou futures:
|
# Evaluations incomplètes ou futures:
|
||||||
@ -276,15 +292,15 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
if e["evaluation_id"] not in complete_eval_ids:
|
if e["evaluation_id"] not in complete_eval_ids:
|
||||||
doc._push()
|
doc._push()
|
||||||
doc.evaluation(
|
doc.evaluation(
|
||||||
jour=DateDMYtoISO(e["jour"], null_is_empty=True),
|
jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True),
|
||||||
heure_debut=TimetoISO8601(
|
heure_debut=ndb.TimetoISO8601(
|
||||||
e["heure_debut"], null_is_empty=True
|
e["heure_debut"], null_is_empty=True
|
||||||
),
|
),
|
||||||
heure_fin=TimetoISO8601(
|
heure_fin=ndb.TimetoISO8601(
|
||||||
e["heure_fin"], null_is_empty=True
|
e["heure_fin"], null_is_empty=True
|
||||||
),
|
),
|
||||||
coefficient=e["coefficient"],
|
coefficient=e["coefficient"],
|
||||||
description=quote_xml_attr(e["description"]),
|
description=scu.quote_xml_attr(e["description"]),
|
||||||
incomplete="1",
|
incomplete="1",
|
||||||
note_max_origin=e[
|
note_max_origin=e[
|
||||||
"note_max"
|
"note_max"
|
||||||
@ -302,27 +318,25 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
doc._push()
|
doc._push()
|
||||||
doc.ue_capitalisee(
|
doc.ue_capitalisee(
|
||||||
id=ue["ue_id"],
|
id=ue["ue_id"],
|
||||||
numero=quote_xml_attr(ue["numero"]),
|
numero=scu.quote_xml_attr(ue["numero"]),
|
||||||
acronyme=quote_xml_attr(ue["acronyme"]),
|
acronyme=scu.quote_xml_attr(ue["acronyme"]),
|
||||||
titre=quote_xml_attr(ue["titre"]),
|
titre=scu.quote_xml_attr(ue["titre"]),
|
||||||
)
|
)
|
||||||
doc._push()
|
doc._push()
|
||||||
doc.note(value=fmt_note(ue_status["moy"]))
|
doc.note(value=scu.fmt_note(ue_status["moy"]))
|
||||||
doc._pop()
|
doc._pop()
|
||||||
doc._push()
|
doc._push()
|
||||||
doc.ects(value=ects_txt)
|
doc.ects(value=ects_txt)
|
||||||
doc._pop()
|
doc._pop()
|
||||||
doc._push()
|
doc._push()
|
||||||
doc.coefficient_ue(value=fmt_note(ue_status["coef_ue"]))
|
doc.coefficient_ue(value=scu.fmt_note(ue_status["coef_ue"]))
|
||||||
doc._pop()
|
doc._pop()
|
||||||
doc._push()
|
doc._push()
|
||||||
doc.date_capitalisation(value=DateDMYtoISO(ue_status["event_date"]))
|
doc.date_capitalisation(value=ndb.DateDMYtoISO(ue_status["event_date"]))
|
||||||
doc._pop()
|
doc._pop()
|
||||||
doc._pop()
|
doc._pop()
|
||||||
# --- Absences
|
# --- Absences
|
||||||
if context.get_preference("bul_show_abs", formsemestre_id):
|
if context.get_preference("bul_show_abs", formsemestre_id):
|
||||||
debut_sem = DateDMYtoISO(sem["date_debut"])
|
|
||||||
fin_sem = DateDMYtoISO(sem["date_fin"])
|
|
||||||
AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid)
|
AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid)
|
||||||
nbabs = AbsEtudSem.CountAbs()
|
nbabs = AbsEtudSem.CountAbs()
|
||||||
nbabsjust = AbsEtudSem.CountAbsJust()
|
nbabsjust = AbsEtudSem.CountAbsJust()
|
||||||
@ -341,7 +355,7 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
format="xml",
|
format="xml",
|
||||||
show_uevalid=context.get_preference("bul_show_uevalid", formsemestre_id),
|
show_uevalid=context.get_preference("bul_show_uevalid", formsemestre_id),
|
||||||
)
|
)
|
||||||
doc.situation(quote_xml_attr(infos["situation"]))
|
doc.situation(scu.quote_xml_attr(infos["situation"]))
|
||||||
if dpv:
|
if dpv:
|
||||||
decision = dpv["decisions"][0]
|
decision = dpv["decisions"][0]
|
||||||
etat = decision["etat"]
|
etat = decision["etat"]
|
||||||
@ -375,9 +389,9 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
doc._push()
|
doc._push()
|
||||||
doc.decision_ue(
|
doc.decision_ue(
|
||||||
ue_id=ue["ue_id"],
|
ue_id=ue["ue_id"],
|
||||||
numero=quote_xml_attr(ue["numero"]),
|
numero=scu.quote_xml_attr(ue["numero"]),
|
||||||
acronyme=quote_xml_attr(ue["acronyme"]),
|
acronyme=scu.quote_xml_attr(ue["acronyme"]),
|
||||||
titre=quote_xml_attr(ue["titre"]),
|
titre=scu.quote_xml_attr(ue["titre"]),
|
||||||
code=decision["decisions_ue"][ue_id]["code"],
|
code=decision["decisions_ue"][ue_id]["code"],
|
||||||
)
|
)
|
||||||
doc._pop()
|
doc._pop()
|
||||||
@ -396,5 +410,7 @@ def make_xml_formsemestre_bulletinetud(
|
|||||||
cnx, args={"etudid": etudid, "formsemestre_id": formsemestre_id}
|
cnx, args={"etudid": etudid, "formsemestre_id": formsemestre_id}
|
||||||
)
|
)
|
||||||
for app in apprecs:
|
for app in apprecs:
|
||||||
doc.appreciation(quote_xml_attr(app["comment"]), date=DateDMYtoISO(app["date"]))
|
doc.appreciation(
|
||||||
|
scu.quote_xml_attr(app["comment"]), date=ndb.DateDMYtoISO(app["date"])
|
||||||
|
)
|
||||||
return doc
|
return doc
|
||||||
|
@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
(coût théorique en heures équivalent TD)
|
(coût théorique en heures équivalent TD)
|
||||||
"""
|
"""
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
import sco_excel, sco_pdf
|
import sco_excel, sco_pdf
|
||||||
@ -39,6 +39,7 @@ from sco_pdf import SU
|
|||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_moduleimpl
|
import sco_moduleimpl
|
||||||
import sco_formsemestre_status
|
import sco_formsemestre_status
|
||||||
|
import VERSION
|
||||||
|
|
||||||
|
|
||||||
def formsemestre_table_estim_cost(
|
def formsemestre_table_estim_cost(
|
||||||
@ -144,7 +145,7 @@ def formsemestre_table_estim_cost(
|
|||||||
(dans ce cas, retoucher le tableau excel exporté).
|
(dans ce cas, retoucher le tableau excel exporté).
|
||||||
</div>
|
</div>
|
||||||
""",
|
""",
|
||||||
origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "",
|
origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "",
|
||||||
filename="EstimCout-S%s" % sem["semestre_id"],
|
filename="EstimCout-S%s" % sem["semestre_id"],
|
||||||
)
|
)
|
||||||
return tab
|
return tab
|
||||||
|
@ -115,7 +115,7 @@ def table_debouche_etudids(context, etudids, keep_numeric=True):
|
|||||||
)
|
)
|
||||||
row = {
|
row = {
|
||||||
"etudid": etudid,
|
"etudid": etudid,
|
||||||
"sexe": etud["sexe"],
|
"civilite": etud["civilite"],
|
||||||
"nom": etud["nom"],
|
"nom": etud["nom"],
|
||||||
"prenom": etud["prenom"],
|
"prenom": etud["prenom"],
|
||||||
"_nom_target": "ficheEtud?etudid=" + etud["etudid"],
|
"_nom_target": "ficheEtud?etudid=" + etud["etudid"],
|
||||||
@ -154,7 +154,7 @@ def table_debouche_etudids(context, etudids, keep_numeric=True):
|
|||||||
L.sort(key=lambda x: x["sem_ident"])
|
L.sort(key=lambda x: x["sem_ident"])
|
||||||
|
|
||||||
titles = {
|
titles = {
|
||||||
"sexe": "",
|
"civilite": "",
|
||||||
"nom": "Nom",
|
"nom": "Nom",
|
||||||
"prenom": "Prénom",
|
"prenom": "Prénom",
|
||||||
"semestre": "Dernier semestre",
|
"semestre": "Dernier semestre",
|
||||||
@ -170,7 +170,7 @@ def table_debouche_etudids(context, etudids, keep_numeric=True):
|
|||||||
"semestre",
|
"semestre",
|
||||||
"semestre_id",
|
"semestre_id",
|
||||||
"periode",
|
"periode",
|
||||||
"sexe",
|
"civilite",
|
||||||
"nom",
|
"nom",
|
||||||
"prenom",
|
"prenom",
|
||||||
"moy",
|
"moy",
|
||||||
|
15
sco_dept.py
15
sco_dept.py
@ -27,14 +27,15 @@
|
|||||||
|
|
||||||
"""Page accueil département (liste des semestres, etc)
|
"""Page accueil département (liste des semestres, etc)
|
||||||
"""
|
"""
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import sco_modalites
|
import sco_modalites
|
||||||
import sco_news
|
import sco_news
|
||||||
import sco_up_to_date
|
import sco_up_to_date
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
|
from sco_permissions import ScoEtudInscrit, ScoEditApo
|
||||||
|
|
||||||
|
|
||||||
def index_html(context, REQUEST=None, showcodes=0, showsemtable=0):
|
def index_html(context, REQUEST=None, showcodes=0, showsemtable=0):
|
||||||
@ -44,7 +45,7 @@ def index_html(context, REQUEST=None, showcodes=0, showsemtable=0):
|
|||||||
|
|
||||||
# News:
|
# News:
|
||||||
# 2020-12-30: abandonne l'icon rss
|
# 2020-12-30: abandonne l'icon rss
|
||||||
# rssicon = icontag("rssscodoc_img", title="Flux RSS", border="0")
|
# rssicon = scu.icontag("rssscodoc_img", title="Flux RSS", border="0")
|
||||||
H.append(sco_news.scolar_news_summary_html(context)) # , rssicon=rssicon))
|
H.append(sco_news.scolar_news_summary_html(context)) # , rssicon=rssicon))
|
||||||
|
|
||||||
# Avertissement de mise à jour:
|
# Avertissement de mise à jour:
|
||||||
@ -55,9 +56,11 @@ def index_html(context, REQUEST=None, showcodes=0, showsemtable=0):
|
|||||||
cursems = [] # semestres "courants"
|
cursems = [] # semestres "courants"
|
||||||
othersems = [] # autres (verrouillés)
|
othersems = [] # autres (verrouillés)
|
||||||
# icon image:
|
# icon image:
|
||||||
groupicon = icontag("groupicon_img", title="Inscrits", border="0")
|
groupicon = scu.icontag("groupicon_img", title="Inscrits", border="0")
|
||||||
emptygroupicon = icontag("emptygroupicon_img", title="Pas d'inscrits", border="0")
|
emptygroupicon = scu.icontag(
|
||||||
lockicon = icontag("lock32_img", title="verrouillé", border="0")
|
"emptygroupicon_img", title="Pas d'inscrits", border="0"
|
||||||
|
)
|
||||||
|
lockicon = scu.icontag("lock32_img", title="verrouillé", border="0")
|
||||||
# Sélection sur l'etat du semestre
|
# Sélection sur l'etat du semestre
|
||||||
for sem in sems:
|
for sem in sems:
|
||||||
if sem["etat"] == "1" and sem["modalite"] != "EXT":
|
if sem["etat"] == "1" and sem["modalite"] != "EXT":
|
||||||
|
@ -46,19 +46,20 @@ pg_dump SCORT | psql ANORT
|
|||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import os
|
||||||
import fcntl
|
import fcntl
|
||||||
import subprocess
|
import subprocess
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
from email.mime.base import MIMEBase
|
from email.mime.base import MIMEBase
|
||||||
from email.header import Header
|
from email.header import Header
|
||||||
|
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
import sco_utils
|
import sco_utils as scu
|
||||||
from sco_utils import *
|
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
|
||||||
SCO_DUMP_LOCK = "/tmp/scodump.lock"
|
SCO_DUMP_LOCK = "/tmp/scodump.lock"
|
||||||
|
|
||||||
@ -67,14 +68,14 @@ 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"""
|
"""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 = [context.sco_header(REQUEST, page_title="Assistance technique")]
|
||||||
# get currect (dept) DB name:
|
# get currect (dept) DB name:
|
||||||
cursor = SimpleQuery(context, "SELECT current_database()", {})
|
cursor = ndb.SimpleQuery(context, "SELECT current_database()", {})
|
||||||
db_name = cursor.fetchone()[0]
|
db_name = cursor.fetchone()[0]
|
||||||
ano_db_name = "ANO" + db_name
|
ano_db_name = "ANO" + db_name
|
||||||
# Lock
|
# Lock
|
||||||
try:
|
try:
|
||||||
x = open(SCO_DUMP_LOCK, "w+")
|
x = open(SCO_DUMP_LOCK, "w+")
|
||||||
fcntl.flock(x, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
fcntl.flock(x, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||||
except fcntl.BlockingIOError:
|
except (IOError, OSError): # exception changed from Python 2 to 3
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
"Un envoi de la base "
|
"Un envoi de la base "
|
||||||
+ db_name
|
+ db_name
|
||||||
@ -93,22 +94,25 @@ def sco_dump_and_send_db(context, REQUEST=None):
|
|||||||
|
|
||||||
# Send
|
# Send
|
||||||
r = _send_db(context, REQUEST, ano_db_name)
|
r = _send_db(context, REQUEST, ano_db_name)
|
||||||
if r.status_code == requests.codes.INSUFFICIENT_STORAGE:
|
if (
|
||||||
|
r.status_code
|
||||||
|
== requests.codes.INSUFFICIENT_STORAGE # pylint: disable=no-member
|
||||||
|
):
|
||||||
H.append(
|
H.append(
|
||||||
"""<p class="warning">
|
"""<p class="warning">
|
||||||
Erreur: espace serveur trop plein.
|
Erreur: espace serveur trop plein.
|
||||||
Merci de contacter <a href="mailto:{0}">{0}</a></p>""".format(
|
Merci de contacter <a href="mailto:{0}">{0}</a></p>""".format(
|
||||||
SCO_DEV_MAIL
|
scu.SCO_DEV_MAIL
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif r.status_code == requests.codes.OK:
|
elif r.status_code == requests.codes.OK: # pylint: disable=no-member
|
||||||
H.append("""<p>Opération effectuée.</p>""")
|
H.append("""<p>Opération effectuée.</p>""")
|
||||||
else:
|
else:
|
||||||
H.append(
|
H.append(
|
||||||
"""<p class="warning">
|
"""<p class="warning">
|
||||||
Erreur: code <tt>{0} {1}</tt>
|
Erreur: code <tt>{0} {1}</tt>
|
||||||
Merci de contacter <a href="mailto:{2}">{2}</a></p>""".format(
|
Merci de contacter <a href="mailto:{2}">{2}</a></p>""".format(
|
||||||
r.status_code, r.reason, SCO_DEV_MAIL
|
r.status_code, r.reason, scu.SCO_DEV_MAIL
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -127,7 +131,7 @@ def _duplicate_db(db_name, ano_db_name):
|
|||||||
cmd = ["createdb", "-E", "UTF-8", ano_db_name]
|
cmd = ["createdb", "-E", "UTF-8", ano_db_name]
|
||||||
log("sco_dump_and_send_db/_duplicate_db: {}".format(cmd))
|
log("sco_dump_and_send_db/_duplicate_db: {}".format(cmd))
|
||||||
try:
|
try:
|
||||||
out = subprocess.check_output(cmd)
|
_ = subprocess.check_output(cmd)
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
log("sco_dump_and_send_db: exception createdb {}".format(e))
|
log("sco_dump_and_send_db: exception createdb {}".format(e))
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
@ -137,7 +141,7 @@ def _duplicate_db(db_name, ano_db_name):
|
|||||||
cmd = "pg_dump {} | psql {}".format(db_name, ano_db_name)
|
cmd = "pg_dump {} | psql {}".format(db_name, ano_db_name)
|
||||||
log("sco_dump_and_send_db/_duplicate_db: {}".format(cmd))
|
log("sco_dump_and_send_db/_duplicate_db: {}".format(cmd))
|
||||||
try:
|
try:
|
||||||
out = subprocess.check_output(cmd, shell=1)
|
_ = subprocess.check_output(cmd, shell=1)
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
log("sco_dump_and_send_db: exception {}".format(e))
|
log("sco_dump_and_send_db: exception {}".format(e))
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
@ -149,10 +153,10 @@ def _duplicate_db(db_name, ano_db_name):
|
|||||||
|
|
||||||
def _anonymize_db(ano_db_name):
|
def _anonymize_db(ano_db_name):
|
||||||
"""Anonymize a departement database"""
|
"""Anonymize a departement database"""
|
||||||
cmd = os.path.join(SCO_TOOLS_DIR, "anonymize_db.py")
|
cmd = os.path.join(scu.SCO_TOOLS_DIR, "anonymize_db.py")
|
||||||
log("_anonymize_db: {}".format(cmd))
|
log("_anonymize_db: {}".format(cmd))
|
||||||
try:
|
try:
|
||||||
subprocess.check_output([cmd, ano_db_name])
|
_ = subprocess.check_output([cmd, ano_db_name])
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
log("sco_dump_and_send_db: exception in anonymisation: {}".format(e))
|
log("sco_dump_and_send_db: exception in anonymisation: {}".format(e))
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
@ -162,7 +166,7 @@ def _anonymize_db(ano_db_name):
|
|||||||
|
|
||||||
def _get_scodoc_serial(context):
|
def _get_scodoc_serial(context):
|
||||||
try:
|
try:
|
||||||
return int(open(os.path.join(SCODOC_VERSION_DIR, "scodoc.sn")).read())
|
return int(open(os.path.join(scu.SCODOC_VERSION_DIR, "scodoc.sn")).read())
|
||||||
except:
|
except:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@ -181,7 +185,7 @@ def _send_db(context, REQUEST, ano_db_name):
|
|||||||
log("uploading anonymized dump...")
|
log("uploading anonymized dump...")
|
||||||
files = {"file": (ano_db_name + ".gz", data)}
|
files = {"file": (ano_db_name + ".gz", data)}
|
||||||
r = requests.post(
|
r = requests.post(
|
||||||
SCO_DUMP_UP_URL,
|
scu.SCO_DUMP_UP_URL,
|
||||||
files=files,
|
files=files,
|
||||||
data={
|
data={
|
||||||
"dept_name": context.get_preference("DeptName"),
|
"dept_name": context.get_preference("DeptName"),
|
||||||
@ -190,8 +194,8 @@ def _send_db(context, REQUEST, ano_db_name):
|
|||||||
"sent_by": context.Users.user_info(str(REQUEST.AUTHENTICATED_USER))[
|
"sent_by": context.Users.user_info(str(REQUEST.AUTHENTICATED_USER))[
|
||||||
"nomcomplet"
|
"nomcomplet"
|
||||||
],
|
],
|
||||||
"sco_version": SCOVERSION,
|
"sco_version": scu.SCOVERSION,
|
||||||
"sco_fullversion": sco_utils.get_scodoc_version(),
|
"sco_fullversion": scu.get_scodoc_version(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
return r
|
return r
|
||||||
@ -209,7 +213,7 @@ def _drop_ano_db(ano_db_name):
|
|||||||
cmd = ["dropdb", ano_db_name]
|
cmd = ["dropdb", ano_db_name]
|
||||||
log("sco_dump_and_send_db: {}".format(cmd))
|
log("sco_dump_and_send_db: {}".format(cmd))
|
||||||
try:
|
try:
|
||||||
out = subprocess.check_output(cmd)
|
_ = subprocess.check_output(cmd)
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
log("sco_dump_and_send_db: exception dropdb {}".format(e))
|
log("sco_dump_and_send_db: exception dropdb {}".format(e))
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
|
@ -28,12 +28,13 @@
|
|||||||
"""Ajout/Modification/Supression formations
|
"""Ajout/Modification/Supression formations
|
||||||
(portage from DTML)
|
(portage from DTML)
|
||||||
"""
|
"""
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from TrivialFormulator import TrivialFormulator, TF
|
from TrivialFormulator import TrivialFormulator, TF, tf_error_message
|
||||||
import sco_codes_parcours
|
import sco_codes_parcours
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
|
||||||
|
|
||||||
def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST=None):
|
def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST=None):
|
||||||
@ -61,7 +62,7 @@ def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST
|
|||||||
'<li><a href="formsemestre_status?formsemestre_id=%(formsemestre_id)s">%(titremois)s</a></li>'
|
'<li><a href="formsemestre_status?formsemestre_id=%(formsemestre_id)s">%(titremois)s</a></li>'
|
||||||
% sem
|
% sem
|
||||||
)
|
)
|
||||||
H.append('</ul><p><a href="%s">Revenir</a></p>' % REQUEST.URL1)
|
H.append('</ul><p><a href="%s">Revenir</a></p>' % context.NotesURL())
|
||||||
else:
|
else:
|
||||||
if not dialog_confirmed:
|
if not dialog_confirmed:
|
||||||
return context.confirmDialog(
|
return context.confirmDialog(
|
||||||
@ -72,7 +73,7 @@ def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST
|
|||||||
% F,
|
% F,
|
||||||
REQUEST=REQUEST,
|
REQUEST=REQUEST,
|
||||||
OK="Supprimer cette formation",
|
OK="Supprimer cette formation",
|
||||||
cancel_url=REQUEST.URL1,
|
cancel_url=context.NotesURL(),
|
||||||
parameters={"formation_id": formation_id},
|
parameters={"formation_id": formation_id},
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -80,7 +81,7 @@ def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST
|
|||||||
H.append(
|
H.append(
|
||||||
"""<p>OK, formation supprimée.</p>
|
"""<p>OK, formation supprimée.</p>
|
||||||
<p><a class="stdlink" href="%s">continuer</a></p>"""
|
<p><a class="stdlink" href="%s">continuer</a></p>"""
|
||||||
% REQUEST.URL1
|
% context.NotesURL()
|
||||||
)
|
)
|
||||||
|
|
||||||
H.append(context.sco_footer(REQUEST))
|
H.append(context.sco_footer(REQUEST))
|
||||||
@ -190,7 +191,7 @@ def formation_edit(context, formation_id=None, create=False, REQUEST=None):
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
|
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(context.NotesURL())
|
||||||
else:
|
else:
|
||||||
# check unicity : constraint UNIQUE(acronyme,titre,version)
|
# check unicity : constraint UNIQUE(acronyme,titre,version)
|
||||||
if create:
|
if create:
|
||||||
@ -202,7 +203,7 @@ def formation_edit(context, formation_id=None, create=False, REQUEST=None):
|
|||||||
"titre": tf[2]["titre"],
|
"titre": tf[2]["titre"],
|
||||||
"version": version,
|
"version": version,
|
||||||
}
|
}
|
||||||
quote_dict(args)
|
ndb.quote_dict(args)
|
||||||
others = context.formation_list(args=args)
|
others = context.formation_list(args=args)
|
||||||
if others and ((len(others) > 1) or others[0]["formation_id"] != formation_id):
|
if others and ((len(others) > 1) or others[0]["formation_id"] != formation_id):
|
||||||
return (
|
return (
|
||||||
|
@ -28,11 +28,12 @@
|
|||||||
"""Ajout/Modification/Supression matieres
|
"""Ajout/Modification/Supression matieres
|
||||||
(portage from DTML)
|
(portage from DTML)
|
||||||
"""
|
"""
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from TrivialFormulator import TrivialFormulator, TF
|
from TrivialFormulator import TrivialFormulator, TF, tf_error_message
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
|
||||||
|
|
||||||
def matiere_create(context, ue_id=None, REQUEST=None):
|
def matiere_create(context, ue_id=None, REQUEST=None):
|
||||||
@ -74,7 +75,7 @@ associé.
|
|||||||
submitlabel="Créer cette matière",
|
submitlabel="Créer cette matière",
|
||||||
)
|
)
|
||||||
|
|
||||||
dest_url = REQUEST.URL1 + "/ue_list?formation_id=" + UE["formation_id"]
|
dest_url = context.NotesURL() + "/ue_list?formation_id=" + UE["formation_id"]
|
||||||
|
|
||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
|
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
|
||||||
@ -90,7 +91,7 @@ associé.
|
|||||||
+ tf[1]
|
+ tf[1]
|
||||||
+ context.sco_footer(REQUEST)
|
+ context.sco_footer(REQUEST)
|
||||||
)
|
)
|
||||||
matiere_id = context.do_matiere_create(tf[2], REQUEST)
|
_ = context.do_matiere_create(tf[2], REQUEST)
|
||||||
return REQUEST.RESPONSE.redirect(dest_url)
|
return REQUEST.RESPONSE.redirect(dest_url)
|
||||||
|
|
||||||
|
|
||||||
@ -103,7 +104,7 @@ def matiere_delete(context, matiere_id=None, REQUEST=None):
|
|||||||
"<h2>Suppression de la matière %(titre)s" % M,
|
"<h2>Suppression de la matière %(titre)s" % M,
|
||||||
" dans l'UE (%(acronyme)s))</h2>" % UE,
|
" dans l'UE (%(acronyme)s))</h2>" % UE,
|
||||||
]
|
]
|
||||||
|
dest_url = context.NotesURL() + "/ue_list?formation_id=" + str(UE["formation_id"])
|
||||||
tf = TrivialFormulator(
|
tf = TrivialFormulator(
|
||||||
REQUEST.URL0,
|
REQUEST.URL0,
|
||||||
REQUEST.form,
|
REQUEST.form,
|
||||||
@ -115,12 +116,10 @@ def matiere_delete(context, matiere_id=None, REQUEST=None):
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
|
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(dest_url)
|
||||||
else:
|
else:
|
||||||
context.do_matiere_delete(matiere_id, REQUEST)
|
context.do_matiere_delete(matiere_id, REQUEST)
|
||||||
return REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(dest_url)
|
||||||
REQUEST.URL1 + "/ue_list?formation_id=" + str(UE["formation_id"])
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def matiere_edit(context, matiere_id=None, REQUEST=None):
|
def matiere_edit(context, matiere_id=None, REQUEST=None):
|
||||||
@ -180,7 +179,7 @@ associé.
|
|||||||
submitlabel="Modifier les valeurs",
|
submitlabel="Modifier les valeurs",
|
||||||
)
|
)
|
||||||
|
|
||||||
dest_url = REQUEST.URL1 + "/ue_list?formation_id=" + U["formation_id"]
|
dest_url = context.NotesURL() + "/ue_list?formation_id=" + U["formation_id"]
|
||||||
|
|
||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + help + context.sco_footer(REQUEST)
|
return "\n".join(H) + tf[1] + help + context.sco_footer(REQUEST)
|
||||||
@ -202,7 +201,7 @@ associé.
|
|||||||
# changement d'UE ?
|
# changement d'UE ?
|
||||||
if tf[2]["ue_id"] != F["ue_id"]:
|
if tf[2]["ue_id"] != F["ue_id"]:
|
||||||
log("attaching mat %s to new UE %s" % (matiere_id, tf[2]["ue_id"]))
|
log("attaching mat %s to new UE %s" % (matiere_id, tf[2]["ue_id"]))
|
||||||
SimpleQuery(
|
ndb.SimpleQuery(
|
||||||
context,
|
context,
|
||||||
"UPDATE notes_modules SET ue_id = %(ue_id)s WHERE matiere_id=%(matiere_id)s",
|
"UPDATE notes_modules SET ue_id = %(ue_id)s WHERE matiere_id=%(matiere_id)s",
|
||||||
{"ue_id": tf[2]["ue_id"], "matiere_id": matiere_id},
|
{"ue_id": tf[2]["ue_id"], "matiere_id": matiere_id},
|
||||||
|
@ -28,14 +28,16 @@
|
|||||||
"""Ajout/Modification/Supression UE
|
"""Ajout/Modification/Supression UE
|
||||||
(portage from DTML)
|
(portage from DTML)
|
||||||
"""
|
"""
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import sco_codes_parcours
|
import sco_codes_parcours
|
||||||
from TrivialFormulator import TrivialFormulator, TF
|
from TrivialFormulator import TrivialFormulator, TF
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_edit_ue
|
import sco_edit_ue
|
||||||
import sco_tag_module
|
import sco_tag_module
|
||||||
|
from sco_permissions import ScoChangeFormation
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
|
||||||
_MODULE_HELP = """<p class="help">
|
_MODULE_HELP = """<p class="help">
|
||||||
Les modules sont décrits dans le programme pédagogique. Un module est pour ce
|
Les modules sont décrits dans le programme pédagogique. Un module est pour ce
|
||||||
@ -99,7 +101,7 @@ def module_create(context, matiere_id=None, REQUEST=None):
|
|||||||
"title": "Type",
|
"title": "Type",
|
||||||
"explanation": "",
|
"explanation": "",
|
||||||
"labels": ("Standard", "Malus"),
|
"labels": ("Standard", "Malus"),
|
||||||
"allowed_values": (str(MODULE_STANDARD), str(MODULE_MALUS)),
|
"allowed_values": (str(scu.MODULE_STANDARD), str(scu.MODULE_MALUS)),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
@ -140,7 +142,7 @@ def module_create(context, matiere_id=None, REQUEST=None):
|
|||||||
{
|
{
|
||||||
"input_type": "menu",
|
"input_type": "menu",
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"title": strcapitalize(parcours.SESSION_NAME),
|
"title": scu.strcapitalize(parcours.SESSION_NAME),
|
||||||
"explanation": "%s de début du module dans la formation standard"
|
"explanation": "%s de début du module dans la formation standard"
|
||||||
% parcours.SESSION_NAME,
|
% parcours.SESSION_NAME,
|
||||||
"labels": [str(x) for x in semestres_indices],
|
"labels": [str(x) for x in semestres_indices],
|
||||||
@ -170,9 +172,9 @@ def module_create(context, matiere_id=None, REQUEST=None):
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
|
return "\n".join(H) + tf[1] + context.sco_footer(REQUEST)
|
||||||
else:
|
else:
|
||||||
moduleid = context.do_module_create(tf[2], REQUEST)
|
context.do_module_create(tf[2], REQUEST)
|
||||||
return REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
REQUEST.URL1 + "/ue_list?formation_id=" + UE["formation_id"]
|
context.NotesURL() + "/ue_list?formation_id=" + UE["formation_id"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -189,7 +191,7 @@ def module_delete(context, module_id=None, REQUEST=None):
|
|||||||
"""<h2>Suppression du module %(titre)s (%(code)s)</h2>""" % Mod,
|
"""<h2>Suppression du module %(titre)s (%(code)s)</h2>""" % Mod,
|
||||||
]
|
]
|
||||||
|
|
||||||
dest_url = REQUEST.URL1 + "/ue_list?formation_id=" + Mod["formation_id"]
|
dest_url = context.NotesURL() + "/ue_list?formation_id=" + Mod["formation_id"]
|
||||||
tf = TrivialFormulator(
|
tf = TrivialFormulator(
|
||||||
REQUEST.URL0,
|
REQUEST.URL0,
|
||||||
REQUEST.form,
|
REQUEST.form,
|
||||||
@ -227,7 +229,7 @@ def module_edit(context, module_id=None, REQUEST=None):
|
|||||||
unlocked = not context.module_is_locked(module_id)
|
unlocked = not context.module_is_locked(module_id)
|
||||||
Fo = context.formation_list(args={"formation_id": Mod["formation_id"]})[0]
|
Fo = context.formation_list(args={"formation_id": Mod["formation_id"]})[0]
|
||||||
parcours = sco_codes_parcours.get_parcours_from_code(Fo["type_parcours"])
|
parcours = sco_codes_parcours.get_parcours_from_code(Fo["type_parcours"])
|
||||||
M = SimpleDictFetch(
|
M = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT ue.acronyme, mat.* FROM notes_matieres mat, notes_ue ue WHERE mat.ue_id = ue.ue_id AND ue.formation_id = %(formation_id)s ORDER BY ue.numero, mat.numero",
|
"SELECT ue.acronyme, mat.* FROM notes_matieres mat, notes_ue ue WHERE mat.ue_id = ue.ue_id AND ue.formation_id = %(formation_id)s ORDER BY ue.numero, mat.numero",
|
||||||
{"formation_id": Mod["formation_id"]},
|
{"formation_id": Mod["formation_id"]},
|
||||||
@ -238,7 +240,7 @@ def module_edit(context, module_id=None, REQUEST=None):
|
|||||||
|
|
||||||
semestres_indices = range(1, parcours.NB_SEM + 1)
|
semestres_indices = range(1, parcours.NB_SEM + 1)
|
||||||
|
|
||||||
dest_url = REQUEST.URL1 + "/ue_list?formation_id=" + Mod["formation_id"]
|
dest_url = context.NotesURL() + "/ue_list?formation_id=" + Mod["formation_id"]
|
||||||
|
|
||||||
H = [
|
H = [
|
||||||
context.sco_header(
|
context.sco_header(
|
||||||
@ -286,7 +288,7 @@ def module_edit(context, module_id=None, REQUEST=None):
|
|||||||
"title": "Type",
|
"title": "Type",
|
||||||
"explanation": "",
|
"explanation": "",
|
||||||
"labels": ("Standard", "Malus"),
|
"labels": ("Standard", "Malus"),
|
||||||
"allowed_values": (str(MODULE_STANDARD), str(MODULE_MALUS)),
|
"allowed_values": (str(scu.MODULE_STANDARD), str(scu.MODULE_MALUS)),
|
||||||
"enabled": unlocked,
|
"enabled": unlocked,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -395,11 +397,10 @@ def edit_module_set_code_apogee(context, id=None, value=None, REQUEST=None):
|
|||||||
modules = context.do_module_list(args={"module_id": module_id})
|
modules = context.do_module_list(args={"module_id": module_id})
|
||||||
if not modules:
|
if not modules:
|
||||||
return "module invalide" # shoud not occur
|
return "module invalide" # shoud not occur
|
||||||
module = modules[0]
|
|
||||||
|
|
||||||
context.do_module_edit({"module_id": module_id, "code_apogee": value})
|
context.do_module_edit({"module_id": module_id, "code_apogee": value})
|
||||||
if not value:
|
if not value:
|
||||||
value = APO_MISSING_CODE_STR
|
value = scu.APO_MISSING_CODE_STR
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
@ -444,14 +445,14 @@ def formation_add_malus_modules(context, formation_id, titre=None, REQUEST=None)
|
|||||||
[
|
[
|
||||||
mod
|
mod
|
||||||
for mod in context.do_module_list(args={"ue_id": ue["ue_id"]})
|
for mod in context.do_module_list(args={"ue_id": ue["ue_id"]})
|
||||||
if mod["module_type"] == MODULE_MALUS
|
if mod["module_type"] == scu.MODULE_MALUS
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
if nb_mod_malus == 0:
|
if nb_mod_malus == 0:
|
||||||
ue_add_malus_module(context, ue["ue_id"], titre=titre, REQUEST=REQUEST)
|
ue_add_malus_module(context, ue["ue_id"], titre=titre, REQUEST=REQUEST)
|
||||||
|
|
||||||
if REQUEST:
|
if REQUEST:
|
||||||
REQUEST.RESPONSE.redirect("ue_list?formation_id=" + formation_id)
|
return REQUEST.RESPONSE.redirect("ue_list?formation_id=" + formation_id)
|
||||||
|
|
||||||
|
|
||||||
def ue_add_malus_module(context, ue_id, titre=None, code=None, REQUEST=None):
|
def ue_add_malus_module(context, ue_id, titre=None, code=None, REQUEST=None):
|
||||||
@ -490,7 +491,7 @@ def ue_add_malus_module(context, ue_id, titre=None, code=None, REQUEST=None):
|
|||||||
"matiere_id": matiere_id,
|
"matiere_id": matiere_id,
|
||||||
"formation_id": ue["formation_id"],
|
"formation_id": ue["formation_id"],
|
||||||
"semestre_id": semestre_id,
|
"semestre_id": semestre_id,
|
||||||
"module_type": MODULE_MALUS,
|
"module_type": scu.MODULE_MALUS,
|
||||||
},
|
},
|
||||||
REQUEST,
|
REQUEST,
|
||||||
)
|
)
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
"""Ajout/Modification/Supression UE
|
"""Ajout/Modification/Supression UE
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from TrivialFormulator import TrivialFormulator, TF
|
from TrivialFormulator import TrivialFormulator, TF
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
@ -38,6 +38,8 @@ import sco_formsemestre
|
|||||||
import sco_formsemestre_validation
|
import sco_formsemestre_validation
|
||||||
import sco_codes_parcours
|
import sco_codes_parcours
|
||||||
import sco_tag_module
|
import sco_tag_module
|
||||||
|
from sco_permissions import ScoChangeFormation, ScoEditFormationTags, ScoImplement
|
||||||
|
from sco_exceptions import ScoValueError, ScoLockedFormError
|
||||||
|
|
||||||
|
|
||||||
def ue_create(context, formation_id=None, REQUEST=None):
|
def ue_create(context, formation_id=None, REQUEST=None):
|
||||||
@ -84,7 +86,7 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None):
|
|||||||
|
|
||||||
ue_types = parcours.ALLOWED_UE_TYPES
|
ue_types = parcours.ALLOWED_UE_TYPES
|
||||||
ue_types.sort()
|
ue_types.sort()
|
||||||
ue_types_names = [UE_TYPE_NAME[k] for k in ue_types]
|
ue_types_names = [sco_codes_parcours.UE_TYPE_NAME[k] for k in ue_types]
|
||||||
ue_types = [str(x) for x in ue_types]
|
ue_types = [str(x) for x in ue_types]
|
||||||
|
|
||||||
fw = [
|
fw = [
|
||||||
@ -158,7 +160,7 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None):
|
|||||||
{
|
{
|
||||||
"input_type": "menu",
|
"input_type": "menu",
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"title": strcapitalize(parcours.SESSION_NAME),
|
"title": scu.strcapitalize(parcours.SESSION_NAME),
|
||||||
"explanation": "%s de début du module dans la formation"
|
"explanation": "%s de début du module dans la formation"
|
||||||
% parcours.SESSION_NAME,
|
% parcours.SESSION_NAME,
|
||||||
"labels": [str(x) for x in semestres_indices],
|
"labels": [str(x) for x in semestres_indices],
|
||||||
@ -204,7 +206,7 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None):
|
|||||||
)
|
)
|
||||||
if parcours.UE_IS_MODULE:
|
if parcours.UE_IS_MODULE:
|
||||||
# dans ce mode, crée un (unique) module dans l'UE:
|
# dans ce mode, crée un (unique) module dans l'UE:
|
||||||
module_id = context.do_module_create(
|
_ = context.do_module_create(
|
||||||
{
|
{
|
||||||
"titre": tf[2]["titre"],
|
"titre": tf[2]["titre"],
|
||||||
"code": tf[2]["acronyme"],
|
"code": tf[2]["acronyme"],
|
||||||
@ -217,9 +219,9 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None):
|
|||||||
REQUEST,
|
REQUEST,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
ue_id = do_ue_edit(context, tf[2])
|
do_ue_edit(context, tf[2])
|
||||||
return REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
REQUEST.URL1 + "/ue_list?formation_id=" + formation_id
|
context.NotesURL() + "/ue_list?formation_id=" + formation_id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -306,15 +308,15 @@ def ue_list(context, formation_id=None, msg="", REQUEST=None):
|
|||||||
editable = perm_change
|
editable = perm_change
|
||||||
tag_editable = authuser.has_permission(ScoEditFormationTags, context) or perm_change
|
tag_editable = authuser.has_permission(ScoEditFormationTags, context) or perm_change
|
||||||
if locked:
|
if locked:
|
||||||
lockicon = icontag("lock32_img", title="verrouillé")
|
lockicon = scu.icontag("lock32_img", title="verrouillé")
|
||||||
else:
|
else:
|
||||||
lockicon = ""
|
lockicon = ""
|
||||||
|
|
||||||
arrow_up, arrow_down, arrow_none = sco_groups.getArrowIconsTags(context, REQUEST)
|
arrow_up, arrow_down, arrow_none = sco_groups.getArrowIconsTags(context, REQUEST)
|
||||||
delete_icon = icontag(
|
delete_icon = scu.icontag(
|
||||||
"delete_small_img", title="Supprimer (module inutilisé)", alt="supprimer"
|
"delete_small_img", title="Supprimer (module inutilisé)", alt="supprimer"
|
||||||
)
|
)
|
||||||
delete_disabled_icon = icontag(
|
delete_disabled_icon = scu.icontag(
|
||||||
"delete_small_dis_img", title="Suppression impossible (module utilisé)"
|
"delete_small_dis_img", title="Suppression impossible (module utilisé)"
|
||||||
)
|
)
|
||||||
H = [
|
H = [
|
||||||
@ -415,7 +417,7 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module
|
|||||||
klass = ""
|
klass = ""
|
||||||
UE["code_apogee_str"] = (
|
UE["code_apogee_str"] = (
|
||||||
""", Apo: <span class="%s" data-url="edit_ue_set_code_apogee" id="%s" data-placeholder="%s">"""
|
""", Apo: <span class="%s" data-url="edit_ue_set_code_apogee" id="%s" data-placeholder="%s">"""
|
||||||
% (klass, UE["ue_id"], APO_MISSING_CODE_STR)
|
% (klass, UE["ue_id"], scu.APO_MISSING_CODE_STR)
|
||||||
+ (UE["code_apogee"] or "")
|
+ (UE["code_apogee"] or "")
|
||||||
+ "</span>"
|
+ "</span>"
|
||||||
)
|
)
|
||||||
@ -424,7 +426,7 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module
|
|||||||
cur_ue_semestre_id = UE["semestre_id"]
|
cur_ue_semestre_id = UE["semestre_id"]
|
||||||
if iue > 0:
|
if iue > 0:
|
||||||
H.append("</ul>")
|
H.append("</ul>")
|
||||||
if UE["semestre_id"] == UE_SEM_DEFAULT:
|
if UE["semestre_id"] == sco_codes_parcours.UE_SEM_DEFAULT:
|
||||||
lab = "Pas d'indication de semestre:"
|
lab = "Pas d'indication de semestre:"
|
||||||
else:
|
else:
|
||||||
lab = "Semestre %s:" % UE["semestre_id"]
|
lab = "Semestre %s:" % UE["semestre_id"]
|
||||||
@ -456,8 +458,11 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module
|
|||||||
% UE
|
% UE
|
||||||
)
|
)
|
||||||
|
|
||||||
if UE["type"] != UE_STANDARD:
|
if UE["type"] != sco_codes_parcours.UE_STANDARD:
|
||||||
H.append('<span class="ue_type">%s</span>' % UE_TYPE_NAME[UE["type"]])
|
H.append(
|
||||||
|
'<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 context.ue_is_locked(UE["ue_id"])
|
||||||
if ue_editable:
|
if ue_editable:
|
||||||
H.append(
|
H.append(
|
||||||
@ -488,7 +493,7 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module
|
|||||||
Mod["module_id"]
|
Mod["module_id"]
|
||||||
)
|
)
|
||||||
klass = "notes_module_list"
|
klass = "notes_module_list"
|
||||||
if Mod["module_type"] == MODULE_MALUS:
|
if Mod["module_type"] == scu.MODULE_MALUS:
|
||||||
klass += " module_malus"
|
klass += " module_malus"
|
||||||
H.append('<li class="%s">' % klass)
|
H.append('<li class="%s">' % klass)
|
||||||
|
|
||||||
@ -527,7 +532,7 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module
|
|||||||
)
|
)
|
||||||
H.append(
|
H.append(
|
||||||
'<span class="formation_module_tit">%s</span>'
|
'<span class="formation_module_tit">%s</span>'
|
||||||
% join_words(Mod["code"], Mod["titre"])
|
% scu.join_words(Mod["code"], Mod["titre"])
|
||||||
)
|
)
|
||||||
if mod_editable:
|
if mod_editable:
|
||||||
H.append("</a>")
|
H.append("</a>")
|
||||||
@ -541,7 +546,7 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module
|
|||||||
klass = ""
|
klass = ""
|
||||||
heurescoef += (
|
heurescoef += (
|
||||||
', Apo: <span class="%s" data-url="edit_module_set_code_apogee" id="%s" data-placeholder="%s">'
|
', Apo: <span class="%s" data-url="edit_module_set_code_apogee" id="%s" data-placeholder="%s">'
|
||||||
% (klass, Mod["module_id"], APO_MISSING_CODE_STR)
|
% (klass, Mod["module_id"], scu.APO_MISSING_CODE_STR)
|
||||||
+ (Mod["code_apogee"] or "")
|
+ (Mod["code_apogee"] or "")
|
||||||
+ "</span>"
|
+ "</span>"
|
||||||
)
|
)
|
||||||
@ -658,9 +663,7 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module
|
|||||||
)
|
)
|
||||||
# <li>(debug) <a class="stdlink" href="check_form_integrity?formation_id=%(formation_id)s">Vérifier cohérence</a></li>
|
# <li>(debug) <a class="stdlink" href="check_form_integrity?formation_id=%(formation_id)s">Vérifier cohérence</a></li>
|
||||||
|
|
||||||
warn, ue_multiples = sco_formsemestre_validation.check_formation_ues(
|
warn, _ = sco_formsemestre_validation.check_formation_ues(context, formation_id)
|
||||||
context, formation_id
|
|
||||||
)
|
|
||||||
H.append(warn)
|
H.append(warn)
|
||||||
|
|
||||||
H.append(context.sco_footer(REQUEST))
|
H.append(context.sco_footer(REQUEST))
|
||||||
@ -764,7 +767,6 @@ def edit_ue_set_code_apogee(context, id=None, value=None, REQUEST=None):
|
|||||||
ues = context.do_ue_list(args={"ue_id": ue_id})
|
ues = context.do_ue_list(args={"ue_id": ue_id})
|
||||||
if not ues:
|
if not ues:
|
||||||
return "ue invalide"
|
return "ue invalide"
|
||||||
ue = ues[0]
|
|
||||||
|
|
||||||
do_ue_edit(
|
do_ue_edit(
|
||||||
context,
|
context,
|
||||||
@ -773,7 +775,7 @@ def edit_ue_set_code_apogee(context, id=None, value=None, REQUEST=None):
|
|||||||
dont_invalidate_cache=False,
|
dont_invalidate_cache=False,
|
||||||
)
|
)
|
||||||
if not value:
|
if not value:
|
||||||
value = APO_MISSING_CODE_STR
|
value = scu.APO_MISSING_CODE_STR
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
@ -845,7 +847,9 @@ def formation_table_recap(context, formation_id, format="html", REQUEST=None):
|
|||||||
columns_ids=columns_ids,
|
columns_ids=columns_ids,
|
||||||
rows=T,
|
rows=T,
|
||||||
titles=titles,
|
titles=titles,
|
||||||
origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "",
|
origin="Généré par %s le " % scu.VERSION.SCONAME
|
||||||
|
+ scu.timedate_human_repr()
|
||||||
|
+ "",
|
||||||
caption=title,
|
caption=title,
|
||||||
html_caption=title,
|
html_caption=title,
|
||||||
html_class="table_leftalign",
|
html_class="table_leftalign",
|
||||||
|
@ -36,8 +36,10 @@ XXX incompatible avec les ics HyperPlanning Paris 13 (était pour GPU).
|
|||||||
import urllib2
|
import urllib2
|
||||||
import traceback
|
import traceback
|
||||||
import icalendar
|
import icalendar
|
||||||
|
import pprint
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
|
from notes_log import log
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_groups
|
import sco_groups
|
||||||
import sco_groups_view
|
import sco_groups_view
|
||||||
@ -84,10 +86,10 @@ def formsemestre_load_ics(context, sem):
|
|||||||
return cal
|
return cal
|
||||||
|
|
||||||
|
|
||||||
def formsemestre_edt_groups_used(context, sem):
|
# def formsemestre_edt_groups_used(context, sem):
|
||||||
"""L'ensemble des groupes EDT utilisés dans l'emplois du temps publié"""
|
# """L'ensemble des groupes EDT utilisés dans l'emploi du temps publié"""
|
||||||
cal = formsemestre_load_ics(context, sem)
|
# cal = formsemestre_load_ics(context, sem)
|
||||||
return {e["X-GROUP-ID"].decode("utf8") for e in events}
|
# return {e["X-GROUP-ID"].decode("utf8") for e in events}
|
||||||
|
|
||||||
|
|
||||||
def get_edt_transcodage_groups(context, formsemestre_id):
|
def get_edt_transcodage_groups(context, formsemestre_id):
|
||||||
@ -147,7 +149,7 @@ def group_edt_json(context, group_id, start="", end="", REQUEST=None):
|
|||||||
}
|
}
|
||||||
J.append(d)
|
J.append(d)
|
||||||
|
|
||||||
return sendJSON(REQUEST, J)
|
return scu.sendJSON(REQUEST, J)
|
||||||
|
|
||||||
|
|
||||||
"""XXX
|
"""XXX
|
||||||
|
@ -75,7 +75,9 @@
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from sco_utils import *
|
import re
|
||||||
|
|
||||||
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import notes_table
|
import notes_table
|
||||||
@ -83,6 +85,7 @@ import sco_groups
|
|||||||
import sco_groups_view
|
import sco_groups_view
|
||||||
import sco_archives
|
import sco_archives
|
||||||
import sco_apogee_csv
|
import sco_apogee_csv
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
|
||||||
|
|
||||||
class ApoCSVArchiver(sco_archives.BaseArchiver):
|
class ApoCSVArchiver(sco_archives.BaseArchiver):
|
||||||
@ -110,7 +113,7 @@ def apo_csv_store(context, csv_data, annee_scolaire, sem_id):
|
|||||||
"""
|
"""
|
||||||
# sanity check
|
# sanity check
|
||||||
filesize = len(csv_data)
|
filesize = len(csv_data)
|
||||||
if filesize < 10 or filesize > CONFIG.ETUD_MAX_FILE_SIZE:
|
if filesize < 10 or filesize > scu.CONFIG.ETUD_MAX_FILE_SIZE:
|
||||||
raise ScoValueError("Fichier csv de taille invalide ! (%d)" % filesize)
|
raise ScoValueError("Fichier csv de taille invalide ! (%d)" % filesize)
|
||||||
|
|
||||||
if not annee_scolaire:
|
if not annee_scolaire:
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_formsemestre_status
|
import sco_formsemestre_status
|
||||||
@ -43,6 +43,7 @@ import sco_apogee_csv
|
|||||||
import sco_portal_apogee
|
import sco_portal_apogee
|
||||||
from sco_apogee_csv import APO_PORTAL_ENCODING, APO_INPUT_ENCODING
|
from sco_apogee_csv import APO_PORTAL_ENCODING, APO_INPUT_ENCODING
|
||||||
import sco_archives
|
import sco_archives
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
|
||||||
|
|
||||||
def apo_semset_maq_status(
|
def apo_semset_maq_status(
|
||||||
@ -447,7 +448,7 @@ def table_apo_csv_list(context, semset, REQUEST=None):
|
|||||||
)
|
)
|
||||||
t["_filename_target"] = view_link
|
t["_filename_target"] = view_link
|
||||||
t["_etape_apo_target"] = view_link
|
t["_etape_apo_target"] = view_link
|
||||||
t["suppress"] = icontag(
|
t["suppress"] = scu.icontag(
|
||||||
"delete_small_img", border="0", alt="supprimer", title="Supprimer"
|
"delete_small_img", border="0", alt="supprimer", title="Supprimer"
|
||||||
)
|
)
|
||||||
t["_suppress_target"] = "view_apo_csv_delete?etape_apo=%s&semset_id=%s" % (
|
t["_suppress_target"] = "view_apo_csv_delete?etape_apo=%s&semset_id=%s" % (
|
||||||
@ -484,8 +485,8 @@ def view_apo_etuds(context, semset_id, title="", nips=[], format="html", REQUEST
|
|||||||
if not semset_id:
|
if not semset_id:
|
||||||
raise ValueError("invalid null semset_id")
|
raise ValueError("invalid null semset_id")
|
||||||
semset = sco_semset.SemSet(context, semset_id=semset_id)
|
semset = sco_semset.SemSet(context, semset_id=semset_id)
|
||||||
annee_scolaire = semset["annee_scolaire"]
|
# annee_scolaire = semset["annee_scolaire"]
|
||||||
sem_id = semset["sem_id"]
|
# sem_id = semset["sem_id"]
|
||||||
|
|
||||||
if nips and type(nips) != type([]):
|
if nips and type(nips) != type([]):
|
||||||
nips = [nips]
|
nips = [nips]
|
||||||
@ -686,7 +687,7 @@ def view_apo_csv(context, etape_apo="", semset_id="", format="html", REQUEST=Non
|
|||||||
sem_id = semset["sem_id"]
|
sem_id = semset["sem_id"]
|
||||||
csv_data = sco_etape_apogee.apo_csv_get(context, etape_apo, annee_scolaire, sem_id)
|
csv_data = sco_etape_apogee.apo_csv_get(context, etape_apo, annee_scolaire, sem_id)
|
||||||
if format == "raw":
|
if format == "raw":
|
||||||
return sendCSVFile(REQUEST, csv_data, etape_apo + ".txt")
|
return scu.sendCSVFile(REQUEST, csv_data, etape_apo + ".txt")
|
||||||
apo_data = sco_apogee_csv.ApoData(csv_data, periode=semset["sem_id"])
|
apo_data = sco_apogee_csv.ApoData(csv_data, periode=semset["sem_id"])
|
||||||
|
|
||||||
(
|
(
|
||||||
@ -838,7 +839,7 @@ def apo_csv_export_results(
|
|||||||
+ "-%s-" % periode
|
+ "-%s-" % periode
|
||||||
+ "-".join(etapes_apo)
|
+ "-".join(etapes_apo)
|
||||||
)
|
)
|
||||||
basename = sco_archives.sanitize_filename(unescape_html(basename))
|
basename = scu.sanitize_filename(scu.unescape_html(basename))
|
||||||
|
|
||||||
dest_zip.close()
|
dest_zip.close()
|
||||||
size = data.tell()
|
size = data.tell()
|
||||||
|
@ -90,6 +90,7 @@ l'inscrition de semestres décalés (S1 en septembre, ...).
|
|||||||
Le filtrage s'effctue sur la date et non plus sur la parité du semestre (1-3/2-4).
|
Le filtrage s'effctue sur la date et non plus sur la parité du semestre (1-3/2-4).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
from sco_portal_apogee import get_inscrits_etape
|
from sco_portal_apogee import get_inscrits_etape
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
@ -540,7 +541,7 @@ class EtapeBilan:
|
|||||||
ind_col,
|
ind_col,
|
||||||
comptage,
|
comptage,
|
||||||
"",
|
"",
|
||||||
self.titres[ind_col].replace("<br/>", " / "),
|
json.dumps(self.titres[ind_col].replace("<br/>", " / "))[1:-1],
|
||||||
)
|
)
|
||||||
elif ind_col == COL_CUMUL:
|
elif ind_col == COL_CUMUL:
|
||||||
javascript = "doFiltrage(%s, %s, '.%s', '*', '%s', '%s', '%s');" % (
|
javascript = "doFiltrage(%s, %s, '.%s', '*', '%s', '%s', '%s');" % (
|
||||||
@ -548,7 +549,7 @@ class EtapeBilan:
|
|||||||
self.all_cols_str,
|
self.all_cols_str,
|
||||||
ind_row,
|
ind_row,
|
||||||
" (%d étudiants)" % count,
|
" (%d étudiants)" % count,
|
||||||
self.titres[ind_row],
|
json.dumps(self.titres[ind_row])[1:-1],
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -558,10 +559,10 @@ class EtapeBilan:
|
|||||||
ind_row,
|
ind_row,
|
||||||
ind_col,
|
ind_col,
|
||||||
comptage,
|
comptage,
|
||||||
self.titres[ind_row],
|
json.dumps(self.titres[ind_row])[1:-1],
|
||||||
self.titres[ind_col].replace("<br/>", " / "),
|
json.dumps(self.titres[ind_col].replace("<br/>", " / "))[1:-1],
|
||||||
)
|
)
|
||||||
return "<a href='#synthese' onclick=\"%s\">%d</a>" % (javascript, count)
|
return '<a href="#synthese" onclick="%s">%d</a>' % (javascript, count)
|
||||||
|
|
||||||
def _diagtable(self):
|
def _diagtable(self):
|
||||||
H = []
|
H = []
|
||||||
|
81
sco_excel.py
81
sco_excel.py
@ -33,8 +33,9 @@ from pyExcelerator import *
|
|||||||
|
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from scolog import logdb
|
from scolog import logdb
|
||||||
from sco_exceptions import *
|
|
||||||
from sco_utils import *
|
from sco_exceptions import ScoValueError
|
||||||
|
import sco_utils as scu
|
||||||
import notesdb
|
import notesdb
|
||||||
|
|
||||||
import time, datetime
|
import time, datetime
|
||||||
@ -57,9 +58,11 @@ def sendExcelFile(REQUEST, data, filename):
|
|||||||
(on ne doit rien avoir émis avant, car ici sont générés les entetes)
|
(on ne doit rien avoir émis avant, car ici sont générés les entetes)
|
||||||
"""
|
"""
|
||||||
filename = (
|
filename = (
|
||||||
unescape_html(suppress_accents(filename)).replace("&", "").replace(" ", "_")
|
scu.unescape_html(scu.suppress_accents(filename))
|
||||||
|
.replace("&", "")
|
||||||
|
.replace(" ", "_")
|
||||||
)
|
)
|
||||||
REQUEST.RESPONSE.setHeader("content-type", XLS_MIMETYPE)
|
REQUEST.RESPONSE.setHeader("content-type", scu.XLS_MIMETYPE)
|
||||||
REQUEST.RESPONSE.setHeader(
|
REQUEST.RESPONSE.setHeader(
|
||||||
"content-disposition", 'attachment; filename="%s"' % filename
|
"content-disposition", 'attachment; filename="%s"' % filename
|
||||||
)
|
)
|
||||||
@ -216,7 +219,7 @@ class ScoExcelSheet:
|
|||||||
sauvegarde = True
|
sauvegarde = True
|
||||||
else:
|
else:
|
||||||
sauvegarde = False
|
sauvegarde = False
|
||||||
ws0 = wb.add_sheet(self.sheet_name.decode(SCO_ENCODING))
|
ws0 = wb.add_sheet(self.sheet_name.decode(scu.SCO_ENCODING))
|
||||||
li = 0
|
li = 0
|
||||||
for l in self.cells:
|
for l in self.cells:
|
||||||
co = 0
|
co = 0
|
||||||
@ -225,7 +228,7 @@ class ScoExcelSheet:
|
|||||||
if type(c) == LongType:
|
if type(c) == LongType:
|
||||||
c = int(c) # assume all ScoDoc longs fits in int !
|
c = int(c) # assume all ScoDoc longs fits in int !
|
||||||
elif type(c) not in (IntType, FloatType):
|
elif type(c) not in (IntType, FloatType):
|
||||||
c = str(c).decode(SCO_ENCODING)
|
c = str(c).decode(scu.SCO_ENCODING)
|
||||||
|
|
||||||
ws0.write(li, co, c, self.get_cell_style(li, co))
|
ws0.write(li, co, c, self.get_cell_style(li, co))
|
||||||
co += 1
|
co += 1
|
||||||
@ -240,14 +243,14 @@ def Excel_SimpleTable(titles=[], lines=[[]], SheetName="feuille", titlesStyles=[
|
|||||||
"""Export simple type 'CSV': 1ere ligne en gras, le reste tel quel"""
|
"""Export simple type 'CSV': 1ere ligne en gras, le reste tel quel"""
|
||||||
# XXX devrait maintenant utiliser ScoExcelSheet
|
# XXX devrait maintenant utiliser ScoExcelSheet
|
||||||
wb = Workbook()
|
wb = Workbook()
|
||||||
ws0 = wb.add_sheet(SheetName.decode(SCO_ENCODING))
|
ws0 = wb.add_sheet(SheetName.decode(scu.SCO_ENCODING))
|
||||||
if not titlesStyles:
|
if not titlesStyles:
|
||||||
style = Excel_MakeStyle(bold=True)
|
style = Excel_MakeStyle(bold=True)
|
||||||
titlesStyles = [style] * len(titles)
|
titlesStyles = [style] * len(titles)
|
||||||
# ligne de titres
|
# ligne de titres
|
||||||
col = 0
|
col = 0
|
||||||
for it in titles:
|
for it in titles:
|
||||||
ws0.write(0, col, it.decode(SCO_ENCODING), titlesStyles[col])
|
ws0.write(0, col, it.decode(scu.SCO_ENCODING), titlesStyles[col])
|
||||||
col += 1
|
col += 1
|
||||||
# suite
|
# suite
|
||||||
default_style = Excel_MakeStyle()
|
default_style = Excel_MakeStyle()
|
||||||
@ -262,7 +265,7 @@ def Excel_SimpleTable(titles=[], lines=[[]], SheetName="feuille", titlesStyles=[
|
|||||||
if type(it) == LongType:
|
if type(it) == LongType:
|
||||||
it = int(it) # assume all ScoDoc longs fits in int !
|
it = int(it) # assume all ScoDoc longs fits in int !
|
||||||
elif type(it) not in (IntType, FloatType):
|
elif type(it) not in (IntType, FloatType):
|
||||||
it = str(it).decode(SCO_ENCODING)
|
it = str(it).decode(scu.SCO_ENCODING)
|
||||||
cell_style = text_style
|
cell_style = text_style
|
||||||
ws0.write(li, col, it, cell_style)
|
ws0.write(li, col, it, cell_style)
|
||||||
col += 1
|
col += 1
|
||||||
@ -279,7 +282,7 @@ def Excel_feuille_saisie(E, titreannee, description, lines):
|
|||||||
"""
|
"""
|
||||||
SheetName = "Saisie notes"
|
SheetName = "Saisie notes"
|
||||||
wb = Workbook()
|
wb = Workbook()
|
||||||
ws0 = wb.add_sheet(SheetName.decode(SCO_ENCODING))
|
ws0 = wb.add_sheet(SheetName.decode(scu.SCO_ENCODING))
|
||||||
# ajuste largeurs colonnes (unite inconnue, empirique)
|
# ajuste largeurs colonnes (unite inconnue, empirique)
|
||||||
ws0.col(0).width = 400 # codes
|
ws0.col(0).width = 400 # codes
|
||||||
ws0.col(1).width = 6000 # noms
|
ws0.col(1).width = 6000 # noms
|
||||||
@ -366,10 +369,14 @@ def Excel_feuille_saisie(E, titreannee, description, lines):
|
|||||||
ws0.write(li, 0, u"Ne pas modifier les cases en mauve !", style_expl)
|
ws0.write(li, 0, u"Ne pas modifier les cases en mauve !", style_expl)
|
||||||
li += 1
|
li += 1
|
||||||
# Nom du semestre
|
# Nom du semestre
|
||||||
ws0.write(li, 0, unescape_html(titreannee).decode(SCO_ENCODING), style_titres)
|
ws0.write(
|
||||||
|
li, 0, scu.unescape_html(titreannee).decode(scu.SCO_ENCODING), style_titres
|
||||||
|
)
|
||||||
li += 1
|
li += 1
|
||||||
# description evaluation
|
# description evaluation
|
||||||
ws0.write(li, 0, unescape_html(description).decode(SCO_ENCODING), style_titres)
|
ws0.write(
|
||||||
|
li, 0, scu.unescape_html(description).decode(scu.SCO_ENCODING), style_titres
|
||||||
|
)
|
||||||
li += 1
|
li += 1
|
||||||
ws0.write(
|
ws0.write(
|
||||||
li, 0, u"Evaluation du %s (coef. %g)" % (E["jour"], E["coefficient"]), style
|
li, 0, u"Evaluation du %s (coef. %g)" % (E["jour"], E["coefficient"]), style
|
||||||
@ -387,7 +394,7 @@ def Excel_feuille_saisie(E, titreannee, description, lines):
|
|||||||
for line in lines:
|
for line in lines:
|
||||||
li += 1
|
li += 1
|
||||||
st = style_nom
|
st = style_nom
|
||||||
ws0.write(li, 0, ("!" + line[0]).decode(SCO_ENCODING), style_ro) # code
|
ws0.write(li, 0, ("!" + line[0]).decode(scu.SCO_ENCODING), style_ro) # code
|
||||||
if line[3] != "I":
|
if line[3] != "I":
|
||||||
st = style_dem
|
st = style_dem
|
||||||
if line[3] == "D": # demissionnaire
|
if line[3] == "D": # demissionnaire
|
||||||
@ -396,15 +403,15 @@ def Excel_feuille_saisie(E, titreannee, description, lines):
|
|||||||
s = line[3] # etat autre
|
s = line[3] # etat autre
|
||||||
else:
|
else:
|
||||||
s = line[4] # groupes TD/TP/...
|
s = line[4] # groupes TD/TP/...
|
||||||
ws0.write(li, 1, line[1].decode(SCO_ENCODING), st)
|
ws0.write(li, 1, line[1].decode(scu.SCO_ENCODING), st)
|
||||||
ws0.write(li, 2, line[2].decode(SCO_ENCODING), st)
|
ws0.write(li, 2, line[2].decode(scu.SCO_ENCODING), st)
|
||||||
ws0.write(li, 3, s.decode(SCO_ENCODING), st)
|
ws0.write(li, 3, s.decode(scu.SCO_ENCODING), st)
|
||||||
try:
|
try:
|
||||||
val = float(line[5])
|
val = float(line[5])
|
||||||
except:
|
except:
|
||||||
val = line[5].decode(SCO_ENCODING)
|
val = line[5].decode(scu.SCO_ENCODING)
|
||||||
ws0.write(li, 4, val, style_notes) # note
|
ws0.write(li, 4, val, style_notes) # note
|
||||||
ws0.write(li, 5, line[6].decode(SCO_ENCODING), style_comment) # comment
|
ws0.write(li, 5, line[6].decode(scu.SCO_ENCODING), style_comment) # comment
|
||||||
# explication en bas
|
# explication en bas
|
||||||
li += 2
|
li += 2
|
||||||
ws0.write(li, 1, u"Code notes", style_titres)
|
ws0.write(li, 1, u"Code notes", style_titres)
|
||||||
@ -426,7 +433,7 @@ def Excel_to_list(data, convert_to_string=str): # we may need 'encoding' argume
|
|||||||
convert_to_string is a conversion function applied to all non-string values (ie numbers)
|
convert_to_string is a conversion function applied to all non-string values (ie numbers)
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
P = parse_xls("", SCO_ENCODING, doc=data)
|
P = parse_xls("", scu.SCO_ENCODING, doc=data)
|
||||||
except:
|
except:
|
||||||
log("Excel_to_list: failure to import document")
|
log("Excel_to_list: failure to import document")
|
||||||
open("/tmp/last_scodoc_import_failure.xls", "w").write(data)
|
open("/tmp/last_scodoc_import_failure.xls", "w").write(data)
|
||||||
@ -443,7 +450,7 @@ def Excel_to_list(data, convert_to_string=str): # we may need 'encoding' argume
|
|||||||
diag.append("Attention: n'utilise que la première feuille du classeur !")
|
diag.append("Attention: n'utilise que la première feuille du classeur !")
|
||||||
# fill matrix
|
# fill matrix
|
||||||
sheet_name, values = P[0]
|
sheet_name, values = P[0]
|
||||||
sheet_name = sheet_name.encode(SCO_ENCODING, "backslashreplace")
|
sheet_name = sheet_name.encode(scu.SCO_ENCODING, "backslashreplace")
|
||||||
if not values:
|
if not values:
|
||||||
diag.append("Aucune valeur trouvée dans le classeur !")
|
diag.append("Aucune valeur trouvée dans le classeur !")
|
||||||
return diag, None
|
return diag, None
|
||||||
@ -454,13 +461,13 @@ def Excel_to_list(data, convert_to_string=str): # we may need 'encoding' argume
|
|||||||
nbcols = max(cols) + 1
|
nbcols = max(cols) + 1
|
||||||
nbrows = max(rows) + 1
|
nbrows = max(rows) + 1
|
||||||
M = []
|
M = []
|
||||||
for i in range(nbrows):
|
for _ in range(nbrows):
|
||||||
M.append([""] * nbcols)
|
M.append([""] * nbcols)
|
||||||
|
|
||||||
for row_idx, col_idx in indexes:
|
for row_idx, col_idx in indexes:
|
||||||
v = values[(row_idx, col_idx)]
|
v = values[(row_idx, col_idx)]
|
||||||
if isinstance(v, unicode):
|
if isinstance(v, unicode):
|
||||||
v = v.encode(SCO_ENCODING, "backslashreplace")
|
v = v.encode(scu.SCO_ENCODING, "backslashreplace")
|
||||||
elif convert_to_string:
|
elif convert_to_string:
|
||||||
v = convert_to_string(v)
|
v = convert_to_string(v)
|
||||||
M[row_idx][col_idx] = v
|
M[row_idx][col_idx] = v
|
||||||
@ -485,7 +492,7 @@ def Excel_feuille_listeappel(
|
|||||||
formsemestre_id = sem["formsemestre_id"]
|
formsemestre_id = sem["formsemestre_id"]
|
||||||
SheetName = "Liste " + groupname
|
SheetName = "Liste " + groupname
|
||||||
wb = Workbook()
|
wb = Workbook()
|
||||||
ws0 = wb.add_sheet(SheetName.decode(SCO_ENCODING))
|
ws0 = wb.add_sheet(SheetName.decode(scu.SCO_ENCODING))
|
||||||
|
|
||||||
font1 = Font()
|
font1 = Font()
|
||||||
font1.name = "Arial"
|
font1.name = "Arial"
|
||||||
@ -569,7 +576,7 @@ def Excel_feuille_listeappel(
|
|||||||
sem["date_debut"],
|
sem["date_debut"],
|
||||||
sem["date_fin"],
|
sem["date_fin"],
|
||||||
)
|
)
|
||||||
).decode(SCO_ENCODING),
|
).decode(scu.SCO_ENCODING),
|
||||||
style2,
|
style2,
|
||||||
)
|
)
|
||||||
# ligne 2
|
# ligne 2
|
||||||
@ -578,7 +585,7 @@ def Excel_feuille_listeappel(
|
|||||||
# ligne 3
|
# ligne 3
|
||||||
li += 1
|
li += 1
|
||||||
ws0.write(li, 1, u"Enseignant :", style2)
|
ws0.write(li, 1, u"Enseignant :", style2)
|
||||||
ws0.write(li, 5, ("Groupe %s" % groupname).decode(SCO_ENCODING), style3)
|
ws0.write(li, 5, ("Groupe %s" % groupname).decode(scu.SCO_ENCODING), style3)
|
||||||
# Avertissement pour ne pas confondre avec listes notes
|
# Avertissement pour ne pas confondre avec listes notes
|
||||||
ws0.write(
|
ws0.write(
|
||||||
li + 1, 2, u"Ne pas utiliser cette feuille pour saisir les notes !", style1i
|
li + 1, 2, u"Ne pas utiliser cette feuille pour saisir les notes !", style1i
|
||||||
@ -590,7 +597,9 @@ def Excel_feuille_listeappel(
|
|||||||
co = 2
|
co = 2
|
||||||
for partition in partitions:
|
for partition in partitions:
|
||||||
if partition["partition_name"]:
|
if partition["partition_name"]:
|
||||||
ws0.write(li, co, partition["partition_name"].decode(SCO_ENCODING), style3)
|
ws0.write(
|
||||||
|
li, co, partition["partition_name"].decode(scu.SCO_ENCODING), style3
|
||||||
|
)
|
||||||
co += 1
|
co += 1
|
||||||
if with_codes:
|
if with_codes:
|
||||||
coc = co
|
coc = co
|
||||||
@ -607,7 +616,11 @@ def Excel_feuille_listeappel(
|
|||||||
li += 1
|
li += 1
|
||||||
ws0.write(li, 0, n, style1b)
|
ws0.write(li, 0, n, style1b)
|
||||||
nomprenom = (
|
nomprenom = (
|
||||||
t["sexe"] + " " + t["nom"] + " " + strcapitalize(strlower(t["prenom"]))
|
t["civilite_str"]
|
||||||
|
+ " "
|
||||||
|
+ t["nom"]
|
||||||
|
+ " "
|
||||||
|
+ scu.strcapitalize(scu.strlower(t["prenom"]))
|
||||||
)
|
)
|
||||||
style_nom = style2t3
|
style_nom = style2t3
|
||||||
if with_paiement:
|
if with_paiement:
|
||||||
@ -618,31 +631,31 @@ def Excel_feuille_listeappel(
|
|||||||
elif not paie:
|
elif not paie:
|
||||||
nomprenom += " (non paiement)"
|
nomprenom += " (non paiement)"
|
||||||
style_nom = style2t3bold
|
style_nom = style2t3bold
|
||||||
ws0.write(li, 1, nomprenom.decode(SCO_ENCODING), style_nom)
|
ws0.write(li, 1, nomprenom.decode(scu.SCO_ENCODING), style_nom)
|
||||||
co = 2
|
co = 2
|
||||||
for partition in partitions:
|
for partition in partitions:
|
||||||
if partition["partition_name"]:
|
if partition["partition_name"]:
|
||||||
ws0.write(
|
ws0.write(
|
||||||
li,
|
li,
|
||||||
co,
|
co,
|
||||||
t.get(partition["partition_id"], "").decode(SCO_ENCODING),
|
t.get(partition["partition_id"], "").decode(scu.SCO_ENCODING),
|
||||||
style2t3,
|
style2t3,
|
||||||
)
|
)
|
||||||
co += 1
|
co += 1
|
||||||
if with_codes:
|
if with_codes:
|
||||||
ws0.write(li, coc, t["etudid"].decode(SCO_ENCODING), style2t3)
|
ws0.write(li, coc, t["etudid"].decode(scu.SCO_ENCODING), style2t3)
|
||||||
if t["code_nip"]:
|
if t["code_nip"]:
|
||||||
code_nip = t["code_nip"].decode(SCO_ENCODING)
|
code_nip = t["code_nip"].decode(scu.SCO_ENCODING)
|
||||||
else:
|
else:
|
||||||
code_nip = u""
|
code_nip = u""
|
||||||
ws0.write(li, coc + 1, code_nip, style2t3)
|
ws0.write(li, coc + 1, code_nip, style2t3)
|
||||||
if t["code_ine"]:
|
if t["code_ine"]:
|
||||||
code_ine = t["code_ine"].decode(SCO_ENCODING)
|
code_ine = t["code_ine"].decode(scu.SCO_ENCODING)
|
||||||
else:
|
else:
|
||||||
code_ine = u""
|
code_ine = u""
|
||||||
ws0.write(li, coc + 2, code_ine, style2t3)
|
ws0.write(li, coc + 2, code_ine, style2t3)
|
||||||
if t["etath"]:
|
if t["etath"]:
|
||||||
etath = t["etath"].decode(SCO_ENCODING)
|
etath = t["etath"].decode(scu.SCO_ENCODING)
|
||||||
else:
|
else:
|
||||||
etath = u""
|
etath = u""
|
||||||
ws0.write(li, co, etath, style2b) # etat
|
ws0.write(li, co, etath, style2b) # etat
|
||||||
@ -654,7 +667,7 @@ def Excel_feuille_listeappel(
|
|||||||
dt = time.strftime("%d/%m/%Y à %Hh%M")
|
dt = time.strftime("%d/%m/%Y à %Hh%M")
|
||||||
if server_name:
|
if server_name:
|
||||||
dt += " sur " + server_name
|
dt += " sur " + server_name
|
||||||
ws0.write(li, 1, ("Liste éditée le " + dt).decode(SCO_ENCODING), style1i)
|
ws0.write(li, 1, ("Liste éditée le " + dt).decode(scu.SCO_ENCODING), style1i)
|
||||||
#
|
#
|
||||||
ws0.col(0).width = 850
|
ws0.col(0).width = 850
|
||||||
ws0.col(1).width = 9000
|
ws0.col(1).width = 9000
|
||||||
|
@ -27,7 +27,11 @@
|
|||||||
|
|
||||||
"""Export d'une table avec les résultats de tous les étudiants
|
"""Export d'une table avec les résultats de tous les étudiants
|
||||||
"""
|
"""
|
||||||
|
from types import ListType
|
||||||
|
|
||||||
|
import notesdb as ndb
|
||||||
|
import sco_utils as scu
|
||||||
|
from notes_log import log
|
||||||
import scolars
|
import scolars
|
||||||
import sco_bac
|
import sco_bac
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
@ -35,11 +39,10 @@ import sco_parcours_dut
|
|||||||
import sco_codes_parcours
|
import sco_codes_parcours
|
||||||
from sco_codes_parcours import NO_SEMESTRE_ID
|
from sco_codes_parcours import NO_SEMESTRE_ID
|
||||||
import sco_excel
|
import sco_excel
|
||||||
from notesdb import *
|
|
||||||
from sco_utils import *
|
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
import sco_pvjury
|
import sco_pvjury
|
||||||
import html_sco_header
|
import html_sco_header
|
||||||
|
import VERSION
|
||||||
|
|
||||||
|
|
||||||
def _build_results_table(context, start_date=None, end_date=None, types_parcours=[]):
|
def _build_results_table(context, start_date=None, end_date=None, types_parcours=[]):
|
||||||
@ -96,9 +99,9 @@ def _build_results_table(context, start_date=None, end_date=None, types_parcours
|
|||||||
rows=rows,
|
rows=rows,
|
||||||
titles=titles,
|
titles=titles,
|
||||||
columns_ids=columns_ids,
|
columns_ids=columns_ids,
|
||||||
filename=make_filename("scodoc-results-%s-%s" % (start_date, end_date)),
|
filename=scu.make_filename("scodoc-results-%s-%s" % (start_date, end_date)),
|
||||||
caption="Résultats ScoDoc de %s à %s" % (start_date, end_date),
|
caption="Résultats ScoDoc de %s à %s" % (start_date, end_date),
|
||||||
origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "",
|
origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "",
|
||||||
html_class="table_leftalign",
|
html_class="table_leftalign",
|
||||||
html_sortable=True,
|
html_sortable=True,
|
||||||
preferences=context.get_preferences(),
|
preferences=context.get_preferences(),
|
||||||
@ -119,7 +122,7 @@ def _build_results_list(context, dpv_by_sem, etuds_infos):
|
|||||||
"code_nip": "NIP",
|
"code_nip": "NIP",
|
||||||
"nom": "Nom",
|
"nom": "Nom",
|
||||||
"prenom": "Prénom",
|
"prenom": "Prénom",
|
||||||
"sexe": "Civ.",
|
"civilite_str": "Civ.",
|
||||||
"nom_usuel": "Nom usuel",
|
"nom_usuel": "Nom usuel",
|
||||||
"bac": "Bac",
|
"bac": "Bac",
|
||||||
"parcours": "Parcours",
|
"parcours": "Parcours",
|
||||||
@ -130,7 +133,7 @@ def _build_results_list(context, dpv_by_sem, etuds_infos):
|
|||||||
"periode",
|
"periode",
|
||||||
"sid",
|
"sid",
|
||||||
"code_nip",
|
"code_nip",
|
||||||
"sexe",
|
"civilite_str",
|
||||||
"nom",
|
"nom",
|
||||||
# 'nom_usuel', # inutile ?
|
# 'nom_usuel', # inutile ?
|
||||||
"prenom",
|
"prenom",
|
||||||
@ -168,7 +171,7 @@ def _build_results_list(context, dpv_by_sem, etuds_infos):
|
|||||||
"nom": etud["nom"],
|
"nom": etud["nom"],
|
||||||
"nom_usuel": etud["nom_usuel"],
|
"nom_usuel": etud["nom_usuel"],
|
||||||
"prenom": etud["prenom"],
|
"prenom": etud["prenom"],
|
||||||
"sexe": etud["sexe"],
|
"civilite_str": etud["civilite_str"],
|
||||||
"_nom_target": "%s/ficheEtud?etudid=%s" % (context.ScoURL(), etudid),
|
"_nom_target": "%s/ficheEtud?etudid=%s" % (context.ScoURL(), etudid),
|
||||||
"_nom_td_attrs": 'id="%s" class="etudinfo"' % etudid,
|
"_nom_td_attrs": 'id="%s" class="etudinfo"' % etudid,
|
||||||
"bac": bac.abbrev(),
|
"bac": bac.abbrev(),
|
||||||
@ -189,7 +192,7 @@ def _build_results_list(context, dpv_by_sem, etuds_infos):
|
|||||||
code = "-"
|
code = "-"
|
||||||
r[sem["semestre_id"]] = code
|
r[sem["semestre_id"]] = code
|
||||||
r["periode"] = sem["periode"]
|
r["periode"] = sem["periode"]
|
||||||
r["anneescolaire"] = annee_scolaire_debut(
|
r["anneescolaire"] = scu.annee_scolaire_debut(
|
||||||
int(sem["annee_debut"]), sem["mois_debut_ord"]
|
int(sem["annee_debut"]), sem["mois_debut_ord"]
|
||||||
)
|
)
|
||||||
r["sid"] = "{} {} {}".format(
|
r["sid"] = "{} {} {}".format(
|
||||||
@ -202,7 +205,7 @@ def _build_results_list(context, dpv_by_sem, etuds_infos):
|
|||||||
|
|
||||||
def get_set_formsemestre_id_dates(context, start_date, end_date):
|
def get_set_formsemestre_id_dates(context, start_date, end_date):
|
||||||
"""Ensemble des formsemestre_id entre ces dates"""
|
"""Ensemble des formsemestre_id entre ces dates"""
|
||||||
s = SimpleDictFetch(
|
s = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT formsemestre_id FROM notes_formsemestre WHERE date_debut >= %(start_date)s AND date_fin <= %(end_date)s",
|
"SELECT formsemestre_id FROM notes_formsemestre WHERE date_debut >= %(start_date)s AND date_fin <= %(end_date)s",
|
||||||
{"start_date": start_date, "end_date": end_date},
|
{"start_date": start_date, "end_date": end_date},
|
||||||
@ -224,9 +227,9 @@ def scodoc_table_results(
|
|||||||
if not isinstance(types_parcours, ListType):
|
if not isinstance(types_parcours, ListType):
|
||||||
types_parcours = [types_parcours]
|
types_parcours = [types_parcours]
|
||||||
if start_date:
|
if start_date:
|
||||||
start_date_iso = DateDMYtoISO(start_date)
|
start_date_iso = ndb.DateDMYtoISO(start_date)
|
||||||
if end_date:
|
if end_date:
|
||||||
end_date_iso = DateDMYtoISO(end_date)
|
end_date_iso = ndb.DateDMYtoISO(end_date)
|
||||||
types_parcours = [int(x) for x in types_parcours if x]
|
types_parcours = [int(x) for x in types_parcours if x]
|
||||||
|
|
||||||
if start_date and end_date:
|
if start_date and end_date:
|
||||||
@ -237,7 +240,7 @@ def scodoc_table_results(
|
|||||||
REQUEST.URL0,
|
REQUEST.URL0,
|
||||||
start_date,
|
start_date,
|
||||||
end_date,
|
end_date,
|
||||||
"&types_parcours=".join([str(x) for s in types_parcours]),
|
"&types_parcours=".join([str(x) for x in types_parcours]),
|
||||||
)
|
)
|
||||||
if format != "html":
|
if format != "html":
|
||||||
return tab.make_page(
|
return tab.make_page(
|
||||||
|
@ -27,17 +27,19 @@
|
|||||||
|
|
||||||
"""Recherche d'étudiants
|
"""Recherche d'étudiants
|
||||||
"""
|
"""
|
||||||
|
from types import ListType
|
||||||
from sco_utils import *
|
|
||||||
import xml.dom.minidom
|
import xml.dom.minidom
|
||||||
|
|
||||||
from notesdb import *
|
import sco_utils as scu
|
||||||
|
|
||||||
|
import notesdb as ndb
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
|
|
||||||
import scolars
|
import scolars
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_groups
|
import sco_groups
|
||||||
|
from sco_permissions import ScoView
|
||||||
|
|
||||||
|
|
||||||
def form_search_etud(
|
def form_search_etud(
|
||||||
@ -128,7 +130,7 @@ def search_etud_in_dept(
|
|||||||
if title:
|
if title:
|
||||||
H.append("<h2>%s</h2>" % title)
|
H.append("<h2>%s</h2>" % title)
|
||||||
|
|
||||||
if is_valid_code_nip(expnom):
|
if scu.is_valid_code_nip(expnom):
|
||||||
etuds = search_etuds_infos(context, code_nip=expnom, REQUEST=REQUEST)
|
etuds = search_etuds_infos(context, code_nip=expnom, REQUEST=REQUEST)
|
||||||
elif expnom:
|
elif expnom:
|
||||||
etuds = search_etuds_infos(context, expnom=expnom, REQUEST=REQUEST)
|
etuds = search_etuds_infos(context, expnom=expnom, REQUEST=REQUEST)
|
||||||
@ -218,10 +220,10 @@ def search_etuds_infos(context, expnom=None, code_nip=None, REQUEST=None):
|
|||||||
"""recherche les étudiants correspondants à expnom ou au code_nip
|
"""recherche les étudiants correspondants à expnom ou au code_nip
|
||||||
et ramene liste de mappings utilisables en DTML.
|
et ramene liste de mappings utilisables en DTML.
|
||||||
"""
|
"""
|
||||||
may_be_nip = is_valid_code_nip(expnom)
|
may_be_nip = scu.is_valid_code_nip(expnom)
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
if expnom and not may_be_nip:
|
if expnom and not may_be_nip:
|
||||||
expnom = strupper(expnom) # les noms dans la BD sont en uppercase
|
expnom = scu.strupper(expnom) # les noms dans la BD sont en uppercase
|
||||||
etuds = scolars.etudident_list(cnx, args={"nom": expnom}, test="~")
|
etuds = scolars.etudident_list(cnx, args={"nom": expnom}, test="~")
|
||||||
else:
|
else:
|
||||||
code_nip = code_nip or expnom
|
code_nip = code_nip or expnom
|
||||||
@ -238,20 +240,19 @@ def search_etud_by_name(context, term, REQUEST=None):
|
|||||||
Accepte aussi un début de code NIP (au moins 6 caractères)
|
Accepte aussi un début de code NIP (au moins 6 caractères)
|
||||||
Renvoie une liste de nom en JSON
|
Renvoie une liste de nom en JSON
|
||||||
"""
|
"""
|
||||||
cnx = context.GetDBConnexion()
|
may_be_nip = scu.is_valid_code_nip(term)
|
||||||
may_be_nip = is_valid_code_nip(term)
|
# term = scu.strupper(term) # conserve les accents
|
||||||
# term = strupper(term) # conserve les accents
|
|
||||||
term = term.upper()
|
term = term.upper()
|
||||||
if (
|
if (
|
||||||
not ALPHANUM_EXP.match(
|
not scu.ALPHANUM_EXP.match(
|
||||||
term.decode(SCO_ENCODING)
|
term.decode(scu.SCO_ENCODING)
|
||||||
) # n'autorise pas les caractères spéciaux
|
) # n'autorise pas les caractères spéciaux
|
||||||
and not may_be_nip
|
and not may_be_nip
|
||||||
):
|
):
|
||||||
data = []
|
data = []
|
||||||
else:
|
else:
|
||||||
if may_be_nip:
|
if may_be_nip:
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT nom, prenom, code_nip FROM identite WHERE code_nip LIKE %(beginning)s ORDER BY nom",
|
"SELECT nom, prenom, code_nip FROM identite WHERE code_nip LIKE %(beginning)s ORDER BY nom",
|
||||||
{"beginning": term + "%"},
|
{"beginning": term + "%"},
|
||||||
@ -265,7 +266,7 @@ def search_etud_by_name(context, term, REQUEST=None):
|
|||||||
for x in r
|
for x in r
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT nom, prenom FROM identite WHERE nom LIKE %(beginning)s ORDER BY nom",
|
"SELECT nom, prenom FROM identite WHERE nom LIKE %(beginning)s ORDER BY nom",
|
||||||
{"beginning": term + "%"},
|
{"beginning": term + "%"},
|
||||||
@ -279,7 +280,7 @@ def search_etud_by_name(context, term, REQUEST=None):
|
|||||||
for x in r
|
for x in r
|
||||||
]
|
]
|
||||||
# log(data)
|
# log(data)
|
||||||
return sendJSON(REQUEST, data)
|
return scu.sendJSON(REQUEST, data)
|
||||||
|
|
||||||
|
|
||||||
# ---------- Recherche sur plusieurs département
|
# ---------- Recherche sur plusieurs département
|
||||||
@ -383,9 +384,9 @@ def search_inscr_etud_by_nip(context, code_nip, REQUEST=None, format="json"):
|
|||||||
Seuls les départements accessibles par l'utilisateur sont cherchés.
|
Seuls les départements accessibles par l'utilisateur sont cherchés.
|
||||||
|
|
||||||
Renvoie une liste des inscriptions de l'étudiants dans tout ScoDoc:
|
Renvoie une liste des inscriptions de l'étudiants dans tout ScoDoc:
|
||||||
code_nip, nom, prenom, sexe, dept, formsemestre_id, date_debut_sem, date_fin_sem
|
code_nip, nom, prenom, civilite_str, dept, formsemestre_id, date_debut_sem, date_fin_sem
|
||||||
"""
|
"""
|
||||||
result, depts = search_etud_in_accessible_depts(
|
result, _ = search_etud_in_accessible_depts(
|
||||||
context, code_nip=code_nip, REQUEST=REQUEST
|
context, code_nip=code_nip, REQUEST=REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -400,7 +401,7 @@ def search_inscr_etud_by_nip(context, code_nip, REQUEST=None, format="json"):
|
|||||||
"dept": DeptId,
|
"dept": DeptId,
|
||||||
"etudid": e["etudid"],
|
"etudid": e["etudid"],
|
||||||
"code_nip": e["code_nip"],
|
"code_nip": e["code_nip"],
|
||||||
"sexe": e["sexe"],
|
"civilite_str": e["civilite_str"],
|
||||||
"nom": e["nom"],
|
"nom": e["nom"],
|
||||||
"prenom": e["prenom"],
|
"prenom": e["prenom"],
|
||||||
"formsemestre_id": sem["formsemestre_id"],
|
"formsemestre_id": sem["formsemestre_id"],
|
||||||
@ -413,7 +414,7 @@ def search_inscr_etud_by_nip(context, code_nip, REQUEST=None, format="json"):
|
|||||||
"dept",
|
"dept",
|
||||||
"etudid",
|
"etudid",
|
||||||
"code_nip",
|
"code_nip",
|
||||||
"sexe",
|
"civilite_str",
|
||||||
"nom",
|
"nom",
|
||||||
"prenom",
|
"prenom",
|
||||||
"formsemestre_id",
|
"formsemestre_id",
|
||||||
|
@ -28,16 +28,19 @@
|
|||||||
"""Import / Export de formations
|
"""Import / Export de formations
|
||||||
"""
|
"""
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
|
|
||||||
from sco_utils import *
|
|
||||||
import xml.dom.minidom
|
import xml.dom.minidom
|
||||||
|
|
||||||
from notesdb import *
|
import sco_utils as scu
|
||||||
|
|
||||||
|
import notesdb as ndb
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import sco_codes_parcours
|
import sco_codes_parcours
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_tag_module
|
import sco_tag_module
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
from sco_permissions import ScoChangeFormation
|
||||||
|
import VERSION
|
||||||
|
|
||||||
|
|
||||||
def formation_export(
|
def formation_export(
|
||||||
@ -81,7 +84,7 @@ def formation_export(
|
|||||||
if mod["ects"] is None:
|
if mod["ects"] is None:
|
||||||
del mod["ects"]
|
del mod["ects"]
|
||||||
|
|
||||||
return sendResult(
|
return scu.sendResult(
|
||||||
REQUEST, F, name="formation", format=format, force_outer_xml_tag=False
|
REQUEST, F, name="formation", format=format, force_outer_xml_tag=False
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -113,7 +116,7 @@ def XMLToDicts(element, encoding):
|
|||||||
|
|
||||||
|
|
||||||
def formation_import_xml(
|
def formation_import_xml(
|
||||||
context, REQUEST, doc, import_tags=True, encoding=SCO_ENCODING
|
context, REQUEST, doc, import_tags=True, encoding=scu.SCO_ENCODING
|
||||||
):
|
):
|
||||||
"""Create a formation from XML representation
|
"""Create a formation from XML representation
|
||||||
(format dumped by formation_export( format='xml' ))
|
(format dumped by formation_export( format='xml' ))
|
||||||
@ -131,11 +134,11 @@ def formation_import_xml(
|
|||||||
F = D[1]
|
F = D[1]
|
||||||
F_quoted = F.copy()
|
F_quoted = F.copy()
|
||||||
log("F=%s" % F)
|
log("F=%s" % F)
|
||||||
quote_dict(F_quoted)
|
ndb.quote_dict(F_quoted)
|
||||||
log("F_quoted=%s" % F_quoted)
|
log("F_quoted=%s" % F_quoted)
|
||||||
# find new version number
|
# find new version number
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
log(
|
log(
|
||||||
"select max(version) from notes_formations where acronyme=%(acronyme)s and titre=%(titre)s"
|
"select max(version) from notes_formations where acronyme=%(acronyme)s and titre=%(titre)s"
|
||||||
% F_quoted
|
% F_quoted
|
||||||
@ -204,13 +207,13 @@ def formation_list_table(context, formation_id=None, args={}, REQUEST=None):
|
|||||||
"""
|
"""
|
||||||
formations = context.formation_list(formation_id=formation_id, args=args)
|
formations = context.formation_list(formation_id=formation_id, args=args)
|
||||||
title = "Programmes pédagogiques"
|
title = "Programmes pédagogiques"
|
||||||
lockicon = icontag(
|
lockicon = scu.icontag(
|
||||||
"lock32_img", title="Comporte des semestres verrouillés", border="0"
|
"lock32_img", title="Comporte des semestres verrouillés", border="0"
|
||||||
)
|
)
|
||||||
suppricon = icontag(
|
suppricon = scu.icontag(
|
||||||
"delete_small_img", border="0", alt="supprimer", title="Supprimer"
|
"delete_small_img", border="0", alt="supprimer", title="Supprimer"
|
||||||
)
|
)
|
||||||
editicon = icontag(
|
editicon = scu.icontag(
|
||||||
"edit_img", border="0", alt="modifier", title="Modifier titres et code"
|
"edit_img", border="0", alt="modifier", title="Modifier titres et code"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -302,7 +305,7 @@ def formation_list_table(context, formation_id=None, args={}, REQUEST=None):
|
|||||||
columns_ids=columns_ids,
|
columns_ids=columns_ids,
|
||||||
rows=formations,
|
rows=formations,
|
||||||
titles=titles,
|
titles=titles,
|
||||||
origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "",
|
origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "",
|
||||||
caption=title,
|
caption=title,
|
||||||
html_caption=title,
|
html_caption=title,
|
||||||
table_id="formation_list_table",
|
table_id="formation_list_table",
|
||||||
|
@ -27,16 +27,18 @@
|
|||||||
|
|
||||||
"""Operations de base sur les formsemestres
|
"""Operations de base sur les formsemestres
|
||||||
"""
|
"""
|
||||||
|
import time
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
|
|
||||||
import sco_codes_parcours
|
import sco_codes_parcours
|
||||||
from sco_codes_parcours import NO_SEMESTRE_ID
|
from sco_codes_parcours import NO_SEMESTRE_ID
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
|
||||||
_formsemestreEditor = EditableTable(
|
_formsemestreEditor = ndb.EditableTable(
|
||||||
"notes_formsemestre",
|
"notes_formsemestre",
|
||||||
"formsemestre_id",
|
"formsemestre_id",
|
||||||
(
|
(
|
||||||
@ -60,16 +62,16 @@ _formsemestreEditor = EditableTable(
|
|||||||
),
|
),
|
||||||
sortkey="date_debut",
|
sortkey="date_debut",
|
||||||
output_formators={
|
output_formators={
|
||||||
"date_debut": DateISOtoDMY,
|
"date_debut": ndb.DateISOtoDMY,
|
||||||
"date_fin": DateISOtoDMY,
|
"date_fin": ndb.DateISOtoDMY,
|
||||||
"gestion_compensation": str,
|
"gestion_compensation": str,
|
||||||
"gestion_semestrielle": str,
|
"gestion_semestrielle": str,
|
||||||
"etat": str,
|
"etat": str,
|
||||||
"bul_hide_xml": str,
|
"bul_hide_xml": str,
|
||||||
},
|
},
|
||||||
input_formators={
|
input_formators={
|
||||||
"date_debut": DateDMYtoISO,
|
"date_debut": ndb.DateDMYtoISO,
|
||||||
"date_fin": DateDMYtoISO,
|
"date_fin": ndb.DateDMYtoISO,
|
||||||
"gestion_compensation": int,
|
"gestion_compensation": int,
|
||||||
"gestion_semestrielle": int,
|
"gestion_semestrielle": int,
|
||||||
"etat": int,
|
"etat": int,
|
||||||
@ -144,9 +146,9 @@ def formsemestre_enrich(context, sem):
|
|||||||
sem["semestre_id"],
|
sem["semestre_id"],
|
||||||
) # eg "DUT Informatique semestre 2"
|
) # eg "DUT Informatique semestre 2"
|
||||||
|
|
||||||
sem["dateord"] = DateDMYtoISO(sem["date_debut"])
|
sem["dateord"] = ndb.DateDMYtoISO(sem["date_debut"])
|
||||||
sem["date_debut_iso"] = DateDMYtoISO(sem["date_debut"])
|
sem["date_debut_iso"] = ndb.DateDMYtoISO(sem["date_debut"])
|
||||||
sem["date_fin_iso"] = DateDMYtoISO(sem["date_fin"])
|
sem["date_fin_iso"] = ndb.DateDMYtoISO(sem["date_fin"])
|
||||||
try:
|
try:
|
||||||
mois_debut, annee_debut = sem["date_debut"].split("/")[1:]
|
mois_debut, annee_debut = sem["date_debut"].split("/")[1:]
|
||||||
except:
|
except:
|
||||||
@ -162,7 +164,9 @@ def formsemestre_enrich(context, sem):
|
|||||||
|
|
||||||
sem["annee"] = annee_debut
|
sem["annee"] = annee_debut
|
||||||
# 2007 ou 2007-2008:
|
# 2007 ou 2007-2008:
|
||||||
sem["anneescolaire"] = annee_scolaire_repr(int(annee_debut), sem["mois_debut_ord"])
|
sem["anneescolaire"] = scu.annee_scolaire_repr(
|
||||||
|
int(annee_debut), sem["mois_debut_ord"]
|
||||||
|
)
|
||||||
# La période: considère comme "S1" (ou S3) les débuts en aout-sept-octobre
|
# La période: considère comme "S1" (ou S3) les débuts en aout-sept-octobre
|
||||||
# devrait sans doute pouvoir etre changé...
|
# devrait sans doute pouvoir etre changé...
|
||||||
if sem["mois_debut_ord"] >= 8 and sem["mois_debut_ord"] <= 10:
|
if sem["mois_debut_ord"] >= 8 and sem["mois_debut_ord"] <= 10:
|
||||||
@ -229,7 +233,7 @@ def read_formsemestre_responsables(context, formsemestre_id):
|
|||||||
"""recupere liste des responsables de ce semestre
|
"""recupere liste des responsables de ce semestre
|
||||||
:returns: liste de chaines
|
:returns: liste de chaines
|
||||||
"""
|
"""
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT responsable_id FROM notes_formsemestre_responsables WHERE formsemestre_id = %(formsemestre_id)s",
|
"SELECT responsable_id FROM notes_formsemestre_responsables WHERE formsemestre_id = %(formsemestre_id)s",
|
||||||
{"formsemestre_id": formsemestre_id},
|
{"formsemestre_id": formsemestre_id},
|
||||||
@ -243,7 +247,7 @@ def write_formsemestre_responsables(context, sem):
|
|||||||
|
|
||||||
# ---------------------- Coefs des UE
|
# ---------------------- Coefs des UE
|
||||||
|
|
||||||
_formsemestre_uecoef_editor = EditableTable(
|
_formsemestre_uecoef_editor = ndb.EditableTable(
|
||||||
"notes_formsemestre_uecoef",
|
"notes_formsemestre_uecoef",
|
||||||
"formsemestre_uecoef_id",
|
"formsemestre_uecoef_id",
|
||||||
("formsemestre_uecoef_id", "formsemestre_id", "ue_id", "coefficient"),
|
("formsemestre_uecoef_id", "formsemestre_id", "ue_id", "coefficient"),
|
||||||
@ -292,7 +296,7 @@ def read_formsemestre_etapes(context, formsemestre_id):
|
|||||||
"""recupere liste des codes etapes associés à ce semestre
|
"""recupere liste des codes etapes associés à ce semestre
|
||||||
:returns: liste d'instance de ApoEtapeVDI
|
:returns: liste d'instance de ApoEtapeVDI
|
||||||
"""
|
"""
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT etape_apo FROM notes_formsemestre_etapes WHERE formsemestre_id = %(formsemestre_id)s",
|
"SELECT etape_apo FROM notes_formsemestre_etapes WHERE formsemestre_id = %(formsemestre_id)s",
|
||||||
{"formsemestre_id": formsemestre_id},
|
{"formsemestre_id": formsemestre_id},
|
||||||
@ -311,7 +315,7 @@ def _write_formsemestre_aux(context, sem, fieldname, valuename):
|
|||||||
if not "etapes" in sem:
|
if not "etapes" in sem:
|
||||||
return
|
return
|
||||||
cnx = context.GetDBConnexion(autocommit=False)
|
cnx = context.GetDBConnexion(autocommit=False)
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
tablename = "notes_formsemestre_" + fieldname
|
tablename = "notes_formsemestre_" + fieldname
|
||||||
try:
|
try:
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
@ -428,7 +432,7 @@ def sem_in_semestre_scolaire(context, sem, year=False, saison=0, REQUEST=None):
|
|||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
if not year:
|
if not year:
|
||||||
year = AnneeScolaire(REQUEST)
|
year = scu.AnneeScolaire(REQUEST)
|
||||||
# est-on dans la même année universitaire ?
|
# est-on dans la même année universitaire ?
|
||||||
if sem["mois_debut_ord"] > 7:
|
if sem["mois_debut_ord"] > 7:
|
||||||
if sem["annee_debut"] != str(year):
|
if sem["annee_debut"] != str(year):
|
||||||
@ -452,7 +456,7 @@ def sem_in_annee_scolaire(context, sem, year=False, REQUEST=None):
|
|||||||
Si annee non specifiée, année scolaire courante
|
Si annee non specifiée, année scolaire courante
|
||||||
"""
|
"""
|
||||||
if not year:
|
if not year:
|
||||||
year = AnneeScolaire(REQUEST)
|
year = scu.AnneeScolaire(REQUEST)
|
||||||
return ((sem["annee_debut"] == str(year)) and (sem["mois_debut_ord"] > 7)) or (
|
return ((sem["annee_debut"] == str(year)) and (sem["mois_debut_ord"] > 7)) or (
|
||||||
(sem["annee_debut"] == str(year + 1)) and (sem["mois_debut_ord"] <= 7)
|
(sem["annee_debut"] == str(year + 1)) and (sem["mois_debut_ord"] <= 7)
|
||||||
)
|
)
|
||||||
@ -481,8 +485,8 @@ def sem_une_annee(context, sem):
|
|||||||
def sem_est_courant(context, sem):
|
def sem_est_courant(context, sem):
|
||||||
"""Vrai si la date actuelle (now) est dans le semestre (les dates de début et fin sont incluses)"""
|
"""Vrai si la date actuelle (now) est dans le semestre (les dates de début et fin sont incluses)"""
|
||||||
now = time.strftime("%Y-%m-%d")
|
now = time.strftime("%Y-%m-%d")
|
||||||
debut = DateDMYtoISO(sem["date_debut"])
|
debut = ndb.DateDMYtoISO(sem["date_debut"])
|
||||||
fin = DateDMYtoISO(sem["date_fin"])
|
fin = ndb.DateDMYtoISO(sem["date_fin"])
|
||||||
return (debut <= now) and (now <= fin)
|
return (debut <= now) and (now <= fin)
|
||||||
|
|
||||||
|
|
||||||
@ -594,7 +598,7 @@ def view_formsemestre_by_etape(context, etape_apo=None, format="html", REQUEST=N
|
|||||||
tab = table_formsemestres(
|
tab = table_formsemestres(
|
||||||
context,
|
context,
|
||||||
list_formsemestre_by_etape(
|
list_formsemestre_by_etape(
|
||||||
context, etape_apo=etape_apo, annee_scolaire=AnneeScolaire(REQUEST)
|
context, etape_apo=etape_apo, annee_scolaire=scu.AnneeScolaire(REQUEST)
|
||||||
),
|
),
|
||||||
html_title=html_title,
|
html_title=html_title,
|
||||||
html_next_section="""<form action="view_formsemestre_by_etape">
|
html_next_section="""<form action="view_formsemestre_by_etape">
|
||||||
|
@ -29,15 +29,15 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from TrivialFormulator import TrivialFormulator, TF
|
from TrivialFormulator import TrivialFormulator, TF
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_formsemestre_status
|
import sco_formsemestre_status
|
||||||
import sco_edt_cal
|
import sco_edt_cal
|
||||||
|
|
||||||
_custommenuEditor = EditableTable(
|
_custommenuEditor = ndb.EditableTable(
|
||||||
"notes_formsemestre_custommenu",
|
"notes_formsemestre_custommenu",
|
||||||
"custommenu_id",
|
"custommenu_id",
|
||||||
("custommenu_id", "formsemestre_id", "title", "url", "idx"),
|
("custommenu_id", "formsemestre_id", "title", "url", "idx"),
|
||||||
@ -80,6 +80,9 @@ def formsemestre_custommenu_html(context, formsemestre_id, base_url=""):
|
|||||||
def formsemestre_custommenu_edit(context, formsemestre_id, REQUEST=None):
|
def formsemestre_custommenu_edit(context, formsemestre_id, REQUEST=None):
|
||||||
"""Dialog to edit the custom menu"""
|
"""Dialog to edit the custom menu"""
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||||
|
dest_url = (
|
||||||
|
context.NotesURL() + "formsemestre_status?formsemestre_id=%s" % formsemestre_id
|
||||||
|
)
|
||||||
H = [
|
H = [
|
||||||
context.html_sem_header(REQUEST, "Modification du menu du semestre ", sem),
|
context.html_sem_header(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">Ce menu, spécifique à chaque semestre, peut être utilisé pour placer des liens vers vos applications préférées.</p>
|
||||||
@ -126,7 +129,7 @@ def formsemestre_custommenu_edit(context, formsemestre_id, REQUEST=None):
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + "\n" + tf[1] + context.sco_footer(REQUEST)
|
return "\n".join(H) + "\n" + tf[1] + context.sco_footer(REQUEST)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(dest_url)
|
||||||
else:
|
else:
|
||||||
# form submission
|
# form submission
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
@ -153,6 +156,4 @@ def formsemestre_custommenu_edit(context, formsemestre_id, REQUEST=None):
|
|||||||
"url": tf[2]["url_" + custommenu_id],
|
"url": tf[2]["url_" + custommenu_id],
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(dest_url)
|
||||||
"formsemestre_status?formsemestre_id=%s" % formsemestre_id
|
|
||||||
)
|
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
"""Form choix modules / responsables et creation formsemestre
|
"""Form choix modules / responsables et creation formsemestre
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
import sco_groups
|
import sco_groups
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from TrivialFormulator import TrivialFormulator, TF
|
from TrivialFormulator import TrivialFormulator, TF
|
||||||
@ -43,6 +43,8 @@ import sco_modalites
|
|||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_moduleimpl
|
import sco_moduleimpl
|
||||||
from sco_formsemestre import ApoEtapeVDI
|
from sco_formsemestre import ApoEtapeVDI
|
||||||
|
from sco_permissions import ScoImplement
|
||||||
|
from sco_exceptions import AccessDenied, ScoValueError
|
||||||
|
|
||||||
|
|
||||||
def _default_sem_title(F):
|
def _default_sem_title(F):
|
||||||
@ -70,9 +72,7 @@ def formsemestre_createwithmodules(context, REQUEST=None):
|
|||||||
def formsemestre_editwithmodules(context, REQUEST, formsemestre_id):
|
def formsemestre_editwithmodules(context, REQUEST, formsemestre_id):
|
||||||
"""Page modification semestre"""
|
"""Page modification semestre"""
|
||||||
# portage from dtml
|
# portage from dtml
|
||||||
authuser = REQUEST.AUTHENTICATED_USER
|
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||||
F = context.formation_list(args={"formation_id": sem["formation_id"]})[0]
|
|
||||||
H = [
|
H = [
|
||||||
context.html_sem_header(
|
context.html_sem_header(
|
||||||
REQUEST,
|
REQUEST,
|
||||||
@ -86,7 +86,7 @@ def formsemestre_editwithmodules(context, REQUEST, formsemestre_id):
|
|||||||
if sem["etat"] != "1":
|
if sem["etat"] != "1":
|
||||||
H.append(
|
H.append(
|
||||||
"""<p>%s<b>Ce semestre est verrouillé.</b></p>"""
|
"""<p>%s<b>Ce semestre est verrouillé.</b></p>"""
|
||||||
% icontag("lock_img", border="0", title="Semestre verrouillé")
|
% scu.icontag("lock_img", border="0", title="Semestre verrouillé")
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
H.append(do_formsemestre_createwithmodules(context, REQUEST=REQUEST, edit=1))
|
H.append(do_formsemestre_createwithmodules(context, REQUEST=REQUEST, edit=1))
|
||||||
@ -176,7 +176,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
|
|||||||
|
|
||||||
# Liste des ID de semestres
|
# Liste des ID de semestres
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute("select semestre_id from notes_semestres")
|
cursor.execute("select semestre_id from notes_semestres")
|
||||||
semestre_id_list = [str(x[0]) for x in cursor.fetchall()]
|
semestre_id_list = [str(x[0]) for x in cursor.fetchall()]
|
||||||
semestre_id_labels = []
|
semestre_id_labels = []
|
||||||
@ -344,7 +344,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
|
|||||||
# fallback: code etape libre
|
# fallback: code etape libre
|
||||||
mf = mf_manual
|
mf = mf_manual
|
||||||
|
|
||||||
for n in range(1, EDIT_NB_ETAPES + 1):
|
for n in range(1, scu.EDIT_NB_ETAPES + 1):
|
||||||
mf["title"] = "Etape Apogée (%d)" % n
|
mf["title"] = "Etape Apogée (%d)" % n
|
||||||
modform.append(("etape_apo" + str(n), mf.copy()))
|
modform.append(("etape_apo" + str(n), mf.copy()))
|
||||||
modform.append(
|
modform.append(
|
||||||
@ -639,10 +639,10 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
|
|||||||
msg = ""
|
msg = ""
|
||||||
if tf[0] == 1:
|
if tf[0] == 1:
|
||||||
# check dates
|
# check dates
|
||||||
if DateDMYtoISO(tf[2]["date_debut"]) > DateDMYtoISO(tf[2]["date_fin"]):
|
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>'
|
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 context.get_preference("always_require_apo_sem_codes") and not any(
|
||||||
[tf[2]["etape_apo" + str(n)] for n in range(0, EDIT_NB_ETAPES + 1)]
|
[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>'
|
msg = '<ul class="tf-msg"><li class="tf-msg">Code étape Apogée manquant</li></ul>'
|
||||||
|
|
||||||
@ -693,7 +693,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
|
|||||||
start_i = 0
|
start_i = 0
|
||||||
else:
|
else:
|
||||||
start_i = 1
|
start_i = 1
|
||||||
for n in range(start_i, EDIT_NB_ETAPES + 1):
|
for n in range(start_i, scu.EDIT_NB_ETAPES + 1):
|
||||||
tf[2]["etapes"].append(
|
tf[2]["etapes"].append(
|
||||||
ApoEtapeVDI(
|
ApoEtapeVDI(
|
||||||
etape=tf[2]["etape_apo" + str(n)], vdi=tf[2]["vdi_apo" + str(n)]
|
etape=tf[2]["etape_apo" + str(n)], vdi=tf[2]["vdi_apo" + str(n)]
|
||||||
@ -709,7 +709,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
|
|||||||
"formsemestre_id": formsemestre_id,
|
"formsemestre_id": formsemestre_id,
|
||||||
"responsable_id": tf[2][module_id],
|
"responsable_id": tf[2][module_id],
|
||||||
}
|
}
|
||||||
mid = sco_moduleimpl.do_moduleimpl_create(context, modargs)
|
_ = sco_moduleimpl.do_moduleimpl_create(context, modargs)
|
||||||
return REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
"formsemestre_status?formsemestre_id=%s&head_message=Nouveau%%20semestre%%20créé"
|
"formsemestre_status?formsemestre_id=%s&head_message=Nouveau%%20semestre%%20créé"
|
||||||
% formsemestre_id
|
% formsemestre_id
|
||||||
@ -846,7 +846,6 @@ def formsemestre_clone(context, formsemestre_id, REQUEST=None):
|
|||||||
"""
|
"""
|
||||||
Formulaire clonage d'un semestre
|
Formulaire clonage d'un semestre
|
||||||
"""
|
"""
|
||||||
authuser = REQUEST.AUTHENTICATED_USER
|
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||||
# Liste des enseignants avec forme pour affichage / saisie avec suggestion
|
# Liste des enseignants avec forme pour affichage / saisie avec suggestion
|
||||||
userlist = context.Users.get_userlist()
|
userlist = context.Users.get_userlist()
|
||||||
@ -942,7 +941,7 @@ def formsemestre_clone(context, formsemestre_id, REQUEST=None):
|
|||||||
msg = ""
|
msg = ""
|
||||||
if tf[0] == 1:
|
if tf[0] == 1:
|
||||||
# check dates
|
# check dates
|
||||||
if DateDMYtoISO(tf[2]["date_debut"]) > DateDMYtoISO(tf[2]["date_fin"]):
|
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>'
|
msg = '<ul class="tf-msg"><li class="tf-msg">Dates de début et fin incompatibles !</li></ul>'
|
||||||
if tf[0] == 0 or msg:
|
if tf[0] == 0 or msg:
|
||||||
return "".join(H) + msg + tf[1] + context.sco_footer(REQUEST)
|
return "".join(H) + msg + tf[1] + context.sco_footer(REQUEST)
|
||||||
@ -1017,7 +1016,7 @@ def do_formsemestre_clone(
|
|||||||
args = e.copy()
|
args = e.copy()
|
||||||
del args["jour"] # erase date
|
del args["jour"] # erase date
|
||||||
args["moduleimpl_id"] = mid
|
args["moduleimpl_id"] = mid
|
||||||
evaluation_id = context.do_evaluation_create(REQUEST=REQUEST, **args)
|
_ = context.do_evaluation_create(REQUEST=REQUEST, **args)
|
||||||
|
|
||||||
# 3- copy uecoefs
|
# 3- copy uecoefs
|
||||||
objs = sco_formsemestre.formsemestre_uecoef_list(
|
objs = sco_formsemestre.formsemestre_uecoef_list(
|
||||||
@ -1026,7 +1025,7 @@ def do_formsemestre_clone(
|
|||||||
for obj in objs:
|
for obj in objs:
|
||||||
args = obj.copy()
|
args = obj.copy()
|
||||||
args["formsemestre_id"] = formsemestre_id
|
args["formsemestre_id"] = formsemestre_id
|
||||||
c = sco_formsemestre.formsemestre_uecoef_create(cnx, args)
|
_ = sco_formsemestre.formsemestre_uecoef_create(cnx, args)
|
||||||
|
|
||||||
# NB: don't copy notes_formsemestre_custommenu (usually specific)
|
# NB: don't copy notes_formsemestre_custommenu (usually specific)
|
||||||
|
|
||||||
@ -1049,7 +1048,7 @@ def do_formsemestre_clone(
|
|||||||
for obj in objs:
|
for obj in objs:
|
||||||
args = obj.copy()
|
args = obj.copy()
|
||||||
args["formsemestre_id"] = formsemestre_id
|
args["formsemestre_id"] = formsemestre_id
|
||||||
c = sco_compute_moy.formsemestre_ue_computation_expr_create(cnx, args)
|
_ = sco_compute_moy.formsemestre_ue_computation_expr_create(cnx, args)
|
||||||
|
|
||||||
# 5- Copy partitions
|
# 5- Copy partitions
|
||||||
if clone_partitions:
|
if clone_partitions:
|
||||||
@ -1059,7 +1058,6 @@ def do_formsemestre_clone(
|
|||||||
for part in sco_groups.get_partitions_list(context, orig_formsemestre_id):
|
for part in sco_groups.get_partitions_list(context, orig_formsemestre_id):
|
||||||
if part["partition_name"] != None:
|
if part["partition_name"] != None:
|
||||||
partname = part["partition_name"]
|
partname = part["partition_name"]
|
||||||
orig_partition_id = part["partition_id"]
|
|
||||||
new_partition_id = sco_groups.partition_create(
|
new_partition_id = sco_groups.partition_create(
|
||||||
context,
|
context,
|
||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
@ -1079,7 +1077,7 @@ def do_formsemestre_clone(
|
|||||||
if newpart["partition_id"] == g[0]:
|
if newpart["partition_id"] == g[0]:
|
||||||
part_id = g[0]
|
part_id = g[0]
|
||||||
for group_name in g[1]:
|
for group_name in g[1]:
|
||||||
group_id = sco_groups.createGroup(
|
_ = sco_groups.createGroup(
|
||||||
context, part_id, group_name=group_name, REQUEST=REQUEST
|
context, part_id, group_name=group_name, REQUEST=REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1261,7 +1259,11 @@ def formsemestre_delete(context, formsemestre_id, REQUEST=None):
|
|||||||
H.append(tf[1])
|
H.append(tf[1])
|
||||||
return "\n".join(H) + context.sco_footer(REQUEST)
|
return "\n".join(H) + context.sco_footer(REQUEST)
|
||||||
elif tf[0] == -1: # cancel
|
elif tf[0] == -1: # cancel
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(
|
||||||
|
context.NotesURL()
|
||||||
|
+ "formsemestre_status?formsemestre_id="
|
||||||
|
+ formsemestre_id
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
"formsemestre_delete2?formsemestre_id=" + formsemestre_id
|
"formsemestre_delete2?formsemestre_id=" + formsemestre_id
|
||||||
@ -1272,9 +1274,6 @@ def formsemestre_delete2(
|
|||||||
context, formsemestre_id, dialog_confirmed=False, REQUEST=None
|
context, formsemestre_id, dialog_confirmed=False, REQUEST=None
|
||||||
):
|
):
|
||||||
"""Delete a formsemestre (confirmation)"""
|
"""Delete a formsemestre (confirmation)"""
|
||||||
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)]
|
|
||||||
# Confirmation dialog
|
# Confirmation dialog
|
||||||
if not dialog_confirmed:
|
if not dialog_confirmed:
|
||||||
return context.confirmDialog(
|
return context.confirmDialog(
|
||||||
@ -1286,14 +1285,16 @@ def formsemestre_delete2(
|
|||||||
)
|
)
|
||||||
# Bon, s'il le faut...
|
# Bon, s'il le faut...
|
||||||
do_formsemestre_delete(context, formsemestre_id, REQUEST)
|
do_formsemestre_delete(context, formsemestre_id, REQUEST)
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL2 + "?head_message=Semestre%20supprimé")
|
return REQUEST.RESPONSE.redirect(
|
||||||
|
context.ScoURL() + "?head_message=Semestre%20supprimé"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def formsemestre_has_decisions_or_compensations(context, formsemestre_id):
|
def formsemestre_has_decisions_or_compensations(context, formsemestre_id):
|
||||||
"""True if decision de jury dans ce semestre
|
"""True if decision de jury dans ce semestre
|
||||||
ou bien compensation de ce semestre par d'autre ssemestres.
|
ou bien compensation de ce semestre par d'autre ssemestres.
|
||||||
"""
|
"""
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT v.* FROM scolar_formsemestre_validation v WHERE v.formsemestre_id = %(formsemestre_id)s OR v.compense_formsemestre_id = %(formsemestre_id)s",
|
"SELECT v.* FROM scolar_formsemestre_validation v WHERE v.formsemestre_id = %(formsemestre_id)s OR v.compense_formsemestre_id = %(formsemestre_id)s",
|
||||||
{"formsemestre_id": formsemestre_id},
|
{"formsemestre_id": formsemestre_id},
|
||||||
@ -1314,17 +1315,17 @@ def do_formsemestre_delete(context, formsemestre_id, REQUEST):
|
|||||||
# evaluations
|
# evaluations
|
||||||
evals = context.do_evaluation_list(args={"moduleimpl_id": mod["moduleimpl_id"]})
|
evals = context.do_evaluation_list(args={"moduleimpl_id": mod["moduleimpl_id"]})
|
||||||
for e in evals:
|
for e in evals:
|
||||||
SimpleQuery(
|
ndb.SimpleQuery(
|
||||||
context,
|
context,
|
||||||
"DELETE FROM notes_notes WHERE evaluation_id=%(evaluation_id)s",
|
"DELETE FROM notes_notes WHERE evaluation_id=%(evaluation_id)s",
|
||||||
e,
|
e,
|
||||||
)
|
)
|
||||||
SimpleQuery(
|
ndb.SimpleQuery(
|
||||||
context,
|
context,
|
||||||
"DELETE FROM notes_notes_log WHERE evaluation_id=%(evaluation_id)s",
|
"DELETE FROM notes_notes_log WHERE evaluation_id=%(evaluation_id)s",
|
||||||
e,
|
e,
|
||||||
)
|
)
|
||||||
SimpleQuery(
|
ndb.SimpleQuery(
|
||||||
context,
|
context,
|
||||||
"DELETE FROM notes_evaluation WHERE evaluation_id=%(evaluation_id)s",
|
"DELETE FROM notes_evaluation WHERE evaluation_id=%(evaluation_id)s",
|
||||||
e,
|
e,
|
||||||
@ -1335,7 +1336,7 @@ def do_formsemestre_delete(context, formsemestre_id, REQUEST):
|
|||||||
context, mod["moduleimpl_id"], formsemestre_id=formsemestre_id
|
context, mod["moduleimpl_id"], formsemestre_id=formsemestre_id
|
||||||
)
|
)
|
||||||
# --- Desinscription des etudiants
|
# --- Desinscription des etudiants
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
req = "DELETE FROM notes_formsemestre_inscription WHERE formsemestre_id=%(formsemestre_id)s"
|
req = "DELETE FROM notes_formsemestre_inscription WHERE formsemestre_id=%(formsemestre_id)s"
|
||||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||||
# --- Suppression des evenements
|
# --- Suppression des evenements
|
||||||
@ -1437,7 +1438,7 @@ def formsemestre_change_lock(
|
|||||||
args = {"formsemestre_id": formsemestre_id, "etat": etat}
|
args = {"formsemestre_id": formsemestre_id, "etat": etat}
|
||||||
context.do_formsemestre_edit(args)
|
context.do_formsemestre_edit(args)
|
||||||
if REQUEST:
|
if REQUEST:
|
||||||
REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
"formsemestre_status?formsemestre_id=%s" % formsemestre_id
|
"formsemestre_status?formsemestre_id=%s" % formsemestre_id
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1477,9 +1478,10 @@ def formsemestre_change_publication_bul(
|
|||||||
args = {"formsemestre_id": formsemestre_id, "bul_hide_xml": etat}
|
args = {"formsemestre_id": formsemestre_id, "bul_hide_xml": etat}
|
||||||
context.do_formsemestre_edit(args)
|
context.do_formsemestre_edit(args)
|
||||||
if REQUEST:
|
if REQUEST:
|
||||||
REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
"formsemestre_status?formsemestre_id=%s" % formsemestre_id
|
"formsemestre_status?formsemestre_id=%s" % formsemestre_id
|
||||||
)
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST=None):
|
def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST=None):
|
||||||
@ -1489,7 +1491,6 @@ def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST=
|
|||||||
if not ok:
|
if not ok:
|
||||||
return err
|
return err
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||||
F = context.formation_list(args={"formation_id": sem["formation_id"]})[0]
|
|
||||||
|
|
||||||
footer = context.sco_footer(REQUEST)
|
footer = context.sco_footer(REQUEST)
|
||||||
help = """<p class="help">
|
help = """<p class="help">
|
||||||
@ -1664,12 +1665,12 @@ def get_formsemestre_session_id(context, sem, F, parcours):
|
|||||||
(modalite or "").replace("FAP", "FA").replace("APP", "FA")
|
(modalite or "").replace("FAP", "FA").replace("APP", "FA")
|
||||||
) # exception pour code Apprentissage
|
) # exception pour code Apprentissage
|
||||||
if sem["semestre_id"] > 0:
|
if sem["semestre_id"] > 0:
|
||||||
decale = sem_decale_str(sem)
|
decale = scu.sem_decale_str(sem)
|
||||||
semestre_id = "S%d" % sem["semestre_id"] + decale
|
semestre_id = "S%d" % sem["semestre_id"] + decale
|
||||||
else:
|
else:
|
||||||
semestre_id = F["code_specialite"]
|
semestre_id = F["code_specialite"]
|
||||||
annee_sco = str(annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"]))
|
annee_sco = str(scu.annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"]))
|
||||||
|
|
||||||
return sanitize_string(
|
return scu.sanitize_string(
|
||||||
"-".join((ImputationDept, parcours_type, modalite, semestre_id, annee_sco))
|
"-".join((ImputationDept, parcours_type, modalite, semestre_id, annee_sco))
|
||||||
)
|
)
|
||||||
|
@ -28,8 +28,11 @@
|
|||||||
"""Opérations d'inscriptions aux semestres et modules
|
"""Opérations d'inscriptions aux semestres et modules
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from sco_utils import ScoEtudInscrit, log, ScoValueError, DictDefault
|
import sco_utils as scu
|
||||||
from sco_utils import UE_STANDARD, UE_SPORT, UE_TYPE_NAME
|
from notes_log import log
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
from sco_permissions import ScoEtudInscrit
|
||||||
|
from sco_codes_parcours import UE_STANDARD, UE_SPORT, UE_TYPE_NAME
|
||||||
from notesdb import ScoDocCursor, DateISOtoDMY, DateDMYtoISO
|
from notesdb import ScoDocCursor, DateISOtoDMY, DateDMYtoISO
|
||||||
|
|
||||||
from TrivialFormulator import TrivialFormulator, TF
|
from TrivialFormulator import TrivialFormulator, TF
|
||||||
@ -287,8 +290,10 @@ def formsemestre_inscription_option(context, etudid, formsemestre_id, REQUEST=No
|
|||||||
)
|
)
|
||||||
inscr = sco_moduleimpl.do_moduleimpl_inscription_list(context, etudid=etudid)
|
inscr = sco_moduleimpl.do_moduleimpl_inscription_list(context, etudid=etudid)
|
||||||
# Formulaire
|
# Formulaire
|
||||||
modimpls_by_ue_ids = DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_id ]
|
modimpls_by_ue_ids = scu.DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_id ]
|
||||||
modimpls_by_ue_names = DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_name ]
|
modimpls_by_ue_names = scu.DictDefault(
|
||||||
|
defaultvalue=[]
|
||||||
|
) # ue_id : [ moduleimpl_name ]
|
||||||
ues = []
|
ues = []
|
||||||
ue_ids = set()
|
ue_ids = set()
|
||||||
initvalues = {}
|
initvalues = {}
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Rewritten from ancient DTML code
|
# Rewritten from ancient DTML code
|
||||||
from mx.DateTime import DateTime as mxDateTime
|
|
||||||
|
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import sco_utils as scu
|
import sco_utils as scu
|
||||||
|
@ -29,14 +29,14 @@
|
|||||||
"""
|
"""
|
||||||
import urllib, time, datetime
|
import urllib, time, datetime
|
||||||
|
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from scolog import logdb
|
from scolog import logdb
|
||||||
from notes_table import *
|
|
||||||
import notes_table
|
import notes_table
|
||||||
|
from TrivialFormulator import TrivialFormulator, tf_error_message
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
from sco_abs import getAbsSemEtud
|
from sco_abs import getAbsSemEtud
|
||||||
|
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_formsemestre_edit
|
import sco_formsemestre_edit
|
||||||
import sco_formsemestre_status
|
import sco_formsemestre_status
|
||||||
@ -346,7 +346,7 @@ def formsemestre_validation_etud(
|
|||||||
raise ValueError("code choix invalide ! (%s)" % codechoice)
|
raise ValueError("code choix invalide ! (%s)" % codechoice)
|
||||||
#
|
#
|
||||||
Se.valide_decision(choice, REQUEST) # enregistre
|
Se.valide_decision(choice, REQUEST) # enregistre
|
||||||
_redirect_valid_choice(
|
return _redirect_valid_choice(
|
||||||
formsemestre_id, etudid, Se, choice, desturl, sortcol, REQUEST
|
formsemestre_id, etudid, Se, choice, desturl, sortcol, REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -393,7 +393,7 @@ def formsemestre_validation_etud_manu(
|
|||||||
#
|
#
|
||||||
Se.valide_decision(choice, REQUEST) # enregistre
|
Se.valide_decision(choice, REQUEST) # enregistre
|
||||||
if redirect:
|
if redirect:
|
||||||
_redirect_valid_choice(
|
return _redirect_valid_choice(
|
||||||
formsemestre_id, etudid, Se, choice, desturl, sortcol, REQUEST
|
formsemestre_id, etudid, Se, choice, desturl, sortcol, REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -407,9 +407,9 @@ def _redirect_valid_choice(
|
|||||||
)
|
)
|
||||||
if sortcol:
|
if sortcol:
|
||||||
adr += "&sortcol=" + sortcol
|
adr += "&sortcol=" + sortcol
|
||||||
if desturl:
|
# if desturl:
|
||||||
desturl += "&desturl=" + desturl
|
# desturl += "&desturl=" + desturl
|
||||||
REQUEST.RESPONSE.redirect(adr)
|
return REQUEST.RESPONSE.redirect(adr)
|
||||||
# Si le precedent a été modifié, demande relecture du parcours.
|
# Si le precedent a été modifié, demande relecture du parcours.
|
||||||
# sinon renvoie au listing general,
|
# sinon renvoie au listing general,
|
||||||
|
|
||||||
@ -486,8 +486,8 @@ def formsemestre_recap_parcours_table(
|
|||||||
"""
|
"""
|
||||||
H = []
|
H = []
|
||||||
linktmpl = '<span onclick="toggle_vis(this);" class="toggle_sem sem_%%s">%s</span>'
|
linktmpl = '<span onclick="toggle_vis(this);" class="toggle_sem sem_%%s">%s</span>'
|
||||||
minuslink = linktmpl % icontag("minus_img", border="0", alt="-")
|
minuslink = linktmpl % scu.icontag("minus_img", border="0", alt="-")
|
||||||
pluslink = linktmpl % icontag("plus_img", border="0", alt="+")
|
pluslink = linktmpl % scu.icontag("plus_img", border="0", alt="+")
|
||||||
if show_details:
|
if show_details:
|
||||||
sd = " recap_show_details"
|
sd = " recap_show_details"
|
||||||
plusminus = minuslink
|
plusminus = minuslink
|
||||||
@ -497,7 +497,7 @@ def formsemestre_recap_parcours_table(
|
|||||||
H.append('<table class="recap_parcours%s"><tr>' % sd)
|
H.append('<table class="recap_parcours%s"><tr>' % sd)
|
||||||
H.append(
|
H.append(
|
||||||
'<th><span onclick="toggle_all_sems(this);" title="Ouvrir/fermer tous les semestres">%s</span></th><th></th><th>Semestre</th>'
|
'<th><span onclick="toggle_all_sems(this);" title="Ouvrir/fermer tous les semestres">%s</span></th><th></th><th>Semestre</th>'
|
||||||
% icontag("plus18_img", width=18, height=18, border=0, title="", alt="+")
|
% scu.icontag("plus18_img", width=18, height=18, border=0, title="", alt="+")
|
||||||
)
|
)
|
||||||
H.append("<th>Etat</th><th>Abs</th>")
|
H.append("<th>Etat</th><th>Abs</th>")
|
||||||
# titres des UE
|
# titres des UE
|
||||||
@ -591,7 +591,7 @@ def formsemestre_recap_parcours_table(
|
|||||||
else:
|
else:
|
||||||
default_sem_info = ""
|
default_sem_info = ""
|
||||||
if sem["etat"] != "1": # locked
|
if sem["etat"] != "1": # locked
|
||||||
lockicon = icontag("lock32_img", title="verrouillé", border="0")
|
lockicon = scu.icontag("lock32_img", title="verrouillé", border="0")
|
||||||
default_sem_info += lockicon
|
default_sem_info += lockicon
|
||||||
if sem["formation_code"] != Se.formation["formation_code"]:
|
if sem["formation_code"] != Se.formation["formation_code"]:
|
||||||
default_sem_info += "Autre formation: %s" % sem["formation_code"]
|
default_sem_info += "Autre formation: %s" % sem["formation_code"]
|
||||||
@ -601,8 +601,7 @@ def formsemestre_recap_parcours_table(
|
|||||||
)
|
)
|
||||||
# Moy Gen (sous le code decision)
|
# Moy Gen (sous le code decision)
|
||||||
H.append(
|
H.append(
|
||||||
'<td class="rcp_moy">%s</td>'
|
'<td class="rcp_moy">%s</td>' % scu.fmt_note(nt.get_etud_moy_gen(etudid))
|
||||||
% notes_table.fmt_note(nt.get_etud_moy_gen(etudid))
|
|
||||||
)
|
)
|
||||||
# Absences (nb d'abs non just. dans ce semestre)
|
# Absences (nb d'abs non just. dans ce semestre)
|
||||||
AbsEtudSem = getAbsSemEtud(context, sem, etudid)
|
AbsEtudSem = getAbsSemEtud(context, sem, etudid)
|
||||||
@ -642,7 +641,7 @@ def formsemestre_recap_parcours_table(
|
|||||||
|
|
||||||
H.append(
|
H.append(
|
||||||
'<td class="%s" title="%s">%s</td>'
|
'<td class="%s" title="%s">%s</td>'
|
||||||
% (class_ue, " ".join(explanation_ue), notes_table.fmt_note(moy_ue))
|
% (class_ue, " ".join(explanation_ue), scu.fmt_note(moy_ue))
|
||||||
)
|
)
|
||||||
if len(ues) < Se.nb_max_ue:
|
if len(ues) < Se.nb_max_ue:
|
||||||
H.append('<td colspan="%d"></td>' % (Se.nb_max_ue - len(ues)))
|
H.append('<td colspan="%d"></td>' % (Se.nb_max_ue - len(ues)))
|
||||||
@ -1035,7 +1034,7 @@ def formsemestre_validation_suppress_etud(context, formsemestre_id, etudid):
|
|||||||
"""Suppression des decisions de jury pour un etudiant."""
|
"""Suppression des decisions de jury pour un etudiant."""
|
||||||
log("formsemestre_validation_suppress_etud( %s, %s)" % (formsemestre_id, etudid))
|
log("formsemestre_validation_suppress_etud( %s, %s)" % (formsemestre_id, etudid))
|
||||||
cnx = context.GetDBConnexion(autocommit=False)
|
cnx = context.GetDBConnexion(autocommit=False)
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
args = {"formsemestre_id": formsemestre_id, "etudid": etudid}
|
args = {"formsemestre_id": formsemestre_id, "etudid": etudid}
|
||||||
try:
|
try:
|
||||||
# -- Validation du semestre et des UEs
|
# -- Validation du semestre et des UEs
|
||||||
@ -1246,7 +1245,7 @@ def do_formsemestre_validate_previous_ue(
|
|||||||
|
|
||||||
def _invalidate_etud_formation_caches(context, etudid, formation_id):
|
def _invalidate_etud_formation_caches(context, etudid, formation_id):
|
||||||
"Invalide tous les semestres de cette formation où l'etudiant est inscrit..."
|
"Invalide tous les semestres de cette formation où l'etudiant est inscrit..."
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"""SELECT sem.*
|
"""SELECT sem.*
|
||||||
FROM notes_formsemestre sem, notes_formsemestre_inscription i
|
FROM notes_formsemestre sem, notes_formsemestre_inscription i
|
||||||
@ -1264,7 +1263,7 @@ def _invalidate_etud_formation_caches(context, etudid, formation_id):
|
|||||||
|
|
||||||
def get_etud_ue_cap_html(context, etudid, formsemestre_id, ue_id, REQUEST=None):
|
def get_etud_ue_cap_html(context, etudid, formsemestre_id, ue_id, REQUEST=None):
|
||||||
"""Ramene bout de HTML pour pouvoir supprimer une validation de cette UE"""
|
"""Ramene bout de HTML pour pouvoir supprimer une validation de cette UE"""
|
||||||
valids = SimpleDictFetch(
|
valids = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"""SELECT SFV.* FROM scolar_formsemestre_validation SFV
|
"""SELECT SFV.* FROM scolar_formsemestre_validation SFV
|
||||||
WHERE ue_id=%(ue_id)s AND etudid=%(etudid)s""",
|
WHERE ue_id=%(ue_id)s AND etudid=%(etudid)s""",
|
||||||
@ -1276,7 +1275,7 @@ def get_etud_ue_cap_html(context, etudid, formsemestre_id, ue_id, REQUEST=None):
|
|||||||
'<div class="existing_valids"><span>Validations existantes pour cette UE:</span><ul>'
|
'<div class="existing_valids"><span>Validations existantes pour cette UE:</span><ul>'
|
||||||
]
|
]
|
||||||
for valid in valids:
|
for valid in valids:
|
||||||
valid["event_date"] = DateISOtoDMY(valid["event_date"])
|
valid["event_date"] = ndb.DateISOtoDMY(valid["event_date"])
|
||||||
if valid["moy_ue"] != None:
|
if valid["moy_ue"] != None:
|
||||||
valid["m"] = ", moyenne %(moy_ue)g/20" % valid
|
valid["m"] = ", moyenne %(moy_ue)g/20" % valid
|
||||||
else:
|
else:
|
||||||
@ -1301,7 +1300,7 @@ def etud_ue_suppress_validation(context, etudid, formsemestre_id, ue_id, REQUEST
|
|||||||
"""Suppress a validation (ue_id, etudid) and redirect to formsemestre"""
|
"""Suppress a validation (ue_id, etudid) and redirect to formsemestre"""
|
||||||
log("etud_ue_suppress_validation( %s, %s, %s)" % (etudid, formsemestre_id, ue_id))
|
log("etud_ue_suppress_validation( %s, %s, %s)" % (etudid, formsemestre_id, ue_id))
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"DELETE FROM scolar_formsemestre_validation WHERE etudid=%(etudid)s and ue_id=%(ue_id)s",
|
"DELETE FROM scolar_formsemestre_validation WHERE etudid=%(etudid)s and ue_id=%(ue_id)s",
|
||||||
{"etudid": etudid, "ue_id": ue_id},
|
{"etudid": etudid, "ue_id": ue_id},
|
||||||
@ -1327,7 +1326,7 @@ def check_formation_ues(context, formation_id):
|
|||||||
ue_multiples = {} # { ue_id : [ liste des formsemestre ] }
|
ue_multiples = {} # { ue_id : [ liste des formsemestre ] }
|
||||||
for ue in ues:
|
for ue in ues:
|
||||||
# formsemestres utilisant cette ue ?
|
# formsemestres utilisant cette ue ?
|
||||||
sems = SimpleDictFetch(
|
sems = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"""SELECT DISTINCT sem.*
|
"""SELECT DISTINCT sem.*
|
||||||
FROM notes_formsemestre sem, notes_modules mod, notes_moduleimpl mi
|
FROM notes_formsemestre sem, notes_modules mod, notes_moduleimpl mi
|
||||||
|
@ -32,7 +32,7 @@ import operator
|
|||||||
import traceback
|
import traceback
|
||||||
from types import FloatType, IntType, LongType, StringType
|
from types import FloatType, IntType, LongType, StringType
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
|
|
||||||
|
|
||||||
|
124
sco_groups.py
124
sco_groups.py
@ -33,22 +33,27 @@ Optimisation possible:
|
|||||||
et éviter ainsi l'appel ulterieur à get_etud_groups() dans _make_table_notes
|
et éviter ainsi l'appel ulterieur à get_etud_groups() dans _make_table_notes
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import time
|
||||||
import re, sets
|
import collections
|
||||||
|
import re
|
||||||
|
import sets
|
||||||
import operator
|
import operator
|
||||||
|
|
||||||
# XML generation package (apt-get install jaxml)
|
# XML generation package (apt-get install jaxml)
|
||||||
import jaxml
|
import jaxml
|
||||||
import xml.dom.minidom
|
import xml.dom.minidom
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from scolog import logdb
|
from scolog import logdb
|
||||||
from TrivialFormulator import TrivialFormulator, TF
|
from TrivialFormulator import TrivialFormulator, TF
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import scolars
|
import scolars
|
||||||
import sco_parcours_dut
|
import sco_parcours_dut
|
||||||
|
import sco_codes_parcours
|
||||||
|
from sco_permissions import ScoEtudChangeGroups
|
||||||
|
from sco_exceptions import ScoException, AccessDenied, ScoValueError
|
||||||
|
|
||||||
|
|
||||||
def can_change_groups(context, REQUEST, formsemestre_id):
|
def can_change_groups(context, REQUEST, formsemestre_id):
|
||||||
@ -70,13 +75,14 @@ def checkGroupName(
|
|||||||
): # XXX unused: now allow any string as a group or partition name
|
): # XXX unused: now allow any string as a group or partition name
|
||||||
"Raises exception if not a valid group name"
|
"Raises exception if not a valid group name"
|
||||||
if groupName and (
|
if groupName and (
|
||||||
not re.match(r"^\w+$", groupName) or (simplesqlquote(groupName) != groupName)
|
not re.match(r"^\w+$", groupName)
|
||||||
|
or (scu.simplesqlquote(groupName) != groupName)
|
||||||
):
|
):
|
||||||
log("!!! invalid group name: " + groupName)
|
log("!!! invalid group name: " + groupName)
|
||||||
raise ValueError("invalid group name: " + groupName)
|
raise ValueError("invalid group name: " + groupName)
|
||||||
|
|
||||||
|
|
||||||
partitionEditor = EditableTable(
|
partitionEditor = ndb.EditableTable(
|
||||||
"partition",
|
"partition",
|
||||||
"partition_id",
|
"partition_id",
|
||||||
(
|
(
|
||||||
@ -90,7 +96,7 @@ partitionEditor = EditableTable(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
groupEditor = EditableTable(
|
groupEditor = ndb.EditableTable(
|
||||||
"group_descr", "group_id", ("group_id", "partition_id", "group_name")
|
"group_descr", "group_id", ("group_id", "partition_id", "group_name")
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -99,7 +105,7 @@ group_list = groupEditor.list
|
|||||||
|
|
||||||
def get_group(context, group_id):
|
def get_group(context, group_id):
|
||||||
"""Returns group object, with partition"""
|
"""Returns group object, with partition"""
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT gd.*, p.* FROM group_descr gd, partition p WHERE gd.group_id=%(group_id)s AND p.partition_id = gd.partition_id",
|
"SELECT gd.*, p.* FROM group_descr gd, partition p WHERE gd.group_id=%(group_id)s AND p.partition_id = gd.partition_id",
|
||||||
{"group_id": group_id},
|
{"group_id": group_id},
|
||||||
@ -114,15 +120,17 @@ def group_delete(context, group, force=False):
|
|||||||
# if not group['group_name'] and not force:
|
# if not group['group_name'] and not force:
|
||||||
# raise ValueError('cannot suppress this group')
|
# raise ValueError('cannot suppress this group')
|
||||||
# remove memberships:
|
# remove memberships:
|
||||||
SimpleQuery(
|
ndb.SimpleQuery(
|
||||||
context, "DELETE FROM group_membership WHERE group_id=%(group_id)s", group
|
context, "DELETE FROM group_membership WHERE group_id=%(group_id)s", group
|
||||||
)
|
)
|
||||||
# delete group:
|
# delete group:
|
||||||
SimpleQuery(context, "DELETE FROM group_descr WHERE group_id=%(group_id)s", group)
|
ndb.SimpleQuery(
|
||||||
|
context, "DELETE FROM group_descr WHERE group_id=%(group_id)s", group
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_partition(context, partition_id):
|
def get_partition(context, partition_id):
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT p.* FROM partition p WHERE p.partition_id = %(partition_id)s",
|
"SELECT p.* FROM partition p WHERE p.partition_id = %(partition_id)s",
|
||||||
{"partition_id": partition_id},
|
{"partition_id": partition_id},
|
||||||
@ -134,7 +142,7 @@ def get_partition(context, partition_id):
|
|||||||
|
|
||||||
def get_partitions_list(context, formsemestre_id, with_default=True):
|
def get_partitions_list(context, formsemestre_id, with_default=True):
|
||||||
"""Liste des partitions pour ce semestre (list of dicts)"""
|
"""Liste des partitions pour ce semestre (list of dicts)"""
|
||||||
partitions = SimpleDictFetch(
|
partitions = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT * FROM partition WHERE formsemestre_id=%(formsemestre_id)s order by numero",
|
"SELECT * FROM partition WHERE formsemestre_id=%(formsemestre_id)s order by numero",
|
||||||
{"formsemestre_id": formsemestre_id},
|
{"formsemestre_id": formsemestre_id},
|
||||||
@ -148,7 +156,7 @@ def get_partitions_list(context, formsemestre_id, with_default=True):
|
|||||||
|
|
||||||
def get_default_partition(context, formsemestre_id):
|
def get_default_partition(context, formsemestre_id):
|
||||||
"""Get partition for 'all' students (this one always exists, with NULL name)"""
|
"""Get partition for 'all' students (this one always exists, with NULL name)"""
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT * FROM partition WHERE formsemestre_id=%(formsemestre_id)s AND partition_name is NULL",
|
"SELECT * FROM partition WHERE formsemestre_id=%(formsemestre_id)s AND partition_name is NULL",
|
||||||
{"formsemestre_id": formsemestre_id},
|
{"formsemestre_id": formsemestre_id},
|
||||||
@ -176,7 +184,7 @@ def get_formsemestre_groups(context, formsemestre_id, with_default=False):
|
|||||||
def get_partition_groups(context, partition):
|
def get_partition_groups(context, partition):
|
||||||
"""List of groups in this partition (list of dicts).
|
"""List of groups in this partition (list of dicts).
|
||||||
Some groups may be empty."""
|
Some groups may be empty."""
|
||||||
return SimpleDictFetch(
|
return ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT gd.*, p.* FROM group_descr gd, partition p WHERE gd.partition_id=%(partition_id)s AND gd.partition_id=p.partition_id ORDER BY group_name",
|
"SELECT gd.*, p.* FROM group_descr gd, partition p WHERE gd.partition_id=%(partition_id)s AND gd.partition_id=p.partition_id ORDER BY group_name",
|
||||||
partition,
|
partition,
|
||||||
@ -185,7 +193,7 @@ def get_partition_groups(context, partition):
|
|||||||
|
|
||||||
def get_default_group(context, formsemestre_id, fix_if_missing=False, REQUEST=None):
|
def get_default_group(context, formsemestre_id, fix_if_missing=False, REQUEST=None):
|
||||||
"""Returns group_id for default ('tous') group"""
|
"""Returns group_id for default ('tous') group"""
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT gd.group_id FROM group_descr gd, partition p WHERE p.formsemestre_id=%(formsemestre_id)s AND p.partition_name is NULL AND p.partition_id = gd.partition_id",
|
"SELECT gd.group_id FROM group_descr gd, partition p WHERE p.formsemestre_id=%(formsemestre_id)s AND p.partition_name is NULL AND p.partition_id = gd.partition_id",
|
||||||
{"formsemestre_id": formsemestre_id},
|
{"formsemestre_id": formsemestre_id},
|
||||||
@ -217,7 +225,7 @@ def get_default_group(context, formsemestre_id, fix_if_missing=False, REQUEST=No
|
|||||||
|
|
||||||
def get_sem_groups(context, formsemestre_id):
|
def get_sem_groups(context, formsemestre_id):
|
||||||
"""Returns groups for this sem (in all partitions)."""
|
"""Returns groups for this sem (in all partitions)."""
|
||||||
return SimpleDictFetch(
|
return ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT gd.*, p.* FROM group_descr gd, partition p WHERE p.formsemestre_id=%(formsemestre_id)s AND p.partition_id = gd.partition_id",
|
"SELECT gd.*, p.* FROM group_descr gd, partition p WHERE p.formsemestre_id=%(formsemestre_id)s AND p.partition_id = gd.partition_id",
|
||||||
{"formsemestre_id": formsemestre_id},
|
{"formsemestre_id": formsemestre_id},
|
||||||
@ -233,14 +241,14 @@ def get_group_members(context, group_id, etat=None):
|
|||||||
if etat is not None:
|
if etat is not None:
|
||||||
req += " and ins.etat = %(etat)s"
|
req += " and ins.etat = %(etat)s"
|
||||||
|
|
||||||
r = SimpleDictFetch(context, req, {"group_id": group_id, "etat": etat})
|
r = ndb.SimpleDictFetch(context, req, {"group_id": group_id, "etat": etat})
|
||||||
|
|
||||||
for etud in r:
|
for etud in r:
|
||||||
scolars.format_etud_ident(etud)
|
scolars.format_etud_ident(etud)
|
||||||
|
|
||||||
r.sort(key=operator.itemgetter("nom_disp", "prenom")) # tri selon nom_usuel ou nom
|
r.sort(key=operator.itemgetter("nom_disp", "prenom")) # tri selon nom_usuel ou nom
|
||||||
|
|
||||||
if CONFIG.ALLOW_NULL_PRENOM:
|
if scu.CONFIG.ALLOW_NULL_PRENOM:
|
||||||
for x in r:
|
for x in r:
|
||||||
x["prenom"] = x["prenom"] or ""
|
x["prenom"] = x["prenom"] or ""
|
||||||
|
|
||||||
@ -294,7 +302,7 @@ def get_group_infos(context, group_id, etat=None): # was _getlisteetud
|
|||||||
else:
|
else:
|
||||||
t["etath"] = "(dem.)"
|
t["etath"] = "(dem.)"
|
||||||
nbdem += 1
|
nbdem += 1
|
||||||
elif t["etat"] == DEF:
|
elif t["etat"] == sco_codes_parcours.DEF:
|
||||||
t["etath"] = "Défaillant"
|
t["etath"] = "Défaillant"
|
||||||
else:
|
else:
|
||||||
t["etath"] = t["etat"]
|
t["etath"] = t["etat"]
|
||||||
@ -329,7 +337,7 @@ def get_etud_groups(context, etudid, sem, exclude_default=False):
|
|||||||
req = "SELECT p.*, g.* from group_descr g, partition p, group_membership gm WHERE gm.etudid=%(etudid)s and gm.group_id = g.group_id and g.partition_id = p.partition_id and p.formsemestre_id = %(formsemestre_id)s"
|
req = "SELECT p.*, g.* from group_descr g, partition p, group_membership gm WHERE gm.etudid=%(etudid)s and gm.group_id = g.group_id and g.partition_id = p.partition_id and p.formsemestre_id = %(formsemestre_id)s"
|
||||||
if exclude_default:
|
if exclude_default:
|
||||||
req += " and p.partition_name is not NULL"
|
req += " and p.partition_name is not NULL"
|
||||||
groups = SimpleDictFetch(
|
groups = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
req + " ORDER BY p.numero",
|
req + " ORDER BY p.numero",
|
||||||
{"etudid": etudid, "formsemestre_id": sem["formsemestre_id"]},
|
{"etudid": etudid, "formsemestre_id": sem["formsemestre_id"]},
|
||||||
@ -357,7 +365,7 @@ def formsemestre_get_etud_groupnames(context, formsemestre_id, attr="group_name"
|
|||||||
"""Recupere les groupes de tous les etudiants d'un semestre
|
"""Recupere les groupes de tous les etudiants d'un semestre
|
||||||
{ etudid : { partition_id : group_name }} (attr=group_name or group_id)
|
{ etudid : { partition_id : group_name }} (attr=group_name or group_id)
|
||||||
"""
|
"""
|
||||||
infos = SimpleDictFetch(
|
infos = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"select i.etudid, p.partition_id, gd.group_name, gd.group_id from notes_formsemestre_inscription i, partition p, group_descr gd, group_membership gm where i.formsemestre_id=%(formsemestre_id)s and i.formsemestre_id=p.formsemestre_id and p.partition_id=gd.partition_id and gm.etudid=i.etudid and gm.group_id = gd.group_id and p.partition_name is not NULL",
|
"select i.etudid, p.partition_id, gd.group_name, gd.group_id from notes_formsemestre_inscription i, partition p, group_descr gd, group_membership gm where i.formsemestre_id=%(formsemestre_id)s and i.formsemestre_id=p.formsemestre_id and p.partition_id=gd.partition_id and gm.etudid=i.etudid and gm.group_id = gd.group_id and p.partition_name is not NULL",
|
||||||
{"formsemestre_id": formsemestre_id},
|
{"formsemestre_id": formsemestre_id},
|
||||||
@ -380,7 +388,7 @@ def etud_add_group_infos(context, etud, sem, sep=" "):
|
|||||||
etud["groupes"] = ""
|
etud["groupes"] = ""
|
||||||
return etud
|
return etud
|
||||||
|
|
||||||
infos = SimpleDictFetch(
|
infos = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT p.partition_name, g.* from group_descr g, partition p, group_membership gm WHERE gm.etudid=%(etudid)s and gm.group_id = g.group_id and g.partition_id = p.partition_id and p.formsemestre_id = %(formsemestre_id)s ORDER BY p.numero",
|
"SELECT p.partition_name, g.* from group_descr g, partition p, group_membership gm WHERE gm.etudid=%(etudid)s and gm.group_id = g.group_id and g.partition_id = p.partition_id and p.formsemestre_id = %(formsemestre_id)s ORDER BY p.numero",
|
||||||
{"etudid": etud["etudid"], "formsemestre_id": sem["formsemestre_id"]},
|
{"etudid": etud["etudid"], "formsemestre_id": sem["formsemestre_id"]},
|
||||||
@ -407,7 +415,7 @@ def etud_add_group_infos(context, etud, sem, sep=" "):
|
|||||||
|
|
||||||
def get_etud_groups_in_partition(context, partition_id):
|
def get_etud_groups_in_partition(context, partition_id):
|
||||||
"""Returns { etudid : group }, with all students in this partition"""
|
"""Returns { etudid : group }, with all students in this partition"""
|
||||||
infos = SimpleDictFetch(
|
infos = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT gd.*, etudid from group_descr gd, group_membership gm where gd.partition_id = %(partition_id)s and gm.group_id = gd.group_id",
|
"SELECT gd.*, etudid from group_descr gd, group_membership gm where gd.partition_id = %(partition_id)s and gm.group_id = gd.group_id",
|
||||||
{"partition_id": partition_id},
|
{"partition_id": partition_id},
|
||||||
@ -426,7 +434,7 @@ def formsemestre_partition_list(context, formsemestre_id, format="xml", REQUEST=
|
|||||||
# Ajoute les groupes
|
# Ajoute les groupes
|
||||||
for p in partitions:
|
for p in partitions:
|
||||||
p["group"] = get_partition_groups(context, p)
|
p["group"] = get_partition_groups(context, p)
|
||||||
return sendResult(REQUEST, partitions, name="partition", format=format)
|
return scu.sendResult(REQUEST, partitions, name="partition", format=format)
|
||||||
|
|
||||||
|
|
||||||
def XMLgetGroupsInPartition(context, partition_id, REQUEST=None): # was XMLgetGroupesTD
|
def XMLgetGroupsInPartition(context, partition_id, REQUEST=None): # was XMLgetGroupesTD
|
||||||
@ -447,8 +455,8 @@ def XMLgetGroupsInPartition(context, partition_id, REQUEST=None): # was XMLgetG
|
|||||||
) # > inscrdict
|
) # > inscrdict
|
||||||
etuds_set = set(nt.inscrdict)
|
etuds_set = set(nt.inscrdict)
|
||||||
# XML response:
|
# XML response:
|
||||||
REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE)
|
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
|
||||||
doc = jaxml.XML_document(encoding=SCO_ENCODING)
|
doc = jaxml.XML_document(encoding=scu.SCO_ENCODING)
|
||||||
doc._text('<ajax-response><response type="object" id="MyUpdater">')
|
doc._text('<ajax-response><response type="object" id="MyUpdater">')
|
||||||
doc._push()
|
doc._push()
|
||||||
|
|
||||||
@ -465,7 +473,8 @@ def XMLgetGroupsInPartition(context, partition_id, REQUEST=None): # was XMLgetG
|
|||||||
doc._push()
|
doc._push()
|
||||||
doc.etud(
|
doc.etud(
|
||||||
etudid=e["etudid"],
|
etudid=e["etudid"],
|
||||||
sexe=scolars.format_sexe(etud["sexe"]),
|
civilite=etud["civilite_str"],
|
||||||
|
sexe=etud["civilite_str"], # compat
|
||||||
nom=scolars.format_nom(etud["nom"]),
|
nom=scolars.format_nom(etud["nom"]),
|
||||||
prenom=scolars.format_prenom(etud["prenom"]),
|
prenom=scolars.format_prenom(etud["prenom"]),
|
||||||
origin=comp_origin(etud, sem),
|
origin=comp_origin(etud, sem),
|
||||||
@ -489,7 +498,7 @@ def XMLgetGroupsInPartition(context, partition_id, REQUEST=None): # was XMLgetG
|
|||||||
doc._push()
|
doc._push()
|
||||||
doc.etud(
|
doc.etud(
|
||||||
etudid=etud["etudid"],
|
etudid=etud["etudid"],
|
||||||
sexe=scolars.format_sexe(etud["sexe"]),
|
sexe=etud["civilite_str"],
|
||||||
nom=scolars.format_nom(etud["nom"]),
|
nom=scolars.format_nom(etud["nom"]),
|
||||||
prenom=scolars.format_prenom(etud["prenom"]),
|
prenom=scolars.format_prenom(etud["prenom"]),
|
||||||
origin=comp_origin(etud, sem),
|
origin=comp_origin(etud, sem),
|
||||||
@ -530,10 +539,10 @@ def set_group(context, etudid, group_id):
|
|||||||
Warning: don't check if group_id exists (the caller should check).
|
Warning: don't check if group_id exists (the caller should check).
|
||||||
"""
|
"""
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
args = {"etudid": etudid, "group_id": group_id}
|
args = {"etudid": etudid, "group_id": group_id}
|
||||||
# déjà inscrit ?
|
# déjà inscrit ?
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT * FROM group_membership gm WHERE etudid=%(etudid)s and group_id=%(group_id)s",
|
"SELECT * FROM group_membership gm WHERE etudid=%(etudid)s and group_id=%(group_id)s",
|
||||||
args,
|
args,
|
||||||
@ -542,7 +551,7 @@ def set_group(context, etudid, group_id):
|
|||||||
if len(r):
|
if len(r):
|
||||||
return False
|
return False
|
||||||
# inscrit
|
# inscrit
|
||||||
SimpleQuery(
|
ndb.SimpleQuery(
|
||||||
context,
|
context,
|
||||||
"INSERT INTO group_membership (etudid, group_id) VALUES (%(etudid)s, %(group_id)s)",
|
"INSERT INTO group_membership (etudid, group_id) VALUES (%(etudid)s, %(group_id)s)",
|
||||||
args,
|
args,
|
||||||
@ -569,7 +578,7 @@ def change_etud_group_in_partition(
|
|||||||
else:
|
else:
|
||||||
partition = get_partition(context, group["partition_id"])
|
partition = get_partition(context, group["partition_id"])
|
||||||
# 1- Supprime membership dans cette partition
|
# 1- Supprime membership dans cette partition
|
||||||
SimpleQuery(
|
ndb.SimpleQuery(
|
||||||
context,
|
context,
|
||||||
"""DELETE FROM group_membership WHERE group_membership_id IN
|
"""DELETE FROM group_membership WHERE group_membership_id IN
|
||||||
(SELECT gm.group_membership_id
|
(SELECT gm.group_membership_id
|
||||||
@ -651,10 +660,10 @@ def setGroups(
|
|||||||
)
|
)
|
||||||
# Retire les anciens membres:
|
# Retire les anciens membres:
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
for etudid in old_members_set:
|
for etudid in old_members_set:
|
||||||
log("removing %s from group %s" % (etudid, group_id))
|
log("removing %s from group %s" % (etudid, group_id))
|
||||||
SimpleQuery(
|
ndb.SimpleQuery(
|
||||||
context,
|
context,
|
||||||
"DELETE FROM group_membership WHERE etudid=%(etudid)s and group_id=%(group_id)s",
|
"DELETE FROM group_membership WHERE etudid=%(etudid)s and group_id=%(group_id)s",
|
||||||
{"etudid": etudid, "group_id": group_id},
|
{"etudid": etudid, "group_id": group_id},
|
||||||
@ -680,7 +689,7 @@ def setGroups(
|
|||||||
if not group_name:
|
if not group_name:
|
||||||
continue
|
continue
|
||||||
# ajax arguments are encoded in utf-8:
|
# ajax arguments are encoded in utf-8:
|
||||||
group_name = unicode(group_name, "utf-8").encode(SCO_ENCODING)
|
group_name = unicode(group_name, "utf-8").encode(scu.SCO_ENCODING)
|
||||||
group_id = createGroup(context, partition_id, group_name, REQUEST=REQUEST)
|
group_id = createGroup(context, partition_id, group_name, REQUEST=REQUEST)
|
||||||
# Place dans ce groupe les etudiants indiqués:
|
# Place dans ce groupe les etudiants indiqués:
|
||||||
for etudid in fs[1:-1]:
|
for etudid in fs[1:-1]:
|
||||||
@ -688,7 +697,7 @@ def setGroups(
|
|||||||
context, etudid, group_id, partition, REQUEST=REQUEST
|
context, etudid, group_id, partition, REQUEST=REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE)
|
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
|
||||||
return (
|
return (
|
||||||
'<?xml version="1.0" encoding="utf-8"?><response>Groupes enregistrés</response>'
|
'<?xml version="1.0" encoding="utf-8"?><response>Groupes enregistrés</response>'
|
||||||
)
|
)
|
||||||
@ -790,9 +799,9 @@ def partition_create(
|
|||||||
def getArrowIconsTags(context, REQUEST):
|
def getArrowIconsTags(context, REQUEST):
|
||||||
"""returns html tags for arrows"""
|
"""returns html tags for arrows"""
|
||||||
#
|
#
|
||||||
arrow_up = icontag("arrow_up", title="remonter")
|
arrow_up = scu.icontag("arrow_up", title="remonter")
|
||||||
arrow_down = icontag("arrow_down", title="descendre")
|
arrow_down = scu.icontag("arrow_down", title="descendre")
|
||||||
arrow_none = icontag("arrow_none", title="")
|
arrow_none = scu.icontag("arrow_none", title="")
|
||||||
|
|
||||||
return arrow_up, arrow_down, arrow_none
|
return arrow_up, arrow_down, arrow_none
|
||||||
|
|
||||||
@ -804,7 +813,7 @@ def editPartitionForm(context, formsemestre_id=None, REQUEST=None):
|
|||||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||||
partitions = get_partitions_list(context, formsemestre_id)
|
partitions = get_partitions_list(context, formsemestre_id)
|
||||||
arrow_up, arrow_down, arrow_none = getArrowIconsTags(context, REQUEST)
|
arrow_up, arrow_down, arrow_none = getArrowIconsTags(context, REQUEST)
|
||||||
suppricon = icontag(
|
suppricon = scu.icontag(
|
||||||
"delete_small_img", border="0", alt="supprimer", title="Supprimer"
|
"delete_small_img", border="0", alt="supprimer", title="Supprimer"
|
||||||
)
|
)
|
||||||
#
|
#
|
||||||
@ -1079,7 +1088,7 @@ def partition_set_name(context, partition_id, partition_name, REQUEST=None, redi
|
|||||||
formsemestre_id = partition["formsemestre_id"]
|
formsemestre_id = partition["formsemestre_id"]
|
||||||
|
|
||||||
# check unicity
|
# check unicity
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT p.* FROM partition p WHERE p.partition_name = %(partition_name)s AND formsemestre_id = %(formsemestre_id)s",
|
"SELECT p.* FROM partition p WHERE p.partition_name = %(partition_name)s AND formsemestre_id = %(formsemestre_id)s",
|
||||||
{"partition_name": partition_name, "formsemestre_id": formsemestre_id},
|
{"partition_name": partition_name, "formsemestre_id": formsemestre_id},
|
||||||
@ -1177,6 +1186,8 @@ def groups_auto_repartition(context, partition_id=None, REQUEST=None):
|
|||||||
"""
|
"""
|
||||||
partition = get_partition(context, partition_id)
|
partition = get_partition(context, partition_id)
|
||||||
formsemestre_id = partition["formsemestre_id"]
|
formsemestre_id = partition["formsemestre_id"]
|
||||||
|
# renvoie sur page édition groupes
|
||||||
|
dest_url = "affectGroups?partition_id=%s" % partition_id
|
||||||
if not can_change_groups(context, REQUEST, formsemestre_id):
|
if not can_change_groups(context, REQUEST, formsemestre_id):
|
||||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||||
@ -1217,7 +1228,7 @@ def groups_auto_repartition(context, partition_id=None, REQUEST=None):
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + "\n" + tf[1] + context.sco_footer(REQUEST)
|
return "\n".join(H) + "\n" + tf[1] + context.sco_footer(REQUEST)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1)
|
return REQUEST.RESPONSE.redirect(dest_url)
|
||||||
else:
|
else:
|
||||||
# form submission
|
# form submission
|
||||||
log(
|
log(
|
||||||
@ -1245,34 +1256,33 @@ def groups_auto_repartition(context, partition_id=None, REQUEST=None):
|
|||||||
context.Notes, formsemestre_id
|
context.Notes, formsemestre_id
|
||||||
) # > identdict
|
) # > identdict
|
||||||
identdict = nt.identdict
|
identdict = nt.identdict
|
||||||
# build: { sexe : liste etudids trie par niveau croissant }
|
# build: { civilite : liste etudids trie par niveau croissant }
|
||||||
sexes = sets.Set([x["sexe"] for x in identdict.values()])
|
civilites = sets.Set([x["civilite"] for x in identdict.values()])
|
||||||
listes = {}
|
listes = {}
|
||||||
for sexe in sexes:
|
for civilite in civilites:
|
||||||
listes[sexe] = [
|
listes[civilite] = [
|
||||||
(get_prev_moy(context.Notes, x["etudid"], formsemestre_id), x["etudid"])
|
(get_prev_moy(context.Notes, x["etudid"], formsemestre_id), x["etudid"])
|
||||||
for x in identdict.values()
|
for x in identdict.values()
|
||||||
if x["sexe"] == sexe
|
if x["civilite"] == civilite
|
||||||
]
|
]
|
||||||
listes[sexe].sort()
|
listes[civilite].sort()
|
||||||
log("listes[%s] = %s" % (sexe, listes[sexe]))
|
log("listes[%s] = %s" % (civilite, listes[civilite]))
|
||||||
# affect aux groupes:
|
# affect aux groupes:
|
||||||
n = len(identdict)
|
n = len(identdict)
|
||||||
igroup = 0
|
igroup = 0
|
||||||
nbgroups = len(group_ids)
|
nbgroups = len(group_ids)
|
||||||
while n > 0:
|
while n > 0:
|
||||||
for sexe in sexes:
|
for civilite in civilites:
|
||||||
if len(listes[sexe]):
|
if len(listes[civilite]):
|
||||||
n -= 1
|
n -= 1
|
||||||
etudid = listes[sexe].pop()[1]
|
etudid = listes[civilite].pop()[1]
|
||||||
group_id = group_ids[igroup]
|
group_id = group_ids[igroup]
|
||||||
igroup = (igroup + 1) % nbgroups
|
igroup = (igroup + 1) % nbgroups
|
||||||
change_etud_group_in_partition(
|
change_etud_group_in_partition(
|
||||||
context, etudid, group_id, partition, REQUEST=REQUEST
|
context, etudid, group_id, partition, REQUEST=REQUEST
|
||||||
)
|
)
|
||||||
log("%s in group %s" % (etudid, group_id))
|
log("%s in group %s" % (etudid, group_id))
|
||||||
# envoie sur page edition groupes
|
return REQUEST.RESPONSE.redirect(dest_url)
|
||||||
return REQUEST.RESPONSE.redirect("affectGroups?partition_id=%s" % partition_id)
|
|
||||||
|
|
||||||
|
|
||||||
def get_prev_moy(context, etudid, formsemestre_id):
|
def get_prev_moy(context, etudid, formsemestre_id):
|
||||||
@ -1374,7 +1384,7 @@ def do_evaluation_listeetuds_groups(
|
|||||||
req += " and Isem.etat='I'"
|
req += " and Isem.etat='I'"
|
||||||
req += r
|
req += r
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(req, {"evaluation_id": evaluation_id})
|
cursor.execute(req, {"evaluation_id": evaluation_id})
|
||||||
# log('listeetuds_groups: getallstudents=%s groups=%s' % (getallstudents,groups))
|
# log('listeetuds_groups: getallstudents=%s groups=%s' % (getallstudents,groups))
|
||||||
# log('req=%s' % (req % { 'evaluation_id' : "'"+evaluation_id+"'" }))
|
# log('req=%s' % (req % { 'evaluation_id' : "'"+evaluation_id+"'" }))
|
||||||
@ -1393,7 +1403,7 @@ def do_evaluation_listegroupes(context, evaluation_id, include_default=False):
|
|||||||
else:
|
else:
|
||||||
c = " AND p.partition_name is not NULL"
|
c = " AND p.partition_name is not NULL"
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"SELECT DISTINCT gd.group_id FROM group_descr gd, group_membership gm, partition p, notes_moduleimpl m, notes_evaluation e WHERE gm.group_id = gd.group_id and gd.partition_id = p.partition_id and p.formsemestre_id = m.formsemestre_id and m.moduleimpl_id = e.moduleimpl_id and e.evaluation_id = %(evaluation_id)s"
|
"SELECT DISTINCT gd.group_id FROM group_descr gd, group_membership gm, partition p, notes_moduleimpl m, notes_evaluation e WHERE gm.group_id = gd.group_id and gd.partition_id = p.partition_id and p.formsemestre_id = m.formsemestre_id and m.moduleimpl_id = e.moduleimpl_id and e.evaluation_id = %(evaluation_id)s"
|
||||||
+ c,
|
+ c,
|
||||||
@ -1406,7 +1416,7 @@ def do_evaluation_listegroupes(context, evaluation_id, include_default=False):
|
|||||||
|
|
||||||
def listgroups(context, group_ids):
|
def listgroups(context, group_ids):
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
groups = []
|
groups = []
|
||||||
for group_id in group_ids:
|
for group_id in group_ids:
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
|
@ -30,11 +30,12 @@
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_groups
|
import sco_groups
|
||||||
|
from sco_exceptions import AccessDenied
|
||||||
|
|
||||||
|
|
||||||
def affectGroups(context, partition_id, REQUEST=None):
|
def affectGroups(context, partition_id, REQUEST=None):
|
||||||
|
@ -464,8 +464,9 @@ def groups_table(
|
|||||||
% (with_paiement, with_archives, with_annotations)
|
% (with_paiement, with_archives, with_annotations)
|
||||||
)
|
)
|
||||||
#
|
#
|
||||||
columns_ids = ["nom_disp", "prenom"] # colonnes a inclure
|
columns_ids = ["civilite_str", "nom_disp", "prenom"] # colonnes a inclure
|
||||||
titles = {
|
titles = {
|
||||||
|
"civilite_str": "Civ.",
|
||||||
"nom_disp": "Nom",
|
"nom_disp": "Nom",
|
||||||
"prenom": "Prénom",
|
"prenom": "Prénom",
|
||||||
"email": "Mail",
|
"email": "Mail",
|
||||||
@ -733,7 +734,7 @@ def groups_table(
|
|||||||
"etudid",
|
"etudid",
|
||||||
"code_nip",
|
"code_nip",
|
||||||
"etat",
|
"etat",
|
||||||
"sexe",
|
"civilite_str",
|
||||||
"nom",
|
"nom",
|
||||||
"nom_usuel",
|
"nom_usuel",
|
||||||
"prenom",
|
"prenom",
|
||||||
|
@ -28,12 +28,18 @@
|
|||||||
"""Import d'utilisateurs via fichier Excel
|
"""Import d'utilisateurs via fichier Excel
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from notesdb import *
|
import email
|
||||||
from sco_utils import *
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
from email.header import Header
|
||||||
|
|
||||||
|
import notesdb as ndb
|
||||||
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from TrivialFormulator import TrivialFormulator, TF
|
from TrivialFormulator import TrivialFormulator, TF
|
||||||
import sco_news
|
import sco_news
|
||||||
import sco_excel
|
import sco_excel
|
||||||
|
from sco_exceptions import AccessDenied, ScoValueError, ScoException
|
||||||
|
|
||||||
TITLES = ("user_name", "nom", "prenom", "email", "roles", "dept")
|
TITLES = ("user_name", "nom", "prenom", "email", "roles", "dept")
|
||||||
|
|
||||||
@ -66,11 +72,11 @@ def import_excel_file(datafile, REQUEST=None, context=None):
|
|||||||
exceldata = datafile.read()
|
exceldata = datafile.read()
|
||||||
if not exceldata:
|
if not exceldata:
|
||||||
raise ScoValueError("Ficher excel vide ou invalide")
|
raise ScoValueError("Ficher excel vide ou invalide")
|
||||||
diag, data = sco_excel.Excel_to_list(exceldata)
|
_, data = sco_excel.Excel_to_list(exceldata)
|
||||||
if not data: # probably a bug
|
if not data: # probably a bug
|
||||||
raise ScoException("import_excel_file: empty file !")
|
raise ScoException("import_excel_file: empty file !")
|
||||||
# 1- --- check title line
|
# 1- --- check title line
|
||||||
fs = [strlower(stripquotes(s)) for s in data[0]]
|
fs = [scu.strlower(scu.stripquotes(s)) for s in data[0]]
|
||||||
log("excel: fs='%s'\ndata=%s" % (str(fs), str(data)))
|
log("excel: fs='%s'\ndata=%s" % (str(fs), str(data)))
|
||||||
# check cols
|
# check cols
|
||||||
cols = {}.fromkeys(TITLES)
|
cols = {}.fromkeys(TITLES)
|
||||||
@ -163,13 +169,6 @@ def generate_password():
|
|||||||
return "".join(RNG.sample(l, PASSLEN))
|
return "".join(RNG.sample(l, PASSLEN))
|
||||||
|
|
||||||
|
|
||||||
import email
|
|
||||||
from email.mime.multipart import MIMEMultipart
|
|
||||||
from email.mime.text import MIMEText
|
|
||||||
from email.mime.base import MIMEBase
|
|
||||||
from email.header import Header
|
|
||||||
|
|
||||||
|
|
||||||
def mail_password(u, context=None, reset=False):
|
def mail_password(u, context=None, reset=False):
|
||||||
"Send password by email"
|
"Send password by email"
|
||||||
if not u["email"]:
|
if not u["email"]:
|
||||||
@ -220,16 +219,16 @@ ScoDoc est un logiciel libre développé à l'Université Paris 13 par Emmanuel
|
|||||||
Pour plus d'informations sur ce logiciel, voir %s
|
Pour plus d'informations sur ce logiciel, voir %s
|
||||||
|
|
||||||
"""
|
"""
|
||||||
% SCO_WEBSITE
|
% scu.SCO_WEBSITE
|
||||||
)
|
)
|
||||||
msg = MIMEMultipart()
|
msg = MIMEMultipart()
|
||||||
if reset:
|
if reset:
|
||||||
msg["Subject"] = Header("Mot de passe ScoDoc", SCO_ENCODING)
|
msg["Subject"] = Header("Mot de passe ScoDoc", scu.SCO_ENCODING)
|
||||||
else:
|
else:
|
||||||
msg["Subject"] = Header("Votre accès ScoDoc", SCO_ENCODING)
|
msg["Subject"] = Header("Votre accès ScoDoc", scu.SCO_ENCODING)
|
||||||
msg["From"] = context.get_preference("email_from_addr")
|
msg["From"] = context.get_preference("email_from_addr")
|
||||||
msg["To"] = u["email"]
|
msg["To"] = u["email"]
|
||||||
msg.epilogue = ""
|
msg.epilogue = ""
|
||||||
txt = MIMEText(txt, "plain", SCO_ENCODING)
|
txt = MIMEText(txt, "plain", scu.SCO_ENCODING)
|
||||||
msg.attach(txt)
|
msg.attach(txt)
|
||||||
context.sendEmail(msg)
|
context.sendEmail(msg)
|
||||||
|
@ -28,12 +28,12 @@
|
|||||||
"""Form. pour inscription rapide des etudiants d'un semestre dans un autre
|
"""Form. pour inscription rapide des etudiants d'un semestre dans un autre
|
||||||
Utilise les autorisations d'inscription délivrées en jury.
|
Utilise les autorisations d'inscription délivrées en jury.
|
||||||
"""
|
"""
|
||||||
|
import datetime
|
||||||
|
|
||||||
from gen_tables import GenTable
|
import notesdb as ndb
|
||||||
|
import sco_utils as scu
|
||||||
from notesdb import *
|
|
||||||
from sco_utils import *
|
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
|
from gen_tables import GenTable
|
||||||
import sco_codes_parcours
|
import sco_codes_parcours
|
||||||
import sco_pvjury
|
import sco_pvjury
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
@ -41,6 +41,7 @@ import sco_formsemestre_inscriptions
|
|||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_groups
|
import sco_groups
|
||||||
import scolars
|
import scolars
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
|
||||||
|
|
||||||
def list_authorized_etuds_by_sem(context, sem, delai=274):
|
def list_authorized_etuds_by_sem(context, sem, delai=274):
|
||||||
@ -60,7 +61,9 @@ def list_authorized_etuds_by_sem(context, sem, delai=274):
|
|||||||
auth_used = False # autorisation deja utilisée ?
|
auth_used = False # autorisation deja utilisée ?
|
||||||
etud = context.getEtudInfo(etudid=e["etudid"], filled=True)[0]
|
etud = context.getEtudInfo(etudid=e["etudid"], filled=True)[0]
|
||||||
for isem in etud["sems"]:
|
for isem in etud["sems"]:
|
||||||
if DateDMYtoISO(isem["date_debut"]) >= DateDMYtoISO(src["date_fin"]):
|
if ndb.DateDMYtoISO(isem["date_debut"]) >= ndb.DateDMYtoISO(
|
||||||
|
src["date_fin"]
|
||||||
|
):
|
||||||
auth_used = True
|
auth_used = True
|
||||||
if not auth_used:
|
if not auth_used:
|
||||||
candidats[e["etudid"]] = etud
|
candidats[e["etudid"]] = etud
|
||||||
@ -134,8 +137,8 @@ def list_inscrits_date(context, sem):
|
|||||||
SAUF sem à la date de début de sem.
|
SAUF sem à la date de début de sem.
|
||||||
"""
|
"""
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
sem["date_debut_iso"] = DateDMYtoISO(sem["date_debut"])
|
sem["date_debut_iso"] = ndb.DateDMYtoISO(sem["date_debut"])
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""select I.etudid
|
"""select I.etudid
|
||||||
from notes_formsemestre_inscription I, notes_formsemestre S
|
from notes_formsemestre_inscription I, notes_formsemestre S
|
||||||
@ -223,14 +226,9 @@ def list_source_sems(context, sem, delai=None):
|
|||||||
othersems = []
|
othersems = []
|
||||||
d, m, y = [int(x) for x in sem["date_debut"].split("/")]
|
d, m, y = [int(x) for x in sem["date_debut"].split("/")]
|
||||||
date_debut_dst = datetime.date(y, m, d)
|
date_debut_dst = datetime.date(y, m, d)
|
||||||
d, m, y = [int(x) for x in sem["date_fin"].split("/")]
|
|
||||||
date_fin_dst = datetime.date(y, m, d)
|
|
||||||
|
|
||||||
delais = datetime.timedelta(delai)
|
delais = datetime.timedelta(delai)
|
||||||
for s in sems:
|
for s in sems:
|
||||||
# pdb.set_trace()
|
|
||||||
# if s['etat'] != '1':
|
|
||||||
# continue # saute semestres pas ouverts
|
|
||||||
if s["formsemestre_id"] == sem["formsemestre_id"]:
|
if s["formsemestre_id"] == sem["formsemestre_id"]:
|
||||||
continue # saute le semestre destination
|
continue # saute le semestre destination
|
||||||
if s["date_fin"]:
|
if s["date_fin"]:
|
||||||
@ -276,9 +274,6 @@ def formsemestre_inscr_passage(
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
inscrit_groupes = int(inscrit_groupes)
|
inscrit_groupes = int(inscrit_groupes)
|
||||||
# log('formsemestre_inscr_passage: formsemestre_id=%s submitted=%s, dialog_confirmed=%s len(etuds)=%d'
|
|
||||||
# % (formsemestre_id, submitted, dialog_confirmed, len(etuds)) )
|
|
||||||
cnx = context.GetDBConnexion()
|
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||||
# -- check lock
|
# -- check lock
|
||||||
if sem["etat"] != "1":
|
if sem["etat"] != "1":
|
||||||
@ -558,7 +553,7 @@ def etuds_select_boxes(
|
|||||||
if base_url and etuds:
|
if base_url and etuds:
|
||||||
H.append(
|
H.append(
|
||||||
'<a href="%s&export_cat_xls=%s">%s</a> '
|
'<a href="%s&export_cat_xls=%s">%s</a> '
|
||||||
% (base_url, src_cat, ICON_XLS)
|
% (base_url, src_cat, scu.ICON_XLS)
|
||||||
)
|
)
|
||||||
H.append("</div>")
|
H.append("</div>")
|
||||||
for etud in etuds:
|
for etud in etuds:
|
||||||
@ -616,7 +611,7 @@ def etuds_select_boxes(
|
|||||||
def etuds_select_box_xls(context, src_cat):
|
def etuds_select_box_xls(context, src_cat):
|
||||||
"export a box to excel"
|
"export a box to excel"
|
||||||
etuds = src_cat["etuds"]
|
etuds = src_cat["etuds"]
|
||||||
columns_ids = ["etudid", "sexe", "nom", "prenom", "etape"]
|
columns_ids = ["etudid", "civilite_str", "nom", "prenom", "etape"]
|
||||||
titles = {x: x for x in columns_ids}
|
titles = {x: x for x in columns_ids}
|
||||||
|
|
||||||
# Ajoute colonne paiement inscription
|
# Ajoute colonne paiement inscription
|
||||||
|
@ -27,12 +27,13 @@
|
|||||||
|
|
||||||
"""Liste des notes d'une évaluation
|
"""Liste des notes d'une évaluation
|
||||||
"""
|
"""
|
||||||
|
import urllib
|
||||||
|
from types import StringType
|
||||||
|
|
||||||
from notesdb import *
|
import sco_utils as scu
|
||||||
from sco_utils import *
|
import notesdb as ndb
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from TrivialFormulator import TrivialFormulator, TF
|
from TrivialFormulator import TrivialFormulator, TF
|
||||||
from notes_table import *
|
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_moduleimpl
|
import sco_moduleimpl
|
||||||
import sco_groups
|
import sco_groups
|
||||||
@ -41,6 +42,7 @@ import htmlutils
|
|||||||
import sco_excel
|
import sco_excel
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
from htmlutils import histogram_notes
|
from htmlutils import histogram_notes
|
||||||
|
import VERSION
|
||||||
|
|
||||||
|
|
||||||
def do_evaluation_listenotes(context, REQUEST):
|
def do_evaluation_listenotes(context, REQUEST):
|
||||||
@ -49,7 +51,6 @@ def do_evaluation_listenotes(context, REQUEST):
|
|||||||
|
|
||||||
args: evaluation_id
|
args: evaluation_id
|
||||||
"""
|
"""
|
||||||
cnx = context.GetDBConnexion()
|
|
||||||
mode = None
|
mode = None
|
||||||
if REQUEST.form.has_key("evaluation_id"):
|
if REQUEST.form.has_key("evaluation_id"):
|
||||||
evaluation_id = REQUEST.form["evaluation_id"]
|
evaluation_id = REQUEST.form["evaluation_id"]
|
||||||
@ -66,9 +67,6 @@ def do_evaluation_listenotes(context, REQUEST):
|
|||||||
|
|
||||||
format = REQUEST.form.get("format", "html")
|
format = REQUEST.form.get("format", "html")
|
||||||
E = evals[0] # il y a au moins une evaluation
|
E = evals[0] # il y a au moins une evaluation
|
||||||
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0]
|
|
||||||
formsemestre_id = M["formsemestre_id"]
|
|
||||||
|
|
||||||
# description de l'evaluation
|
# description de l'evaluation
|
||||||
if mode == "eval":
|
if mode == "eval":
|
||||||
H = [
|
H = [
|
||||||
@ -315,11 +313,11 @@ def _make_table_notes(
|
|||||||
"code": code,
|
"code": code,
|
||||||
"_code_td_attrs": 'style="padding-left: 1em; padding-right: 2em;"',
|
"_code_td_attrs": 'style="padding-left: 1em; padding-right: 2em;"',
|
||||||
"etudid": etudid,
|
"etudid": etudid,
|
||||||
"nom": strupper(etud["nom"]),
|
"nom": scu.strupper(etud["nom"]),
|
||||||
"_nomprenom_target": "formsemestre_bulletinetud?formsemestre_id=%s&etudid=%s"
|
"_nomprenom_target": "formsemestre_bulletinetud?formsemestre_id=%s&etudid=%s"
|
||||||
% (M["formsemestre_id"], etudid),
|
% (M["formsemestre_id"], etudid),
|
||||||
"_nomprenom_td_attrs": 'id="%s" class="etudinfo"' % (etud["etudid"]),
|
"_nomprenom_td_attrs": 'id="%s" class="etudinfo"' % (etud["etudid"]),
|
||||||
"prenom": strcapitalize(strlower(etud["prenom"])),
|
"prenom": scu.strcapitalize(scu.strlower(etud["prenom"])),
|
||||||
"nomprenom": etud["nomprenom"],
|
"nomprenom": etud["nomprenom"],
|
||||||
"group": grc,
|
"group": grc,
|
||||||
"email": etud["email"],
|
"email": etud["email"],
|
||||||
@ -432,9 +430,9 @@ def _make_table_notes(
|
|||||||
if with_emails:
|
if with_emails:
|
||||||
gl = "&with_emails%3Alist=yes" + gl
|
gl = "&with_emails%3Alist=yes" + gl
|
||||||
if len(evals) == 1:
|
if len(evals) == 1:
|
||||||
evalname = "%s-%s" % (Mod["code"], DateDMYtoISO(E["jour"]))
|
evalname = "%s-%s" % (Mod["code"], ndb.DateDMYtoISO(E["jour"]))
|
||||||
hh = "%s, %s (%d étudiants)" % (E["description"], gr_title, len(etudids))
|
hh = "%s, %s (%d étudiants)" % (E["description"], gr_title, len(etudids))
|
||||||
filename = make_filename("notes_%s_%s" % (evalname, gr_title_filename))
|
filename = scu.make_filename("notes_%s_%s" % (evalname, gr_title_filename))
|
||||||
caption = hh
|
caption = hh
|
||||||
pdf_title = "%(description)s (%(jour)s)" % e
|
pdf_title = "%(description)s (%(jour)s)" % e
|
||||||
html_title = ""
|
html_title = ""
|
||||||
@ -444,7 +442,7 @@ def _make_table_notes(
|
|||||||
% (nb_abs, nb_att)
|
% (nb_abs, nb_att)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
filename = make_filename("notes_%s_%s" % (Mod["code"], gr_title_filename))
|
filename = scu.make_filename("notes_%s_%s" % (Mod["code"], gr_title_filename))
|
||||||
title = "Notes du module %(code)s %(titre)s" % Mod
|
title = "Notes du module %(code)s %(titre)s" % Mod
|
||||||
title += " semestre %(titremois)s" % sem
|
title += " semestre %(titremois)s" % sem
|
||||||
if gr_title and gr_title != "tous":
|
if gr_title and gr_title != "tous":
|
||||||
@ -467,7 +465,7 @@ def _make_table_notes(
|
|||||||
html_sortable=True,
|
html_sortable=True,
|
||||||
base_url=base_url,
|
base_url=base_url,
|
||||||
filename=filename,
|
filename=filename,
|
||||||
origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "",
|
origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "",
|
||||||
caption=caption,
|
caption=caption,
|
||||||
html_next_section=html_next_section,
|
html_next_section=html_next_section,
|
||||||
page_title="Notes de " + sem["titremois"],
|
page_title="Notes de " + sem["titremois"],
|
||||||
@ -549,10 +547,10 @@ def _add_eval_columns(
|
|||||||
val = NotesDB[etudid]["value"]
|
val = NotesDB[etudid]["value"]
|
||||||
if val is None:
|
if val is None:
|
||||||
nb_abs += 1
|
nb_abs += 1
|
||||||
if val == NOTES_ATTENTE:
|
if val == scu.NOTES_ATTENTE:
|
||||||
nb_att += 1
|
nb_att += 1
|
||||||
# calcul moyenne SANS LES ABSENTS
|
# calcul moyenne SANS LES ABSENTS
|
||||||
if val != None and val != NOTES_NEUTRALISE and val != NOTES_ATTENTE:
|
if val != None and val != scu.NOTES_NEUTRALISE and val != scu.NOTES_ATTENTE:
|
||||||
if e["note_max"] > 0:
|
if e["note_max"] > 0:
|
||||||
valsur20 = val * 20.0 / e["note_max"] # remet sur 20
|
valsur20 = val * 20.0 / e["note_max"] # remet sur 20
|
||||||
else:
|
else:
|
||||||
@ -562,7 +560,7 @@ def _add_eval_columns(
|
|||||||
val = valsur20 # affichage notes / 20 demandé
|
val = valsur20 # affichage notes / 20 demandé
|
||||||
nb_notes = nb_notes + 1
|
nb_notes = nb_notes + 1
|
||||||
sum_notes += val
|
sum_notes += val
|
||||||
val_fmt = fmt_note(val, keep_numeric=keep_numeric)
|
val_fmt = scu.fmt_note(val, keep_numeric=keep_numeric)
|
||||||
comment = NotesDB[etudid]["comment"]
|
comment = NotesDB[etudid]["comment"]
|
||||||
if comment is None:
|
if comment is None:
|
||||||
comment = ""
|
comment = ""
|
||||||
@ -603,13 +601,13 @@ def _add_eval_columns(
|
|||||||
|
|
||||||
coefs[evaluation_id] = "coef. %s" % e["coefficient"]
|
coefs[evaluation_id] = "coef. %s" % e["coefficient"]
|
||||||
if note_sur_20:
|
if note_sur_20:
|
||||||
nmx = 20.0
|
nmax = 20.0
|
||||||
else:
|
else:
|
||||||
nmx = e["note_max"]
|
nmax = e["note_max"]
|
||||||
if keep_numeric:
|
if keep_numeric:
|
||||||
note_max[evaluation_id] = nmx
|
note_max[evaluation_id] = nmax
|
||||||
else:
|
else:
|
||||||
note_max[evaluation_id] = "/ %s" % nmx
|
note_max[evaluation_id] = "/ %s" % nmax
|
||||||
|
|
||||||
if nb_notes > 0:
|
if nb_notes > 0:
|
||||||
moys[evaluation_id] = "%.3g" % (sum_notes / nb_notes)
|
moys[evaluation_id] = "%.3g" % (sum_notes / nb_notes)
|
||||||
@ -658,7 +656,7 @@ def _add_moymod_column(
|
|||||||
val = nt.get_etud_mod_moy(
|
val = nt.get_etud_mod_moy(
|
||||||
e["moduleimpl_id"], etudid
|
e["moduleimpl_id"], etudid
|
||||||
) # note sur 20, ou 'NA','NI'
|
) # note sur 20, ou 'NA','NI'
|
||||||
row[col_id] = fmt_note(val, keep_numeric=keep_numeric)
|
row[col_id] = scu.fmt_note(val, keep_numeric=keep_numeric)
|
||||||
row["_" + col_id + "_td_attrs"] = ' class="moyenne" '
|
row["_" + col_id + "_td_attrs"] = ' class="moyenne" '
|
||||||
if type(val) != StringType:
|
if type(val) != StringType:
|
||||||
notes.append(val)
|
notes.append(val)
|
||||||
@ -712,8 +710,6 @@ def evaluation_check_absences(context, evaluation_id):
|
|||||||
if not E["jour"]:
|
if not E["jour"]:
|
||||||
return [], [], [], [], [] # evaluation sans date
|
return [], [], [], [], [] # evaluation sans date
|
||||||
|
|
||||||
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0]
|
|
||||||
formsemestre_id = M["formsemestre_id"]
|
|
||||||
etudids = sco_groups.do_evaluation_listeetuds_groups(
|
etudids = sco_groups.do_evaluation_listeetuds_groups(
|
||||||
context, evaluation_id, getallstudents=True
|
context, evaluation_id, getallstudents=True
|
||||||
)
|
)
|
||||||
@ -721,12 +717,12 @@ def evaluation_check_absences(context, evaluation_id):
|
|||||||
am, pm, demijournee = _eval_demijournee(E)
|
am, pm, demijournee = _eval_demijournee(E)
|
||||||
|
|
||||||
# Liste les absences à ce moment:
|
# Liste les absences à ce moment:
|
||||||
A = context.Absences.ListeAbsJour(DateDMYtoISO(E["jour"]), am=am, pm=pm)
|
A = context.Absences.ListeAbsJour(ndb.DateDMYtoISO(E["jour"]), am=am, pm=pm)
|
||||||
As = set([x["etudid"] for x in A]) # ensemble des etudiants absents
|
As = set([x["etudid"] for x in A]) # ensemble des etudiants absents
|
||||||
NJ = context.Absences.ListeAbsNonJustJour(DateDMYtoISO(E["jour"]), am=am, pm=pm)
|
NJ = context.Absences.ListeAbsNonJustJour(ndb.DateDMYtoISO(E["jour"]), am=am, pm=pm)
|
||||||
NJs = set([x["etudid"] for x in NJ]) # ensemble des etudiants absents non justifies
|
NJs = set([x["etudid"] for x in NJ]) # ensemble des etudiants absents non justifies
|
||||||
Just = context.Absences.ListeAbsJour(
|
Just = context.Absences.ListeAbsJour(
|
||||||
DateDMYtoISO(E["jour"]), am=am, pm=pm, is_abs=None, is_just=True
|
ndb.DateDMYtoISO(E["jour"]), am=am, pm=pm, is_abs=None, is_just=True
|
||||||
)
|
)
|
||||||
Justs = set([x["etudid"] for x in Just]) # ensemble des etudiants avec justif
|
Justs = set([x["etudid"] for x in Just]) # ensemble des etudiants avec justif
|
||||||
|
|
||||||
@ -741,17 +737,17 @@ def evaluation_check_absences(context, evaluation_id):
|
|||||||
if NotesDB.has_key(etudid):
|
if NotesDB.has_key(etudid):
|
||||||
val = NotesDB[etudid]["value"]
|
val = NotesDB[etudid]["value"]
|
||||||
if (
|
if (
|
||||||
val != None and val != NOTES_NEUTRALISE and val != NOTES_ATTENTE
|
val != None and val != scu.NOTES_NEUTRALISE and val != scu.NOTES_ATTENTE
|
||||||
) and etudid in As:
|
) and etudid in As:
|
||||||
# note valide et absent
|
# note valide et absent
|
||||||
ValButAbs.append(etudid)
|
ValButAbs.append(etudid)
|
||||||
if val is None and not etudid in As:
|
if val is None and not etudid in As:
|
||||||
# absent mais pas signale comme tel
|
# absent mais pas signale comme tel
|
||||||
AbsNonSignalee.append(etudid)
|
AbsNonSignalee.append(etudid)
|
||||||
if val == NOTES_NEUTRALISE and not etudid in As:
|
if val == scu.NOTES_NEUTRALISE and not etudid in As:
|
||||||
# Neutralisé mais pas signale absent
|
# Neutralisé mais pas signale absent
|
||||||
ExcNonSignalee.append(etudid)
|
ExcNonSignalee.append(etudid)
|
||||||
if val == NOTES_NEUTRALISE and etudid in NJs:
|
if val == scu.NOTES_NEUTRALISE and etudid in NJs:
|
||||||
# EXC mais pas justifié
|
# EXC mais pas justifié
|
||||||
ExcNonJust.append(etudid)
|
ExcNonJust.append(etudid)
|
||||||
if val is None and etudid in Justs:
|
if val is None and etudid in Justs:
|
||||||
|
13
sco_lycee.py
13
sco_lycee.py
@ -32,14 +32,14 @@
|
|||||||
|
|
||||||
import tempfile, urllib, re
|
import tempfile, urllib, re
|
||||||
|
|
||||||
from notesdb import *
|
import sco_utils as scu
|
||||||
from sco_utils import *
|
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import scolars
|
import scolars
|
||||||
import sco_groups
|
import sco_groups
|
||||||
import sco_report
|
import sco_report
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
|
import VERSION
|
||||||
|
|
||||||
|
|
||||||
def formsemestre_table_etuds_lycees(
|
def formsemestre_table_etuds_lycees(
|
||||||
@ -100,7 +100,7 @@ def _table_etuds_lycees(
|
|||||||
context, etuds, group_lycees, title, preferences, no_links=False
|
context, etuds, group_lycees, title, preferences, no_links=False
|
||||||
):
|
):
|
||||||
etuds = [scolars.etud_add_lycee_infos(e) for e in etuds]
|
etuds = [scolars.etud_add_lycee_infos(e) for e in etuds]
|
||||||
etuds_by_lycee = group_by_key(etuds, "codelycee")
|
etuds_by_lycee = scu.group_by_key(etuds, "codelycee")
|
||||||
#
|
#
|
||||||
if group_lycees:
|
if group_lycees:
|
||||||
L = [etuds_by_lycee[codelycee][0] for codelycee in etuds_by_lycee]
|
L = [etuds_by_lycee[codelycee][0] for codelycee in etuds_by_lycee]
|
||||||
@ -128,7 +128,7 @@ def _table_etuds_lycees(
|
|||||||
else:
|
else:
|
||||||
L = etuds
|
L = etuds
|
||||||
columns_ids = (
|
columns_ids = (
|
||||||
"sexe",
|
"civilite_str",
|
||||||
"nom",
|
"nom",
|
||||||
"prenom",
|
"prenom",
|
||||||
"codelycee",
|
"codelycee",
|
||||||
@ -148,7 +148,7 @@ def _table_etuds_lycees(
|
|||||||
rows=L,
|
rows=L,
|
||||||
titles={
|
titles={
|
||||||
"nbetuds": "Nb d'étudiants",
|
"nbetuds": "Nb d'étudiants",
|
||||||
"sexe": "",
|
"civilite_str": "",
|
||||||
"nom": "Nom",
|
"nom": "Nom",
|
||||||
"prenom": "Prénom",
|
"prenom": "Prénom",
|
||||||
"etudid": "etudid",
|
"etudid": "etudid",
|
||||||
@ -157,7 +157,7 @@ def _table_etuds_lycees(
|
|||||||
"nomlycee": "Lycée",
|
"nomlycee": "Lycée",
|
||||||
"villelycee": "Commune",
|
"villelycee": "Commune",
|
||||||
},
|
},
|
||||||
origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "",
|
origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "",
|
||||||
caption=title,
|
caption=title,
|
||||||
page_title="Carte lycées d'origine",
|
page_title="Carte lycées d'origine",
|
||||||
html_sortable=True,
|
html_sortable=True,
|
||||||
@ -177,7 +177,6 @@ def formsemestre_etuds_lycees(
|
|||||||
REQUEST=None,
|
REQUEST=None,
|
||||||
):
|
):
|
||||||
"""Table des lycées d'origine"""
|
"""Table des lycées d'origine"""
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
|
||||||
tab, etuds_by_lycee = formsemestre_table_etuds_lycees(
|
tab, etuds_by_lycee = formsemestre_table_etuds_lycees(
|
||||||
context, formsemestre_id, only_primo=only_primo, group_lycees=not no_grouping
|
context, formsemestre_id, only_primo=only_primo, group_lycees=not no_grouping
|
||||||
)
|
)
|
||||||
|
@ -108,5 +108,5 @@ def do_modalite_edit(context, *args, **kw):
|
|||||||
"edit a modalite"
|
"edit a modalite"
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
# check
|
# check
|
||||||
m = do_modalite_list(context, {"form_modalite_id": args[0]["form_modalite_id"]})[0]
|
_ = do_modalite_list(context, {"form_modalite_id": args[0]["form_modalite_id"]})[0]
|
||||||
_modaliteEditor.edit(cnx, *args, **kw)
|
_modaliteEditor.edit(cnx, *args, **kw)
|
||||||
|
@ -29,15 +29,16 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from scolog import logdb
|
from scolog import logdb
|
||||||
from notes_table import *
|
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_moduleimpl
|
import sco_moduleimpl
|
||||||
import sco_groups
|
import sco_groups
|
||||||
import htmlutils
|
import htmlutils
|
||||||
|
from sco_permissions import ScoEtudInscrit
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
|
||||||
|
|
||||||
def moduleimpl_inscriptions_edit(
|
def moduleimpl_inscriptions_edit(
|
||||||
@ -182,7 +183,7 @@ def moduleimpl_inscriptions_edit(
|
|||||||
sco_moduleimpl.do_moduleimpl_inscrit_etuds(
|
sco_moduleimpl.do_moduleimpl_inscrit_etuds(
|
||||||
context, moduleimpl_id, formsemestre_id, etuds, reset=True, REQUEST=REQUEST
|
context, moduleimpl_id, formsemestre_id, etuds, reset=True, REQUEST=REQUEST
|
||||||
)
|
)
|
||||||
REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
"moduleimpl_status?moduleimpl_id=%s" % (moduleimpl_id)
|
"moduleimpl_status?moduleimpl_id=%s" % (moduleimpl_id)
|
||||||
)
|
)
|
||||||
#
|
#
|
||||||
@ -453,7 +454,7 @@ def get_etuds_with_capitalized_ue(context, formsemestre_id):
|
|||||||
"""For each UE, computes list of students capitalizing the UE.
|
"""For each UE, computes list of students capitalizing the UE.
|
||||||
returns { ue_id : [ { infos } ] }
|
returns { ue_id : [ { infos } ] }
|
||||||
"""
|
"""
|
||||||
UECaps = DictDefault(defaultvalue=[])
|
UECaps = scu.DictDefault(defaultvalue=[])
|
||||||
nt = context._getNotesCache().get_NotesTable(
|
nt = context._getNotesCache().get_NotesTable(
|
||||||
context, formsemestre_id
|
context, formsemestre_id
|
||||||
) # > get_ues, get_etud_ue_status
|
) # > get_ues, get_etud_ue_status
|
||||||
@ -481,7 +482,7 @@ def is_inscrit_ue(context, etudid, formsemestre_id, ue_id):
|
|||||||
"""Modules de cette UE dans ce semestre
|
"""Modules de cette UE dans ce semestre
|
||||||
auxquels l'étudiant est inscrit.
|
auxquels l'étudiant est inscrit.
|
||||||
"""
|
"""
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"""SELECT mod.*
|
"""SELECT mod.*
|
||||||
FROM notes_moduleimpl mi, notes_modules mod,
|
FROM notes_moduleimpl mi, notes_modules mod,
|
||||||
@ -502,7 +503,7 @@ def is_inscrit_ue(context, etudid, formsemestre_id, ue_id):
|
|||||||
def do_etud_desinscrit_ue(context, etudid, formsemestre_id, ue_id, REQUEST=None):
|
def do_etud_desinscrit_ue(context, etudid, formsemestre_id, ue_id, REQUEST=None):
|
||||||
"""Desincrit l'etudiant de tous les modules de cette UE dans ce semestre."""
|
"""Desincrit l'etudiant de tous les modules de cette UE dans ce semestre."""
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""DELETE FROM notes_moduleimpl_inscription
|
"""DELETE FROM notes_moduleimpl_inscription
|
||||||
WHERE moduleimpl_inscription_id IN (
|
WHERE moduleimpl_inscription_id IN (
|
||||||
@ -543,7 +544,7 @@ def do_etud_inscrit_ue(context, etudid, formsemestre_id, ue_id, REQUEST=None):
|
|||||||
raise ScoValueError("%s n'est pas inscrit au semestre !" % etudid)
|
raise ScoValueError("%s n'est pas inscrit au semestre !" % etudid)
|
||||||
|
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""SELECT mi.moduleimpl_id
|
"""SELECT mi.moduleimpl_id
|
||||||
FROM notes_moduleimpl mi, notes_modules mod, notes_formsemestre sem
|
FROM notes_moduleimpl mi, notes_modules mod, notes_formsemestre sem
|
||||||
|
12
sco_news.py
12
sco_news.py
@ -37,20 +37,20 @@ from email.mime.multipart import MIMEMultipart
|
|||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
from email.header import Header
|
from email.header import Header
|
||||||
|
|
||||||
from notesdb import * # pylint: disable=unused-wildcard-import
|
import notesdb as ndb # pylint: disable=unused-wildcard-import
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import scolars
|
import scolars
|
||||||
from sco_utils import SCO_ENCODING, SCO_ANNONCES_WEBSITE
|
from sco_utils import SCO_ENCODING, SCO_ANNONCES_WEBSITE
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_moduleimpl
|
import sco_moduleimpl
|
||||||
|
|
||||||
_scolar_news_editor = EditableTable(
|
_scolar_news_editor = ndb.EditableTable(
|
||||||
"scolar_news",
|
"scolar_news",
|
||||||
"news_id",
|
"news_id",
|
||||||
("date", "authenticated_user", "type", "object", "text", "url"),
|
("date", "authenticated_user", "type", "object", "text", "url"),
|
||||||
sortkey="date desc",
|
sortkey="date desc",
|
||||||
output_formators={"date": DateISOtoDMY},
|
output_formators={"date": ndb.DateISOtoDMY},
|
||||||
input_formators={"date": DateDMYtoISO},
|
input_formators={"date": ndb.DateDMYtoISO},
|
||||||
html_quote=False, # no user supplied data, needed to store html links
|
html_quote=False, # no user supplied data, needed to store html links
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ def scolar_news_summary(context, n=5):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute("select * from scolar_news order by date desc limit 100")
|
cursor.execute("select * from scolar_news order by date desc limit 100")
|
||||||
selected_news = {} # (type,object) : news dict
|
selected_news = {} # (type,object) : news dict
|
||||||
news = cursor.dictfetchall() # la plus récente d'abord
|
news = cursor.dictfetchall() # la plus récente d'abord
|
||||||
@ -118,7 +118,7 @@ def scolar_news_summary(context, n=5):
|
|||||||
for r in reversed(news): # la plus ancienne d'abord
|
for r in reversed(news): # la plus ancienne d'abord
|
||||||
# si on a deja une news avec meme (type,object)
|
# si on a deja une news avec meme (type,object)
|
||||||
# et du meme jour, on la remplace
|
# et du meme jour, on la remplace
|
||||||
dmy = DateISOtoDMY(r["date"]) # round
|
dmy = ndb.DateISOtoDMY(r["date"]) # round
|
||||||
key = (r["type"], r["object"], dmy)
|
key = (r["type"], r["object"], dmy)
|
||||||
selected_news[key] = r
|
selected_news[key] = r
|
||||||
|
|
||||||
|
@ -31,8 +31,9 @@
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
|
from notes_log import log
|
||||||
import scolars
|
import scolars
|
||||||
import sco_bac
|
import sco_bac
|
||||||
import sco_photos
|
import sco_photos
|
||||||
@ -43,9 +44,17 @@ import sco_formsemestre_status
|
|||||||
import htmlutils
|
import htmlutils
|
||||||
from sco_bulletins import etud_descr_situation_semestre
|
from sco_bulletins import etud_descr_situation_semestre
|
||||||
import sco_parcours_dut
|
import sco_parcours_dut
|
||||||
|
import sco_codes_parcours
|
||||||
from sco_formsemestre_validation import formsemestre_recap_parcours_table
|
from sco_formsemestre_validation import formsemestre_recap_parcours_table
|
||||||
import sco_archives_etud
|
import sco_archives_etud
|
||||||
import sco_report
|
import sco_report
|
||||||
|
from sco_permissions import (
|
||||||
|
ScoEtudChangeGroups,
|
||||||
|
ScoEtudInscrit,
|
||||||
|
ScoImplement,
|
||||||
|
ScoEtudChangeAdr,
|
||||||
|
)
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
|
||||||
|
|
||||||
def _menuScolarite(context, authuser, sem, etudid):
|
def _menuScolarite(context, authuser, sem, etudid):
|
||||||
@ -54,7 +63,7 @@ def _menuScolarite(context, authuser, sem, etudid):
|
|||||||
"""
|
"""
|
||||||
locked = sem["etat"] != "1"
|
locked = sem["etat"] != "1"
|
||||||
if locked:
|
if locked:
|
||||||
lockicon = icontag("lock32_img", title="verrouillé", border="0")
|
lockicon = scu.icontag("lock32_img", title="verrouillé", border="0")
|
||||||
return lockicon # no menu
|
return lockicon # no menu
|
||||||
if not authuser.has_permission(
|
if not authuser.has_permission(
|
||||||
ScoEtudInscrit, context
|
ScoEtudInscrit, context
|
||||||
@ -76,12 +85,12 @@ def _menuScolarite(context, authuser, sem, etudid):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Note: seul un etudiant inscrit (I) peut devenir défaillant.
|
# Note: seul un etudiant inscrit (I) peut devenir défaillant.
|
||||||
if ins["etat"] != DEF:
|
if ins["etat"] != sco_codes_parcours.DEF:
|
||||||
def_title = "Déclarer défaillance"
|
def_title = "Déclarer défaillance"
|
||||||
def_url = (
|
def_url = (
|
||||||
"formDef?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s" % args
|
"formDef?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s" % args
|
||||||
)
|
)
|
||||||
elif ins["etat"] == DEF:
|
elif ins["etat"] == sco_codes_parcours.DEF:
|
||||||
def_title = "Annuler la défaillance"
|
def_title = "Annuler la défaillance"
|
||||||
def_url = (
|
def_url = (
|
||||||
"doCancelDef?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s"
|
"doCancelDef?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s"
|
||||||
@ -212,7 +221,7 @@ def ficheEtud(context, etudid=None, REQUEST=None):
|
|||||||
sem_info = {}
|
sem_info = {}
|
||||||
for sem in info["sems"]:
|
for sem in info["sems"]:
|
||||||
if sem["ins"]["etat"] != "I":
|
if sem["ins"]["etat"] != "I":
|
||||||
descr, junk = etud_descr_situation_semestre(
|
descr, _ = etud_descr_situation_semestre(
|
||||||
context.Notes,
|
context.Notes,
|
||||||
etudid,
|
etudid,
|
||||||
sem["formsemestre_id"],
|
sem["formsemestre_id"],
|
||||||
@ -280,7 +289,7 @@ def ficheEtud(context, etudid=None, REQUEST=None):
|
|||||||
] = '<td class="annodel"><a href="doSuppressAnnotation?etudid=%s&annotation_id=%s">%s</a></td>' % (
|
] = '<td class="annodel"><a href="doSuppressAnnotation?etudid=%s&annotation_id=%s">%s</a></td>' % (
|
||||||
etudid,
|
etudid,
|
||||||
a["id"],
|
a["id"],
|
||||||
icontag(
|
scu.icontag(
|
||||||
"delete_img",
|
"delete_img",
|
||||||
border="0",
|
border="0",
|
||||||
alt="suppress",
|
alt="suppress",
|
||||||
@ -379,7 +388,7 @@ def ficheEtud(context, etudid=None, REQUEST=None):
|
|||||||
else:
|
else:
|
||||||
info["tit_anno"] = ""
|
info["tit_anno"] = ""
|
||||||
# Inscriptions
|
# Inscriptions
|
||||||
if info["sems"]:
|
if info["sems"]: # XXX rcl unused ? à voir
|
||||||
rcl = (
|
rcl = (
|
||||||
"""(<a href="%(ScoURL)s/Notes/formsemestre_validation_etud_form?check=1&etudid=%(etudid)s&formsemestre_id=%(last_formsemestre_id)s&desturl=ficheEtud?etudid=%(etudid)s">récapitulatif parcours</a>)"""
|
"""(<a href="%(ScoURL)s/Notes/formsemestre_validation_etud_form?check=1&etudid=%(etudid)s&formsemestre_id=%(last_formsemestre_id)s&desturl=ficheEtud?etudid=%(etudid)s">récapitulatif parcours</a>)"""
|
||||||
% info
|
% info
|
||||||
|
@ -27,12 +27,39 @@
|
|||||||
|
|
||||||
"""Semestres: gestion parcours DUT (Arreté du 13 août 2005)
|
"""Semestres: gestion parcours DUT (Arreté du 13 août 2005)
|
||||||
"""
|
"""
|
||||||
from notesdb import *
|
from types import FloatType
|
||||||
|
|
||||||
|
import sco_utils as scu
|
||||||
|
import notesdb as ndb
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from scolog import logdb
|
from scolog import logdb
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
from sco_codes_parcours import *
|
|
||||||
|
from sco_codes_parcours import (
|
||||||
|
CMP,
|
||||||
|
ADC,
|
||||||
|
ADJ,
|
||||||
|
ADM,
|
||||||
|
AJ,
|
||||||
|
ATT,
|
||||||
|
NO_SEMESTRE_ID,
|
||||||
|
BUG,
|
||||||
|
NEXT,
|
||||||
|
NEXT2,
|
||||||
|
NEXT_OR_NEXT2,
|
||||||
|
REO,
|
||||||
|
REDOANNEE,
|
||||||
|
REDOSEM,
|
||||||
|
RA_OR_NEXT,
|
||||||
|
RA_OR_RS,
|
||||||
|
RS_OR_NEXT,
|
||||||
|
CODES_SEM_VALIDES,
|
||||||
|
NOTES_BARRE_GEN_COMPENSATION,
|
||||||
|
code_semestre_attente,
|
||||||
|
code_semestre_validant,
|
||||||
|
)
|
||||||
from dutrules import DUTRules # regles generees a partir du CSV
|
from dutrules import DUTRules # regles generees a partir du CSV
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
|
||||||
|
|
||||||
class DecisionSem:
|
class DecisionSem:
|
||||||
@ -165,7 +192,7 @@ class SituationEtudParcoursGeneric:
|
|||||||
if rule.conclusion[5] == BUG:
|
if rule.conclusion[5] == BUG:
|
||||||
log("get_possible_choices: inconsistency: state=%s" % str(state))
|
log("get_possible_choices: inconsistency: state=%s" % str(state))
|
||||||
#
|
#
|
||||||
valid_semestre = code_semestre_validant(rule.conclusion[0])
|
# valid_semestre = code_semestre_validant(rule.conclusion[0])
|
||||||
choices.append(
|
choices.append(
|
||||||
DecisionSem(
|
DecisionSem(
|
||||||
code_etat=rule.conclusion[0],
|
code_etat=rule.conclusion[0],
|
||||||
@ -390,7 +417,7 @@ class SituationEtudParcoursGeneric:
|
|||||||
)
|
)
|
||||||
self.moy_gen = self.nt.get_etud_moy_gen(self.etudid)
|
self.moy_gen = self.nt.get_etud_moy_gen(self.etudid)
|
||||||
self.barre_moy_ok = (type(self.moy_gen) == FloatType) and (
|
self.barre_moy_ok = (type(self.moy_gen) == FloatType) and (
|
||||||
self.moy_gen >= (self.parcours.BARRE_MOY - NOTES_TOLERANCE)
|
self.moy_gen >= (self.parcours.BARRE_MOY - scu.NOTES_TOLERANCE)
|
||||||
)
|
)
|
||||||
# conserve etat UEs
|
# conserve etat UEs
|
||||||
ue_ids = [
|
ue_ids = [
|
||||||
@ -607,7 +634,7 @@ class SituationEtudParcoursGeneric:
|
|||||||
) # > modif decisions jury (sem, UE)
|
) # > modif decisions jury (sem, UE)
|
||||||
|
|
||||||
# -- supprime autorisations venant de ce formsemestre
|
# -- supprime autorisations venant de ce formsemestre
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
try:
|
try:
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""delete from scolar_autorisation_inscription
|
"""delete from scolar_autorisation_inscription
|
||||||
@ -742,7 +769,7 @@ def int_or_null(s):
|
|||||||
return int(s)
|
return int(s)
|
||||||
|
|
||||||
|
|
||||||
_scolar_formsemestre_validation_editor = EditableTable(
|
_scolar_formsemestre_validation_editor = ndb.EditableTable(
|
||||||
"scolar_formsemestre_validation",
|
"scolar_formsemestre_validation",
|
||||||
"formsemestre_validation_id",
|
"formsemestre_validation_id",
|
||||||
(
|
(
|
||||||
@ -758,8 +785,8 @@ _scolar_formsemestre_validation_editor = EditableTable(
|
|||||||
"semestre_id",
|
"semestre_id",
|
||||||
"is_external",
|
"is_external",
|
||||||
),
|
),
|
||||||
output_formators={"event_date": DateISOtoDMY, "assidu": str},
|
output_formators={"event_date": ndb.DateISOtoDMY, "assidu": str},
|
||||||
input_formators={"event_date": DateDMYtoISO, "assidu": int_or_null},
|
input_formators={"event_date": ndb.DateDMYtoISO, "assidu": int_or_null},
|
||||||
)
|
)
|
||||||
|
|
||||||
scolar_formsemestre_validation_create = _scolar_formsemestre_validation_editor.create
|
scolar_formsemestre_validation_create = _scolar_formsemestre_validation_editor.create
|
||||||
@ -779,7 +806,7 @@ def formsemestre_validate_sem(
|
|||||||
"Ajoute ou change validation semestre"
|
"Ajoute ou change validation semestre"
|
||||||
args = {"formsemestre_id": formsemestre_id, "etudid": etudid}
|
args = {"formsemestre_id": formsemestre_id, "etudid": etudid}
|
||||||
# delete existing
|
# delete existing
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
try:
|
try:
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""delete from scolar_formsemestre_validation
|
"""delete from scolar_formsemestre_validation
|
||||||
@ -827,7 +854,7 @@ def formsemestre_update_validation_sem(
|
|||||||
"assidu": int(assidu),
|
"assidu": int(assidu),
|
||||||
}
|
}
|
||||||
log("formsemestre_update_validation_sem: %s" % args)
|
log("formsemestre_update_validation_sem: %s" % args)
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
to_invalidate = []
|
to_invalidate = []
|
||||||
|
|
||||||
# enleve compensations si necessaire
|
# enleve compensations si necessaire
|
||||||
@ -945,7 +972,7 @@ def do_formsemestre_validate_ue(
|
|||||||
args["event_date"] = date
|
args["event_date"] = date
|
||||||
|
|
||||||
# delete existing
|
# delete existing
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
try:
|
try:
|
||||||
cond = "etudid = %(etudid)s and ue_id=%(ue_id)s"
|
cond = "etudid = %(etudid)s and ue_id=%(ue_id)s"
|
||||||
if formsemestre_id:
|
if formsemestre_id:
|
||||||
@ -983,7 +1010,7 @@ def formsemestre_has_decisions(context, formsemestre_id):
|
|||||||
|
|
||||||
def etud_est_inscrit_ue(cnx, etudid, formsemestre_id, ue_id):
|
def etud_est_inscrit_ue(cnx, etudid, formsemestre_id, ue_id):
|
||||||
"""Vrai si l'étudiant est inscrit a au moins un module de cette UE dans ce semestre"""
|
"""Vrai si l'étudiant est inscrit a au moins un module de cette UE dans ce semestre"""
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""select mi.* from notes_moduleimpl mi, notes_modules mo, notes_ue ue, notes_moduleimpl_inscription i
|
"""select mi.* from notes_moduleimpl mi, notes_modules mo, notes_ue ue, notes_moduleimpl_inscription i
|
||||||
where i.etudid = %(etudid)s and i.moduleimpl_id=mi.moduleimpl_id
|
where i.etudid = %(etudid)s and i.moduleimpl_id=mi.moduleimpl_id
|
||||||
@ -997,12 +1024,12 @@ def etud_est_inscrit_ue(cnx, etudid, formsemestre_id, ue_id):
|
|||||||
return len(cursor.fetchall())
|
return len(cursor.fetchall())
|
||||||
|
|
||||||
|
|
||||||
_scolar_autorisation_inscription_editor = EditableTable(
|
_scolar_autorisation_inscription_editor = ndb.EditableTable(
|
||||||
"scolar_autorisation_inscription",
|
"scolar_autorisation_inscription",
|
||||||
"autorisation_inscription_id",
|
"autorisation_inscription_id",
|
||||||
("etudid", "formation_code", "semestre_id", "date", "origin_formsemestre_id"),
|
("etudid", "formation_code", "semestre_id", "date", "origin_formsemestre_id"),
|
||||||
output_formators={"date": DateISOtoDMY},
|
output_formators={"date": ndb.DateISOtoDMY},
|
||||||
input_formators={"date": DateDMYtoISO},
|
input_formators={"date": ndb.DateDMYtoISO},
|
||||||
)
|
)
|
||||||
scolar_autorisation_inscription_list = _scolar_autorisation_inscription_editor.list
|
scolar_autorisation_inscription_list = _scolar_autorisation_inscription_editor.list
|
||||||
|
|
||||||
@ -1033,7 +1060,7 @@ def formsemestre_get_etud_capitalisation(context, sem, etudid):
|
|||||||
} ]
|
} ]
|
||||||
"""
|
"""
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""select distinct SFV.*, ue.ue_code from notes_ue ue, notes_formations nf, notes_formations nf2,
|
"""select distinct SFV.*, ue.ue_code from notes_ue ue, notes_formations nf, notes_formations nf2,
|
||||||
scolar_formsemestre_validation SFV, notes_formsemestre sem
|
scolar_formsemestre_validation SFV, notes_formsemestre sem
|
||||||
@ -1058,7 +1085,7 @@ def formsemestre_get_etud_capitalisation(context, sem, etudid):
|
|||||||
"etudid": etudid,
|
"etudid": etudid,
|
||||||
"formation_id": sem["formation_id"],
|
"formation_id": sem["formation_id"],
|
||||||
"semestre_id": sem["semestre_id"],
|
"semestre_id": sem["semestre_id"],
|
||||||
"date_debut": DateDMYtoISO(sem["date_debut"]),
|
"date_debut": ndb.DateDMYtoISO(sem["date_debut"]),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1072,7 +1099,7 @@ def list_formsemestre_utilisateurs_uecap(context, formsemestre_id):
|
|||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||||
F = context.formation_list(args={"formation_id": sem["formation_id"]})[0]
|
F = context.formation_list(args={"formation_id": sem["formation_id"]})[0]
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""select sem.formsemestre_id
|
"""select sem.formsemestre_id
|
||||||
from notes_formsemestre sem, notes_formations F
|
from notes_formsemestre sem, notes_formations F
|
||||||
@ -1086,7 +1113,7 @@ def list_formsemestre_utilisateurs_uecap(context, formsemestre_id):
|
|||||||
"formation_code": F["formation_code"],
|
"formation_code": F["formation_code"],
|
||||||
"semestre_id": sem["semestre_id"],
|
"semestre_id": sem["semestre_id"],
|
||||||
"formsemestre_id": formsemestre_id,
|
"formsemestre_id": formsemestre_id,
|
||||||
"date_debut": DateDMYtoISO(sem["date_debut"]),
|
"date_debut": ndb.DateDMYtoISO(sem["date_debut"]),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
return [x[0] for x in cursor.fetchall()]
|
return [x[0] for x in cursor.fetchall()]
|
||||||
|
@ -30,9 +30,11 @@
|
|||||||
Contribution M. Salomon, UFC / IUT DE BELFORT-MONTBÉLIARD, 2016
|
Contribution M. Salomon, UFC / IUT DE BELFORT-MONTBÉLIARD, 2016
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import urllib
|
||||||
|
import random
|
||||||
|
|
||||||
from notesdb import *
|
import sco_utils as scu
|
||||||
from sco_utils import *
|
import notesdb as ndb
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import scolars
|
import scolars
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
@ -42,8 +44,9 @@ import sco_evaluations
|
|||||||
import sco_saisie_notes
|
import sco_saisie_notes
|
||||||
import sco_excel
|
import sco_excel
|
||||||
from sco_excel import *
|
from sco_excel import *
|
||||||
|
from TrivialFormulator import TrivialFormulator
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
import random
|
import VERSION
|
||||||
|
|
||||||
|
|
||||||
def do_placement_selectetuds(context, REQUEST):
|
def do_placement_selectetuds(context, REQUEST):
|
||||||
@ -124,7 +127,10 @@ def do_placement_selectetuds(context, REQUEST):
|
|||||||
(
|
(
|
||||||
"group_ids",
|
"group_ids",
|
||||||
{
|
{
|
||||||
"default": [g["group_id"] for g in groups],
|
"default": [
|
||||||
|
g["group_id"] # pylint: disable=invalid-sequence-index
|
||||||
|
for g in groups
|
||||||
|
],
|
||||||
"input_type": "hidden",
|
"input_type": "hidden",
|
||||||
"type": "list",
|
"type": "list",
|
||||||
},
|
},
|
||||||
@ -211,7 +217,9 @@ def do_placement_selectetuds(context, REQUEST):
|
|||||||
)
|
)
|
||||||
+ "&".join(gs)
|
+ "&".join(gs)
|
||||||
)
|
)
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "/do_placement?" + query)
|
return REQUEST.RESPONSE.redirect(
|
||||||
|
context.NotesURL() + "/do_placement?" + query
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"invalid placement_method (%s)" % tf[2]["placement_method"]
|
"invalid placement_method (%s)" % tf[2]["placement_method"]
|
||||||
@ -260,7 +268,6 @@ def do_placement(context, REQUEST):
|
|||||||
|
|
||||||
if None in [g["group_name"] for g in groups]: # tous les etudiants
|
if None in [g["group_name"] for g in groups]: # tous les etudiants
|
||||||
getallstudents = True
|
getallstudents = True
|
||||||
gr_title = "tous"
|
|
||||||
gr_title_filename = "tous"
|
gr_title_filename = "tous"
|
||||||
else:
|
else:
|
||||||
getallstudents = False
|
getallstudents = False
|
||||||
@ -273,7 +280,7 @@ def do_placement(context, REQUEST):
|
|||||||
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0]
|
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0]
|
||||||
Mod = context.do_module_list(args={"module_id": M["module_id"]})[0]
|
Mod = context.do_module_list(args={"module_id": M["module_id"]})[0]
|
||||||
sem = sco_formsemestre.get_formsemestre(context, M["formsemestre_id"])
|
sem = sco_formsemestre.get_formsemestre(context, M["formsemestre_id"])
|
||||||
evalname = "%s-%s" % (Mod["code"], DateDMYtoISO(E["jour"]))
|
evalname = "%s-%s" % (Mod["code"], ndb.DateDMYtoISO(E["jour"]))
|
||||||
if E["description"]:
|
if E["description"]:
|
||||||
evaltitre = E["description"]
|
evaltitre = E["description"]
|
||||||
else:
|
else:
|
||||||
@ -297,8 +304,8 @@ def do_placement(context, REQUEST):
|
|||||||
{"etudid": etudid, "formsemestre_id": M["formsemestre_id"]}
|
{"etudid": etudid, "formsemestre_id": M["formsemestre_id"]}
|
||||||
)[0]
|
)[0]
|
||||||
if inscr["etat"] != "D":
|
if inscr["etat"] != "D":
|
||||||
nom = strupper(ident["nom"])
|
nom = scu.strupper(ident["nom"])
|
||||||
prenom = strcapitalize(strlower(ident["prenom"]))
|
prenom = scu.strcapitalize(scu.strlower(ident["prenom"]))
|
||||||
listetud.append((nom, prenom))
|
listetud.append((nom, prenom))
|
||||||
random.shuffle(listetud)
|
random.shuffle(listetud)
|
||||||
|
|
||||||
@ -374,7 +381,9 @@ def do_placement(context, REQUEST):
|
|||||||
columns_ids=columns_ids,
|
columns_ids=columns_ids,
|
||||||
rows=rows,
|
rows=rows,
|
||||||
filename=filename,
|
filename=filename,
|
||||||
origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "",
|
origin="Généré par %s le " % VERSION.SCONAME
|
||||||
|
+ scu.timedate_human_repr()
|
||||||
|
+ "",
|
||||||
pdf_title=pdf_title,
|
pdf_title=pdf_title,
|
||||||
# pdf_shorttitle = '',
|
# pdf_shorttitle = '',
|
||||||
preferences=context.get_preferences(M["formsemestre_id"]),
|
preferences=context.get_preferences(M["formsemestre_id"]),
|
||||||
@ -444,7 +453,7 @@ def Excel_feuille_placement(
|
|||||||
wb = Workbook()
|
wb = Workbook()
|
||||||
|
|
||||||
SheetName0 = "Emargement"
|
SheetName0 = "Emargement"
|
||||||
ws0 = wb.add_sheet(SheetName0.decode(SCO_ENCODING))
|
ws0 = wb.add_sheet(SheetName0.decode(scu.SCO_ENCODING))
|
||||||
# ajuste largeurs colonnes (unite inconnue, empirique)
|
# ajuste largeurs colonnes (unite inconnue, empirique)
|
||||||
width = 4500
|
width = 4500
|
||||||
if nbcolumns > 5:
|
if nbcolumns > 5:
|
||||||
@ -455,7 +464,7 @@ def Excel_feuille_placement(
|
|||||||
ws0.col(0).width = 750
|
ws0.col(0).width = 750
|
||||||
|
|
||||||
SheetName1 = "Positions"
|
SheetName1 = "Positions"
|
||||||
ws1 = wb.add_sheet(SheetName1.decode(SCO_ENCODING))
|
ws1 = wb.add_sheet(SheetName1.decode(scu.SCO_ENCODING))
|
||||||
if numbering == "coordinate":
|
if numbering == "coordinate":
|
||||||
ws1.col(0).width = 4000
|
ws1.col(0).width = 4000
|
||||||
ws1.col(1).width = 4500
|
ws1.col(1).width = 4500
|
||||||
@ -654,8 +663,8 @@ def Excel_feuille_placement(
|
|||||||
else:
|
else:
|
||||||
li += 1
|
li += 1
|
||||||
line += 1
|
line += 1
|
||||||
ws0.write(li, 0, desceval[0].decode(SCO_ENCODING), style_titres)
|
ws0.write(li, 0, desceval[0].decode(scu.SCO_ENCODING), style_titres)
|
||||||
ws1.write(li, 0, desceval[0].decode(SCO_ENCODING), style_titres)
|
ws1.write(li, 0, desceval[0].decode(scu.SCO_ENCODING), style_titres)
|
||||||
li += 1
|
li += 1
|
||||||
ws0.write(
|
ws0.write(
|
||||||
li,
|
li,
|
||||||
@ -727,8 +736,8 @@ def Excel_feuille_placement(
|
|||||||
ws0.write(li0, 0, line, style2b)
|
ws0.write(li0, 0, line, style2b)
|
||||||
col = 1
|
col = 1
|
||||||
for etudid in linetud:
|
for etudid in linetud:
|
||||||
ws0.write(li0, col, (etudid[0]).decode(SCO_ENCODING), style1t)
|
ws0.write(li0, col, (etudid[0]).decode(scu.SCO_ENCODING), style1t)
|
||||||
ws0.write(li0 + 1, col, (etudid[1]).decode(SCO_ENCODING), style1m)
|
ws0.write(li0 + 1, col, (etudid[1]).decode(scu.SCO_ENCODING), style1m)
|
||||||
ws0.row(li0 + 2).height = space
|
ws0.row(li0 + 2).height = space
|
||||||
if numbering == "coordinate":
|
if numbering == "coordinate":
|
||||||
ws0.write(li0 + 2, col, " ", style1bb)
|
ws0.write(li0 + 2, col, " ", style1bb)
|
||||||
@ -757,8 +766,8 @@ def Excel_feuille_placement(
|
|||||||
for etudid in orderetud:
|
for etudid in orderetud:
|
||||||
li1 += 1
|
li1 += 1
|
||||||
line += 1
|
line += 1
|
||||||
ws1.write(li1, col, (etudid[0]).decode(SCO_ENCODING), style2l)
|
ws1.write(li1, col, (etudid[0]).decode(scu.SCO_ENCODING), style2l)
|
||||||
ws1.write(li1, col + 1, (etudid[1]).decode(SCO_ENCODING), style2m1)
|
ws1.write(li1, col + 1, (etudid[1]).decode(scu.SCO_ENCODING), style2m1)
|
||||||
if numbering == "coordinate":
|
if numbering == "coordinate":
|
||||||
ws1.write(li1, col + 2, etudid[2], style2m2)
|
ws1.write(li1, col + 2, etudid[2], style2m2)
|
||||||
ws1.write(li1, col + 3, etudid[3], style2r)
|
ws1.write(li1, col + 3, etudid[3], style2r)
|
||||||
|
@ -35,11 +35,13 @@ import xml.sax.saxutils
|
|||||||
import xml.dom.minidom
|
import xml.dom.minidom
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
import sco_utils
|
import sco_utils as scu
|
||||||
from sco_utils import ScoEtudInscrit, log, ScoValueError, DictDefault
|
from sco_utils import SCO_ENCODING
|
||||||
from sco_utils import SCO_TMP_DIR, SCO_ENCODING
|
from sco_permissions import ScoEtudInscrit
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
from notes_log import log
|
||||||
|
|
||||||
SCO_CACHE_ETAPE_FILENAME = os.path.join(SCO_TMP_DIR, "last_etapes.xml")
|
SCO_CACHE_ETAPE_FILENAME = os.path.join(scu.SCO_TMP_DIR, "last_etapes.xml")
|
||||||
|
|
||||||
|
|
||||||
def has_portal(context):
|
def has_portal(context):
|
||||||
@ -162,7 +164,7 @@ def get_inscrits_etape(context, code_etape, anneeapogee=None, ntrials=2):
|
|||||||
if portal_timeout > 0:
|
if portal_timeout > 0:
|
||||||
actual_timeout = max(1, actual_timeout)
|
actual_timeout = max(1, actual_timeout)
|
||||||
for _ntrial in range(ntrials):
|
for _ntrial in range(ntrials):
|
||||||
doc = sco_utils.query_portal(req, timeout=actual_timeout)
|
doc = scu.query_portal(req, timeout=actual_timeout)
|
||||||
if doc:
|
if doc:
|
||||||
break
|
break
|
||||||
if not doc:
|
if not doc:
|
||||||
@ -203,7 +205,7 @@ def query_apogee_portal(context, **args):
|
|||||||
return []
|
return []
|
||||||
portal_timeout = context.get_preference("portal_timeout")
|
portal_timeout = context.get_preference("portal_timeout")
|
||||||
req = etud_url + "?" + urllib.urlencode(args.items())
|
req = etud_url + "?" + urllib.urlencode(args.items())
|
||||||
doc = sco_utils.query_portal(req, timeout=portal_timeout) # sco_utils
|
doc = scu.query_portal(req, timeout=portal_timeout) # sco_utils
|
||||||
return xml_to_list_of_dicts(doc, req=req)
|
return xml_to_list_of_dicts(doc, req=req)
|
||||||
|
|
||||||
|
|
||||||
@ -259,7 +261,7 @@ def get_infos_apogee_allaccents(context, nom, prenom):
|
|||||||
"essai recup infos avec differents codages des accents"
|
"essai recup infos avec differents codages des accents"
|
||||||
if nom:
|
if nom:
|
||||||
unom = unicode(nom, SCO_ENCODING)
|
unom = unicode(nom, SCO_ENCODING)
|
||||||
nom_noaccents = str(sco_utils.suppression_diacritics(unom))
|
nom_noaccents = str(scu.suppression_diacritics(unom))
|
||||||
nom_utf8 = unom.encode("utf-8")
|
nom_utf8 = unom.encode("utf-8")
|
||||||
else:
|
else:
|
||||||
nom_noaccents = nom
|
nom_noaccents = nom
|
||||||
@ -267,7 +269,7 @@ def get_infos_apogee_allaccents(context, nom, prenom):
|
|||||||
|
|
||||||
if prenom:
|
if prenom:
|
||||||
uprenom = unicode(prenom, SCO_ENCODING)
|
uprenom = unicode(prenom, SCO_ENCODING)
|
||||||
prenom_noaccents = str(sco_utils.suppression_diacritics(uprenom))
|
prenom_noaccents = str(scu.suppression_diacritics(uprenom))
|
||||||
prenom_utf8 = uprenom.encode("utf-8")
|
prenom_utf8 = uprenom.encode("utf-8")
|
||||||
else:
|
else:
|
||||||
prenom_noaccents = prenom
|
prenom_noaccents = prenom
|
||||||
@ -323,7 +325,7 @@ def get_etud_apogee(context, code_nip):
|
|||||||
return {}
|
return {}
|
||||||
portal_timeout = context.get_preference("portal_timeout")
|
portal_timeout = context.get_preference("portal_timeout")
|
||||||
req = etud_url + "?" + urllib.urlencode((("nip", code_nip),))
|
req = etud_url + "?" + urllib.urlencode((("nip", code_nip),))
|
||||||
doc = sco_utils.query_portal(req, timeout=portal_timeout)
|
doc = scu.query_portal(req, timeout=portal_timeout)
|
||||||
d = _normalize_apo_fields(xml_to_list_of_dicts(doc, req=req))
|
d = _normalize_apo_fields(xml_to_list_of_dicts(doc, req=req))
|
||||||
if not d:
|
if not d:
|
||||||
return None
|
return None
|
||||||
@ -387,7 +389,7 @@ def get_etapes_apogee(context):
|
|||||||
"get_etapes_apogee: requesting '%s' with timeout=%s"
|
"get_etapes_apogee: requesting '%s' with timeout=%s"
|
||||||
% (etapes_url, portal_timeout)
|
% (etapes_url, portal_timeout)
|
||||||
)
|
)
|
||||||
doc = sco_utils.query_portal(etapes_url, timeout=portal_timeout)
|
doc = scu.query_portal(etapes_url, timeout=portal_timeout)
|
||||||
try:
|
try:
|
||||||
infos = _parse_etapes_from_xml(context, doc)
|
infos = _parse_etapes_from_xml(context, doc)
|
||||||
# cache le resultat (utile si le portail repond de façon intermitente)
|
# cache le resultat (utile si le portail repond de façon intermitente)
|
||||||
@ -482,7 +484,7 @@ def _normalize_apo_fields(infolist):
|
|||||||
for infos in infolist:
|
for infos in infolist:
|
||||||
if infos.has_key("paiementinscription"):
|
if infos.has_key("paiementinscription"):
|
||||||
infos["paiementinscription"] = (
|
infos["paiementinscription"] = (
|
||||||
sco_utils.strlower(infos["paiementinscription"]) == "true"
|
scu.strlower(infos["paiementinscription"]) == "true"
|
||||||
)
|
)
|
||||||
if infos["paiementinscription"]:
|
if infos["paiementinscription"]:
|
||||||
infos["paiementinscription_str"] = "ok"
|
infos["paiementinscription_str"] = "ok"
|
||||||
@ -562,5 +564,5 @@ def get_maquette_apogee(context, etape="", annee_scolaire=""):
|
|||||||
+ "?"
|
+ "?"
|
||||||
+ urllib.urlencode((("etape", etape), ("annee", annee_scolaire)))
|
+ urllib.urlencode((("etape", etape), ("annee", annee_scolaire)))
|
||||||
)
|
)
|
||||||
doc = sco_utils.query_portal(req, timeout=portal_timeout)
|
doc = scu.query_portal(req, timeout=portal_timeout)
|
||||||
return doc
|
return doc
|
||||||
|
@ -29,21 +29,22 @@
|
|||||||
|
|
||||||
Recapitule tous les semestres validés dans une feuille excel.
|
Recapitule tous les semestres validés dans une feuille excel.
|
||||||
"""
|
"""
|
||||||
|
import collections
|
||||||
|
|
||||||
from notesdb import *
|
import sco_utils as scu
|
||||||
from sco_utils import *
|
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_groups
|
import sco_groups
|
||||||
import sco_abs
|
import sco_abs
|
||||||
from sco_codes_parcours import code_semestre_validant, code_semestre_attente
|
from sco_codes_parcours import code_semestre_validant, code_semestre_attente
|
||||||
|
import VERSION
|
||||||
|
|
||||||
|
|
||||||
def etud_get_poursuite_info(context, sem, etud):
|
def etud_get_poursuite_info(context, sem, etud):
|
||||||
"""{ 'nom' : ..., 'semlist' : [ { 'semestre_id': , 'moy' : ... }, {}, ...] }"""
|
"""{ 'nom' : ..., 'semlist' : [ { 'semestre_id': , 'moy' : ... }, {}, ...] }"""
|
||||||
I = {}
|
I = {}
|
||||||
I.update(etud) # copie nom, prenom, sexe, ...
|
I.update(etud) # copie nom, prenom, civilite, ...
|
||||||
|
|
||||||
# Now add each semester, starting from the first one
|
# Now add each semester, starting from the first one
|
||||||
semlist = []
|
semlist = []
|
||||||
@ -62,7 +63,7 @@ def etud_get_poursuite_info(context, sem, etud):
|
|||||||
moy_ues = [
|
moy_ues = [
|
||||||
(
|
(
|
||||||
ue["acronyme"],
|
ue["acronyme"],
|
||||||
fmt_note(nt.get_etud_ue_status(etudid, ue["ue_id"])["moy"]),
|
scu.fmt_note(nt.get_etud_ue_status(etudid, ue["ue_id"])["moy"]),
|
||||||
)
|
)
|
||||||
for ue in ues
|
for ue in ues
|
||||||
]
|
]
|
||||||
@ -79,7 +80,7 @@ def etud_get_poursuite_info(context, sem, etud):
|
|||||||
for modimpl in modimpls: # dans chaque UE les modules
|
for modimpl in modimpls: # dans chaque UE les modules
|
||||||
if modimpl["module"]["ue_id"] == ue["ue_id"]:
|
if modimpl["module"]["ue_id"] == ue["ue_id"]:
|
||||||
codeModule = modimpl["module"]["code"]
|
codeModule = modimpl["module"]["code"]
|
||||||
noteModule = fmt_note(
|
noteModule = scu.fmt_note(
|
||||||
nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid)
|
nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid)
|
||||||
)
|
)
|
||||||
if noteModule != "NI": # si étudiant inscrit au module
|
if noteModule != "NI": # si étudiant inscrit au module
|
||||||
@ -103,8 +104,8 @@ def etud_get_poursuite_info(context, sem, etud):
|
|||||||
and nt.get_etud_etat(etudid) == "I"
|
and nt.get_etud_etat(etudid) == "I"
|
||||||
):
|
):
|
||||||
d = [
|
d = [
|
||||||
("moy", fmt_note(nt.get_etud_moy_gen(etudid))),
|
("moy", scu.fmt_note(nt.get_etud_moy_gen(etudid))),
|
||||||
("moy_promo", fmt_note(nt.moy_moy)),
|
("moy_promo", scu.fmt_note(nt.moy_moy)),
|
||||||
("rang", nt.get_etud_rang(etudid)),
|
("rang", nt.get_etud_rang(etudid)),
|
||||||
("effectif", len(nt.T)),
|
("effectif", len(nt.T)),
|
||||||
("date_debut", s["date_debut"]),
|
("date_debut", s["date_debut"]),
|
||||||
@ -154,7 +155,6 @@ def formsemestre_poursuite_report(
|
|||||||
):
|
):
|
||||||
"""Table avec informations "poursuite" """
|
"""Table avec informations "poursuite" """
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||||
nt = context._getNotesCache().get_NotesTable(context, formsemestre_id)
|
|
||||||
etuds = context.getEtudInfoGroupes(
|
etuds = context.getEtudInfoGroupes(
|
||||||
[sco_groups.get_default_group(context, formsemestre_id)]
|
[sco_groups.get_default_group(context, formsemestre_id)]
|
||||||
)
|
)
|
||||||
@ -174,7 +174,7 @@ def formsemestre_poursuite_report(
|
|||||||
infos.append(info)
|
infos.append(info)
|
||||||
#
|
#
|
||||||
column_ids = (
|
column_ids = (
|
||||||
("sexe", "nom", "prenom", "annee", "date_naissance")
|
("civilite_str", "nom", "prenom", "annee", "date_naissance")
|
||||||
+ tuple(ids)
|
+ tuple(ids)
|
||||||
+ ("debouche",)
|
+ ("debouche",)
|
||||||
)
|
)
|
||||||
@ -191,9 +191,9 @@ def formsemestre_poursuite_report(
|
|||||||
pdf_link=False, # pas d'export pdf
|
pdf_link=False, # pas d'export pdf
|
||||||
preferences=context.get_preferences(formsemestre_id),
|
preferences=context.get_preferences(formsemestre_id),
|
||||||
)
|
)
|
||||||
tab.filename = make_filename("poursuite " + sem["titreannee"])
|
tab.filename = scu.make_filename("poursuite " + sem["titreannee"])
|
||||||
|
|
||||||
tab.origin = "Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + ""
|
tab.origin = "Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + ""
|
||||||
tab.caption = "Récapitulatif %s." % sem["titreannee"]
|
tab.caption = "Récapitulatif %s." % sem["titreannee"]
|
||||||
tab.html_caption = "Récapitulatif %s." % sem["titreannee"]
|
tab.html_caption = "Récapitulatif %s." % sem["titreannee"]
|
||||||
tab.base_url = "%s?formsemestre_id=%s" % (REQUEST.URL0, formsemestre_id)
|
tab.base_url = "%s?formsemestre_id=%s" % (REQUEST.URL0, formsemestre_id)
|
||||||
|
@ -28,11 +28,13 @@
|
|||||||
"""ScoDoc preferences (replaces old Zope properties)
|
"""ScoDoc preferences (replaces old Zope properties)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
|
from notes_log import log
|
||||||
from TrivialFormulator import TrivialFormulator, TF
|
from TrivialFormulator import TrivialFormulator, TF
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_bulletins_generator
|
import sco_bulletins_generator
|
||||||
|
from sco_exceptions import ScoValueError, ScoException
|
||||||
|
|
||||||
"""Global/Semestre Preferences for ScoDoc (version dec 2008)
|
"""Global/Semestre Preferences for ScoDoc (version dec 2008)
|
||||||
|
|
||||||
@ -1722,7 +1724,7 @@ PREFS_DICT = dict(PREFS)
|
|||||||
|
|
||||||
|
|
||||||
class sco_base_preferences:
|
class sco_base_preferences:
|
||||||
_editor = EditableTable(
|
_editor = ndb.EditableTable(
|
||||||
"sco_prefs",
|
"sco_prefs",
|
||||||
"pref_id",
|
"pref_id",
|
||||||
("pref_id", "name", "value", "formsemestre_id"),
|
("pref_id", "name", "value", "formsemestre_id"),
|
||||||
@ -1741,7 +1743,7 @@ class sco_base_preferences:
|
|||||||
"""Load all preferences from db"""
|
"""Load all preferences from db"""
|
||||||
log("loading preferences")
|
log("loading preferences")
|
||||||
try:
|
try:
|
||||||
GSL.acquire()
|
scu.GSL.acquire()
|
||||||
cnx = self.context.GetDBConnexion()
|
cnx = self.context.GetDBConnexion()
|
||||||
preflist = self._editor.list(cnx)
|
preflist = self._editor.list(cnx)
|
||||||
self.prefs = {None: {}} # { formsemestre_id (or None) : { name : value } }
|
self.prefs = {None: {}} # { formsemestre_id (or None) : { name : value } }
|
||||||
@ -1788,9 +1790,9 @@ class sco_base_preferences:
|
|||||||
% (name, value)
|
% (name, value)
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
# search in CONFIG
|
# search in scu.CONFIG
|
||||||
if hasattr(CONFIG, name):
|
if hasattr(scu.CONFIG, name):
|
||||||
value = getattr(CONFIG, name)
|
value = getattr(scu.CONFIG, name)
|
||||||
log(
|
log(
|
||||||
"sco_preferences: found default value in config for %s=%s"
|
"sco_preferences: found default value in config for %s=%s"
|
||||||
% (name, value)
|
% (name, value)
|
||||||
@ -1805,7 +1807,7 @@ class sco_base_preferences:
|
|||||||
# add to db table
|
# add to db table
|
||||||
self._editor.create(cnx, {"name": name, "value": value})
|
self._editor.create(cnx, {"name": name, "value": value})
|
||||||
finally:
|
finally:
|
||||||
GSL.release()
|
scu.GSL.release()
|
||||||
|
|
||||||
def get(self, formsemestre_id, name):
|
def get(self, formsemestre_id, name):
|
||||||
"""Returns preference value.
|
"""Returns preference value.
|
||||||
@ -1837,7 +1839,7 @@ class sco_base_preferences:
|
|||||||
def save(self, formsemestre_id=None, name=None):
|
def save(self, formsemestre_id=None, name=None):
|
||||||
"""Write one or all (if name is None) values to db"""
|
"""Write one or all (if name is None) values to db"""
|
||||||
try:
|
try:
|
||||||
GSL.acquire()
|
scu.GSL.acquire()
|
||||||
modif = False
|
modif = False
|
||||||
cnx = self.context.GetDBConnexion()
|
cnx = self.context.GetDBConnexion()
|
||||||
if name is None:
|
if name is None:
|
||||||
@ -1884,7 +1886,7 @@ class sco_base_preferences:
|
|||||||
if modif:
|
if modif:
|
||||||
self.context.Notes._inval_cache(pdfonly=False) # > modif preferences
|
self.context.Notes._inval_cache(pdfonly=False) # > modif preferences
|
||||||
finally:
|
finally:
|
||||||
GSL.release()
|
scu.GSL.release()
|
||||||
|
|
||||||
def set(self, formsemestre_id, name, value):
|
def set(self, formsemestre_id, name, value):
|
||||||
if not name or name[0] == "_" or name not in PREFS_NAMES:
|
if not name or name[0] == "_" or name not in PREFS_NAMES:
|
||||||
@ -1900,7 +1902,7 @@ class sco_base_preferences:
|
|||||||
if not formsemestre_id:
|
if not formsemestre_id:
|
||||||
raise ScoException()
|
raise ScoException()
|
||||||
try:
|
try:
|
||||||
GSL.acquire()
|
scu.GSL.acquire()
|
||||||
if formsemestre_id in self.prefs and name in self.prefs[formsemestre_id]:
|
if formsemestre_id in self.prefs and name in self.prefs[formsemestre_id]:
|
||||||
del self.prefs[formsemestre_id][name]
|
del self.prefs[formsemestre_id][name]
|
||||||
cnx = self.context.GetDBConnexion()
|
cnx = self.context.GetDBConnexion()
|
||||||
@ -1912,7 +1914,7 @@ class sco_base_preferences:
|
|||||||
self._editor.delete(cnx, pdb[0]["pref_id"])
|
self._editor.delete(cnx, pdb[0]["pref_id"])
|
||||||
self.context.Notes._inval_cache(pdfonly=False) # > modif preferences
|
self.context.Notes._inval_cache(pdfonly=False) # > modif preferences
|
||||||
finally:
|
finally:
|
||||||
GSL.release()
|
scu.GSL.release()
|
||||||
|
|
||||||
def edit(self, REQUEST):
|
def edit(self, REQUEST):
|
||||||
"""HTML dialog: edit global preferences"""
|
"""HTML dialog: edit global preferences"""
|
||||||
@ -1934,13 +1936,13 @@ class sco_base_preferences:
|
|||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + self.context.sco_footer(REQUEST)
|
return "\n".join(H) + tf[1] + self.context.sco_footer(REQUEST)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1) # cancel
|
return REQUEST.RESPONSE.redirect(self.context.ScoURL()) # cancel
|
||||||
else:
|
else:
|
||||||
for pref in PREFS:
|
for pref in PREFS:
|
||||||
self.prefs[None][pref[0]] = tf[2][pref[0]]
|
self.prefs[None][pref[0]] = tf[2][pref[0]]
|
||||||
self.save()
|
self.save()
|
||||||
return REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
REQUEST.URL1 + "?head_message=Préférences modifiées"
|
self.context.ScoURL() + "?head_message=Préférences modifiées"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -1982,7 +1984,6 @@ class sem_preferences:
|
|||||||
# The dialog
|
# The dialog
|
||||||
def edit(self, categories=[], REQUEST=None):
|
def edit(self, categories=[], REQUEST=None):
|
||||||
"""Dialog to edit semestre preferences in given categories"""
|
"""Dialog to edit semestre preferences in given categories"""
|
||||||
# log('XXX edit')
|
|
||||||
if not self.formsemestre_id:
|
if not self.formsemestre_id:
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
"sem_preferences.edit doit etre appele sur un semestre !"
|
"sem_preferences.edit doit etre appele sur un semestre !"
|
||||||
@ -2029,7 +2030,6 @@ function set_global_pref(el, pref_name) {
|
|||||||
form.append(("create_local", {"input_type": "hidden"}))
|
form.append(("create_local", {"input_type": "hidden"}))
|
||||||
form.append(("destination", {"input_type": "hidden"}))
|
form.append(("destination", {"input_type": "hidden"}))
|
||||||
form.append(("formsemestre_id", {"input_type": "hidden"}))
|
form.append(("formsemestre_id", {"input_type": "hidden"}))
|
||||||
# log('REQUEST form=%s'%REQUEST.form)
|
|
||||||
tf = TrivialFormulator(
|
tf = TrivialFormulator(
|
||||||
REQUEST.URL0,
|
REQUEST.URL0,
|
||||||
REQUEST.form,
|
REQUEST.form,
|
||||||
@ -2038,17 +2038,19 @@ function set_global_pref(el, pref_name) {
|
|||||||
cssclass="sco_pref",
|
cssclass="sco_pref",
|
||||||
submitlabel="Enregistrer les modifications",
|
submitlabel="Enregistrer les modifications",
|
||||||
)
|
)
|
||||||
|
dest_url = (
|
||||||
|
self.context.NotesURL()
|
||||||
|
+ "formsemestre_status?formsemestre_id=%s" % self.formsemestre_id
|
||||||
|
)
|
||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return "\n".join(H) + tf[1] + self.context.sco_footer(REQUEST)
|
return "\n".join(H) + tf[1] + self.context.sco_footer(REQUEST)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
REQUEST.URL1 + "?head_message=Annulé"
|
dest_url + "&head_message=Annulé"
|
||||||
) # cancel
|
) # cancel
|
||||||
else:
|
else:
|
||||||
# log('tf[2]=%s' % tf[2]) # XXX
|
|
||||||
# Supprime pref locale du semestre (retour à la valeur globale)
|
# Supprime pref locale du semestre (retour à la valeur globale)
|
||||||
if tf[2]["suppress"]:
|
if tf[2]["suppress"]:
|
||||||
# log('suppress %s' % tf[2]['suppress']) # XXX
|
|
||||||
self.base_prefs.delete(self.formsemestre_id, tf[2]["suppress"])
|
self.base_prefs.delete(self.formsemestre_id, tf[2]["suppress"])
|
||||||
# Cree pref local (copie valeur globale)
|
# Cree pref local (copie valeur globale)
|
||||||
if tf[2]["create_local"]:
|
if tf[2]["create_local"]:
|
||||||
@ -2080,9 +2082,7 @@ function set_global_pref(el, pref_name) {
|
|||||||
destination = tf[2]["destination"]
|
destination = tf[2]["destination"]
|
||||||
if destination == "done" or destination == "":
|
if destination == "done" or destination == "":
|
||||||
return REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
REQUEST.URL1
|
dest_url + "&head_message=Préférences modifiées"
|
||||||
+ "/formsemestre_status?head_message=Préférences modifiées&formsemestre_id="
|
|
||||||
+ self.formsemestre_id
|
|
||||||
)
|
)
|
||||||
elif destination == "again":
|
elif destination == "again":
|
||||||
return REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
|
@ -27,9 +27,9 @@
|
|||||||
|
|
||||||
"""Feuille excel pour preparation des jurys
|
"""Feuille excel pour preparation des jurys
|
||||||
"""
|
"""
|
||||||
|
import time
|
||||||
|
|
||||||
from notesdb import *
|
import sco_utils as scu
|
||||||
from sco_utils import *
|
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import notes_table
|
import notes_table
|
||||||
import sco_groups
|
import sco_groups
|
||||||
@ -37,8 +37,9 @@ import sco_excel
|
|||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_parcours_dut
|
import sco_parcours_dut
|
||||||
import sco_codes_parcours
|
import sco_codes_parcours
|
||||||
from scolars import format_nom, format_prenom, format_sexe, format_lycee
|
from scolars import format_nom, format_prenom, format_civilite, format_lycee
|
||||||
from sco_abs import getAbsSemEtud
|
from sco_abs import getAbsSemEtud
|
||||||
|
import VERSION
|
||||||
|
|
||||||
|
|
||||||
def feuille_preparation_jury(context, formsemestre_id, REQUEST):
|
def feuille_preparation_jury(context, formsemestre_id, REQUEST):
|
||||||
@ -54,10 +55,10 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST):
|
|||||||
context, formsemestre_id
|
context, formsemestre_id
|
||||||
)["partition_id"]
|
)["partition_id"]
|
||||||
|
|
||||||
prev_moy_ue = DictDefault(defaultvalue={}) # ue_code_s : { etudid : moy ue }
|
prev_moy_ue = scu.DictDefault(defaultvalue={}) # ue_code_s : { etudid : moy ue }
|
||||||
prev_ue_acro = {} # ue_code_s : acronyme (à afficher)
|
prev_ue_acro = {} # ue_code_s : acronyme (à afficher)
|
||||||
prev_moy = {} # moyennes gen sem prec
|
prev_moy = {} # moyennes gen sem prec
|
||||||
moy_ue = DictDefault(defaultvalue={}) # ue_acro : moyennes { etudid : moy ue }
|
moy_ue = scu.DictDefault(defaultvalue={}) # ue_acro : moyennes { etudid : moy ue }
|
||||||
ue_acro = {} # ue_code_s : acronyme (à afficher)
|
ue_acro = {} # ue_code_s : acronyme (à afficher)
|
||||||
moy = {} # moyennes gen
|
moy = {} # moyennes gen
|
||||||
moy_inter = {} # moyenne gen. sur les 2 derniers semestres
|
moy_inter = {} # moyenne gen. sur les 2 derniers semestres
|
||||||
@ -136,11 +137,17 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST):
|
|||||||
# Codes des UE "semestre précédent":
|
# Codes des UE "semestre précédent":
|
||||||
ue_prev_codes = prev_moy_ue.keys()
|
ue_prev_codes = prev_moy_ue.keys()
|
||||||
ue_prev_codes.sort(
|
ue_prev_codes.sort(
|
||||||
lambda x, y, prev_ue_acro=prev_ue_acro: cmp(prev_ue_acro[x], prev_ue_acro[y])
|
lambda x, y, prev_ue_acro=prev_ue_acro: cmp( # pylint: disable=undefined-variable
|
||||||
|
prev_ue_acro[x], prev_ue_acro[y]
|
||||||
|
)
|
||||||
)
|
)
|
||||||
# Codes des UE "semestre courant":
|
# Codes des UE "semestre courant":
|
||||||
ue_codes = moy_ue.keys()
|
ue_codes = moy_ue.keys()
|
||||||
ue_codes.sort(lambda x, y, ue_acro=ue_acro: cmp(ue_acro[x], ue_acro[y]))
|
ue_codes.sort(
|
||||||
|
lambda x, y, ue_acro=ue_acro: cmp( # pylint: disable=undefined-variable
|
||||||
|
ue_acro[x], ue_acro[y]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
sid = sem["semestre_id"]
|
sid = sem["semestre_id"]
|
||||||
sn = sp = ""
|
sn = sp = ""
|
||||||
@ -150,7 +157,7 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST):
|
|||||||
sp = "S%s" % (sid - 1)
|
sp = "S%s" % (sid - 1)
|
||||||
|
|
||||||
L = sco_excel.ScoExcelSheet(sheet_name="Prepa Jury %s" % sn)
|
L = sco_excel.ScoExcelSheet(sheet_name="Prepa Jury %s" % sn)
|
||||||
L.append(["Feuille préparation Jury %s" % unescape_html(sem["titreannee"])])
|
L.append(["Feuille préparation Jury %s" % scu.unescape_html(sem["titreannee"])])
|
||||||
L.append([]) # empty line
|
L.append([]) # empty line
|
||||||
|
|
||||||
titles = ["Rang"]
|
titles = ["Rang"]
|
||||||
@ -206,7 +213,7 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST):
|
|||||||
|
|
||||||
def fmt(x):
|
def fmt(x):
|
||||||
"reduit les notes a deux chiffres"
|
"reduit les notes a deux chiffres"
|
||||||
x = notes_table.fmt_note(x, keep_numeric=False)
|
x = scu.fmt_note(x, keep_numeric=False)
|
||||||
try:
|
try:
|
||||||
return float(x)
|
return float(x)
|
||||||
except:
|
except:
|
||||||
@ -222,7 +229,7 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST):
|
|||||||
l.append(etud["code_ine"])
|
l.append(etud["code_ine"])
|
||||||
l += [
|
l += [
|
||||||
etudid,
|
etudid,
|
||||||
format_sexe(etud["sexe"]),
|
etud["civilite_str"],
|
||||||
format_nom(etud["nom"]),
|
format_nom(etud["nom"]),
|
||||||
format_prenom(etud["prenom"]),
|
format_prenom(etud["prenom"]),
|
||||||
etud["date_naissance"],
|
etud["date_naissance"],
|
||||||
|
@ -27,7 +27,13 @@
|
|||||||
|
|
||||||
"""Edition des PV de jury
|
"""Edition des PV de jury
|
||||||
"""
|
"""
|
||||||
|
import time
|
||||||
|
from reportlab.platypus import Paragraph
|
||||||
|
from reportlab.lib import styles
|
||||||
|
|
||||||
|
import sco_utils as scu
|
||||||
|
import notesdb as ndb
|
||||||
|
from notes_log import log
|
||||||
import scolars
|
import scolars
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_groups
|
import sco_groups
|
||||||
@ -36,11 +42,11 @@ import sco_parcours_dut
|
|||||||
import sco_codes_parcours
|
import sco_codes_parcours
|
||||||
from sco_codes_parcours import NO_SEMESTRE_ID
|
from sco_codes_parcours import NO_SEMESTRE_ID
|
||||||
import sco_excel
|
import sco_excel
|
||||||
from notesdb import *
|
from TrivialFormulator import TrivialFormulator
|
||||||
from sco_utils import *
|
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
import sco_pvpdf
|
import sco_pvpdf
|
||||||
from sco_pdf import *
|
import sco_pdf
|
||||||
|
from sco_pdf import PDFLOCK
|
||||||
|
|
||||||
"""PV Jury IUTV 2006: on détaillait 8 cas:
|
"""PV Jury IUTV 2006: on détaillait 8 cas:
|
||||||
Jury de semestre n
|
Jury de semestre n
|
||||||
@ -71,9 +77,9 @@ def _descr_decisions_ues(context, nt, etudid, decisions_ue, decision_sem):
|
|||||||
for ue_id in decisions_ue.keys():
|
for ue_id in decisions_ue.keys():
|
||||||
try:
|
try:
|
||||||
if decisions_ue[ue_id] and (
|
if decisions_ue[ue_id] and (
|
||||||
decisions_ue[ue_id]["code"] == ADM
|
decisions_ue[ue_id]["code"] == sco_codes_parcours.ADM
|
||||||
or (
|
or (
|
||||||
CONFIG.CAPITALIZE_ALL_UES
|
scu.CONFIG.CAPITALIZE_ALL_UES
|
||||||
and sco_codes_parcours.code_semestre_validant(decision_sem["code"])
|
and sco_codes_parcours.code_semestre_validant(decision_sem["code"])
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
@ -135,7 +141,7 @@ def _comp_ects_by_ue_code_and_type(nt, decision_ues):
|
|||||||
return {}, {}
|
return {}, {}
|
||||||
|
|
||||||
ects_by_ue_code = {}
|
ects_by_ue_code = {}
|
||||||
ects_by_ue_type = DictDefault(defaultvalue=0) # { ue_type : ects validés }
|
ects_by_ue_type = scu.DictDefault(defaultvalue=0) # { ue_type : ects validés }
|
||||||
for ue_id in decision_ues:
|
for ue_id in decision_ues:
|
||||||
d = decision_ues[ue_id]
|
d = decision_ues[ue_id]
|
||||||
ue = nt.uedict[ue_id]
|
ue = nt.uedict[ue_id]
|
||||||
@ -245,7 +251,7 @@ def dict_pvjury(
|
|||||||
if d["decision_sem"] and sco_codes_parcours.code_semestre_validant(
|
if d["decision_sem"] and sco_codes_parcours.code_semestre_validant(
|
||||||
d["decision_sem"]["code"]
|
d["decision_sem"]["code"]
|
||||||
):
|
):
|
||||||
d["mention"] = get_mention(nt.get_etud_moy_gen(etudid))
|
d["mention"] = scu.get_mention(nt.get_etud_moy_gen(etudid))
|
||||||
else:
|
else:
|
||||||
d["mention"] = ""
|
d["mention"] = ""
|
||||||
# Versions "en français": (avec les UE capitalisées d'ailleurs)
|
# Versions "en français": (avec les UE capitalisées d'ailleurs)
|
||||||
@ -310,13 +316,13 @@ def dict_pvjury(
|
|||||||
|
|
||||||
# Cherche la date de decision (sem ou UE) la plus récente:
|
# Cherche la date de decision (sem ou UE) la plus récente:
|
||||||
if d["decision_sem"]:
|
if d["decision_sem"]:
|
||||||
date = DateDMYtoISO(d["decision_sem"]["event_date"])
|
date = ndb.DateDMYtoISO(d["decision_sem"]["event_date"])
|
||||||
if date > max_date: # decision plus recente
|
if date > max_date: # decision plus recente
|
||||||
max_date = date
|
max_date = date
|
||||||
if d["decisions_ue"]:
|
if d["decisions_ue"]:
|
||||||
for dec_ue in d["decisions_ue"].values():
|
for dec_ue in d["decisions_ue"].values():
|
||||||
if dec_ue:
|
if dec_ue:
|
||||||
date = DateDMYtoISO(dec_ue["event_date"])
|
date = ndb.DateDMYtoISO(dec_ue["event_date"])
|
||||||
if date > max_date: # decision plus recente
|
if date > max_date: # decision plus recente
|
||||||
max_date = date
|
max_date = date
|
||||||
# Code semestre precedent
|
# Code semestre precedent
|
||||||
@ -343,7 +349,7 @@ def dict_pvjury(
|
|||||||
D[etudid] = d
|
D[etudid] = d
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"date": DateISOtoDMY(max_date),
|
"date": ndb.DateISOtoDMY(max_date),
|
||||||
"formsemestre": sem,
|
"formsemestre": sem,
|
||||||
"has_prev": has_prev,
|
"has_prev": has_prev,
|
||||||
"semestre_non_terminal": semestre_non_terminal,
|
"semestre_non_terminal": semestre_non_terminal,
|
||||||
@ -412,9 +418,11 @@ def pvjury_table(
|
|||||||
if context.get_preference("bul_show_ects", formsemestre_id):
|
if context.get_preference("bul_show_ects", formsemestre_id):
|
||||||
columns_ids += ["ects"]
|
columns_ids += ["ects"]
|
||||||
|
|
||||||
# if dpv['semestre_non_terminal']:
|
# XXX if not dpv["semestre_non_terminal"]:
|
||||||
# dec 2017: indique toujours le devenir ("diplôme obtenu" ou semestre suivant)
|
# La colonne doit être présente: redoublants validant leur diplome
|
||||||
columns_ids += ["validation_parcours_code", "devenir"]
|
# en répétant un semestre ancien: exemple: S1 (ADM), S2 (ADM), S3 (AJ), S4 (ADM), S3 (ADM)=> diplôme
|
||||||
|
columns_ids += ["validation_parcours_code"]
|
||||||
|
columns_ids += ["devenir"]
|
||||||
columns_ids += ["observations"]
|
columns_ids += ["observations"]
|
||||||
|
|
||||||
lines = []
|
lines = []
|
||||||
@ -432,9 +440,9 @@ def pvjury_table(
|
|||||||
context, e["etat"], e["decision_sem"]
|
context, e["etat"], e["decision_sem"]
|
||||||
),
|
),
|
||||||
"ue_cap": e["decisions_ue_descr"],
|
"ue_cap": e["decisions_ue_descr"],
|
||||||
"validation_parcours_code": "ADM" if e["validation_parcours"] else "AJ",
|
"validation_parcours_code": "ADM" if e["validation_parcours"] else "",
|
||||||
"devenir": e["autorisations_descr"],
|
"devenir": e["autorisations_descr"],
|
||||||
"observations": unquote(e["observation"]),
|
"observations": ndb.unquote(e["observation"]),
|
||||||
"mention": e["mention"],
|
"mention": e["mention"],
|
||||||
"ects": str(e["sum_ects"]),
|
"ects": str(e["sum_ects"]),
|
||||||
}
|
}
|
||||||
@ -449,10 +457,10 @@ def pvjury_table(
|
|||||||
) # vertical space
|
) # vertical space
|
||||||
i = e["identite"]
|
i = e["identite"]
|
||||||
l["nomprenom"] = [
|
l["nomprenom"] = [
|
||||||
Paragraph(SU(i["nomprenom"]), cell_style),
|
Paragraph(sco_pdf.SU(i["nomprenom"]), cell_style),
|
||||||
Paragraph(SU(i["code_nip"]), cell_style),
|
Paragraph(sco_pdf.SU(i["code_nip"]), cell_style),
|
||||||
Paragraph(
|
Paragraph(
|
||||||
SU(
|
sco_pdf.SU(
|
||||||
"Né le %s" % i["date_naissance"]
|
"Né le %s" % i["date_naissance"]
|
||||||
+ (" à %s" % i["lieu_naissance"] if i["lieu_naissance"] else "")
|
+ (" à %s" % i["lieu_naissance"] if i["lieu_naissance"] else "")
|
||||||
+ (" (%s)" % i["dept_naissance"] if i["dept_naissance"] else "")
|
+ (" (%s)" % i["dept_naissance"] if i["dept_naissance"] else "")
|
||||||
@ -513,8 +521,10 @@ def formsemestre_pvjury(
|
|||||||
rows=rows,
|
rows=rows,
|
||||||
titles=titles,
|
titles=titles,
|
||||||
columns_ids=columns_ids,
|
columns_ids=columns_ids,
|
||||||
filename=make_filename("decisions " + sem["titreannee"]),
|
filename=scu.make_filename("decisions " + sem["titreannee"]),
|
||||||
origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "",
|
origin="Généré par %s le " % scu.VERSION.SCONAME
|
||||||
|
+ scu.timedate_human_repr()
|
||||||
|
+ "",
|
||||||
caption="Décisions jury pour " + sem["titreannee"],
|
caption="Décisions jury pour " + sem["titreannee"],
|
||||||
html_class="table_leftalign",
|
html_class="table_leftalign",
|
||||||
html_sortable=True,
|
html_sortable=True,
|
||||||
@ -552,7 +562,7 @@ def formsemestre_pvjury(
|
|||||||
H.append(tab.html())
|
H.append(tab.html())
|
||||||
|
|
||||||
# Count number of cases for each decision
|
# Count number of cases for each decision
|
||||||
counts = DictDefault()
|
counts = scu.DictDefault()
|
||||||
for row in rows:
|
for row in rows:
|
||||||
counts[row["decision"]] += 1
|
counts[row["decision"]] += 1
|
||||||
# add codes for previous (for explanation, without count)
|
# add codes for previous (for explanation, without count)
|
||||||
@ -673,10 +683,6 @@ def formsemestre_pvjury_pdf(
|
|||||||
tf[2]["showTitle"] = True
|
tf[2]["showTitle"] = True
|
||||||
else:
|
else:
|
||||||
tf[2]["showTitle"] = False
|
tf[2]["showTitle"] = False
|
||||||
if tf[2]["with_paragraph_nom"]:
|
|
||||||
tf[2]["with_paragraph_nom"] = True
|
|
||||||
else:
|
|
||||||
tf[2]["with_paragraph_nom"] = False
|
|
||||||
if tf[2]["anonymous"]:
|
if tf[2]["anonymous"]:
|
||||||
tf[2]["anonymous"] = True
|
tf[2]["anonymous"] = True
|
||||||
else:
|
else:
|
||||||
@ -705,7 +711,7 @@ def formsemestre_pvjury_pdf(
|
|||||||
else:
|
else:
|
||||||
groups_filename = ""
|
groups_filename = ""
|
||||||
filename = "PV-%s%s-%s.pdf" % (sem["titre_num"], groups_filename, dt)
|
filename = "PV-%s%s-%s.pdf" % (sem["titre_num"], groups_filename, dt)
|
||||||
return sendPDFFile(REQUEST, pdfdoc, filename)
|
return scu.sendPDFFile(REQUEST, pdfdoc, filename)
|
||||||
|
|
||||||
|
|
||||||
def descrform_pvjury(context, sem):
|
def descrform_pvjury(context, sem):
|
||||||
@ -771,12 +777,10 @@ def descrform_pvjury(context, sem):
|
|||||||
(
|
(
|
||||||
"with_paragraph_nom",
|
"with_paragraph_nom",
|
||||||
{
|
{
|
||||||
"input_type": "checkbox",
|
"input_type": "boolcheckbox",
|
||||||
"title": "Avec date naissance et code",
|
"title": "Avec date naissance et code",
|
||||||
"explanation": "ajoute informations sous le nom",
|
"explanation": "ajoute informations sous le nom",
|
||||||
"default": "1",
|
"default": True,
|
||||||
"labels": [""],
|
|
||||||
"allowed_values": ("1",),
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
@ -848,7 +852,6 @@ def formsemestre_lettres_individuelles(
|
|||||||
else:
|
else:
|
||||||
# submit
|
# submit
|
||||||
sf = tf[2]["signature"]
|
sf = tf[2]["signature"]
|
||||||
# pdb.set_trace()
|
|
||||||
signature = sf.read() # image of signature
|
signature = sf.read() # image of signature
|
||||||
try:
|
try:
|
||||||
PDFLOCK.acquire()
|
PDFLOCK.acquire()
|
||||||
@ -872,7 +875,7 @@ def formsemestre_lettres_individuelles(
|
|||||||
dt = time.strftime("%Y-%m-%d")
|
dt = time.strftime("%Y-%m-%d")
|
||||||
groups_filename = "-" + groups_infos.groups_filename
|
groups_filename = "-" + groups_infos.groups_filename
|
||||||
filename = "lettres-%s%s-%s.pdf" % (sem["titre_num"], groups_filename, dt)
|
filename = "lettres-%s%s-%s.pdf" % (sem["titre_num"], groups_filename, dt)
|
||||||
return sendPDFFile(REQUEST, pdfdoc, filename)
|
return scu.sendPDFFile(REQUEST, pdfdoc, filename)
|
||||||
|
|
||||||
|
|
||||||
def descrform_lettres_individuelles():
|
def descrform_lettres_individuelles():
|
||||||
|
75
sco_pvpdf.py
75
sco_pvpdf.py
@ -27,26 +27,39 @@
|
|||||||
|
|
||||||
"""Edition des PV de jury
|
"""Edition des PV de jury
|
||||||
"""
|
"""
|
||||||
|
import os
|
||||||
|
import types
|
||||||
|
import re
|
||||||
|
import cStringIO
|
||||||
|
import reportlab
|
||||||
|
from reportlab.lib.units import cm, mm
|
||||||
|
from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
|
||||||
|
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Frame, PageBreak
|
||||||
|
from reportlab.platypus import Table, TableStyle, Image, KeepInFrame
|
||||||
|
from reportlab.platypus.flowables import Flowable
|
||||||
|
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
|
||||||
|
from reportlab.lib.pagesizes import A4, landscape
|
||||||
|
from reportlab.lib import styles
|
||||||
|
from reportlab.lib.colors import Color
|
||||||
|
|
||||||
|
import sco_utils as scu
|
||||||
|
import sco_pdf
|
||||||
|
from sco_pdf import SU
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
from sco_pdf import *
|
|
||||||
import sco_pvjury
|
import sco_pvjury
|
||||||
import sco_codes_parcours
|
import sco_codes_parcours
|
||||||
from sco_utils import *
|
|
||||||
from sco_pdf import PDFLOCK
|
from sco_pdf import PDFLOCK
|
||||||
import sco_preferences
|
import sco_preferences
|
||||||
import sco_bulletins_pdf
|
import sco_bulletins_pdf
|
||||||
|
import VERSION
|
||||||
|
|
||||||
import os
|
LOGO_FOOTER_ASPECT = scu.CONFIG.LOGO_FOOTER_ASPECT # XXX A AUTOMATISER
|
||||||
import types
|
LOGO_FOOTER_HEIGHT = scu.CONFIG.LOGO_FOOTER_HEIGHT * mm
|
||||||
|
LOGO_FOOTER_WIDTH = LOGO_FOOTER_HEIGHT * scu.CONFIG.LOGO_FOOTER_ASPECT
|
||||||
|
|
||||||
LOGO_FOOTER_ASPECT = CONFIG.LOGO_FOOTER_ASPECT # XXX A AUTOMATISER
|
LOGO_HEADER_ASPECT = scu.CONFIG.LOGO_HEADER_ASPECT # XXX logo IUTV (A AUTOMATISER)
|
||||||
LOGO_FOOTER_HEIGHT = CONFIG.LOGO_FOOTER_HEIGHT * mm
|
LOGO_HEADER_HEIGHT = scu.CONFIG.LOGO_HEADER_HEIGHT * mm
|
||||||
LOGO_FOOTER_WIDTH = LOGO_FOOTER_HEIGHT * CONFIG.LOGO_FOOTER_ASPECT
|
LOGO_HEADER_WIDTH = LOGO_HEADER_HEIGHT * scu.CONFIG.LOGO_HEADER_ASPECT
|
||||||
|
|
||||||
LOGO_HEADER_ASPECT = CONFIG.LOGO_HEADER_ASPECT # XXX logo IUTV (A AUTOMATISER)
|
|
||||||
LOGO_HEADER_HEIGHT = CONFIG.LOGO_HEADER_HEIGHT * mm
|
|
||||||
LOGO_HEADER_WIDTH = LOGO_HEADER_HEIGHT * CONFIG.LOGO_HEADER_ASPECT
|
|
||||||
|
|
||||||
|
|
||||||
def pageFooter(canvas, doc, logo, preferences, with_page_numbers=True):
|
def pageFooter(canvas, doc, logo, preferences, with_page_numbers=True):
|
||||||
@ -76,7 +89,7 @@ def pageFooter(canvas, doc, logo, preferences, with_page_numbers=True):
|
|||||||
RightFootStyle.fontSize = preferences["SCOLAR_FONT_SIZE_FOOT"]
|
RightFootStyle.fontSize = preferences["SCOLAR_FONT_SIZE_FOOT"]
|
||||||
RightFootStyle.alignment = TA_RIGHT
|
RightFootStyle.alignment = TA_RIGHT
|
||||||
|
|
||||||
p = makeParas(
|
p = sco_pdf.makeParas(
|
||||||
"""<para>%s</para><para>%s</para>"""
|
"""<para>%s</para><para>%s</para>"""
|
||||||
% (preferences["INSTITUTION_NAME"], preferences["INSTITUTION_ADDRESS"]),
|
% (preferences["INSTITUTION_NAME"], preferences["INSTITUTION_ADDRESS"]),
|
||||||
LeftFootStyle,
|
LeftFootStyle,
|
||||||
@ -186,12 +199,12 @@ class CourrierIndividuelTemplate(PageTemplate):
|
|||||||
self.background_image_filename = None
|
self.background_image_filename = None
|
||||||
self.logo_footer = None
|
self.logo_footer = None
|
||||||
self.logo_header = None
|
self.logo_header = None
|
||||||
# Search logos in dept specific dir, then in global config dir
|
# Search logos in dept specific dir, then in global scu.CONFIG dir
|
||||||
for image_dir in (
|
for image_dir in (
|
||||||
SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/",
|
scu.SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/",
|
||||||
SCODOC_LOGOS_DIR + "/", # global logos
|
scu.SCODOC_LOGOS_DIR + "/", # global logos
|
||||||
):
|
):
|
||||||
for suffix in LOGOS_IMAGES_ALLOWED_TYPES:
|
for suffix in scu.LOGOS_IMAGES_ALLOWED_TYPES:
|
||||||
if template_name == "PVJuryTemplate":
|
if template_name == "PVJuryTemplate":
|
||||||
fn = image_dir + "/pvjury_background" + "." + suffix
|
fn = image_dir + "/pvjury_background" + "." + suffix
|
||||||
else:
|
else:
|
||||||
@ -354,7 +367,7 @@ def pdf_lettres_individuelles(
|
|||||||
if e["decision_sem"]: # decision prise
|
if e["decision_sem"]: # decision prise
|
||||||
etud = context.getEtudInfo(e["identite"]["etudid"], filled=True)[0]
|
etud = context.getEtudInfo(e["identite"]["etudid"], filled=True)[0]
|
||||||
params["nomEtud"] = etud["nomprenom"]
|
params["nomEtud"] = etud["nomprenom"]
|
||||||
bookmarks[npages + 1] = suppress_accents(etud["nomprenom"])
|
bookmarks[npages + 1] = scu.suppress_accents(etud["nomprenom"])
|
||||||
objects += pdf_lettre_individuelle(
|
objects += pdf_lettre_individuelle(
|
||||||
dpv["formsemestre"], e, etud, params, signature, context=context
|
dpv["formsemestre"], e, etud, params, signature, context=context
|
||||||
)
|
)
|
||||||
@ -377,7 +390,7 @@ def pdf_lettres_individuelles(
|
|||||||
CourrierIndividuelTemplate(
|
CourrierIndividuelTemplate(
|
||||||
document,
|
document,
|
||||||
context=context,
|
context=context,
|
||||||
author="%s %s (E. Viennet)" % (SCONAME, SCOVERSION),
|
author="%s %s (E. Viennet)" % (VERSION.SCONAME, VERSION.SCOVERSION),
|
||||||
title="Lettres décision %s" % sem["titreannee"],
|
title="Lettres décision %s" % sem["titreannee"],
|
||||||
subject="Décision jury",
|
subject="Décision jury",
|
||||||
margins=margins,
|
margins=margins,
|
||||||
@ -514,7 +527,7 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None, context
|
|||||||
% params
|
% params
|
||||||
)
|
)
|
||||||
sig = _simulate_br(sig, '<para leftindent="%(htab1)s">')
|
sig = _simulate_br(sig, '<para leftindent="%(htab1)s">')
|
||||||
objects += makeParas(
|
objects += sco_pdf.makeParas(
|
||||||
(
|
(
|
||||||
"""<para leftindent="%(htab1)s" spaceBefore="25mm">"""
|
"""<para leftindent="%(htab1)s" spaceBefore="25mm">"""
|
||||||
+ sig
|
+ sig
|
||||||
@ -529,7 +542,7 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None, context
|
|||||||
% params
|
% params
|
||||||
)
|
)
|
||||||
sig = _simulate_br(sig, '<para leftindent="%(htab1)s">')
|
sig = _simulate_br(sig, '<para leftindent="%(htab1)s">')
|
||||||
objects += makeParas(
|
objects += sco_pdf.makeParas(
|
||||||
(
|
(
|
||||||
"""<para leftindent="%(htab1)s" spaceBefore="25mm">"""
|
"""<para leftindent="%(htab1)s" spaceBefore="25mm">"""
|
||||||
+ sig
|
+ sig
|
||||||
@ -650,7 +663,7 @@ def pvjury_pdf(
|
|||||||
PVTemplate(
|
PVTemplate(
|
||||||
document,
|
document,
|
||||||
context=context,
|
context=context,
|
||||||
author="%s %s (E. Viennet)" % (SCONAME, SCOVERSION),
|
author="%s %s (E. Viennet)" % (VERSION.SCONAME, VERSION.SCOVERSION),
|
||||||
title=SU("PV du jury de %s" % sem["titre_num"]),
|
title=SU("PV du jury de %s" % sem["titre_num"]),
|
||||||
subject="PV jury",
|
subject="PV jury",
|
||||||
preferences=context.get_preferences(formsemestre_id),
|
preferences=context.get_preferences(formsemestre_id),
|
||||||
@ -683,7 +696,7 @@ def _pvjury_pdf_type(
|
|||||||
|
|
||||||
sem = dpv["formsemestre"]
|
sem = dpv["formsemestre"]
|
||||||
formsemestre_id = sem["formsemestre_id"]
|
formsemestre_id = sem["formsemestre_id"]
|
||||||
titre_jury, titre_court_jury = _descr_jury(sem, diplome)
|
titre_jury, _ = _descr_jury(sem, diplome)
|
||||||
titre_diplome = pv_title or dpv["formation"]["titre_officiel"]
|
titre_diplome = pv_title or dpv["formation"]["titre_officiel"]
|
||||||
objects = []
|
objects = []
|
||||||
|
|
||||||
@ -708,7 +721,7 @@ def _pvjury_pdf_type(
|
|||||||
bulletStyle.spaceAfter = 5 * mm
|
bulletStyle.spaceAfter = 5 * mm
|
||||||
|
|
||||||
objects += [Spacer(0, 5 * mm)]
|
objects += [Spacer(0, 5 * mm)]
|
||||||
objects += makeParas(
|
objects += sco_pdf.makeParas(
|
||||||
"""
|
"""
|
||||||
<para align="center"><b>Procès-verbal de %s du département %s - Session unique %s</b></para>
|
<para align="center"><b>Procès-verbal de %s du département %s - Session unique %s</b></para>
|
||||||
"""
|
"""
|
||||||
@ -720,7 +733,7 @@ def _pvjury_pdf_type(
|
|||||||
style,
|
style,
|
||||||
)
|
)
|
||||||
|
|
||||||
objects += makeParas(
|
objects += sco_pdf.makeParas(
|
||||||
"""
|
"""
|
||||||
<para align="center"><b><i>%s</i></b></para>
|
<para align="center"><b><i>%s</i></b></para>
|
||||||
"""
|
"""
|
||||||
@ -729,20 +742,20 @@ def _pvjury_pdf_type(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if showTitle:
|
if showTitle:
|
||||||
objects += makeParas(
|
objects += sco_pdf.makeParas(
|
||||||
"""<para align="center"><b>Semestre: %s</b></para>""" % sem["titre"], style
|
"""<para align="center"><b>Semestre: %s</b></para>""" % sem["titre"], style
|
||||||
)
|
)
|
||||||
if context.get_preference("PV_TITLE_WITH_VDI", formsemestre_id):
|
if context.get_preference("PV_TITLE_WITH_VDI", formsemestre_id):
|
||||||
objects += makeParas(
|
objects += sco_pdf.makeParas(
|
||||||
"""<para align="center">VDI et Code: %s</para>""" % (VDICode or ""), style
|
"""<para align="center">VDI et Code: %s</para>""" % (VDICode or ""), style
|
||||||
)
|
)
|
||||||
|
|
||||||
if date_jury:
|
if date_jury:
|
||||||
objects += makeParas(
|
objects += sco_pdf.makeParas(
|
||||||
"""<para align="center">Jury tenu le %s</para>""" % date_jury, style
|
"""<para align="center">Jury tenu le %s</para>""" % date_jury, style
|
||||||
)
|
)
|
||||||
|
|
||||||
objects += makeParas(
|
objects += sco_pdf.makeParas(
|
||||||
"<para>"
|
"<para>"
|
||||||
+ context.get_preference("PV_INTRO", formsemestre_id)
|
+ context.get_preference("PV_INTRO", formsemestre_id)
|
||||||
% {
|
% {
|
||||||
@ -757,7 +770,7 @@ def _pvjury_pdf_type(
|
|||||||
bulletStyle,
|
bulletStyle,
|
||||||
)
|
)
|
||||||
|
|
||||||
objects += makeParas(
|
objects += sco_pdf.makeParas(
|
||||||
"""<para>Le jury propose les décisions suivantes :</para>""", style
|
"""<para>Le jury propose les décisions suivantes :</para>""", style
|
||||||
)
|
)
|
||||||
objects += [Spacer(0, 4 * mm)]
|
objects += [Spacer(0, 4 * mm)]
|
||||||
@ -809,7 +822,7 @@ def _pvjury_pdf_type(
|
|||||||
objects.append(Table(Pt, repeatRows=1, colWidths=widths, style=table_style))
|
objects.append(Table(Pt, repeatRows=1, colWidths=widths, style=table_style))
|
||||||
|
|
||||||
# Signature du directeur
|
# Signature du directeur
|
||||||
objects += makeParas(
|
objects += sco_pdf.makeParas(
|
||||||
"""<para spaceBefore="10mm" align="right">
|
"""<para spaceBefore="10mm" align="right">
|
||||||
Le %s, %s</para>"""
|
Le %s, %s</para>"""
|
||||||
% (
|
% (
|
||||||
@ -822,7 +835,7 @@ def _pvjury_pdf_type(
|
|||||||
# Légende des codes
|
# Légende des codes
|
||||||
codes = sco_codes_parcours.CODES_EXPL.keys()
|
codes = sco_codes_parcours.CODES_EXPL.keys()
|
||||||
codes.sort()
|
codes.sort()
|
||||||
objects += makeParas(
|
objects += sco_pdf.makeParas(
|
||||||
"""<para spaceBefore="15mm" fontSize="14">
|
"""<para spaceBefore="15mm" fontSize="14">
|
||||||
<b>Codes utilisés :</b></para>""",
|
<b>Codes utilisés :</b></para>""",
|
||||||
style,
|
style,
|
||||||
|
@ -27,8 +27,13 @@
|
|||||||
|
|
||||||
"""Tableau recapitulatif des notes d'un semestre
|
"""Tableau recapitulatif des notes d'un semestre
|
||||||
"""
|
"""
|
||||||
|
import time
|
||||||
|
import datetime
|
||||||
|
import jaxml
|
||||||
|
|
||||||
from notes_table import *
|
import sco_utils as scu
|
||||||
|
from notes_log import log
|
||||||
|
import scolars
|
||||||
import sco_bulletins, sco_excel
|
import sco_bulletins, sco_excel
|
||||||
import sco_groups
|
import sco_groups
|
||||||
import sco_evaluations
|
import sco_evaluations
|
||||||
@ -37,6 +42,7 @@ import sco_formsemestre_status
|
|||||||
import sco_bulletins_xml
|
import sco_bulletins_xml
|
||||||
import sco_bulletins_json
|
import sco_bulletins_json
|
||||||
import sco_codes_parcours
|
import sco_codes_parcours
|
||||||
|
from sco_codes_parcours import DEF, UE_SPORT
|
||||||
import sco_bac
|
import sco_bac
|
||||||
|
|
||||||
|
|
||||||
@ -133,7 +139,7 @@ def formsemestre_recapcomplet(
|
|||||||
H.append("checked")
|
H.append("checked")
|
||||||
H.append(""" >cacher bac</input>""")
|
H.append(""" >cacher bac</input>""")
|
||||||
if tabformat == "xml":
|
if tabformat == "xml":
|
||||||
REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE)
|
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
|
||||||
H.append(
|
H.append(
|
||||||
do_formsemestre_recapcomplet(
|
do_formsemestre_recapcomplet(
|
||||||
context,
|
context,
|
||||||
@ -201,11 +207,11 @@ def do_formsemestre_recapcomplet(
|
|||||||
if format == "xml" or format == "html":
|
if format == "xml" or format == "html":
|
||||||
return data
|
return data
|
||||||
elif format == "csv":
|
elif format == "csv":
|
||||||
return sendCSVFile(REQUEST, data, filename)
|
return scu.sendCSVFile(REQUEST, data, filename)
|
||||||
elif format[:3] == "xls":
|
elif format[:3] == "xls":
|
||||||
return sco_excel.sendExcelFile(REQUEST, data, filename)
|
return sco_excel.sendExcelFile(REQUEST, data, filename)
|
||||||
elif format == "json":
|
elif format == "json":
|
||||||
return sendJSON(REQUEST, data)
|
return scu.sendJSON(REQUEST, data)
|
||||||
else:
|
else:
|
||||||
raise ValueError("unknown format %s" % format)
|
raise ValueError("unknown format %s" % format)
|
||||||
|
|
||||||
@ -229,6 +235,7 @@ def make_formsemestre_recapcomplet(
|
|||||||
pour tous les étudiants, les moyennes par UE et générale,
|
pour tous les étudiants, les moyennes par UE et générale,
|
||||||
trié par moyenne générale décroissante.
|
trié par moyenne générale décroissante.
|
||||||
"""
|
"""
|
||||||
|
civ_nom_prenom = False # 3 colonnes différentes ou une seule avec prénom abrégé ?
|
||||||
if format == "xml":
|
if format == "xml":
|
||||||
return _formsemestre_recapcomplet_xml(
|
return _formsemestre_recapcomplet_xml(
|
||||||
context,
|
context,
|
||||||
@ -246,6 +253,7 @@ def make_formsemestre_recapcomplet(
|
|||||||
force_publishing=force_publishing,
|
force_publishing=force_publishing,
|
||||||
)
|
)
|
||||||
if format[:3] == "xls":
|
if format[:3] == "xls":
|
||||||
|
civ_nom_prenom = True # 3 cols: civilite, nom, prenom
|
||||||
keep_numeric = True # pas de conversion des notes en strings
|
keep_numeric = True # pas de conversion des notes en strings
|
||||||
else:
|
else:
|
||||||
keep_numeric = False
|
keep_numeric = False
|
||||||
@ -265,7 +273,7 @@ def make_formsemestre_recapcomplet(
|
|||||||
)[0]
|
)[0]
|
||||||
nt = context._getNotesCache().get_NotesTable(
|
nt = context._getNotesCache().get_NotesTable(
|
||||||
context, formsemestre_id
|
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_nom_long, get_etud_decision_sem,
|
) # > 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()
|
modimpls = nt.get_modimpls()
|
||||||
ues = nt.get_ues() # incluant le(s) UE de sport
|
ues = nt.get_ues() # incluant le(s) UE de sport
|
||||||
#
|
#
|
||||||
@ -287,7 +295,11 @@ def make_formsemestre_recapcomplet(
|
|||||||
|
|
||||||
# Construit une liste de listes de chaines: le champs du tableau resultat (HTML ou CSV)
|
# Construit une liste de listes de chaines: le champs du tableau resultat (HTML ou CSV)
|
||||||
F = []
|
F = []
|
||||||
h = [rank_label, "Nom"]
|
h = [rank_label]
|
||||||
|
if civ_nom_prenom:
|
||||||
|
h += ["Civilité", "Nom", "Prénom"]
|
||||||
|
else:
|
||||||
|
h += ["Nom"]
|
||||||
if not hidebac:
|
if not hidebac:
|
||||||
h.append("Bac")
|
h.append("Bac")
|
||||||
|
|
||||||
@ -345,7 +357,7 @@ def make_formsemestre_recapcomplet(
|
|||||||
return val
|
return val
|
||||||
|
|
||||||
# Compte les decisions de jury
|
# Compte les decisions de jury
|
||||||
codes_nb = DictDefault(defaultvalue=0)
|
codes_nb = scu.DictDefault(defaultvalue=0)
|
||||||
#
|
#
|
||||||
is_dem = {} # etudid : bool
|
is_dem = {} # etudid : bool
|
||||||
for t in T:
|
for t in T:
|
||||||
@ -365,7 +377,7 @@ def make_formsemestre_recapcomplet(
|
|||||||
gr_name = group["group_name"] or ""
|
gr_name = group["group_name"] or ""
|
||||||
is_dem[etudid] = False
|
is_dem[etudid] = False
|
||||||
if rank_partition_id:
|
if rank_partition_id:
|
||||||
rang_gr, ninscrits_gr, rank_gr_name = sco_bulletins.get_etud_rangs_groups(
|
rang_gr, _, rank_gr_name = sco_bulletins.get_etud_rangs_groups(
|
||||||
context, etudid, formsemestre_id, partitions, partitions_etud_groups, nt
|
context, etudid, formsemestre_id, partitions, partitions_etud_groups, nt
|
||||||
)
|
)
|
||||||
if rank_gr_name[rank_partition_id]:
|
if rank_gr_name[rank_partition_id]:
|
||||||
@ -378,8 +390,13 @@ def make_formsemestre_recapcomplet(
|
|||||||
else:
|
else:
|
||||||
rank = nt.get_etud_rang(etudid)
|
rank = nt.get_etud_rang(etudid)
|
||||||
|
|
||||||
l = [rank, nt.get_nom_short(etudid)] # rang, nom,
|
|
||||||
e = nt.identdict[etudid]
|
e = nt.identdict[etudid]
|
||||||
|
if civ_nom_prenom:
|
||||||
|
scolars.format_etud_ident(e)
|
||||||
|
l = [rank, e["civilite_str"], e["nom_disp"], e["prenom"]] # civ, nom prenom
|
||||||
|
else:
|
||||||
|
l = [rank, nt.get_nom_short(etudid)] # rang, nom,
|
||||||
|
|
||||||
if not hidebac:
|
if not hidebac:
|
||||||
bac = sco_bac.Baccalaureat(e["bac"], e["specialite"])
|
bac = sco_bac.Baccalaureat(e["bac"], e["specialite"])
|
||||||
l.append(bac.abbrev())
|
l.append(bac.abbrev())
|
||||||
@ -396,7 +413,7 @@ def make_formsemestre_recapcomplet(
|
|||||||
else:
|
else:
|
||||||
l.append(gr_name) # groupe
|
l.append(gr_name) # groupe
|
||||||
|
|
||||||
l.append(fmtnum(fmt_note(t[0], keep_numeric=keep_numeric))) # moy_gen
|
l.append(fmtnum(scu.fmt_note(t[0], keep_numeric=keep_numeric))) # moy_gen
|
||||||
# Ajoute rangs dans groupes seulement si CSV ou XLS
|
# Ajoute rangs dans groupes seulement si CSV ou XLS
|
||||||
if format[:3] == "xls" or format == "csv":
|
if format[:3] == "xls" or format == "csv":
|
||||||
rang_gr, ninscrits_gr, gr_name = sco_bulletins.get_etud_rangs_groups(
|
rang_gr, ninscrits_gr, gr_name = sco_bulletins.get_etud_rangs_groups(
|
||||||
@ -410,7 +427,7 @@ def make_formsemestre_recapcomplet(
|
|||||||
i += 1
|
i += 1
|
||||||
if ue["type"] != UE_SPORT:
|
if ue["type"] != UE_SPORT:
|
||||||
l.append(
|
l.append(
|
||||||
fmtnum(fmt_note(t[i], keep_numeric=keep_numeric))
|
fmtnum(scu.fmt_note(t[i], keep_numeric=keep_numeric))
|
||||||
) # moyenne etud dans ue
|
) # moyenne etud dans ue
|
||||||
else: # UE_SPORT:
|
else: # UE_SPORT:
|
||||||
# n'affiche pas la moyenne d'UE dans ce cas
|
# n'affiche pas la moyenne d'UE dans ce cas
|
||||||
@ -423,7 +440,9 @@ def make_formsemestre_recapcomplet(
|
|||||||
if modimpl["module"]["ue_id"] == ue["ue_id"]:
|
if modimpl["module"]["ue_id"] == ue["ue_id"]:
|
||||||
l.append(
|
l.append(
|
||||||
fmtnum(
|
fmtnum(
|
||||||
fmt_note(t[j + len(ues) + 1], keep_numeric=keep_numeric)
|
scu.fmt_note(
|
||||||
|
t[j + len(ues) + 1], keep_numeric=keep_numeric
|
||||||
|
)
|
||||||
)
|
)
|
||||||
) # moyenne etud dans module
|
) # moyenne etud dans module
|
||||||
if format == "xlsall":
|
if format == "xlsall":
|
||||||
@ -450,6 +469,8 @@ def make_formsemestre_recapcomplet(
|
|||||||
|
|
||||||
def add_bottom_stat(key, title, corner_value=""):
|
def add_bottom_stat(key, title, corner_value=""):
|
||||||
l = ["", title]
|
l = ["", title]
|
||||||
|
if civ_nom_prenom:
|
||||||
|
l += ["", ""]
|
||||||
if not hidebac:
|
if not hidebac:
|
||||||
l.append("")
|
l.append("")
|
||||||
if format[:3] == "xls" or format == "csv":
|
if format[:3] == "xls" or format == "csv":
|
||||||
@ -458,7 +479,7 @@ def make_formsemestre_recapcomplet(
|
|||||||
l += [""]
|
l += [""]
|
||||||
l.append(corner_value)
|
l.append(corner_value)
|
||||||
if format[:3] == "xls" or format == "csv":
|
if format[:3] == "xls" or format == "csv":
|
||||||
for partition in partitions:
|
for _ in partitions:
|
||||||
l += [""] # rangs dans les groupes
|
l += [""] # rangs dans les groupes
|
||||||
for ue in ues:
|
for ue in ues:
|
||||||
if ue["type"] != UE_SPORT:
|
if ue["type"] != UE_SPORT:
|
||||||
@ -476,7 +497,7 @@ def make_formsemestre_recapcomplet(
|
|||||||
else:
|
else:
|
||||||
l.append(str(ue[key]))
|
l.append(str(ue[key]))
|
||||||
else:
|
else:
|
||||||
l.append(fmt_note(ue[key], keep_numeric=keep_numeric))
|
l.append(scu.fmt_note(ue[key], keep_numeric=keep_numeric))
|
||||||
else: # UE_SPORT:
|
else: # UE_SPORT:
|
||||||
# n'affiche pas la moyenne d'UE dans ce cas
|
# n'affiche pas la moyenne d'UE dans ce cas
|
||||||
if not hidemodules:
|
if not hidemodules:
|
||||||
@ -500,7 +521,7 @@ def make_formsemestre_recapcomplet(
|
|||||||
): # garde val numerique pour excel
|
): # garde val numerique pour excel
|
||||||
val = str(val)
|
val = str(val)
|
||||||
else: # moyenne du module
|
else: # moyenne du module
|
||||||
val = fmt_note(val, keep_numeric=keep_numeric)
|
val = scu.fmt_note(val, keep_numeric=keep_numeric)
|
||||||
l.append(val)
|
l.append(val)
|
||||||
|
|
||||||
if format == "xlsall":
|
if format == "xlsall":
|
||||||
@ -514,13 +535,15 @@ def make_formsemestre_recapcomplet(
|
|||||||
F.append(l + ["", ""]) # ajoute cellules code_nip et etudid inutilisees ici
|
F.append(l + ["", ""]) # ajoute cellules code_nip et etudid inutilisees ici
|
||||||
|
|
||||||
add_bottom_stat(
|
add_bottom_stat(
|
||||||
"min", "Min", corner_value=fmt_note(nt.moy_min, keep_numeric=keep_numeric)
|
"min", "Min", corner_value=scu.fmt_note(nt.moy_min, keep_numeric=keep_numeric)
|
||||||
)
|
)
|
||||||
add_bottom_stat(
|
add_bottom_stat(
|
||||||
"max", "Max", corner_value=fmt_note(nt.moy_max, keep_numeric=keep_numeric)
|
"max", "Max", corner_value=scu.fmt_note(nt.moy_max, keep_numeric=keep_numeric)
|
||||||
)
|
)
|
||||||
add_bottom_stat(
|
add_bottom_stat(
|
||||||
"moy", "Moyennes", corner_value=fmt_note(nt.moy_moy, keep_numeric=keep_numeric)
|
"moy",
|
||||||
|
"Moyennes",
|
||||||
|
corner_value=scu.fmt_note(nt.moy_moy, keep_numeric=keep_numeric),
|
||||||
)
|
)
|
||||||
add_bottom_stat("coef", "Coef")
|
add_bottom_stat("coef", "Coef")
|
||||||
add_bottom_stat("nb_valid_evals", "Nb évals")
|
add_bottom_stat("nb_valid_evals", "Nb évals")
|
||||||
@ -619,7 +642,6 @@ def make_formsemestre_recapcomplet(
|
|||||||
"formsemestre_id": formsemestre_id,
|
"formsemestre_id": formsemestre_id,
|
||||||
"etudid": etudid,
|
"etudid": etudid,
|
||||||
"name": l[1],
|
"name": l[1],
|
||||||
"nomprenom": nt.get_nom_long(etudid),
|
|
||||||
}
|
}
|
||||||
if ir % 2 == 0:
|
if ir % 2 == 0:
|
||||||
cells = '<tr class="recap_row_even" id="etudid%s">' % etudid
|
cells = '<tr class="recap_row_even" id="etudid%s">' % etudid
|
||||||
@ -645,7 +667,9 @@ def make_formsemestre_recapcomplet(
|
|||||||
idx_col_moy = idx_col_gr + 1
|
idx_col_moy = idx_col_gr + 1
|
||||||
cssclass = "recap_col_moy"
|
cssclass = "recap_col_moy"
|
||||||
try:
|
try:
|
||||||
if float(nsn[idx_col_moy]) < (nt.parcours.BARRE_MOY - NOTES_TOLERANCE):
|
if float(nsn[idx_col_moy]) < (
|
||||||
|
nt.parcours.BARRE_MOY - scu.NOTES_TOLERANCE
|
||||||
|
):
|
||||||
cssclass = "recap_col_moy_inf"
|
cssclass = "recap_col_moy_inf"
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
@ -734,7 +758,7 @@ def make_formsemestre_recapcomplet(
|
|||||||
H.append("</table>")
|
H.append("</table>")
|
||||||
return "\n".join(H), "", "html"
|
return "\n".join(H), "", "html"
|
||||||
elif format == "csv":
|
elif format == "csv":
|
||||||
CSV = CSV_LINESEP.join([CSV_FIELDSEP.join(str(x)) for x in F])
|
CSV = scu.CSV_LINESEP.join([scu.CSV_FIELDSEP.join(str(x)) for x in F])
|
||||||
semname = sem["titre_num"].replace(" ", "_")
|
semname = sem["titre_num"].replace(" ", "_")
|
||||||
date = time.strftime("%d-%m-%Y")
|
date = time.strftime("%d-%m-%Y")
|
||||||
filename = "notes_modules-%s-%s.csv" % (semname, date)
|
filename = "notes_modules-%s-%s.csv" % (semname, date)
|
||||||
@ -774,8 +798,8 @@ def _list_notes_evals(context, evals, etudid):
|
|||||||
val = NotesDB[etudid]["value"]
|
val = NotesDB[etudid]["value"]
|
||||||
else:
|
else:
|
||||||
# Note manquante mais prise en compte immédiate: affiche ATT
|
# Note manquante mais prise en compte immédiate: affiche ATT
|
||||||
val = NOTES_ATTENTE
|
val = scu.NOTES_ATTENTE
|
||||||
val_fmt = fmt_note(val, keep_numeric=True)
|
val_fmt = scu.fmt_note(val, keep_numeric=True)
|
||||||
L.append(val_fmt)
|
L.append(val_fmt)
|
||||||
return L
|
return L
|
||||||
|
|
||||||
@ -806,7 +830,7 @@ def _list_notes_evals_stats(context, evals, key):
|
|||||||
):
|
):
|
||||||
if key == "moy":
|
if key == "moy":
|
||||||
val = e["etat"]["moy_num"]
|
val = e["etat"]["moy_num"]
|
||||||
L.append(fmt_note(val, keep_numeric=True))
|
L.append(scu.fmt_note(val, keep_numeric=True))
|
||||||
elif key == "max":
|
elif key == "max":
|
||||||
L.append(e["note_max"])
|
L.append(e["note_max"])
|
||||||
elif key == "min":
|
elif key == "min":
|
||||||
@ -834,7 +858,7 @@ def _formsemestre_recapcomplet_xml(
|
|||||||
if not T:
|
if not T:
|
||||||
return "", "", "xml"
|
return "", "", "xml"
|
||||||
|
|
||||||
doc = jaxml.XML_document(encoding=SCO_ENCODING)
|
doc = jaxml.XML_document(encoding=scu.SCO_ENCODING)
|
||||||
if xml_nodate:
|
if xml_nodate:
|
||||||
docdate = ""
|
docdate = ""
|
||||||
else:
|
else:
|
||||||
@ -928,4 +952,4 @@ def formsemestres_bulletins(context, annee_scolaire, REQUEST=None):
|
|||||||
)
|
)
|
||||||
jslist.append(J)
|
jslist.append(J)
|
||||||
|
|
||||||
return sendJSON(REQUEST, jslist)
|
return scu.sendJSON(REQUEST, jslist)
|
||||||
|
154
sco_report.py
154
sco_report.py
@ -34,9 +34,7 @@ import tempfile
|
|||||||
import urllib
|
import urllib
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
import mx
|
import datetime
|
||||||
import mx.DateTime
|
|
||||||
from mx.DateTime import DateTime as mxDateTime
|
|
||||||
|
|
||||||
import sco_utils as scu
|
import sco_utils as scu
|
||||||
import VERSION
|
import VERSION
|
||||||
@ -295,7 +293,7 @@ def formsemestre_report_counts(
|
|||||||
"codedecision",
|
"codedecision",
|
||||||
"devenir",
|
"devenir",
|
||||||
"etat",
|
"etat",
|
||||||
"sexe",
|
"civilite",
|
||||||
"qualite",
|
"qualite",
|
||||||
"villelycee",
|
"villelycee",
|
||||||
"statut",
|
"statut",
|
||||||
@ -367,7 +365,7 @@ def table_suivi_cohorte(
|
|||||||
bac="", # selection sur type de bac
|
bac="", # selection sur type de bac
|
||||||
bacspecialite="",
|
bacspecialite="",
|
||||||
annee_bac="",
|
annee_bac="",
|
||||||
sexe="",
|
civilite=None,
|
||||||
statut="",
|
statut="",
|
||||||
only_primo=False,
|
only_primo=False,
|
||||||
):
|
):
|
||||||
@ -406,7 +404,7 @@ def table_suivi_cohorte(
|
|||||||
bacs = set()
|
bacs = set()
|
||||||
bacspecialites = set()
|
bacspecialites = set()
|
||||||
annee_bacs = set()
|
annee_bacs = set()
|
||||||
sexes = set()
|
civilites = set()
|
||||||
statuts = set()
|
statuts = set()
|
||||||
for etudid in etudids:
|
for etudid in etudids:
|
||||||
etud = context.getEtudInfo(etudid=etudid, filled=True)[0]
|
etud = context.getEtudInfo(etudid=etudid, filled=True)[0]
|
||||||
@ -416,7 +414,7 @@ def table_suivi_cohorte(
|
|||||||
(not bac or (bac == etud["bac"]))
|
(not bac or (bac == etud["bac"]))
|
||||||
and (not bacspecialite or (bacspecialite == bacspe))
|
and (not bacspecialite or (bacspecialite == bacspe))
|
||||||
and (not annee_bac or (annee_bac == str(etud["annee_bac"])))
|
and (not annee_bac or (annee_bac == str(etud["annee_bac"])))
|
||||||
and (not sexe or (sexe == etud["sexe"]))
|
and (not civilite or (civilite == etud["civilite"]))
|
||||||
and (not statut or (statut == etud["statut"]))
|
and (not statut or (statut == etud["statut"]))
|
||||||
and (not only_primo or context.isPrimoEtud(etud, sem))
|
and (not only_primo or context.isPrimoEtud(etud, sem))
|
||||||
):
|
):
|
||||||
@ -428,15 +426,15 @@ def table_suivi_cohorte(
|
|||||||
bacs.add(etud["bac"])
|
bacs.add(etud["bac"])
|
||||||
bacspecialites.add(bacspe)
|
bacspecialites.add(bacspe)
|
||||||
annee_bacs.add(etud["annee_bac"])
|
annee_bacs.add(etud["annee_bac"])
|
||||||
sexes.add(etud["sexe"])
|
civilites.add(etud["civilite"])
|
||||||
if etud["statut"]: # ne montre pas les statuts non renseignés
|
if etud["statut"]: # ne montre pas les statuts non renseignés
|
||||||
statuts.add(etud["statut"])
|
statuts.add(etud["statut"])
|
||||||
sems = S.values()
|
sems = S.values()
|
||||||
# tri les semestres par date de debut
|
# tri les semestres par date de debut
|
||||||
for s in sems:
|
for s in sems:
|
||||||
d, m, y = [int(x) for x in s["date_debut"].split("/")]
|
d, m, y = [int(x) for x in s["date_debut"].split("/")]
|
||||||
s["date_debut_mx"] = mxDateTime(y, m, d) # pylint: disable=not-callable
|
s["date_debut_dt"] = datetime.datetime(y, m, d)
|
||||||
sems.sort(lambda x, y: cmp(x["date_debut_mx"], y["date_debut_mx"]))
|
sems.sort(lambda x, y: cmp(x["date_debut_dt"], y["date_debut_dt"]))
|
||||||
|
|
||||||
# 2-- Pour chaque semestre, trouve l'ensemble des etudiants venant de sem
|
# 2-- Pour chaque semestre, trouve l'ensemble des etudiants venant de sem
|
||||||
logt("B: etuds sets")
|
logt("B: etuds sets")
|
||||||
@ -467,21 +465,21 @@ def table_suivi_cohorte(
|
|||||||
# semestre de depart:
|
# semestre de depart:
|
||||||
porigin = periodsem()
|
porigin = periodsem()
|
||||||
d, m, y = [int(x) for x in sem["date_debut"].split("/")]
|
d, m, y = [int(x) for x in sem["date_debut"].split("/")]
|
||||||
porigin.datedebut = mxDateTime(y, m, d) # pylint: disable=not-callable
|
porigin.datedebut = datetime.datetime(y, m, d)
|
||||||
porigin.sems = [sem]
|
porigin.sems = [sem]
|
||||||
|
|
||||||
#
|
#
|
||||||
tolerance = mx.DateTime.DateTimeDelta(45) # 45 days
|
tolerance = datetime.timedelta(days=45)
|
||||||
for s in sems:
|
for s in sems:
|
||||||
merged = False
|
merged = False
|
||||||
for p in P:
|
for p in P:
|
||||||
if abs(s["date_debut_mx"] - p.datedebut) < tolerance:
|
if abs(s["date_debut_dt"] - p.datedebut) < tolerance:
|
||||||
p.sems.append(s)
|
p.sems.append(s)
|
||||||
merged = True
|
merged = True
|
||||||
break
|
break
|
||||||
if not merged:
|
if not merged:
|
||||||
p = periodsem()
|
p = periodsem()
|
||||||
p.datedebut = s["date_debut_mx"]
|
p.datedebut = s["date_debut_dt"]
|
||||||
p.sems = [s]
|
p.sems = [s]
|
||||||
P.append(p)
|
P.append(p)
|
||||||
|
|
||||||
@ -619,8 +617,8 @@ def table_suivi_cohorte(
|
|||||||
dbac += " (spécialité %s)" % bacspecialite
|
dbac += " (spécialité %s)" % bacspecialite
|
||||||
if annee_bac:
|
if annee_bac:
|
||||||
dbac += " (année bac %s)" % annee_bac
|
dbac += " (année bac %s)" % annee_bac
|
||||||
if sexe:
|
if civilite:
|
||||||
dbac += " genre: %s" % sexe
|
dbac += " civilité: %s" % civilite
|
||||||
if statut:
|
if statut:
|
||||||
dbac += " statut: %s" % statut
|
dbac += " statut: %s" % statut
|
||||||
tab = GenTable(
|
tab = GenTable(
|
||||||
@ -654,7 +652,15 @@ def table_suivi_cohorte(
|
|||||||
expl.append(", ".join(ls) + "</li>")
|
expl.append(", ".join(ls) + "</li>")
|
||||||
expl.append("</ul>")
|
expl.append("</ul>")
|
||||||
logt("Z: table_suivi_cohorte done")
|
logt("Z: table_suivi_cohorte done")
|
||||||
return tab, "\n".join(expl), bacs, bacspecialites, annee_bacs, sexes, statuts
|
return (
|
||||||
|
tab,
|
||||||
|
"\n".join(expl),
|
||||||
|
bacs,
|
||||||
|
bacspecialites,
|
||||||
|
annee_bacs,
|
||||||
|
civilites,
|
||||||
|
statuts,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def formsemestre_suivi_cohorte(
|
def formsemestre_suivi_cohorte(
|
||||||
@ -665,27 +671,35 @@ def formsemestre_suivi_cohorte(
|
|||||||
bac="",
|
bac="",
|
||||||
bacspecialite="",
|
bacspecialite="",
|
||||||
annee_bac="",
|
annee_bac="",
|
||||||
sexe="",
|
civilite=None,
|
||||||
statut="",
|
statut="",
|
||||||
only_primo=False,
|
only_primo=False,
|
||||||
REQUEST=None,
|
REQUEST=None,
|
||||||
):
|
):
|
||||||
"""Affiche suivi cohortes par numero de semestre"""
|
"""Affiche suivi cohortes par numero de semestre"""
|
||||||
percent = int(percent)
|
percent = int(percent)
|
||||||
tab, expl, bacs, bacspecialites, annee_bacs, sexes, statuts = table_suivi_cohorte(
|
(
|
||||||
|
tab,
|
||||||
|
expl,
|
||||||
|
bacs,
|
||||||
|
bacspecialites,
|
||||||
|
annee_bacs,
|
||||||
|
civilites,
|
||||||
|
statuts,
|
||||||
|
) = table_suivi_cohorte(
|
||||||
context,
|
context,
|
||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
percent=percent,
|
percent=percent,
|
||||||
bac=bac,
|
bac=bac,
|
||||||
bacspecialite=bacspecialite,
|
bacspecialite=bacspecialite,
|
||||||
annee_bac=annee_bac,
|
annee_bac=annee_bac,
|
||||||
sexe=sexe,
|
civilite=civilite,
|
||||||
statut=statut,
|
statut=statut,
|
||||||
only_primo=only_primo,
|
only_primo=only_primo,
|
||||||
)
|
)
|
||||||
tab.base_url = (
|
tab.base_url = (
|
||||||
"%s?formsemestre_id=%s&percent=%s&bac=%s&bacspecialite=%s&sexe=%s"
|
"%s?formsemestre_id=%s&percent=%s&bac=%s&bacspecialite=%s&civilite=%s"
|
||||||
% (REQUEST.URL0, formsemestre_id, percent, bac, bacspecialite, sexe)
|
% (REQUEST.URL0, formsemestre_id, percent, bac, bacspecialite, civilite)
|
||||||
)
|
)
|
||||||
if only_primo:
|
if only_primo:
|
||||||
tab.base_url += "&only_primo=on"
|
tab.base_url += "&only_primo=on"
|
||||||
@ -695,8 +709,8 @@ def formsemestre_suivi_cohorte(
|
|||||||
|
|
||||||
base_url = REQUEST.URL0
|
base_url = REQUEST.URL0
|
||||||
burl = (
|
burl = (
|
||||||
"%s?formsemestre_id=%s&bac=%s&bacspecialite=%s&sexe=%s&statut=%s"
|
"%s?formsemestre_id=%s&bac=%s&bacspecialite=%s&civilite=%s&statut=%s"
|
||||||
% (base_url, formsemestre_id, bac, bacspecialite, sexe, statut)
|
% (base_url, formsemestre_id, bac, bacspecialite, civilite, statut)
|
||||||
)
|
)
|
||||||
if percent:
|
if percent:
|
||||||
pplink = (
|
pplink = (
|
||||||
@ -726,12 +740,12 @@ def formsemestre_suivi_cohorte(
|
|||||||
bac=bac,
|
bac=bac,
|
||||||
bacspecialite=bacspecialite,
|
bacspecialite=bacspecialite,
|
||||||
annee_bac=annee_bac,
|
annee_bac=annee_bac,
|
||||||
sexe=sexe,
|
civilite=civilite,
|
||||||
statut=statut,
|
statut=statut,
|
||||||
bacs=bacs,
|
bacs=bacs,
|
||||||
bacspecialites=bacspecialites,
|
bacspecialites=bacspecialites,
|
||||||
annee_bacs=annee_bacs,
|
annee_bacs=annee_bacs,
|
||||||
sexes=sexes,
|
civilites=civilites,
|
||||||
statuts=statuts,
|
statuts=statuts,
|
||||||
percent=percent,
|
percent=percent,
|
||||||
),
|
),
|
||||||
@ -751,12 +765,12 @@ def _gen_form_selectetuds(
|
|||||||
bac=None,
|
bac=None,
|
||||||
bacspecialite=None,
|
bacspecialite=None,
|
||||||
annee_bac=None,
|
annee_bac=None,
|
||||||
sexe=None,
|
civilite=None,
|
||||||
statut=None,
|
statut=None,
|
||||||
bacs=None,
|
bacs=None,
|
||||||
bacspecialites=None,
|
bacspecialites=None,
|
||||||
annee_bacs=None,
|
annee_bacs=None,
|
||||||
sexes=None,
|
civilites=None,
|
||||||
statuts=None,
|
statuts=None,
|
||||||
):
|
):
|
||||||
"""HTML form pour choix criteres selection etudiants"""
|
"""HTML form pour choix criteres selection etudiants"""
|
||||||
@ -766,8 +780,8 @@ def _gen_form_selectetuds(
|
|||||||
bacspecialites.sort()
|
bacspecialites.sort()
|
||||||
annee_bacs = list(annee_bacs)
|
annee_bacs = list(annee_bacs)
|
||||||
annee_bacs.sort()
|
annee_bacs.sort()
|
||||||
sexes = list(sexes)
|
civilites = list(civilites)
|
||||||
sexes.sort()
|
civilites.sort()
|
||||||
statuts = list(statuts)
|
statuts = list(statuts)
|
||||||
statuts.sort()
|
statuts.sort()
|
||||||
#
|
#
|
||||||
@ -826,13 +840,13 @@ def _gen_form_selectetuds(
|
|||||||
F.append("</select>")
|
F.append("</select>")
|
||||||
#
|
#
|
||||||
F.append(
|
F.append(
|
||||||
""" Genre: <select name="sexe" onchange="javascript: submit(this);">
|
""" Genre: <select name="civilite" onchange="javascript: submit(this);">
|
||||||
<option value="" %s>tous</option>
|
<option value="" %s>tous</option>
|
||||||
"""
|
"""
|
||||||
% selected
|
% selected
|
||||||
)
|
)
|
||||||
for b in sexes:
|
for b in civilites:
|
||||||
if sexe == b:
|
if civilite == b:
|
||||||
selected = 'selected="selected"'
|
selected = 'selected="selected"'
|
||||||
else:
|
else:
|
||||||
selected = ""
|
selected = ""
|
||||||
@ -986,7 +1000,7 @@ def tsp_etud_list(
|
|||||||
bac="", # selection sur type de bac
|
bac="", # selection sur type de bac
|
||||||
bacspecialite="",
|
bacspecialite="",
|
||||||
annee_bac="",
|
annee_bac="",
|
||||||
sexe="",
|
civilite="",
|
||||||
statut="",
|
statut="",
|
||||||
):
|
):
|
||||||
"""Liste des etuds a considerer dans table suivi parcours
|
"""Liste des etuds a considerer dans table suivi parcours
|
||||||
@ -1002,7 +1016,7 @@ def tsp_etud_list(
|
|||||||
bacs = set()
|
bacs = set()
|
||||||
bacspecialites = set()
|
bacspecialites = set()
|
||||||
annee_bacs = set()
|
annee_bacs = set()
|
||||||
sexes = set()
|
civilites = set()
|
||||||
statuts = set()
|
statuts = set()
|
||||||
for etudid in etudids:
|
for etudid in etudids:
|
||||||
etud = context.getEtudInfo(etudid=etudid, filled=True)[0]
|
etud = context.getEtudInfo(etudid=etudid, filled=True)[0]
|
||||||
@ -1012,7 +1026,7 @@ def tsp_etud_list(
|
|||||||
(not bac or (bac == etud["bac"]))
|
(not bac or (bac == etud["bac"]))
|
||||||
and (not bacspecialite or (bacspecialite == bacspe))
|
and (not bacspecialite or (bacspecialite == bacspe))
|
||||||
and (not annee_bac or (annee_bac == str(etud["annee_bac"])))
|
and (not annee_bac or (annee_bac == str(etud["annee_bac"])))
|
||||||
and (not sexe or (sexe == etud["sexe"]))
|
and (not civilite or (civilite == etud["civilite"]))
|
||||||
and (not statut or (statut == etud["statut"]))
|
and (not statut or (statut == etud["statut"]))
|
||||||
and (not only_primo or context.isPrimoEtud(etud, sem))
|
and (not only_primo or context.isPrimoEtud(etud, sem))
|
||||||
):
|
):
|
||||||
@ -1021,11 +1035,11 @@ def tsp_etud_list(
|
|||||||
bacs.add(etud["bac"])
|
bacs.add(etud["bac"])
|
||||||
bacspecialites.add(bacspe)
|
bacspecialites.add(bacspe)
|
||||||
annee_bacs.add(etud["annee_bac"])
|
annee_bacs.add(etud["annee_bac"])
|
||||||
sexes.add(etud["sexe"])
|
civilites.add(etud["civilite"])
|
||||||
if etud["statut"]: # ne montre pas les statuts non renseignés
|
if etud["statut"]: # ne montre pas les statuts non renseignés
|
||||||
statuts.add(etud["statut"])
|
statuts.add(etud["statut"])
|
||||||
# log('tsp_etud_list: %s etuds' % len(etuds))
|
# log('tsp_etud_list: %s etuds' % len(etuds))
|
||||||
return etuds, bacs, bacspecialites, annee_bacs, sexes, statuts
|
return etuds, bacs, bacspecialites, annee_bacs, civilites, statuts
|
||||||
|
|
||||||
|
|
||||||
def tsp_grouped_list(context, codes_etuds):
|
def tsp_grouped_list(context, codes_etuds):
|
||||||
@ -1051,7 +1065,7 @@ def table_suivi_parcours(
|
|||||||
):
|
):
|
||||||
"""Tableau recapitulant tous les parcours"""
|
"""Tableau recapitulant tous les parcours"""
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||||
etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = tsp_etud_list(
|
etuds, bacs, bacspecialites, annee_bacs, civilites, statuts = tsp_etud_list(
|
||||||
context, formsemestre_id, only_primo=only_primo
|
context, formsemestre_id, only_primo=only_primo
|
||||||
)
|
)
|
||||||
codes_etuds = scu.DictDefault(defaultvalue=[])
|
codes_etuds = scu.DictDefault(defaultvalue=[])
|
||||||
@ -1067,7 +1081,7 @@ def table_suivi_parcours(
|
|||||||
titles = {
|
titles = {
|
||||||
"parcours": "Code parcours",
|
"parcours": "Code parcours",
|
||||||
"nb": "Nombre d'étudiants",
|
"nb": "Nombre d'étudiants",
|
||||||
"sexe": "",
|
"civilite": "",
|
||||||
"nom": "Nom",
|
"nom": "Nom",
|
||||||
"prenom": "Prénom",
|
"prenom": "Prénom",
|
||||||
"etudid": "etudid",
|
"etudid": "etudid",
|
||||||
@ -1084,7 +1098,7 @@ def table_suivi_parcours(
|
|||||||
L = etuds
|
L = etuds
|
||||||
columns_ids = (
|
columns_ids = (
|
||||||
"etudid",
|
"etudid",
|
||||||
"sexe",
|
"civilite",
|
||||||
"nom",
|
"nom",
|
||||||
"prenom",
|
"prenom",
|
||||||
"bac",
|
"bac",
|
||||||
@ -1211,25 +1225,25 @@ def graph_parcours(
|
|||||||
bac="", # selection sur type de bac
|
bac="", # selection sur type de bac
|
||||||
bacspecialite="",
|
bacspecialite="",
|
||||||
annee_bac="",
|
annee_bac="",
|
||||||
sexe="",
|
civilite="",
|
||||||
statut="",
|
statut="",
|
||||||
):
|
):
|
||||||
""""""
|
""""""
|
||||||
if not scu.WITH_PYDOT:
|
if not scu.WITH_PYDOT:
|
||||||
raise ScoValueError("pydot module is not installed")
|
raise ScoValueError("pydot module is not installed")
|
||||||
etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = tsp_etud_list(
|
etuds, bacs, bacspecialites, annee_bacs, civilites, statuts = tsp_etud_list(
|
||||||
context,
|
context,
|
||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
only_primo=only_primo,
|
only_primo=only_primo,
|
||||||
bac=bac,
|
bac=bac,
|
||||||
bacspecialite=bacspecialite,
|
bacspecialite=bacspecialite,
|
||||||
annee_bac=annee_bac,
|
annee_bac=annee_bac,
|
||||||
sexe=sexe,
|
civilite=civilite,
|
||||||
statut=statut,
|
statut=statut,
|
||||||
)
|
)
|
||||||
# log('graph_parcours: %s etuds (only_primo=%s)' % (len(etuds), only_primo))
|
# log('graph_parcours: %s etuds (only_primo=%s)' % (len(etuds), only_primo))
|
||||||
if not etuds:
|
if not etuds:
|
||||||
return "", etuds, bacs, bacspecialites, annee_bacs, sexes, statuts
|
return "", etuds, bacs, bacspecialites, annee_bacs, civilites, statuts
|
||||||
edges = scu.DictDefault(
|
edges = scu.DictDefault(
|
||||||
defaultvalue=set()
|
defaultvalue=set()
|
||||||
) # {(formsemestre_id_origin, formsemestre_id_dest) : etud_set}
|
) # {(formsemestre_id_origin, formsemestre_id_dest) : etud_set}
|
||||||
@ -1242,7 +1256,7 @@ def graph_parcours(
|
|||||||
dem_nodes = {} # formsemestre_id : noeud pour demissionnaires
|
dem_nodes = {} # formsemestre_id : noeud pour demissionnaires
|
||||||
nar_nodes = {} # formsemestre_id : noeud pour NAR
|
nar_nodes = {} # formsemestre_id : noeud pour NAR
|
||||||
for etud in etuds:
|
for etud in etuds:
|
||||||
nxt = None
|
nxt = {}
|
||||||
etudid = etud["etudid"]
|
etudid = etud["etudid"]
|
||||||
for s in etud["sems"]: # du plus recent au plus ancien
|
for s in etud["sems"]: # du plus recent au plus ancien
|
||||||
nt = context._getNotesCache().get_NotesTable(
|
nt = context._getNotesCache().get_NotesTable(
|
||||||
@ -1419,7 +1433,7 @@ def graph_parcours(
|
|||||||
# cf http://groups.google.com/group/pydot/browse_thread/thread/b3704c53e331e2ec
|
# cf http://groups.google.com/group/pydot/browse_thread/thread/b3704c53e331e2ec
|
||||||
data = data.replace("font-family:Arial", "font-family:Helvetica")
|
data = data.replace("font-family:Arial", "font-family:Helvetica")
|
||||||
|
|
||||||
return data, etuds, bacs, bacspecialites, annee_bacs, sexes, statuts
|
return data, etuds, bacs, bacspecialites, annee_bacs, civilites, statuts
|
||||||
|
|
||||||
|
|
||||||
def formsemestre_graph_parcours(
|
def formsemestre_graph_parcours(
|
||||||
@ -1430,7 +1444,7 @@ def formsemestre_graph_parcours(
|
|||||||
bac="", # selection sur type de bac
|
bac="", # selection sur type de bac
|
||||||
bacspecialite="",
|
bacspecialite="",
|
||||||
annee_bac="",
|
annee_bac="",
|
||||||
sexe="",
|
civilite="",
|
||||||
statut="",
|
statut="",
|
||||||
allkeys=False, # unused
|
allkeys=False, # unused
|
||||||
REQUEST=None,
|
REQUEST=None,
|
||||||
@ -1439,7 +1453,15 @@ def formsemestre_graph_parcours(
|
|||||||
# log("formsemestre_graph_parcours")
|
# log("formsemestre_graph_parcours")
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||||
if format == "pdf":
|
if format == "pdf":
|
||||||
doc, etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = graph_parcours(
|
(
|
||||||
|
doc,
|
||||||
|
etuds,
|
||||||
|
bacs,
|
||||||
|
bacspecialites,
|
||||||
|
annee_bacs,
|
||||||
|
civilites,
|
||||||
|
statuts,
|
||||||
|
) = graph_parcours(
|
||||||
context,
|
context,
|
||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
format="pdf",
|
format="pdf",
|
||||||
@ -1447,14 +1469,22 @@ def formsemestre_graph_parcours(
|
|||||||
bac=bac,
|
bac=bac,
|
||||||
bacspecialite=bacspecialite,
|
bacspecialite=bacspecialite,
|
||||||
annee_bac=annee_bac,
|
annee_bac=annee_bac,
|
||||||
sexe=sexe,
|
civilite=civilite,
|
||||||
statut=statut,
|
statut=statut,
|
||||||
)
|
)
|
||||||
filename = scu.make_filename("flux " + sem["titreannee"])
|
filename = scu.make_filename("flux " + sem["titreannee"])
|
||||||
return scu.sendPDFFile(REQUEST, doc, filename + ".pdf")
|
return scu.sendPDFFile(REQUEST, doc, filename + ".pdf")
|
||||||
elif format == "png":
|
elif format == "png":
|
||||||
#
|
#
|
||||||
doc, etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = graph_parcours(
|
(
|
||||||
|
doc,
|
||||||
|
etuds,
|
||||||
|
bacs,
|
||||||
|
bacspecialites,
|
||||||
|
annee_bacs,
|
||||||
|
civilites,
|
||||||
|
statuts,
|
||||||
|
) = graph_parcours(
|
||||||
context,
|
context,
|
||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
format="png",
|
format="png",
|
||||||
@ -1462,7 +1492,7 @@ def formsemestre_graph_parcours(
|
|||||||
bac=bac,
|
bac=bac,
|
||||||
bacspecialite=bacspecialite,
|
bacspecialite=bacspecialite,
|
||||||
annee_bac=annee_bac,
|
annee_bac=annee_bac,
|
||||||
sexe=sexe,
|
civilite=civilite,
|
||||||
statut=statut,
|
statut=statut,
|
||||||
)
|
)
|
||||||
filename = scu.make_filename("flux " + sem["titreannee"])
|
filename = scu.make_filename("flux " + sem["titreannee"])
|
||||||
@ -1477,17 +1507,25 @@ def formsemestre_graph_parcours(
|
|||||||
else:
|
else:
|
||||||
op = ""
|
op = ""
|
||||||
url = urllib.quote(
|
url = urllib.quote(
|
||||||
"formsemestre_graph_parcours?formsemestre_id=%s&%sbac=%s&bacspecialite=%s&sexe=%s&statut=%s&format="
|
"formsemestre_graph_parcours?formsemestre_id=%s&%sbac=%s&bacspecialite=%s&civilite=%s&statut=%s&format="
|
||||||
% (formsemestre_id, op, bac, bacspecialite, sexe, statut)
|
% (formsemestre_id, op, bac, bacspecialite, civilite, statut)
|
||||||
)
|
)
|
||||||
doc, etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = graph_parcours(
|
(
|
||||||
|
doc,
|
||||||
|
etuds,
|
||||||
|
bacs,
|
||||||
|
bacspecialites,
|
||||||
|
annee_bacs,
|
||||||
|
civilites,
|
||||||
|
statuts,
|
||||||
|
) = graph_parcours(
|
||||||
context,
|
context,
|
||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
only_primo=only_primo,
|
only_primo=only_primo,
|
||||||
bac=bac,
|
bac=bac,
|
||||||
bacspecialite=bacspecialite,
|
bacspecialite=bacspecialite,
|
||||||
annee_bac=annee_bac,
|
annee_bac=annee_bac,
|
||||||
sexe=sexe,
|
civilite=civilite,
|
||||||
statut=statut,
|
statut=statut,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1507,12 +1545,12 @@ def formsemestre_graph_parcours(
|
|||||||
bac=bac,
|
bac=bac,
|
||||||
bacspecialite=bacspecialite,
|
bacspecialite=bacspecialite,
|
||||||
annee_bac=annee_bac,
|
annee_bac=annee_bac,
|
||||||
sexe=sexe,
|
civilite=civilite,
|
||||||
statut=statut,
|
statut=statut,
|
||||||
bacs=bacs,
|
bacs=bacs,
|
||||||
bacspecialites=bacspecialites,
|
bacspecialites=bacspecialites,
|
||||||
annee_bacs=annee_bacs,
|
annee_bacs=annee_bacs,
|
||||||
sexes=sexes,
|
civilites=civilites,
|
||||||
statuts=statuts,
|
statuts=statuts,
|
||||||
percent=0,
|
percent=0,
|
||||||
),
|
),
|
||||||
|
@ -33,7 +33,6 @@ import time
|
|||||||
import datetime
|
import datetime
|
||||||
import psycopg2
|
import psycopg2
|
||||||
|
|
||||||
# from notesdb import *
|
|
||||||
import sco_utils as scu
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from TrivialFormulator import TrivialFormulator, TF
|
from TrivialFormulator import TrivialFormulator, TF
|
||||||
@ -258,9 +257,7 @@ def do_evaluation_upload_xls(context, REQUEST):
|
|||||||
)
|
)
|
||||||
raise InvalidNoteValue()
|
raise InvalidNoteValue()
|
||||||
# -- check values
|
# -- check values
|
||||||
L, invalids, withoutnotes, absents, tosuppress = _check_notes(
|
L, invalids, withoutnotes, absents, _ = _check_notes(notes, E, M["module"])
|
||||||
notes, E, M["module"]
|
|
||||||
)
|
|
||||||
if len(invalids):
|
if len(invalids):
|
||||||
diag.append(
|
diag.append(
|
||||||
"Erreur: la feuille contient %d notes invalides</p>" % len(invalids)
|
"Erreur: la feuille contient %d notes invalides</p>" % len(invalids)
|
||||||
@ -339,7 +336,7 @@ def do_evaluation_set_missing(
|
|||||||
if not NotesDB.has_key(etudid): # pas de note
|
if not NotesDB.has_key(etudid): # pas de note
|
||||||
notes.append((etudid, value))
|
notes.append((etudid, value))
|
||||||
# Check value
|
# Check value
|
||||||
L, invalids, withoutnotes, absents, tosuppress = _check_notes(notes, E, M["module"])
|
L, invalids, _, _, _ = _check_notes(notes, E, M["module"])
|
||||||
diag = ""
|
diag = ""
|
||||||
if len(invalids):
|
if len(invalids):
|
||||||
diag = "Valeur %s invalide" % value
|
diag = "Valeur %s invalide" % value
|
||||||
@ -368,9 +365,7 @@ def do_evaluation_set_missing(
|
|||||||
)
|
)
|
||||||
# ok
|
# ok
|
||||||
comment = "Initialisation notes manquantes"
|
comment = "Initialisation notes manquantes"
|
||||||
nb_changed, nb_suppress, existing_decisions = _notes_add(
|
nb_changed, _, _ = _notes_add(context, authuser, evaluation_id, L, comment)
|
||||||
context, authuser, evaluation_id, L, comment
|
|
||||||
)
|
|
||||||
# news
|
# news
|
||||||
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0]
|
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0]
|
||||||
mod = context.do_module_list(args={"module_id": M["module_id"]})[0]
|
mod = context.do_module_list(args={"module_id": M["module_id"]})[0]
|
||||||
@ -479,7 +474,7 @@ def _notes_add(context, uid, evaluation_id, notes, comment=None, do_it=True):
|
|||||||
psycopg2.Timestamp, time.localtime()[:6]
|
psycopg2.Timestamp, time.localtime()[:6]
|
||||||
) # datetime.datetime.now().isoformat()
|
) # datetime.datetime.now().isoformat()
|
||||||
# Verifie inscription et valeur note
|
# Verifie inscription et valeur note
|
||||||
inscrits = {}.fromkeys(
|
_ = {}.fromkeys(
|
||||||
sco_groups.do_evaluation_listeetuds_groups(
|
sco_groups.do_evaluation_listeetuds_groups(
|
||||||
context, evaluation_id, getallstudents=True, include_dems=True
|
context, evaluation_id, getallstudents=True, include_dems=True
|
||||||
)
|
)
|
||||||
@ -806,10 +801,10 @@ def feuille_saisie_notes(context, evaluation_id, group_ids=[], REQUEST=None):
|
|||||||
)
|
)
|
||||||
groups = sco_groups.listgroups(context, groups_infos.group_ids)
|
groups = sco_groups.listgroups(context, groups_infos.group_ids)
|
||||||
gr_title_filename = sco_groups.listgroups_filename(groups)
|
gr_title_filename = sco_groups.listgroups_filename(groups)
|
||||||
gr_title = sco_groups.listgroups_abbrev(groups)
|
# gr_title = sco_groups.listgroups_abbrev(groups)
|
||||||
if None in [g["group_name"] for g in groups]: # tous les etudiants
|
if None in [g["group_name"] for g in groups]: # tous les etudiants
|
||||||
getallstudents = True
|
getallstudents = True
|
||||||
gr_title = "tous"
|
# gr_title = "tous"
|
||||||
gr_title_filename = "tous"
|
gr_title_filename = "tous"
|
||||||
else:
|
else:
|
||||||
getallstudents = False
|
getallstudents = False
|
||||||
@ -954,9 +949,15 @@ def saisie_notes(context, evaluation_id, group_ids=[], REQUEST=None):
|
|||||||
H.append("""</td></tr></table></div>""")
|
H.append("""</td></tr></table></div>""")
|
||||||
|
|
||||||
# Le formulaire de saisie des notes:
|
# Le formulaire de saisie des notes:
|
||||||
form = _form_saisie_notes(context, E, M, groups_infos.group_ids, REQUEST=REQUEST)
|
destination = "%s/Notes/moduleimpl_status?moduleimpl_id=%s" % (
|
||||||
|
context.ScoURL(),
|
||||||
|
E["moduleimpl_id"],
|
||||||
|
)
|
||||||
|
form = _form_saisie_notes(
|
||||||
|
context, E, M, groups_infos.group_ids, destination=destination, REQUEST=REQUEST
|
||||||
|
)
|
||||||
if form is None:
|
if form is None:
|
||||||
return "" # redirect
|
return REQUEST.RESPONSE.redirect(destination)
|
||||||
H.append(form)
|
H.append(form)
|
||||||
#
|
#
|
||||||
H.append("</div>") # /saisie_notes
|
H.append("</div>") # /saisie_notes
|
||||||
@ -1046,7 +1047,7 @@ def _get_sorted_etuds(context, E, etudids, formsemestre_id):
|
|||||||
return etuds
|
return etuds
|
||||||
|
|
||||||
|
|
||||||
def _form_saisie_notes(context, E, M, group_ids, REQUEST=None):
|
def _form_saisie_notes(context, E, M, group_ids, destination="", REQUEST=None):
|
||||||
"""Formulaire HTML saisie des notes dans l'évaluation E du moduleimpl M
|
"""Formulaire HTML saisie des notes dans l'évaluation E du moduleimpl M
|
||||||
pour les groupes indiqués.
|
pour les groupes indiqués.
|
||||||
|
|
||||||
@ -1126,7 +1127,13 @@ def _form_saisie_notes(context, E, M, group_ids, REQUEST=None):
|
|||||||
for group_info in e["groups"]:
|
for group_info in e["groups"]:
|
||||||
etud_classes.append(group_info["group_id"])
|
etud_classes.append(group_info["group_id"])
|
||||||
|
|
||||||
label = '<span class="%s">' % classdem + e["nomprenom"] + "</span>"
|
label = (
|
||||||
|
'<span class="%s">' % classdem
|
||||||
|
+ e["civilite_str"]
|
||||||
|
+ " "
|
||||||
|
+ scolars.format_nomprenom(e, reverse=True)
|
||||||
|
+ "</span>"
|
||||||
|
)
|
||||||
|
|
||||||
# Historique des saisies de notes:
|
# Historique des saisies de notes:
|
||||||
if not disabled:
|
if not disabled:
|
||||||
@ -1181,11 +1188,6 @@ def _form_saisie_notes(context, E, M, group_ids, REQUEST=None):
|
|||||||
)
|
)
|
||||||
# H.append('''<div id="sco_msg" class="head_message"></div>''')
|
# H.append('''<div id="sco_msg" class="head_message"></div>''')
|
||||||
|
|
||||||
destination = "%s/Notes/moduleimpl_status?moduleimpl_id=%s" % (
|
|
||||||
context.ScoURL(),
|
|
||||||
M["moduleimpl_id"],
|
|
||||||
)
|
|
||||||
|
|
||||||
tf = TF(
|
tf = TF(
|
||||||
destination,
|
destination,
|
||||||
REQUEST.form,
|
REQUEST.form,
|
||||||
@ -1196,7 +1198,6 @@ def _form_saisie_notes(context, E, M, group_ids, REQUEST=None):
|
|||||||
)
|
)
|
||||||
H.append(tf.getform()) # check and init
|
H.append(tf.getform()) # check and init
|
||||||
if tf.canceled():
|
if tf.canceled():
|
||||||
REQUEST.RESPONSE.redirect(destination)
|
|
||||||
return None
|
return None
|
||||||
elif (not tf.submitted()) or not tf.result:
|
elif (not tf.submitted()) or not tf.result:
|
||||||
# ajout formularie saisie notes manquantes
|
# ajout formularie saisie notes manquantes
|
||||||
@ -1218,7 +1219,6 @@ def _form_saisie_notes(context, E, M, group_ids, REQUEST=None):
|
|||||||
else:
|
else:
|
||||||
# form submission
|
# form submission
|
||||||
# rien à faire
|
# rien à faire
|
||||||
REQUEST.RESPONSE.redirect(destination)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@ -1240,11 +1240,9 @@ def save_note(
|
|||||||
if not can_edit_notes(context, authuser, E["moduleimpl_id"]):
|
if not can_edit_notes(context, authuser, E["moduleimpl_id"]):
|
||||||
result["status"] = "unauthorized"
|
result["status"] = "unauthorized"
|
||||||
else:
|
else:
|
||||||
L, invalids, withoutnotes, absents, tosuppress = _check_notes(
|
L, _, _, _, _ = _check_notes([(etudid, value)], E, Mod)
|
||||||
[(etudid, value)], E, Mod
|
|
||||||
)
|
|
||||||
if L:
|
if L:
|
||||||
nbchanged, nbsuppress, existing_decisions = _notes_add(
|
nbchanged, _, existing_decisions = _notes_add(
|
||||||
context, authuser, evaluation_id, L, comment=comment, do_it=True
|
context, authuser, evaluation_id, L, comment=comment, do_it=True
|
||||||
)
|
)
|
||||||
sco_news.add(
|
sco_news.add(
|
||||||
|
@ -39,8 +39,8 @@ sem_set_list(context)
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
from sco_formsemestre import ApoEtapeVDI
|
from sco_formsemestre import ApoEtapeVDI
|
||||||
@ -49,9 +49,10 @@ import sco_etape_apogee
|
|||||||
from sco_etape_bilan import EtapeBilan
|
from sco_etape_bilan import EtapeBilan
|
||||||
import sco_portal_apogee
|
import sco_portal_apogee
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
|
||||||
|
|
||||||
_semset_editor = EditableTable(
|
_semset_editor = ndb.EditableTable(
|
||||||
"notes_semset", "semset_id", ("semset_id", "title", "annee_scolaire", "sem_id")
|
"notes_semset", "semset_id", ("semset_id", "title", "annee_scolaire", "sem_id")
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -81,7 +82,7 @@ class SemSet(dict):
|
|||||||
self["title"] = L[0]["title"]
|
self["title"] = L[0]["title"]
|
||||||
self["annee_scolaire"] = L[0]["annee_scolaire"]
|
self["annee_scolaire"] = L[0]["annee_scolaire"]
|
||||||
self["sem_id"] = L[0]["sem_id"]
|
self["sem_id"] = L[0]["sem_id"]
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT formsemestre_id FROM notes_semset_formsemestre WHERE semset_id = %(semset_id)s",
|
"SELECT formsemestre_id FROM notes_semset_formsemestre WHERE semset_id = %(semset_id)s",
|
||||||
{"semset_id": semset_id},
|
{"semset_id": semset_id},
|
||||||
@ -150,7 +151,7 @@ class SemSet(dict):
|
|||||||
% (formsemestre_id, self.semset_id)
|
% (formsemestre_id, self.semset_id)
|
||||||
)
|
)
|
||||||
|
|
||||||
SimpleQuery(
|
ndb.SimpleQuery(
|
||||||
self.context,
|
self.context,
|
||||||
"INSERT INTO notes_semset_formsemestre (formsemestre_id, semset_id) VALUES (%(formsemestre_id)s, %(semset_id)s)",
|
"INSERT INTO notes_semset_formsemestre (formsemestre_id, semset_id) VALUES (%(formsemestre_id)s, %(semset_id)s)",
|
||||||
{"formsemestre_id": formsemestre_id, "semset_id": self.semset_id},
|
{"formsemestre_id": formsemestre_id, "semset_id": self.semset_id},
|
||||||
@ -158,7 +159,7 @@ class SemSet(dict):
|
|||||||
self.load_sems() # update our list
|
self.load_sems() # update our list
|
||||||
|
|
||||||
def remove(self, formsemestre_id):
|
def remove(self, formsemestre_id):
|
||||||
SimpleQuery(
|
ndb.SimpleQuery(
|
||||||
self.context,
|
self.context,
|
||||||
"DELETE FROM notes_semset_formsemestre WHERE semset_id=%(semset_id)s AND formsemestre_id=%(formsemestre_id)s",
|
"DELETE FROM notes_semset_formsemestre WHERE semset_id=%(semset_id)s AND formsemestre_id=%(formsemestre_id)s",
|
||||||
{"formsemestre_id": formsemestre_id, "semset_id": self.semset_id},
|
{"formsemestre_id": formsemestre_id, "semset_id": self.semset_id},
|
||||||
@ -416,7 +417,7 @@ def semset_page(context, format="html", REQUEST=None):
|
|||||||
"""
|
"""
|
||||||
semsets = get_semsets_list(context)
|
semsets = get_semsets_list(context)
|
||||||
for s in semsets:
|
for s in semsets:
|
||||||
s["suppress"] = icontag(
|
s["suppress"] = scu.icontag(
|
||||||
"delete_small_img", border="0", alt="supprimer", title="Supprimer"
|
"delete_small_img", border="0", alt="supprimer", title="Supprimer"
|
||||||
)
|
)
|
||||||
s["_suppress_target"] = "do_semset_delete?semset_id=%s" % (s["semset_id"])
|
s["_suppress_target"] = "do_semset_delete?semset_id=%s" % (s["semset_id"])
|
||||||
@ -478,7 +479,7 @@ def semset_page(context, format="html", REQUEST=None):
|
|||||||
]
|
]
|
||||||
H.append(tab.html())
|
H.append(tab.html())
|
||||||
|
|
||||||
annee_courante = int(AnneeScolaire(REQUEST))
|
annee_courante = int(scu.AnneeScolaire(REQUEST))
|
||||||
menu_annee = "\n".join(
|
menu_annee = "\n".join(
|
||||||
[
|
[
|
||||||
'<option value="%s">%s</option>' % (i, i)
|
'<option value="%s">%s</option>' % (i, i)
|
||||||
|
@ -31,9 +31,11 @@
|
|||||||
import time
|
import time
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
from sco_utils import ScoEtudInscrit, annee_scolaire_debut, log, ScoValueError
|
import sco_utils as scu
|
||||||
|
from sco_permissions import ScoEtudInscrit
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
from notesdb import ScoDocCursor
|
from notesdb import ScoDocCursor
|
||||||
|
from notes_log import log
|
||||||
import sco_portal_apogee
|
import sco_portal_apogee
|
||||||
import sco_inscr_passage
|
import sco_inscr_passage
|
||||||
import scolars
|
import scolars
|
||||||
@ -111,7 +113,7 @@ def formsemestre_synchro_etuds(
|
|||||||
|
|
||||||
if anneeapogee == None: # année d'inscription par défaut
|
if anneeapogee == None: # année d'inscription par défaut
|
||||||
anneeapogee = str(
|
anneeapogee = str(
|
||||||
annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"])
|
scu.annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"])
|
||||||
)
|
)
|
||||||
|
|
||||||
if type(etuds) == type(""):
|
if type(etuds) == type(""):
|
||||||
@ -406,7 +408,7 @@ def list_synch(context, sem, anneeapogee=None):
|
|||||||
etud = etudsapo_ident[key]
|
etud = etudsapo_ident[key]
|
||||||
|
|
||||||
etud["etudid"] = ""
|
etud["etudid"] = ""
|
||||||
etud["sexe"] = etud.get(
|
etud["civilite"] = etud.get(
|
||||||
"sexe", etud.get("gender", "")
|
"sexe", etud.get("gender", "")
|
||||||
) # la cle 'sexe' est prioritaire sur 'gender'
|
) # la cle 'sexe' est prioritaire sur 'gender'
|
||||||
etud["inscrit"] = is_inscrit # checkbox state
|
etud["inscrit"] = is_inscrit # checkbox state
|
||||||
@ -543,16 +545,14 @@ def formsemestre_synchro_etuds_help(context, sem):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def gender2sex(gender):
|
def gender2civilite(gender):
|
||||||
"""Le portail code en 'M', 'F', et ScoDoc en 'MR', 'MME'
|
"""Le portail code en 'M', 'F', et ScoDoc en 'M', 'F', 'X'"""
|
||||||
Les F sont ici codées en MME
|
if gender == "M" or gender == "F" or gender == "X":
|
||||||
"""
|
return gender
|
||||||
if gender == "M":
|
elif not gender:
|
||||||
return "MR"
|
return "X"
|
||||||
elif gender == "F":
|
log('gender2civilite: invalid value "%s", defaulting to "X"' % gender)
|
||||||
return "MME"
|
return "X" # "X" en général n'est pas affiché, donc bon choix si invalide
|
||||||
log('gender2sex: invalid value "%s", defaulting to "M"' % gender)
|
|
||||||
return "MR"
|
|
||||||
|
|
||||||
|
|
||||||
def get_opt_str(etud, k):
|
def get_opt_str(etud, k):
|
||||||
@ -596,7 +596,7 @@ def do_import_etuds_from_portal(context, sem, a_importer, etudsapo_ident, REQUES
|
|||||||
"prenom": etud["prenom"].strip(),
|
"prenom": etud["prenom"].strip(),
|
||||||
# Les champs suivants sont facultatifs (pas toujours renvoyés par le portail)
|
# Les champs suivants sont facultatifs (pas toujours renvoyés par le portail)
|
||||||
"code_ine": etud.get("ine", "").strip(),
|
"code_ine": etud.get("ine", "").strip(),
|
||||||
"sexe": gender2sex(etud["gender"].strip()),
|
"civilite": gender2civilite(etud["gender"].strip()),
|
||||||
"etape": etud.get("etape", None),
|
"etape": etud.get("etape", None),
|
||||||
"email": etud.get("mail", "").strip(),
|
"email": etud.get("mail", "").strip(),
|
||||||
"emailperso": etud.get("mailperso", "").strip(),
|
"emailperso": etud.get("mailperso", "").strip(),
|
||||||
@ -736,9 +736,9 @@ def do_import_etud_admission(
|
|||||||
if x:
|
if x:
|
||||||
args[sco_field] = x
|
args[sco_field] = x
|
||||||
# Champs spécifiques:
|
# Champs spécifiques:
|
||||||
sexe = gender2sex(etud["gender"].strip())
|
civilite = gender2civilite(etud["gender"].strip())
|
||||||
if sexe:
|
if civilite:
|
||||||
args["sexe"] = sexe
|
args["civilite"] = civilite
|
||||||
|
|
||||||
scolars.identite_edit_nocheck(cnx, args)
|
scolars.identite_edit_nocheck(cnx, args)
|
||||||
|
|
||||||
@ -791,7 +791,9 @@ def formsemestre_import_etud_admission(
|
|||||||
# Essaie de recuperer les etudiants des étapes, car
|
# Essaie de recuperer les etudiants des étapes, car
|
||||||
# la requete get_inscrits_etape est en général beaucoup plus
|
# la requete get_inscrits_etape est en général beaucoup plus
|
||||||
# rapide que les requetes individuelles get_etud_apogee
|
# rapide que les requetes individuelles get_etud_apogee
|
||||||
anneeapogee = str(annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"]))
|
anneeapogee = str(
|
||||||
|
scu.annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"])
|
||||||
|
)
|
||||||
apo_etuds = {} # nip : etud apo
|
apo_etuds = {} # nip : etud apo
|
||||||
for etape in sem["etapes"]:
|
for etape in sem["etapes"]:
|
||||||
etudsapo = sco_portal_apogee.get_inscrits_etape(
|
etudsapo = sco_portal_apogee.get_inscrits_etape(
|
||||||
|
@ -34,9 +34,13 @@
|
|||||||
Pour l'UI, voir https://goodies.pixabay.com/jquery/tag-editor/demo.html
|
Pour l'UI, voir https://goodies.pixabay.com/jquery/tag-editor/demo.html
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from sco_utils import *
|
import types
|
||||||
from notesdb import *
|
|
||||||
|
import sco_utils as scu
|
||||||
|
import notesdb as ndb
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
|
from sco_exceptions import ScoValueError, AccessDenied
|
||||||
|
from sco_permissions import ScoEditFormationTags, ScoChangeFormation
|
||||||
|
|
||||||
# Opérations à implementer:
|
# Opérations à implementer:
|
||||||
# + liste des modules des formations de code donné (formation_code) avec ce tag
|
# + liste des modules des formations de code donné (formation_code) avec ce tag
|
||||||
@ -66,7 +70,7 @@ class ScoTag:
|
|||||||
self.title = title.strip()
|
self.title = title.strip()
|
||||||
if not self.title:
|
if not self.title:
|
||||||
raise ScoValueError("invalid empty tag")
|
raise ScoValueError("invalid empty tag")
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT * FROM " + self.tag_table + " WHERE title = %(title)s",
|
"SELECT * FROM " + self.tag_table + " WHERE title = %(title)s",
|
||||||
{"title": self.title},
|
{"title": self.title},
|
||||||
@ -77,8 +81,10 @@ class ScoTag:
|
|||||||
# Create new tag:
|
# Create new tag:
|
||||||
log("creating new tag: %s" % self.title)
|
log("creating new tag: %s" % self.title)
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
oid = DBInsertDict(cnx, self.tag_table, {"title": self.title}, commit=True)
|
oid = ndb.DBInsertDict(
|
||||||
self.tag_id = SimpleDictFetch(
|
cnx, self.tag_table, {"title": self.title}, commit=True
|
||||||
|
)
|
||||||
|
self.tag_id = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT tag_id FROM " + self.tag_table + " WHERE oid=%(oid)s",
|
"SELECT tag_id FROM " + self.tag_table + " WHERE oid=%(oid)s",
|
||||||
{"oid": oid},
|
{"oid": oid},
|
||||||
@ -94,7 +100,7 @@ class ScoTag:
|
|||||||
This object should not be used after this call !
|
This object should not be used after this call !
|
||||||
"""
|
"""
|
||||||
args = {"tag_id": self.tag_id}
|
args = {"tag_id": self.tag_id}
|
||||||
SimpleQuery(
|
ndb.SimpleQuery(
|
||||||
self.context,
|
self.context,
|
||||||
"DELETE FROM " + self.tag_table + " t WHERE t.tag_id = %(tag_id)s",
|
"DELETE FROM " + self.tag_table + " t WHERE t.tag_id = %(tag_id)s",
|
||||||
args,
|
args,
|
||||||
@ -103,7 +109,7 @@ class ScoTag:
|
|||||||
def tag_object(self, object_id):
|
def tag_object(self, object_id):
|
||||||
"""Associate tag to given object"""
|
"""Associate tag to given object"""
|
||||||
args = {self.obj_colname: object_id, "tag_id": self.tag_id}
|
args = {self.obj_colname: object_id, "tag_id": self.tag_id}
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
self.context,
|
self.context,
|
||||||
"SELECT * FROM "
|
"SELECT * FROM "
|
||||||
+ self.assoc_table
|
+ self.assoc_table
|
||||||
@ -117,7 +123,7 @@ class ScoTag:
|
|||||||
if not r:
|
if not r:
|
||||||
log("tag %s with %s" % (object_id, self.title))
|
log("tag %s with %s" % (object_id, self.title))
|
||||||
cnx = self.context.GetDBConnexion()
|
cnx = self.context.GetDBConnexion()
|
||||||
DBInsertDict(cnx, self.assoc_table, args, commit=True)
|
ndb.DBInsertDict(cnx, self.assoc_table, args, commit=True)
|
||||||
|
|
||||||
def remove_tag_from_object(self, object_id):
|
def remove_tag_from_object(self, object_id):
|
||||||
"""Remove tag from module.
|
"""Remove tag from module.
|
||||||
@ -126,7 +132,7 @@ class ScoTag:
|
|||||||
"""
|
"""
|
||||||
log("removing tag %s from %s" % (self.title, object_id))
|
log("removing tag %s from %s" % (self.title, object_id))
|
||||||
args = {"object_id": object_id, "tag_id": self.tag_id}
|
args = {"object_id": object_id, "tag_id": self.tag_id}
|
||||||
SimpleQuery(
|
ndb.SimpleQuery(
|
||||||
self.context,
|
self.context,
|
||||||
"DELETE FROM "
|
"DELETE FROM "
|
||||||
+ self.assoc_table
|
+ self.assoc_table
|
||||||
@ -135,7 +141,7 @@ class ScoTag:
|
|||||||
+ " = %(object_id)s AND a.tag_id = %(tag_id)s",
|
+ " = %(object_id)s AND a.tag_id = %(tag_id)s",
|
||||||
args,
|
args,
|
||||||
)
|
)
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
self.context,
|
self.context,
|
||||||
"""SELECT * FROM notes_modules_tags mt WHERE tag_id = %(tag_id)s
|
"""SELECT * FROM notes_modules_tags mt WHERE tag_id = %(tag_id)s
|
||||||
""",
|
""",
|
||||||
@ -143,7 +149,7 @@ class ScoTag:
|
|||||||
)
|
)
|
||||||
if not r:
|
if not r:
|
||||||
# tag no more used, delete
|
# tag no more used, delete
|
||||||
SimpleQuery(
|
ndb.SimpleQuery(
|
||||||
self.context,
|
self.context,
|
||||||
"""DELETE FROM notes_tags t WHERE t.tag_id = %(tag_id)s""",
|
"""DELETE FROM notes_tags t WHERE t.tag_id = %(tag_id)s""",
|
||||||
args,
|
args,
|
||||||
@ -162,7 +168,7 @@ class ModuleTag(ScoTag):
|
|||||||
args = {"tag_id": self.tag_id}
|
args = {"tag_id": self.tag_id}
|
||||||
if not formation_code:
|
if not formation_code:
|
||||||
# tous les modules de toutes les formations !
|
# tous les modules de toutes les formations !
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
self.context,
|
self.context,
|
||||||
"SELECT "
|
"SELECT "
|
||||||
+ self.obj_colname
|
+ self.obj_colname
|
||||||
@ -174,7 +180,7 @@ class ModuleTag(ScoTag):
|
|||||||
else:
|
else:
|
||||||
args["formation_code"] = formation_code
|
args["formation_code"] = formation_code
|
||||||
|
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
self.context,
|
self.context,
|
||||||
"""SELECT mt.module_id
|
"""SELECT mt.module_id
|
||||||
FROM notes_modules_tags mt, notes_modules m, notes_formations f
|
FROM notes_modules_tags mt, notes_modules m, notes_formations f
|
||||||
@ -194,22 +200,22 @@ class ModuleTag(ScoTag):
|
|||||||
def module_tag_search(context, term, REQUEST=None):
|
def module_tag_search(context, term, REQUEST=None):
|
||||||
"""List all used tag names (for auto-completion)"""
|
"""List all used tag names (for auto-completion)"""
|
||||||
# restrict charset to avoid injections
|
# restrict charset to avoid injections
|
||||||
if not ALPHANUM_EXP.match(term.decode(SCO_ENCODING)):
|
if not scu.ALPHANUM_EXP.match(term.decode(scu.SCO_ENCODING)):
|
||||||
data = []
|
data = []
|
||||||
else:
|
else:
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"SELECT title FROM notes_tags WHERE title LIKE %(term)s",
|
"SELECT title FROM notes_tags WHERE title LIKE %(term)s",
|
||||||
{"term": term + "%"},
|
{"term": term + "%"},
|
||||||
)
|
)
|
||||||
data = [x["title"] for x in r]
|
data = [x["title"] for x in r]
|
||||||
|
|
||||||
return sendJSON(REQUEST, data)
|
return scu.sendJSON(REQUEST, data)
|
||||||
|
|
||||||
|
|
||||||
def module_tag_list(context, module_id=""):
|
def module_tag_list(context, module_id=""):
|
||||||
"""les noms de tags associés à ce module"""
|
"""les noms de tags associés à ce module"""
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"""SELECT t.title
|
"""SELECT t.title
|
||||||
FROM notes_modules_tags mt, notes_tags t
|
FROM notes_modules_tags mt, notes_tags t
|
||||||
@ -237,7 +243,7 @@ def module_tag_set(context, module_id="", taglist=[], REQUEST=None):
|
|||||||
#
|
#
|
||||||
if not taglist:
|
if not taglist:
|
||||||
taglist = []
|
taglist = []
|
||||||
elif type(taglist) == StringType:
|
elif type(taglist) == types.StringType:
|
||||||
taglist = taglist.split(",")
|
taglist = taglist.split(",")
|
||||||
taglist = [t.strip() for t in taglist]
|
taglist = [t.strip() for t in taglist]
|
||||||
log("module_tag_set: module_id=%s taglist=%s" % (module_id, taglist))
|
log("module_tag_set: module_id=%s taglist=%s" % (module_id, taglist))
|
||||||
|
125
sco_trombino.py
125
sco_trombino.py
@ -28,16 +28,29 @@
|
|||||||
"""Photos: trombinoscopes
|
"""Photos: trombinoscopes
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
except:
|
|
||||||
from StringIO import StringIO
|
|
||||||
from zipfile import ZipFile, BadZipfile
|
from zipfile import ZipFile, BadZipfile
|
||||||
import xml
|
import xml
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import reportlab
|
||||||
|
from reportlab.lib.units import cm, mm
|
||||||
|
from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
|
||||||
|
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Frame, PageBreak
|
||||||
|
from reportlab.platypus import Table, TableStyle, Image, KeepInFrame
|
||||||
|
from reportlab.platypus.flowables import Flowable
|
||||||
|
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
|
||||||
|
from reportlab.lib.pagesizes import A4, landscape
|
||||||
|
from reportlab.lib import styles
|
||||||
|
from reportlab.lib.colors import Color
|
||||||
|
from reportlab.lib import colors
|
||||||
|
from PIL import Image as PILImage
|
||||||
|
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
|
import sco_pdf
|
||||||
|
from sco_pdf import SU
|
||||||
|
from sco_exceptions import ScoValueError
|
||||||
|
from TrivialFormulator import TrivialFormulator
|
||||||
import scolars
|
import scolars
|
||||||
import sco_photos
|
import sco_photos
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
@ -45,10 +58,8 @@ import sco_groups
|
|||||||
import sco_groups_view
|
import sco_groups_view
|
||||||
import sco_portal_apogee
|
import sco_portal_apogee
|
||||||
import htmlutils
|
import htmlutils
|
||||||
from sco_pdf import *
|
|
||||||
import ImportScolars
|
import ImportScolars
|
||||||
import sco_excel
|
import sco_excel
|
||||||
from reportlab.lib import colors
|
|
||||||
|
|
||||||
|
|
||||||
def trombino(
|
def trombino(
|
||||||
@ -165,8 +176,7 @@ def check_local_photos_availability(context, groups_infos, REQUEST, format=""):
|
|||||||
"""
|
"""
|
||||||
nb_missing = 0
|
nb_missing = 0
|
||||||
for t in groups_infos.members:
|
for t in groups_infos.members:
|
||||||
etudid = t["etudid"]
|
_ = sco_photos.etud_photo_url(
|
||||||
url = sco_photos.etud_photo_url(
|
|
||||||
context, t, REQUEST=REQUEST
|
context, t, REQUEST=REQUEST
|
||||||
) # -> copy distant files if needed
|
) # -> copy distant files if needed
|
||||||
if not sco_photos.etud_photo_is_local(context, t):
|
if not sco_photos.etud_photo_is_local(context, t):
|
||||||
@ -327,13 +337,7 @@ def _trombino_pdf(context, groups_infos, REQUEST):
|
|||||||
[img],
|
[img],
|
||||||
[
|
[
|
||||||
Paragraph(
|
Paragraph(
|
||||||
SU(
|
SU(scolars.format_nomprenom(t)),
|
||||||
scolars.format_sexe(t["sexe"])
|
|
||||||
+ " "
|
|
||||||
+ scolars.format_prenom(t["prenom"])
|
|
||||||
+ " "
|
|
||||||
+ scolars.format_nom(t["nom"])
|
|
||||||
),
|
|
||||||
StyleSheet["Normal"],
|
StyleSheet["Normal"],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@ -366,7 +370,7 @@ def _trombino_pdf(context, groups_infos, REQUEST):
|
|||||||
# Build document
|
# Build document
|
||||||
document = BaseDocTemplate(report)
|
document = BaseDocTemplate(report)
|
||||||
document.addPageTemplates(
|
document.addPageTemplates(
|
||||||
ScolarsPageTemplate(
|
sco_pdf.ScolarsPageTemplate(
|
||||||
document,
|
document,
|
||||||
context=context,
|
context=context,
|
||||||
preferences=context.get_preferences(sem["formsemestre_id"]),
|
preferences=context.get_preferences(sem["formsemestre_id"]),
|
||||||
@ -375,7 +379,7 @@ def _trombino_pdf(context, groups_infos, REQUEST):
|
|||||||
document.build(objects)
|
document.build(objects)
|
||||||
data = report.getvalue()
|
data = report.getvalue()
|
||||||
|
|
||||||
return sendPDFFile(REQUEST, data, filename)
|
return scu.sendPDFFile(REQUEST, data, filename)
|
||||||
|
|
||||||
|
|
||||||
# --------------------- Sur une idée de l'IUT d'Orléans:
|
# --------------------- Sur une idée de l'IUT d'Orléans:
|
||||||
@ -385,8 +389,8 @@ def _listeappel_photos_pdf(context, groups_infos, REQUEST):
|
|||||||
sem = groups_infos.formsemestre # suppose 1 seul semestre
|
sem = groups_infos.formsemestre # suppose 1 seul semestre
|
||||||
|
|
||||||
PHOTOWIDTH = 2 * cm
|
PHOTOWIDTH = 2 * cm
|
||||||
COLWIDTH = 3.6 * cm
|
# COLWIDTH = 3.6 * cm
|
||||||
ROWS_PER_PAGE = 26 # XXX should be in ScoDoc preferences
|
# ROWS_PER_PAGE = 26 # XXX should be in ScoDoc preferences
|
||||||
|
|
||||||
StyleSheet = styles.getSampleStyleSheet()
|
StyleSheet = styles.getSampleStyleSheet()
|
||||||
report = StringIO() # in-memory document, no disk file
|
report = StringIO() # in-memory document, no disk file
|
||||||
@ -412,13 +416,7 @@ def _listeappel_photos_pdf(context, groups_infos, REQUEST):
|
|||||||
t = groups_infos.members[i]
|
t = groups_infos.members[i]
|
||||||
img = _get_etud_platypus_image(context, t, image_width=PHOTOWIDTH)
|
img = _get_etud_platypus_image(context, t, image_width=PHOTOWIDTH)
|
||||||
txt = Paragraph(
|
txt = Paragraph(
|
||||||
SU(
|
SU(scolars.format_nomprenom(t)),
|
||||||
scolars.format_sexe(t["sexe"])
|
|
||||||
+ " "
|
|
||||||
+ scolars.format_prenom(t["prenom"])
|
|
||||||
+ " "
|
|
||||||
+ scolars.format_nom(t["nom"])
|
|
||||||
),
|
|
||||||
StyleSheet["Normal"],
|
StyleSheet["Normal"],
|
||||||
)
|
)
|
||||||
if currow:
|
if currow:
|
||||||
@ -449,7 +447,7 @@ def _listeappel_photos_pdf(context, groups_infos, REQUEST):
|
|||||||
# Build document
|
# Build document
|
||||||
document = BaseDocTemplate(report)
|
document = BaseDocTemplate(report)
|
||||||
document.addPageTemplates(
|
document.addPageTemplates(
|
||||||
ScolarsPageTemplate(
|
sco_pdf.ScolarsPageTemplate(
|
||||||
document,
|
document,
|
||||||
context,
|
context,
|
||||||
preferences=context.get_preferences(sem["formsemestre_id"]),
|
preferences=context.get_preferences(sem["formsemestre_id"]),
|
||||||
@ -458,72 +456,7 @@ def _listeappel_photos_pdf(context, groups_infos, REQUEST):
|
|||||||
document.build(objects)
|
document.build(objects)
|
||||||
data = report.getvalue()
|
data = report.getvalue()
|
||||||
|
|
||||||
return sendPDFFile(REQUEST, data, filename)
|
return scu.sendPDFFile(REQUEST, data, filename)
|
||||||
|
|
||||||
objects = []
|
|
||||||
StyleSheet = styles.getSampleStyleSheet()
|
|
||||||
report = StringIO() # in-memory document, no disk file
|
|
||||||
filename = ("trombino-%s.pdf" % ng).replace(
|
|
||||||
" ", "_"
|
|
||||||
) # XXX should sanitize this filename
|
|
||||||
objects.append(
|
|
||||||
Paragraph(SU("Liste " + sem["titreannee"] + " " + ng), StyleSheet["Heading3"])
|
|
||||||
)
|
|
||||||
PHOTOWIDTH = 3 * cm
|
|
||||||
COLWIDTH = 3.6 * cm
|
|
||||||
|
|
||||||
L = [] # cells
|
|
||||||
n = 0
|
|
||||||
currow = []
|
|
||||||
for t in T:
|
|
||||||
n = n + 1
|
|
||||||
img = _get_etud_platypus_image(context, t, image_width=2 * cm)
|
|
||||||
currow += [
|
|
||||||
Paragraph(
|
|
||||||
SU(
|
|
||||||
scolars.format_sexe(t["sexe"])
|
|
||||||
+ " "
|
|
||||||
+ scolars.format_prenom(t["prenom"])
|
|
||||||
+ " "
|
|
||||||
+ scolars.format_nom(t["nom"])
|
|
||||||
),
|
|
||||||
StyleSheet["Normal"],
|
|
||||||
),
|
|
||||||
"", # empty cell (signature ou autre info a remplir sur papier)
|
|
||||||
img,
|
|
||||||
]
|
|
||||||
|
|
||||||
if not L:
|
|
||||||
table = Paragraph(SU("Aucune photo à exporter !"), StyleSheet["Normal"])
|
|
||||||
else:
|
|
||||||
table = Table(
|
|
||||||
L,
|
|
||||||
colWidths=[COLWIDTH] * 7,
|
|
||||||
style=TableStyle(
|
|
||||||
[
|
|
||||||
("VALIGN", (0, 0), (-1, -1), "TOP"),
|
|
||||||
("GRID", (0, 0), (2, -1), 0.25, colors.grey),
|
|
||||||
("GRID", (2, 0), (-1, -1), 0.25, colors.red), # <<<
|
|
||||||
]
|
|
||||||
),
|
|
||||||
)
|
|
||||||
objects.append(table)
|
|
||||||
|
|
||||||
# Réduit sur une page
|
|
||||||
objects = [KeepInFrame(0, 0, objects, mode="shrink")]
|
|
||||||
|
|
||||||
# --- Build document
|
|
||||||
document = BaseDocTemplate(report)
|
|
||||||
document.addPageTemplates(
|
|
||||||
ScolarsPageTemplate(
|
|
||||||
document,
|
|
||||||
context=context,
|
|
||||||
preferences=context.get_preferences(sem["formsemestre_id"]),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
document.build(objects)
|
|
||||||
data = report.getvalue()
|
|
||||||
return sendPDFFile(REQUEST, data, filename)
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------- Upload des photos de tout un groupe
|
# --------------------- Upload des photos de tout un groupe
|
||||||
@ -614,7 +547,7 @@ def photos_import_files(
|
|||||||
def callback(context, etud, data, filename, REQUEST):
|
def callback(context, etud, data, filename, REQUEST):
|
||||||
sco_photos.store_photo(context, etud, data, REQUEST)
|
sco_photos.store_photo(context, etud, data, REQUEST)
|
||||||
|
|
||||||
r = zip_excel_import_files(
|
zip_excel_import_files(
|
||||||
context, xlsfile, zipfile, REQUEST, callback, filename_title, page_title
|
context, xlsfile, zipfile, REQUEST, callback, filename_title, page_title
|
||||||
)
|
)
|
||||||
return REQUEST.RESPONSE.redirect(back_url + "&head_message=photos%20 importees")
|
return REQUEST.RESPONSE.redirect(back_url + "&head_message=photos%20 importees")
|
||||||
@ -638,7 +571,7 @@ def zip_excel_import_files(
|
|||||||
exceldata = xlsfile.read()
|
exceldata = xlsfile.read()
|
||||||
if not exceldata:
|
if not exceldata:
|
||||||
raise ScoValueError("Fichier excel vide ou invalide")
|
raise ScoValueError("Fichier excel vide ou invalide")
|
||||||
diag, data = sco_excel.Excel_to_list(exceldata)
|
_, data = sco_excel.Excel_to_list(exceldata)
|
||||||
if not data: # probably a bug
|
if not data: # probably a bug
|
||||||
raise ScoValueError("Fichier excel vide !")
|
raise ScoValueError("Fichier excel vide !")
|
||||||
# on doit avoir une colonne etudid et une colonne filename_title ('fichier_photo')
|
# on doit avoir une colonne etudid et une colonne filename_title ('fichier_photo')
|
||||||
@ -657,7 +590,7 @@ def zip_excel_import_files(
|
|||||||
fn = fn.replace("\\", "/") # not sure if this is necessary ?
|
fn = fn.replace("\\", "/") # not sure if this is necessary ?
|
||||||
fn = fn.strip()
|
fn = fn.strip()
|
||||||
if lowercase:
|
if lowercase:
|
||||||
fn = strlower(fn)
|
fn = scu.strlower(fn)
|
||||||
fn = fn.split("/")[-1] # use only last component, not directories
|
fn = fn.split("/")[-1] # use only last component, not directories
|
||||||
return fn
|
return fn
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ from zipfile import ZipFile, BadZipfile
|
|||||||
import xml
|
import xml
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from sco_utils import *
|
|
||||||
import sco_abs
|
import sco_abs
|
||||||
import scolars
|
import scolars
|
||||||
import sco_photos
|
import sco_photos
|
||||||
@ -283,7 +283,7 @@ def pdf_trombino_tours(
|
|||||||
document.build(objects)
|
document.build(objects)
|
||||||
data = report.getvalue()
|
data = report.getvalue()
|
||||||
|
|
||||||
return sendPDFFile(REQUEST, data, filename)
|
return scu.sendPDFFile(REQUEST, data, filename)
|
||||||
|
|
||||||
|
|
||||||
# Feuille d'absences en pdf avec photos:
|
# Feuille d'absences en pdf avec photos:
|
||||||
@ -477,4 +477,4 @@ def pdf_feuille_releve_absences(
|
|||||||
document.build(objects)
|
document.build(objects)
|
||||||
data = report.getvalue()
|
data = report.getvalue()
|
||||||
|
|
||||||
return sendPDFFile(REQUEST, data, filename)
|
return scu.sendPDFFile(REQUEST, data, filename)
|
||||||
|
@ -54,14 +54,17 @@ Solution proposée (nov 2014):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_moduleimpl
|
import sco_moduleimpl
|
||||||
import sco_edit_ue
|
import sco_edit_ue
|
||||||
import sco_saisie_notes
|
import sco_saisie_notes
|
||||||
import sco_codes_parcours
|
import sco_codes_parcours
|
||||||
|
from TrivialFormulator import TrivialFormulator, tf_error_message
|
||||||
|
from sco_permissions import ScoImplement
|
||||||
|
from sco_exceptions import AccessDenied, ScoValueError
|
||||||
|
|
||||||
|
|
||||||
def external_ue_create(
|
def external_ue_create(
|
||||||
@ -69,7 +72,7 @@ def external_ue_create(
|
|||||||
formsemestre_id,
|
formsemestre_id,
|
||||||
titre="",
|
titre="",
|
||||||
acronyme="",
|
acronyme="",
|
||||||
ue_type=UE_STANDARD,
|
ue_type=sco_codes_parcours.UE_STANDARD,
|
||||||
ects=0.0,
|
ects=0.0,
|
||||||
REQUEST=None,
|
REQUEST=None,
|
||||||
):
|
):
|
||||||
@ -162,7 +165,7 @@ def external_ue_inscrit_et_note(
|
|||||||
description="note externe",
|
description="note externe",
|
||||||
)
|
)
|
||||||
# Saisie des notes
|
# Saisie des notes
|
||||||
nbchanged, nbsuppress, existing_decisions = sco_saisie_notes._notes_add(
|
_, _, _ = sco_saisie_notes._notes_add(
|
||||||
context,
|
context,
|
||||||
REQUEST.AUTHENTICATED_USER,
|
REQUEST.AUTHENTICATED_USER,
|
||||||
evaluation_id,
|
evaluation_id,
|
||||||
@ -178,7 +181,7 @@ def get_existing_external_ue(context, formation_id):
|
|||||||
|
|
||||||
def get_external_moduleimpl_id(context, formsemestre_id, ue_id):
|
def get_external_moduleimpl_id(context, formsemestre_id, ue_id):
|
||||||
"moduleimpl correspondant à l'UE externe indiquée de ce formsemestre"
|
"moduleimpl correspondant à l'UE externe indiquée de ce formsemestre"
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"""
|
"""
|
||||||
SELECT moduleimpl_id FROM notes_moduleimpl mi, notes_modules mo
|
SELECT moduleimpl_id FROM notes_moduleimpl mi, notes_modules mo
|
||||||
@ -235,7 +238,7 @@ def external_ue_create_form(context, formsemestre_id, etudid, REQUEST=None):
|
|||||||
parcours = sco_codes_parcours.get_parcours_from_code(Fo["type_parcours"])
|
parcours = sco_codes_parcours.get_parcours_from_code(Fo["type_parcours"])
|
||||||
ue_types = parcours.ALLOWED_UE_TYPES
|
ue_types = parcours.ALLOWED_UE_TYPES
|
||||||
ue_types.sort()
|
ue_types.sort()
|
||||||
ue_types_names = [UE_TYPE_NAME[k] for k in ue_types]
|
ue_types_names = [sco_codes_parcours.UE_TYPE_NAME[k] for k in ue_types]
|
||||||
ue_types = [str(x) for x in ue_types]
|
ue_types = [str(x) for x in ue_types]
|
||||||
|
|
||||||
if existing_external_ue:
|
if existing_external_ue:
|
||||||
|
@ -35,7 +35,7 @@ Pour une évaluation:
|
|||||||
- historique: table notes_notes_log
|
- historique: table notes_notes_log
|
||||||
|
|
||||||
saisie de notes == saisir ou supprimer une ou plusieurs notes (mêmes date et uid)
|
saisie de notes == saisir ou supprimer une ou plusieurs notes (mêmes date et uid)
|
||||||
/!\ tolérance sur les dates (200ms ?)
|
! tolérance sur les dates (200ms ?)
|
||||||
Chaque saisie affecte ou remplace une ou plusieurs notes.
|
Chaque saisie affecte ou remplace une ou plusieurs notes.
|
||||||
|
|
||||||
Opérations:
|
Opérations:
|
||||||
@ -48,12 +48,13 @@ Opérations:
|
|||||||
import datetime
|
import datetime
|
||||||
from intervals import intervalmap
|
from intervals import intervalmap
|
||||||
|
|
||||||
from sco_utils import *
|
import sco_utils as scu
|
||||||
from notesdb import *
|
import notesdb as ndb
|
||||||
from notes_log import log
|
from notes_log import log
|
||||||
from gen_tables import GenTable
|
from gen_tables import GenTable
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
import sco_moduleimpl
|
import sco_moduleimpl
|
||||||
|
import VERSION
|
||||||
|
|
||||||
# deux notes (de même uid) sont considérées comme de la même opération si
|
# deux notes (de même uid) sont considérées comme de la même opération si
|
||||||
# elles sont séparées de moins de 2*tolerance:
|
# elles sont séparées de moins de 2*tolerance:
|
||||||
@ -121,7 +122,7 @@ def list_operations(context, evaluation_id):
|
|||||||
|
|
||||||
Ops = []
|
Ops = []
|
||||||
for uid in NotesDates.keys():
|
for uid in NotesDates.keys():
|
||||||
for (t0, t1), notes in NotesDates[uid].items():
|
for (t0, _), notes in NotesDates[uid].items():
|
||||||
Op = NotesOperation(
|
Op = NotesOperation(
|
||||||
evaluation_id=evaluation_id,
|
evaluation_id=evaluation_id,
|
||||||
date=t0,
|
date=t0,
|
||||||
@ -166,7 +167,7 @@ def formsemestre_list_saisies_notes(
|
|||||||
):
|
):
|
||||||
"""Table listant toutes les operations de saisies de notes, dans toutes les evaluations du semestre."""
|
"""Table listant toutes les operations de saisies de notes, dans toutes les evaluations du semestre."""
|
||||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||||
r = SimpleDictFetch(
|
r = ndb.SimpleDictFetch(
|
||||||
context,
|
context,
|
||||||
"""select i.nom, n.*, mod.titre, e.description, e.jour from notes_notes n, notes_evaluation e, notes_moduleimpl m, notes_modules mod, identite i where m.moduleimpl_id = e.moduleimpl_id and m.module_id = mod.module_id and e.evaluation_id=n.evaluation_id and i.etudid=n.etudid and m.formsemestre_id=%(formsemestre_id)s order by date desc""",
|
"""select i.nom, n.*, mod.titre, e.description, e.jour from notes_notes n, notes_evaluation e, notes_moduleimpl m, notes_modules mod, identite i where m.moduleimpl_id = e.moduleimpl_id and m.module_id = mod.module_id and e.evaluation_id=n.evaluation_id and i.etudid=n.etudid and m.formsemestre_id=%(formsemestre_id)s order by date desc""",
|
||||||
{"formsemestre_id": formsemestre_id},
|
{"formsemestre_id": formsemestre_id},
|
||||||
@ -201,7 +202,7 @@ def formsemestre_list_saisies_notes(
|
|||||||
caption="Saisies de notes dans %s" % sem["titreannee"],
|
caption="Saisies de notes dans %s" % sem["titreannee"],
|
||||||
preferences=context.get_preferences(formsemestre_id),
|
preferences=context.get_preferences(formsemestre_id),
|
||||||
base_url="%s?formsemestre_id=%s" % (REQUEST.URL0, formsemestre_id),
|
base_url="%s?formsemestre_id=%s" % (REQUEST.URL0, formsemestre_id),
|
||||||
origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "",
|
origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "",
|
||||||
)
|
)
|
||||||
return tab.make_page(context, format=format, REQUEST=REQUEST)
|
return tab.make_page(context, format=format, REQUEST=REQUEST)
|
||||||
|
|
||||||
@ -212,7 +213,7 @@ def get_note_history(context, evaluation_id, etudid, REQUEST=None, fmt=""):
|
|||||||
[ { 'value', 'date', 'comment', 'uid' } ]
|
[ { 'value', 'date', 'comment', 'uid' } ]
|
||||||
"""
|
"""
|
||||||
cnx = context.GetDBConnexion()
|
cnx = context.GetDBConnexion()
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
|
|
||||||
# Valeur courante
|
# Valeur courante
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
@ -242,7 +243,7 @@ def get_note_history(context, evaluation_id, etudid, REQUEST=None, fmt=""):
|
|||||||
x["user_name"] = context.Users.user_info(x["uid"])["nomcomplet"]
|
x["user_name"] = context.Users.user_info(x["uid"])["nomcomplet"]
|
||||||
|
|
||||||
if fmt == "json":
|
if fmt == "json":
|
||||||
return sendJSON(REQUEST, history)
|
return scu.sendJSON(REQUEST, history)
|
||||||
else:
|
else:
|
||||||
return history
|
return history
|
||||||
|
|
||||||
|
@ -29,8 +29,11 @@
|
|||||||
""" Verification version logiciel vs version "stable" sur serveur
|
""" Verification version logiciel vs version "stable" sur serveur
|
||||||
N'effectue pas la mise à jour automatiquement, mais permet un affichage d'avertissement.
|
N'effectue pas la mise à jour automatiquement, mais permet un affichage d'avertissement.
|
||||||
"""
|
"""
|
||||||
import sco_utils
|
import datetime
|
||||||
from sco_utils import *
|
import re
|
||||||
|
|
||||||
|
import sco_utils as scu
|
||||||
|
from notes_log import log
|
||||||
|
|
||||||
# Appel renvoyant la subversion "stable"
|
# Appel renvoyant la subversion "stable"
|
||||||
# La notion de "stable" est juste là pour éviter d'afficher trop frequemment
|
# La notion de "stable" est juste là pour éviter d'afficher trop frequemment
|
||||||
@ -46,7 +49,9 @@ def get_last_stable_version():
|
|||||||
(do not wait server answer more than 3 seconds)
|
(do not wait server answer more than 3 seconds)
|
||||||
"""
|
"""
|
||||||
global _LAST_UP_TO_DATE_REQUEST
|
global _LAST_UP_TO_DATE_REQUEST
|
||||||
ans = query_portal(GET_VER_URL, msg="ScoDoc version server", timeout=3) # sco_utils
|
ans = scu.query_portal(
|
||||||
|
GET_VER_URL, msg="ScoDoc version server", timeout=3
|
||||||
|
) # sco_utils
|
||||||
if ans:
|
if ans:
|
||||||
ans = ans.strip()
|
ans = ans.strip()
|
||||||
_LAST_UP_TO_DATE_REQUEST = datetime.datetime.now()
|
_LAST_UP_TO_DATE_REQUEST = datetime.datetime.now()
|
||||||
@ -76,7 +81,7 @@ def is_up_to_date(context):
|
|||||||
# return _UP_TO_DATE, _UP_TO_DATE_MSG
|
# return _UP_TO_DATE, _UP_TO_DATE_MSG
|
||||||
|
|
||||||
# last_stable_ver = get_last_stable_version()
|
# last_stable_ver = get_last_stable_version()
|
||||||
# cur_ver = sco_utils.get_scodoc_version()
|
# cur_ver = scu.get_svn_version(context.file_path) # in sco_utils
|
||||||
# cur_ver2 = cur_ver
|
# cur_ver2 = cur_ver
|
||||||
# cur_ver_num = -1
|
# cur_ver_num = -1
|
||||||
# # Convert versions to integers:
|
# # Convert versions to integers:
|
||||||
|
69
sco_utils.py
69
sco_utils.py
@ -28,30 +28,22 @@
|
|||||||
|
|
||||||
""" Common definitions
|
""" Common definitions
|
||||||
"""
|
"""
|
||||||
import pdb
|
import os
|
||||||
import os, sys, copy, re
|
import sys
|
||||||
import pprint
|
import copy
|
||||||
import traceback
|
import re
|
||||||
from types import (
|
import bisect
|
||||||
StringType,
|
import types
|
||||||
IntType,
|
|
||||||
FloatType,
|
|
||||||
UnicodeType,
|
|
||||||
ListType,
|
|
||||||
TupleType,
|
|
||||||
InstanceType,
|
|
||||||
)
|
|
||||||
import operator, bisect
|
|
||||||
import collections
|
|
||||||
import numbers
|
import numbers
|
||||||
import thread
|
import thread
|
||||||
import urllib
|
|
||||||
import urllib2
|
import urllib2
|
||||||
import socket
|
|
||||||
import xml.sax.saxutils
|
import xml.sax.saxutils
|
||||||
import xml, xml.dom.minidom
|
import time
|
||||||
import time, datetime, cgi
|
import datetime
|
||||||
import mx
|
import json
|
||||||
|
|
||||||
|
# XML generation package (apt-get install jaxml)
|
||||||
|
import jaxml
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import six
|
import six
|
||||||
@ -59,25 +51,16 @@ try:
|
|||||||
STRING_TYPES = six.string_types
|
STRING_TYPES = six.string_types
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# fallback for very old ScoDoc instances
|
# fallback for very old ScoDoc instances
|
||||||
STRING_TYPES = StringType
|
STRING_TYPES = types.StringType
|
||||||
|
|
||||||
from PIL import Image as PILImage
|
from PIL import Image as PILImage
|
||||||
|
|
||||||
# XML generation package (apt-get install jaxml)
|
|
||||||
import jaxml
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
from VERSION import SCOVERSION
|
from VERSION import SCOVERSION
|
||||||
import VERSION
|
import VERSION
|
||||||
|
|
||||||
from SuppressAccents import suppression_diacritics
|
from SuppressAccents import suppression_diacritics
|
||||||
from sco_exceptions import *
|
from notes_log import log
|
||||||
from sco_permissions import *
|
from sco_codes_parcours import NOTES_TOLERANCE, CODES_EXPL
|
||||||
from TrivialFormulator import TrivialFormulator, TF, tf_error_message
|
|
||||||
from notes_log import log, logCallStack
|
|
||||||
|
|
||||||
from sco_codes_parcours import *
|
|
||||||
|
|
||||||
# ----- CALCUL ET PRESENTATION DES NOTES
|
# ----- CALCUL ET PRESENTATION DES NOTES
|
||||||
NOTES_PRECISION = 1e-4 # evite eventuelles erreurs d'arrondis
|
NOTES_PRECISION = 1e-4 # evite eventuelles erreurs d'arrondis
|
||||||
@ -140,7 +123,7 @@ def fmt_note(val, note_max=None, keep_numeric=False):
|
|||||||
return "EXC" # excuse, note neutralise
|
return "EXC" # excuse, note neutralise
|
||||||
if val == NOTES_ATTENTE:
|
if val == NOTES_ATTENTE:
|
||||||
return "ATT" # attente, note neutralisee
|
return "ATT" # attente, note neutralisee
|
||||||
if type(val) == FloatType or type(val) == IntType:
|
if type(val) == types.FloatType or type(val) == types.IntType:
|
||||||
if note_max != None and note_max > 0:
|
if note_max != None and note_max > 0:
|
||||||
val = val * 20.0 / note_max
|
val = val * 20.0 / note_max
|
||||||
if keep_numeric:
|
if keep_numeric:
|
||||||
@ -369,7 +352,7 @@ def unescape_html_dict(d):
|
|||||||
indices = range(len(d))
|
indices = range(len(d))
|
||||||
for k in indices:
|
for k in indices:
|
||||||
v = d[k]
|
v = d[k]
|
||||||
if type(v) == StringType:
|
if type(v) == types.StringType:
|
||||||
d[k] = unescape_html(v)
|
d[k] = unescape_html(v)
|
||||||
elif isiterable(v):
|
elif isiterable(v):
|
||||||
unescape_html_dict(v)
|
unescape_html_dict(v)
|
||||||
@ -414,11 +397,11 @@ def simple_dictlist2xml(dictlist, doc=None, tagname=None, quote=False):
|
|||||||
raise ValueError("invalid empty tagname !")
|
raise ValueError("invalid empty tagname !")
|
||||||
if not doc:
|
if not doc:
|
||||||
doc = jaxml.XML_document(encoding=SCO_ENCODING)
|
doc = jaxml.XML_document(encoding=SCO_ENCODING)
|
||||||
scalar_types = [StringType, UnicodeType, IntType, FloatType]
|
scalar_types = [types.StringType, types.UnicodeType, types.IntType, types.FloatType]
|
||||||
for d in dictlist:
|
for d in dictlist:
|
||||||
doc._push()
|
doc._push()
|
||||||
if (
|
if (
|
||||||
type(d) == InstanceType or type(d) in scalar_types
|
type(d) == types.InstanceType or type(d) in scalar_types
|
||||||
): # pour ApoEtapeVDI et listes de chaines
|
): # pour ApoEtapeVDI et listes de chaines
|
||||||
getattr(doc, tagname)(code=str(d))
|
getattr(doc, tagname)(code=str(d))
|
||||||
else:
|
else:
|
||||||
@ -435,7 +418,7 @@ def simple_dictlist2xml(dictlist, doc=None, tagname=None, quote=False):
|
|||||||
[(k, v) for (k, v) in d.items() if type(v) in scalar_types]
|
[(k, v) for (k, v) in d.items() if type(v) in scalar_types]
|
||||||
)
|
)
|
||||||
getattr(doc, tagname)(**d_scalar)
|
getattr(doc, tagname)(**d_scalar)
|
||||||
d_list = dict([(k, v) for (k, v) in d.items() if type(v) == ListType])
|
d_list = dict([(k, v) for (k, v) in d.items() if type(v) == types.ListType])
|
||||||
if d_list:
|
if d_list:
|
||||||
for (k, v) in d_list.items():
|
for (k, v) in d_list.items():
|
||||||
simple_dictlist2xml(v, doc=doc, tagname=k, quote=quote)
|
simple_dictlist2xml(v, doc=doc, tagname=k, quote=quote)
|
||||||
@ -547,15 +530,15 @@ class ScoDocJSONEncoder(json.JSONEncoder):
|
|||||||
def default(self, o): # pylint: disable=E0202
|
def default(self, o): # pylint: disable=E0202
|
||||||
import sco_formsemestre
|
import sco_formsemestre
|
||||||
|
|
||||||
# horrible hack pour encoder les dates mx
|
# ScoDoc 7.22 n'utilise plus mx:
|
||||||
if str(type(o)) == "<type 'mx.DateTime.DateTime'>":
|
if str(type(o)) == "<type 'mx.DateTime.DateTime'>":
|
||||||
|
log("Warning: mx.DateTime object detected !")
|
||||||
return o.strftime("%Y-%m-%dT%H:%M:%S")
|
return o.strftime("%Y-%m-%dT%H:%M:%S")
|
||||||
if isinstance(o, (datetime.date, datetime.datetime)):
|
if isinstance(o, (datetime.date, datetime.datetime)):
|
||||||
return o.isoformat()
|
return o.isoformat()
|
||||||
elif isinstance(o, sco_formsemestre.ApoEtapeVDI):
|
elif isinstance(o, sco_formsemestre.ApoEtapeVDI):
|
||||||
return str(o)
|
return str(o)
|
||||||
else:
|
else:
|
||||||
log("not mx: %s" % type(o))
|
|
||||||
return json.JSONEncoder.default(self, o)
|
return json.JSONEncoder.default(self, o)
|
||||||
|
|
||||||
|
|
||||||
@ -567,7 +550,7 @@ def sendJSON(REQUEST, data):
|
|||||||
|
|
||||||
|
|
||||||
def sendXML(REQUEST, data, tagname=None, force_outer_xml_tag=True):
|
def sendXML(REQUEST, data, tagname=None, force_outer_xml_tag=True):
|
||||||
if type(data) != ListType:
|
if type(data) != types.ListType:
|
||||||
data = [data] # always list-of-dicts
|
data = [data] # always list-of-dicts
|
||||||
if force_outer_xml_tag:
|
if force_outer_xml_tag:
|
||||||
root_tagname = tagname + "_list"
|
root_tagname = tagname + "_list"
|
||||||
@ -702,7 +685,7 @@ if WITH_PYDOT:
|
|||||||
junk_graph = pydot.Dot("junk")
|
junk_graph = pydot.Dot("junk")
|
||||||
junk_graph.add_node(pydot.Node("a"))
|
junk_graph.add_node(pydot.Node("a"))
|
||||||
n = junk_graph.get_node("a")
|
n = junk_graph.get_node("a")
|
||||||
if type(n) == type([]):
|
if type(n) == type([]): # "modern" pydot
|
||||||
|
|
||||||
def pydot_get_node(g, name):
|
def pydot_get_node(g, name):
|
||||||
r = g.get_node(name)
|
r = g.get_node(name)
|
||||||
@ -711,7 +694,7 @@ if WITH_PYDOT:
|
|||||||
else:
|
else:
|
||||||
return r[0]
|
return r[0]
|
||||||
|
|
||||||
else:
|
else: # very old pydot
|
||||||
|
|
||||||
def pydot_get_node(g, name):
|
def pydot_get_node(g, name):
|
||||||
return g.get_node(name)
|
return g.get_node(name)
|
||||||
@ -757,7 +740,7 @@ def scodoc_html2txt(html):
|
|||||||
|
|
||||||
def is_valid_mail(email):
|
def is_valid_mail(email):
|
||||||
"""True if well-formed email address"""
|
"""True if well-formed email address"""
|
||||||
return re.match("^.+@.+\..{2,3}$", email)
|
return re.match(r"^.+@.+\..{2,3}$", email)
|
||||||
|
|
||||||
|
|
||||||
ICONSIZES = {} # name : (width, height) cache image sizes
|
ICONSIZES = {} # name : (width, height) cache image sizes
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
"""Imports et configuration des composants Zope
|
"""Imports et configuration des composants Zope
|
||||||
"""
|
"""
|
||||||
|
# Avoid pylint warnings when linting without Zope
|
||||||
|
# pylint: skip-file
|
||||||
|
|
||||||
# Allows code linting on platforms without Zope:
|
# Allows code linting on platforms without Zope:
|
||||||
# pylint: disable=import-error
|
# pylint: disable=import-error
|
||||||
|
79
scolars.py
79
scolars.py
@ -98,7 +98,7 @@ def format_etud_ident(etud):
|
|||||||
else:
|
else:
|
||||||
etud["nom_usuel"] = ""
|
etud["nom_usuel"] = ""
|
||||||
etud["prenom"] = format_prenom(etud["prenom"])
|
etud["prenom"] = format_prenom(etud["prenom"])
|
||||||
etud["sexe"] = format_sexe(etud["sexe"])
|
etud["civilite_str"] = format_civilite(etud["civilite"])
|
||||||
# Nom à afficher:
|
# Nom à afficher:
|
||||||
if etud["nom_usuel"]:
|
if etud["nom_usuel"]:
|
||||||
etud["nom_disp"] = etud["nom_usuel"]
|
etud["nom_disp"] = etud["nom_usuel"]
|
||||||
@ -108,10 +108,12 @@ def format_etud_ident(etud):
|
|||||||
etud["nom_disp"] = etud["nom"]
|
etud["nom_disp"] = etud["nom"]
|
||||||
|
|
||||||
etud["nomprenom"] = format_nomprenom(etud) # M. Pierre DUPONT
|
etud["nomprenom"] = format_nomprenom(etud) # M. Pierre DUPONT
|
||||||
if etud["sexe"] == "M.":
|
if etud["civilite"] == "M":
|
||||||
etud["ne"] = ""
|
etud["ne"] = ""
|
||||||
else:
|
elif etud["civilite"] == "F":
|
||||||
etud["ne"] = "e"
|
etud["ne"] = "e"
|
||||||
|
else: # 'X'
|
||||||
|
etud["ne"] = "(e)"
|
||||||
# Mail à utiliser pour les envois vers l'étudiant:
|
# Mail à utiliser pour les envois vers l'étudiant:
|
||||||
# choix qui pourrait être controé par une preference
|
# choix qui pourrait être controé par une preference
|
||||||
# ici priorité au mail institutionnel:
|
# ici priorité au mail institutionnel:
|
||||||
@ -124,15 +126,22 @@ def force_uppercase(s):
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
def format_nomprenom(etud):
|
def format_nomprenom(etud, reverse=False):
|
||||||
"formatte sexe/nom/prenom pour affichages"
|
"""Formatte civilité/nom/prenom pour affichages: "M. Pierre Dupont"
|
||||||
return " ".join(
|
Si reverse, "Dupont Pierre", sans civilité.
|
||||||
[format_sexe(etud["sexe"]), format_prenom(etud["prenom"]), etud["nom_disp"]]
|
"""
|
||||||
)
|
nom = etud.get("nom_disp", "") or etud.get("nom_usuel", "") or etud["nom"]
|
||||||
|
prenom = format_prenom(etud["prenom"])
|
||||||
|
civilite = format_civilite(etud["civilite"])
|
||||||
|
if reverse:
|
||||||
|
fs = [nom, prenom]
|
||||||
|
else:
|
||||||
|
fs = [civilite, prenom, nom]
|
||||||
|
return " ".join([x for x in fs if x])
|
||||||
|
|
||||||
|
|
||||||
def format_prenom(s):
|
def format_prenom(s):
|
||||||
"formatte prenom etudiant pour affichage"
|
"Formatte prenom etudiant pour affichage"
|
||||||
if not s:
|
if not s:
|
||||||
return ""
|
return ""
|
||||||
frags = s.split()
|
frags = s.split()
|
||||||
@ -159,22 +168,33 @@ def format_nom(s, uppercase=True):
|
|||||||
return format_prenom(s)
|
return format_prenom(s)
|
||||||
|
|
||||||
|
|
||||||
def format_sexe(sexe):
|
def input_civilite(s):
|
||||||
sexe = scu.strlower(sexe)
|
"""Converts external representation of civilite to internal:
|
||||||
if sexe == "mr" or sexe == "m." or sexe == "m":
|
'M', 'F', or 'X' (and nothing else).
|
||||||
return "M."
|
Raises valueError if conversion fails.
|
||||||
else:
|
"""
|
||||||
return "Mme"
|
s = scu.strupper(s).strip()
|
||||||
|
if s in ("M", "M.", "MR", "H"):
|
||||||
|
return "M"
|
||||||
|
elif s in ("F", "MLLE", "MLLE.", "MELLE", "MME"):
|
||||||
|
return "F"
|
||||||
|
elif s == "X" or not s:
|
||||||
|
return "X"
|
||||||
|
raise ValueError("valeur invalide pour la civilité: %s" % s)
|
||||||
|
|
||||||
|
|
||||||
def normalize_sexe(sexe):
|
def format_civilite(civilite):
|
||||||
"returns 'MR' ou 'MME'"
|
"""returns 'M.' ou 'Mme' ou '' (pour le genre neutre,
|
||||||
sexe = scu.strupper(sexe).strip()
|
personne ne souhaitant pas d'affichage)
|
||||||
if sexe in ("M.", "M", "MR", "H"):
|
"""
|
||||||
return "MR"
|
try:
|
||||||
elif sexe in ("MLLE", "MLLE.", "MELLE", "MME", "F"):
|
return {
|
||||||
return "MME"
|
"M": "M.",
|
||||||
raise ValueError("valeur invalide pour le sexe: %s" % sexe)
|
"F": "Mme",
|
||||||
|
"X": "",
|
||||||
|
}[civilite]
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError("valeur invalide pour la civilité: %s" % civilite)
|
||||||
|
|
||||||
|
|
||||||
def format_lycee(nomlycee):
|
def format_lycee(nomlycee):
|
||||||
@ -238,7 +258,7 @@ _identiteEditor = EditableTable(
|
|||||||
"nom",
|
"nom",
|
||||||
"nom_usuel",
|
"nom_usuel",
|
||||||
"prenom",
|
"prenom",
|
||||||
"sexe",
|
"civilite", # 'M", "F", or "X"
|
||||||
"date_naissance",
|
"date_naissance",
|
||||||
"lieu_naissance",
|
"lieu_naissance",
|
||||||
"dept_naissance",
|
"dept_naissance",
|
||||||
@ -254,10 +274,10 @@ _identiteEditor = EditableTable(
|
|||||||
input_formators={
|
input_formators={
|
||||||
"nom": force_uppercase,
|
"nom": force_uppercase,
|
||||||
"prenom": force_uppercase,
|
"prenom": force_uppercase,
|
||||||
"sexe": force_uppercase,
|
"civilite": input_civilite,
|
||||||
"date_naissance": DateDMYtoISO,
|
"date_naissance": DateDMYtoISO,
|
||||||
},
|
},
|
||||||
output_formators={"date_naissance": DateISOtoDMY, "sexe": normalize_sexe},
|
output_formators={"date_naissance": DateISOtoDMY},
|
||||||
convert_null_outputs_to_empty=True,
|
convert_null_outputs_to_empty=True,
|
||||||
allow_set_id=True, # car on specifie le code Apogee a la creation
|
allow_set_id=True, # car on specifie le code Apogee a la creation
|
||||||
)
|
)
|
||||||
@ -266,13 +286,14 @@ identite_delete = _identiteEditor.delete
|
|||||||
|
|
||||||
|
|
||||||
def identite_list(cnx, *a, **kw):
|
def identite_list(cnx, *a, **kw):
|
||||||
"list, add 'annee_naissance'"
|
"""List, adding on the fly 'annee_naissance' and 'civilite_str' (M., Mme, "")."""
|
||||||
objs = _identiteEditor.list(cnx, *a, **kw)
|
objs = _identiteEditor.list(cnx, *a, **kw)
|
||||||
for o in objs:
|
for o in objs:
|
||||||
if o["date_naissance"]:
|
if o["date_naissance"]:
|
||||||
o["annee_naissance"] = int(o["date_naissance"].split("/")[2])
|
o["annee_naissance"] = int(o["date_naissance"].split("/")[2])
|
||||||
else:
|
else:
|
||||||
o["annee_naissance"] = o["date_naissance"]
|
o["annee_naissance"] = o["date_naissance"]
|
||||||
|
o["civilite_str"] = format_civilite(o["civilite"])
|
||||||
return objs
|
return objs
|
||||||
|
|
||||||
|
|
||||||
@ -369,7 +390,6 @@ def identite_edit(cnx, args, context=None, REQUEST=None):
|
|||||||
if notify_to:
|
if notify_to:
|
||||||
# etat AVANT edition pour envoyer diffs
|
# etat AVANT edition pour envoyer diffs
|
||||||
before = identite_list(cnx, {"etudid": args["etudid"]})[0]
|
before = identite_list(cnx, {"etudid": args["etudid"]})[0]
|
||||||
before["sexe"] = format_sexe(before["sexe"])
|
|
||||||
|
|
||||||
identite_edit_nocheck(cnx, args)
|
identite_edit_nocheck(cnx, args)
|
||||||
|
|
||||||
@ -377,7 +397,6 @@ def identite_edit(cnx, args, context=None, REQUEST=None):
|
|||||||
if notify_to:
|
if notify_to:
|
||||||
etud = context.getEtudInfo(etudid=args["etudid"], filled=True)[0]
|
etud = context.getEtudInfo(etudid=args["etudid"], filled=True)[0]
|
||||||
after = identite_list(cnx, {"etudid": args["etudid"]})[0]
|
after = identite_list(cnx, {"etudid": args["etudid"]})[0]
|
||||||
after["sexe"] = format_sexe(after["sexe"])
|
|
||||||
notify_etud_change(
|
notify_etud_change(
|
||||||
context,
|
context,
|
||||||
notify_to,
|
notify_to,
|
||||||
@ -409,7 +428,7 @@ def notify_etud_change(context, email_addr, etud, before, after, subject):
|
|||||||
"""
|
"""
|
||||||
txt = [
|
txt = [
|
||||||
"Code NIP:" + etud["code_nip"],
|
"Code NIP:" + etud["code_nip"],
|
||||||
"Genre: " + etud["sexe"],
|
"Civilité: " + etud["civilite_str"],
|
||||||
"Nom: " + etud["nom"],
|
"Nom: " + etud["nom"],
|
||||||
"Prénom: " + etud["prenom"],
|
"Prénom: " + etud["prenom"],
|
||||||
"Etudid: " + etud["etudid"],
|
"Etudid: " + etud["etudid"],
|
||||||
|
14
scolog.py
14
scolog.py
@ -26,9 +26,11 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
|
|
||||||
import pdb, os, sys
|
import pdb
|
||||||
from sco_exceptions import *
|
import os
|
||||||
from notesdb import *
|
import sys
|
||||||
|
|
||||||
|
import notesdb as ndb
|
||||||
from notes_log import retreive_request
|
from notes_log import retreive_request
|
||||||
|
|
||||||
|
|
||||||
@ -46,8 +48,8 @@ def logdb(REQUEST=None, cnx=None, method=None, etudid=None, msg=None, commit=Tru
|
|||||||
else:
|
else:
|
||||||
args = {"authenticated_user": None, "remote_addr": None, "remote_host": None}
|
args = {"authenticated_user": None, "remote_addr": None, "remote_host": None}
|
||||||
args.update({"method": method, "etudid": etudid, "msg": msg})
|
args.update({"method": method, "etudid": etudid, "msg": msg})
|
||||||
quote_dict(args)
|
ndb.quote_dict(args)
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"insert into scolog (authenticated_user,remote_addr,remote_host,method,etudid,msg) values (%(authenticated_user)s,%(remote_addr)s,%(remote_host)s,%(method)s,%(etudid)s,%(msg)s)",
|
"insert into scolog (authenticated_user,remote_addr,remote_host,method,etudid,msg) values (%(authenticated_user)s,%(remote_addr)s,%(remote_host)s,%(method)s,%(etudid)s,%(msg)s)",
|
||||||
args,
|
args,
|
||||||
@ -58,7 +60,7 @@ def logdb(REQUEST=None, cnx=None, method=None, etudid=None, msg=None, commit=Tru
|
|||||||
|
|
||||||
def loglist(cnx, method=None, authenticated_user=None):
|
def loglist(cnx, method=None, authenticated_user=None):
|
||||||
"""List of events logged for these method and user"""
|
"""List of events logged for these method and user"""
|
||||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"select * from scolog where method=%(method)s and authenticated_user=%(authenticated_user)s",
|
"select * from scolog where method=%(method)s and authenticated_user=%(authenticated_user)s",
|
||||||
{"method": method, "authenticated_user": authenticated_user},
|
{"method": method, "authenticated_user": authenticated_user},
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user