- Set -> set

- recapcomplet en JSON
- minor code cleaning.
This commit is contained in:
viennet 2020-12-02 01:00:23 +01:00
parent 317252575a
commit 861c3ad6ca
19 changed files with 249 additions and 224 deletions

View File

@ -116,8 +116,7 @@ def sco_import_format(with_codesemestre=True):
def sco_import_format_dict(with_codesemestre=True): def sco_import_format_dict(with_codesemestre=True):
""" Attribut: { 'type': , 'table', 'allow_nulls' , 'description' } """Attribut: { 'type': , 'table', 'allow_nulls' , 'description' }"""
"""
fmt = sco_import_format(with_codesemestre=with_codesemestre) fmt = sco_import_format(with_codesemestre=with_codesemestre)
R = collections.OrderedDict() R = collections.OrderedDict()
for l in fmt: for l in fmt:
@ -260,7 +259,7 @@ def scolars_import_excel_file(
if not data: # probably a bug if not data: # probably a bug
raise ScoException("scolars_import_excel_file: empty file !") raise ScoException("scolars_import_excel_file: empty file !")
formsemestre_to_invalidate = Set() formsemestre_to_invalidate = set()
# 1- --- check title line # 1- --- check title line
titles = {} titles = {}
@ -555,18 +554,18 @@ def scolars_import_admission(
"""Importe données admission depuis un fichier Excel quelconque """Importe données admission depuis un fichier Excel quelconque
par exemple ceux utilisés avec APB par exemple ceux utilisés avec APB
Cherche dans ce fichier les étudiants qui correspondent à des inscrits du Cherche dans ce fichier les étudiants qui correspondent à des inscrits du
semestre formsemestre_id. semestre formsemestre_id.
Le fichier n'a pas l'INE ni le NIP ni l'etudid, la correspondance se fait Le fichier n'a pas l'INE ni le NIP ni l'etudid, la correspondance se fait
via les noms/prénoms qui doivent être égaux (la casse, les accents et caractères spéciaux via les noms/prénoms qui doivent être égaux (la casse, les accents et caractères spéciaux
étant ignorés). étant ignorés).
On tolère plusieurs variantes pour chaque nom de colonne (ici aussi, la casse, les espaces On tolère plusieurs variantes pour chaque nom de colonne (ici aussi, la casse, les espaces
et les caractères spéciaux sont ignorés. Ainsi, la colonne "Prénom:" sera considéré comme "prenom". et les caractères spéciaux sont ignorés. Ainsi, la colonne "Prénom:" sera considéré comme "prenom".
Le parametre type_admission remplace les valeurs vides (dans la base ET dans le fichier importé) du champ type_admission. Le parametre type_admission remplace les valeurs vides (dans la base ET dans le fichier importé) du champ type_admission.
Si une valeur existe ou est présente dans le fichier importé, ce paramètre est ignoré. Si une valeur existe ou est présente dans le fichier importé, ce paramètre est ignoré.
TODO: TODO:
- choix onglet du classeur - choix onglet du classeur
""" """
@ -611,7 +610,7 @@ def scolars_import_admission(
% formsemestre_id, % formsemestre_id,
) )
modifiable_fields = Set(ADMISSION_MODIFIABLE_FIELDS) modifiable_fields = set(ADMISSION_MODIFIABLE_FIELDS)
nline = 2 # la premiere ligne de donnees du fichier excel est 2 nline = 2 # la premiere ligne de donnees du fichier excel est 2
n_import = 0 n_import = 0
@ -748,8 +747,7 @@ def adm_convert_real(v):
def adm_table_description_format(context): def adm_table_description_format(context):
"""Table HTML (ou autre format) decrivant les donnees d'admissions importables """Table HTML (ou autre format) decrivant les donnees d'admissions importables"""
"""
Fmt = sco_import_format_dict(with_codesemestre=False) Fmt = sco_import_format_dict(with_codesemestre=False)
for k in Fmt: for k in Fmt:
Fmt[k]["attribute"] = k Fmt[k]["attribute"] = k

View File

@ -28,8 +28,6 @@
"""Interface Zope <-> Notes """Interface Zope <-> Notes
""" """
from sets import Set
from sco_zope import * from sco_zope import *
# --------------- # ---------------
@ -2241,7 +2239,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
{"moduleimpl_id": moduleimpl_id}, {"moduleimpl_id": moduleimpl_id},
) )
# Inscriptions au module: # Inscriptions au module:
inmod_set = Set( inmod_set = set(
[ [
x["etudid"] x["etudid"]
for x in self.do_moduleimpl_inscription_list( for x in self.do_moduleimpl_inscription_list(

View File

@ -101,8 +101,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
return self.absolute_url() return self.absolute_url()
def _check_admin_perm(self, REQUEST): def _check_admin_perm(self, REQUEST):
"""Check if user has permission to add/delete departements """Check if user has permission to add/delete departements"""
"""
authuser = REQUEST.AUTHENTICATED_USER authuser = REQUEST.AUTHENTICATED_USER
if authuser.has_role("manager") or authuser.has_permission(ScoSuperAdmin, self): if authuser.has_role("manager") or authuser.has_permission(ScoSuperAdmin, self):
return "" return ""
@ -110,8 +109,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
return """<h2>Vous n'avez pas le droit d'accéder à cette page</h2>""" return """<h2>Vous n'avez pas le droit d'accéder à cette page</h2>"""
def _check_users_folder(self, REQUEST=None): def _check_users_folder(self, REQUEST=None):
"""Vérifie UserFolder et le crée s'il le faut """Vérifie UserFolder et le crée s'il le faut"""
"""
try: try:
udb = self.UsersDB udb = self.UsersDB
return "<!-- uf ok -->" return "<!-- uf ok -->"
@ -127,8 +125,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
security.declareProtected("View", "create_users_folder") security.declareProtected("View", "create_users_folder")
def create_users_folder(self, REQUEST=None): def create_users_folder(self, REQUEST=None):
"""Create Zope user folder """Create Zope user folder"""
"""
e = self._check_admin_perm(REQUEST) e = self._check_admin_perm(REQUEST)
if e: if e:
return e return e
@ -304,8 +301,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
security.declareProtected("View", "delete_dept") security.declareProtected("View", "delete_dept")
def delete_dept(self, REQUEST=None, DeptId="", force=False): def delete_dept(self, REQUEST=None, DeptId="", force=False):
"""Supprime un departement (de Zope seulement, ne touche pas la BD) """Supprime un departement (de Zope seulement, ne touche pas la BD)"""
"""
e = self._check_admin_perm(REQUEST) e = self._check_admin_perm(REQUEST)
if e: if e:
return e return e
@ -373,8 +369,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
security.declareProtected("View", "index_html") security.declareProtected("View", "index_html")
def index_html(self, REQUEST=None, message=None): def index_html(self, REQUEST=None, message=None):
"""Top level page for ScoDoc """Top level page for ScoDoc"""
"""
authuser = REQUEST.AUTHENTICATED_USER authuser = REQUEST.AUTHENTICATED_USER
deptList = self.list_depts() deptList = self.list_depts()
self._fix_users_folder() # fix our exUserFolder self._fix_users_folder() # fix our exUserFolder
@ -825,8 +820,7 @@ subversion: %(svn_version)s
security.declareProtected("View", "scodoc_admin") security.declareProtected("View", "scodoc_admin")
def scodoc_admin(self, REQUEST=None): def scodoc_admin(self, REQUEST=None):
"""Page Operations d'administration """Page Operations d'administration"""
"""
e = self._check_admin_perm(REQUEST) e = self._check_admin_perm(REQUEST)
if e: if e:
return e return e
@ -847,8 +841,8 @@ subversion: %(svn_version)s
] ]
deptList = [x.id for x in self.list_depts()] # definis dans Zope deptList = [x.id for x in self.list_depts()] # definis dans Zope
deptIds = Set(self._list_depts_ids()) # definis sur le filesystem deptIds = set(self._list_depts_ids()) # definis sur le filesystem
existingDepts = Set(deptList) existingDepts = set(deptList)
addableDepts = deptIds - existingDepts addableDepts = deptIds - existingDepts
if not addableDepts: if not addableDepts:

View File

@ -98,7 +98,7 @@ def formsemestre_bulletinetud_dict(
): ):
"""Collecte informations pour bulletin de notes """Collecte informations pour bulletin de notes
Retourne un dictionnaire (avec valeur par défaut chaine vide). Retourne un dictionnaire (avec valeur par défaut chaine vide).
Le contenu du dictionnaire dépend des options (rangs, ...) Le contenu du dictionnaire dépend des options (rangs, ...)
et de la version choisie (short, long, selectedevals). et de la version choisie (short, long, selectedevals).
Cette fonction est utilisée pour les bulletins HTML et PDF, mais pas ceux en XML. Cette fonction est utilisée pour les bulletins HTML et PDF, mais pas ceux en XML.
@ -131,9 +131,11 @@ def formsemestre_bulletinetud_dict(
I["etud"] = context.getEtudInfo(etudid=etudid, filled=1)[0] I["etud"] = context.getEtudInfo(etudid=etudid, filled=1)[0]
I["descr_situation"] = I["etud"]["inscriptionstr"] I["descr_situation"] = I["etud"]["inscriptionstr"]
if I["etud"]["inscription_formsemestre_id"]: if I["etud"]["inscription_formsemestre_id"]:
I["descr_situation_html"] = ( I[
"""<a href="formsemestre_status?formsemestre_id=%s">%s</a>""" "descr_situation_html"
% (I["etud"]["inscription_formsemestre_id"], I["descr_situation"]) ] = """<a href="formsemestre_status?formsemestre_id=%s">%s</a>""" % (
I["etud"]["inscription_formsemestre_id"],
I["descr_situation"],
) )
else: else:
I["descr_situation_html"] = I["descr_situation"] I["descr_situation_html"] = I["descr_situation"]
@ -314,14 +316,13 @@ def formsemestre_bulletinetud_dict(
u["ue_descr_txt"] = "Capitalisée le %s" % DateISOtoDMY( u["ue_descr_txt"] = "Capitalisée le %s" % DateISOtoDMY(
ue_status["event_date"] ue_status["event_date"]
) )
u["ue_descr_html"] = ( u[
'<a href="formsemestre_bulletinetud?formsemestre_id=%s&amp;etudid=%s" title="%s" class="bull_link">%s</a>' "ue_descr_html"
% ( ] = '<a href="formsemestre_bulletinetud?formsemestre_id=%s&amp;etudid=%s" title="%s" class="bull_link">%s</a>' % (
sem_origin["formsemestre_id"], sem_origin["formsemestre_id"],
etudid, etudid,
sem_origin["titreannee"], sem_origin["titreannee"],
u["ue_descr_txt"], u["ue_descr_txt"],
)
) )
# log('cap details %s' % ue_status['moy']) # log('cap details %s' % ue_status['moy'])
if ue_status["moy"] != "NA" and ue_status["formsemestre_id"]: if ue_status["moy"] != "NA" and ue_status["formsemestre_id"]:
@ -539,7 +540,7 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
# Evaluations incomplètes ou futures: # Evaluations incomplètes ou futures:
mod["evaluations_incompletes"] = [] mod["evaluations_incompletes"] = []
if context.get_preference("bul_show_all_evals", formsemestre_id): if context.get_preference("bul_show_all_evals", formsemestre_id):
complete_eval_ids = Set([e["evaluation_id"] for e in evals]) complete_eval_ids = set([e["evaluation_id"] for e in evals])
all_evals = context.do_evaluation_list( all_evals = context.do_evaluation_list(
args={"moduleimpl_id": modimpl["moduleimpl_id"]} args={"moduleimpl_id": modimpl["moduleimpl_id"]}
) )
@ -578,8 +579,7 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
def get_etud_rangs_groups( def get_etud_rangs_groups(
context, etudid, formsemestre_id, partitions, partitions_etud_groups, nt context, etudid, formsemestre_id, partitions, partitions_etud_groups, nt
): ):
"""Ramene rang et nb inscrits dans chaque partition """Ramene rang et nb inscrits dans chaque partition"""
"""
rang_gr, ninscrits_gr, gr_name = {}, {}, {} rang_gr, ninscrits_gr, gr_name = {}, {}, {}
for partition in partitions: for partition in partitions:
if partition["partition_name"] != None: if partition["partition_name"] != None:
@ -616,7 +616,7 @@ def etud_descr_situation_semestre(
situation : chaine résumant en français la situation de l'étudiant. situation : chaine résumant en français la situation de l'étudiant.
Par ex. "Inscrit le 31/12/1999. Décision jury: Validé. ..." Par ex. "Inscrit le 31/12/1999. Décision jury: Validé. ..."
date_inscription : (vide si show_date_inscr est faux) date_inscription : (vide si show_date_inscr est faux)
date_demission : (vide si pas demission ou si show_date_inscr est faux) date_demission : (vide si pas demission ou si show_date_inscr est faux)
descr_inscription : "Inscrit" ou "Pas inscrit[e]" descr_inscription : "Inscrit" ou "Pas inscrit[e]"
@ -820,8 +820,7 @@ def formsemestre_bulletinetud(
def can_send_bulletin_by_mail(context, formsemestre_id, REQUEST): def can_send_bulletin_by_mail(context, formsemestre_id, REQUEST):
"""True if current user is allowed to send a bulletin by mail """True if current user is allowed to send a bulletin by mail"""
"""
authuser = REQUEST.AUTHENTICATED_USER authuser = REQUEST.AUTHENTICATED_USER
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
return ( return (
@ -1177,8 +1176,7 @@ def _formsemestre_bulletinetud_header_html(
def formsemestre_bulletins_choice( def formsemestre_bulletins_choice(
context, REQUEST, formsemestre_id, title="", explanation="", choose_mail=False context, REQUEST, formsemestre_id, title="", explanation="", choose_mail=False
): ):
"""Choix d'une version de bulletin """Choix d'une version de bulletin"""
"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
H = [ H = [
context.html_sem_header(REQUEST, title, sem), context.html_sem_header(REQUEST, title, sem),

View File

@ -273,7 +273,7 @@ def formsemestre_bulletinetud_published_dict(
) )
) )
# Evaluations incomplètes ou futures: # Evaluations incomplètes ou futures:
complete_eval_ids = Set([e["evaluation_id"] for e in evals]) complete_eval_ids = set([e["evaluation_id"] for e in evals])
if context.get_preference("bul_show_all_evals", formsemestre_id): if context.get_preference("bul_show_all_evals", formsemestre_id):
all_evals = context.do_evaluation_list( all_evals = context.do_evaluation_list(
args={"moduleimpl_id": modimpl["moduleimpl_id"]} args={"moduleimpl_id": modimpl["moduleimpl_id"]}

View File

@ -265,7 +265,7 @@ def make_xml_formsemestre_bulletinetud(
doc.note(value=val) doc.note(value=val)
doc._pop() doc._pop()
# Evaluations incomplètes ou futures: # Evaluations incomplètes ou futures:
complete_eval_ids = Set([e["evaluation_id"] for e in evals]) complete_eval_ids = set([e["evaluation_id"] for e in evals])
if context.get_preference("bul_show_all_evals", formsemestre_id): if context.get_preference("bul_show_all_evals", formsemestre_id):
all_evals = context.do_evaluation_list( all_evals = context.do_evaluation_list(
args={"moduleimpl_id": modimpl["moduleimpl_id"]} args={"moduleimpl_id": modimpl["moduleimpl_id"]}

View File

@ -28,7 +28,6 @@
"""Calcul des moyennes de module """Calcul des moyennes de module
""" """
from sets import Set
import traceback import traceback
from sco_utils import * from sco_utils import *
@ -92,8 +91,7 @@ formsemestre_ue_computation_expr_edit = _formsemestre_ue_computation_exprEditor.
def get_ue_expression(formsemestre_id, ue_id, cnx, html_quote=False): def get_ue_expression(formsemestre_id, ue_id, cnx, html_quote=False):
"""Returns UE expression (formula), or None if no expression has been defined """Returns UE expression (formula), or None if no expression has been defined"""
"""
el = formsemestre_ue_computation_expr_list( el = formsemestre_ue_computation_expr_list(
cnx, {"formsemestre_id": formsemestre_id, "ue_id": ue_id} cnx, {"formsemestre_id": formsemestre_id, "ue_id": ue_id}
) )
@ -196,7 +194,7 @@ def do_moduleimpl_moyennes(context, nt, mod):
moduleimpl_id moduleimpl_id
) # tous, y compris demissions ) # tous, y compris demissions
# Inscrits au semestre (pour traiter les demissions): # Inscrits au semestre (pour traiter les demissions):
inssem_set = Set( inssem_set = set(
[ [
x["etudid"] x["etudid"]
for x in context.do_formsemestre_inscription_listinscrits( for x in context.do_formsemestre_inscription_listinscrits(

View File

@ -27,7 +27,6 @@
"""Evaluations """Evaluations
""" """
from sets import Set
from notes_log import log, logCallStack from notes_log import log, logCallStack
from sco_utils import * from sco_utils import *
@ -117,7 +116,7 @@ def do_evaluation_etat(
context, evaluation_id, partition_id=None, select_first_partition=False context, evaluation_id, partition_id=None, select_first_partition=False
): ):
"""donne infos sur l'etat du evaluation """donne infos sur l'etat du evaluation
{ nb_inscrits, nb_notes, nb_abs, nb_neutre, nb_att, { nb_inscrits, nb_notes, nb_abs, nb_neutre, nb_att,
moyenne, mediane, mini, maxi, moyenne, mediane, mini, maxi,
date_last_modif, gr_complets, gr_incomplets, evalcomplete } date_last_modif, gr_complets, gr_incomplets, evalcomplete }
evalcomplete est vrai si l'eval est complete (tous les inscrits evalcomplete est vrai si l'eval est complete (tous les inscrits
@ -176,7 +175,7 @@ def do_evaluation_etat(
# au module (pour gerer les modules optionnels correctement) # au module (pour gerer les modules optionnels correctement)
insem = context.do_formsemestre_inscription_listinscrits(formsemestre_id) insem = context.do_formsemestre_inscription_listinscrits(formsemestre_id)
insmod = context.do_moduleimpl_inscription_list(moduleimpl_id=E["moduleimpl_id"]) insmod = context.do_moduleimpl_inscription_list(moduleimpl_id=E["moduleimpl_id"])
insmodset = Set([x["etudid"] for x in insmod]) insmodset = set([x["etudid"] for x in insmod])
# retire de insem ceux qui ne sont pas inscrits au module # retire de insem ceux qui ne sont pas inscrits au module
ins = [i for i in insem if i["etudid"] in insmodset] ins = [i for i in insem if i["etudid"] in insmodset]
@ -292,50 +291,50 @@ def do_evaluation_etat(
def do_evaluation_list_in_sem(context, formsemestre_id): def do_evaluation_list_in_sem(context, formsemestre_id):
"""Liste les evaluations de tous les modules de ce semestre. """Liste les evaluations de tous les modules de ce semestre.
Donne pour chaque eval son état (voir do_evaluation_etat) Donne pour chaque eval son état (voir do_evaluation_etat)
{ evaluation_id,nb_inscrits, nb_notes, nb_abs, nb_neutre, moy, median, last_modif ... } { evaluation_id,nb_inscrits, nb_notes, nb_abs, nb_neutre, moy, median, last_modif ... }
Exemple: Exemple:
[ { [ {
'coefficient': 1.0, 'coefficient': 1.0,
'description': 'QCM et cas pratiques', 'description': 'QCM et cas pratiques',
'etat': {'evalattente': False, 'etat': {'evalattente': False,
'evalcomplete': True, 'evalcomplete': True,
'evaluation_id': 'GEAEVAL82883', 'evaluation_id': 'GEAEVAL82883',
'gr_incomplets': [], 'gr_incomplets': [],
'gr_moyennes': [{'gr_median': '12.00', 'gr_moyennes': [{'gr_median': '12.00',
'gr_median_num' : 12., 'gr_median_num' : 12.,
'gr_moy': '11.88', 'gr_moy': '11.88',
'gr_moy_num' : 11.88, 'gr_moy_num' : 11.88,
'gr_nb_att': 0, 'gr_nb_att': 0,
'gr_nb_notes': 166, 'gr_nb_notes': 166,
'group_id': 'GEAG266762', 'group_id': 'GEAG266762',
'group_name': None}], 'group_name': None}],
'groups': {'GEAG266762': {'etudid': 'GEAEID80603', 'groups': {'GEAG266762': {'etudid': 'GEAEID80603',
'group_id': 'GEAG266762', 'group_id': 'GEAG266762',
'group_name': None, 'group_name': None,
'partition_id': 'GEAP266761'} 'partition_id': 'GEAP266761'}
}, },
'last_modif': datetime.datetime(2015, 12, 3, 15, 15, 16), 'last_modif': datetime.datetime(2015, 12, 3, 15, 15, 16),
'median': '12.00', 'median': '12.00',
'moy': '11.84', 'moy': '11.84',
'nb_abs': 2, 'nb_abs': 2,
'nb_att': 0, 'nb_att': 0,
'nb_inscrits': 166, 'nb_inscrits': 166,
'nb_neutre': 0, 'nb_neutre': 0,
'nb_notes': 168, 'nb_notes': 168,
'nb_notes_total': 169 'nb_notes_total': 169
}, },
'evaluation_id': 'GEAEVAL82883', 'evaluation_id': 'GEAEVAL82883',
'evaluation_type': 0, 'evaluation_type': 0,
'heure_debut': datetime.time(8, 0), 'heure_debut': datetime.time(8, 0),
'heure_fin': datetime.time(9, 30), 'heure_fin': datetime.time(9, 30),
'jour': datetime.date(2015, 11, 3), // vide => 1/1/1 'jour': datetime.date(2015, 11, 3), // vide => 1/1/1
'moduleimpl_id': 'GEAMIP80490', 'moduleimpl_id': 'GEAMIP80490',
'note_max': 20.0, 'note_max': 20.0,
'numero': 0, 'numero': 0,
'publish_incomplete': 0, 'publish_incomplete': 0,
'visibulletin': 1} ] 'visibulletin': 1} ]
""" """
req = "select E.* from notes_evaluation E, notes_moduleimpl MI where MI.formsemestre_id = %(formsemestre_id)s and MI.moduleimpl_id = E.moduleimpl_id" req = "select E.* from notes_evaluation E, notes_moduleimpl MI where MI.formsemestre_id = %(formsemestre_id)s and MI.moduleimpl_id = E.moduleimpl_id"
@ -410,8 +409,7 @@ def do_evaluation_etat_in_sem(context, formsemestre_id, REQUEST=None):
def do_evaluation_etat_in_mod(context, nt, moduleimpl_id): def do_evaluation_etat_in_mod(context, nt, moduleimpl_id):
""" """"""
"""
evals = nt.get_mod_evaluation_etat_list(moduleimpl_id) evals = nt.get_mod_evaluation_etat_list(moduleimpl_id)
etat = _eval_etat(evals) etat = _eval_etat(evals)
etat["attente"] = moduleimpl_id in [ etat["attente"] = moduleimpl_id in [
@ -522,7 +520,7 @@ def evaluation_date_first_completion(context, evaluation_id):
# au module (pour gerer les modules optionnels correctement) # au module (pour gerer les modules optionnels correctement)
insem = context.do_formsemestre_inscription_listinscrits(formsemestre_id) insem = context.do_formsemestre_inscription_listinscrits(formsemestre_id)
insmod = context.do_moduleimpl_inscription_list(moduleimpl_id=E["moduleimpl_id"]) insmod = context.do_moduleimpl_inscription_list(moduleimpl_id=E["moduleimpl_id"])
insmodset = Set([x["etudid"] for x in insmod]) insmodset = set([x["etudid"] for x in insmod])
# retire de insem ceux qui ne sont pas inscrits au module # retire de insem ceux qui ne sont pas inscrits au module
ins = [i for i in insem if i["etudid"] in insmodset] ins = [i for i in insem if i["etudid"] in insmodset]

View File

@ -28,12 +28,13 @@
"""Opérations d'inscriptions aux semestres et modules """Opérations d'inscriptions aux semestres et modules
""" """
from sco_utils import ScoEtudInscrit, log, ScoValueError, DictDefault
from sco_utils import UE_STANDARD, UE_SPORT, UE_TYPE_NAME
from notesdb import ScoDocCursor, DateISOtoDMY, DateDMYtoISO
from notesdb import *
from sco_utils import *
from notes_log import log
from TrivialFormulator import TrivialFormulator, TF from TrivialFormulator import TrivialFormulator, TF
from notes_table import *
# from notes_table import *
import sco_find_etud import sco_find_etud
import sco_formsemestre import sco_formsemestre
import sco_groups import sco_groups
@ -283,7 +284,7 @@ def formsemestre_inscription_option(context, etudid, formsemestre_id, REQUEST=No
modimpls_by_ue_ids = DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_id ] modimpls_by_ue_ids = DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_id ]
modimpls_by_ue_names = DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_name ] modimpls_by_ue_names = DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_name ]
ues = [] ues = []
ue_ids = Set() ue_ids = set()
initvalues = {} initvalues = {}
for mod in mods: for mod in mods:
ue_id = mod["ue"]["ue_id"] ue_id = mod["ue"]["ue_id"]
@ -402,7 +403,7 @@ function chkbx_select(field_id, state) {
if not insdict.has_key(moduleimpl_id): if not insdict.has_key(moduleimpl_id):
del a_desinscrire[moduleimpl_id] del a_desinscrire[moduleimpl_id]
a_inscrire = Set() a_inscrire = set()
for ue in ues: for ue in ues:
ue_id = ue["ue_id"] ue_id = ue["ue_id"]
a_inscrire.update(tf[2]["moduleimpls_%s" % ue_id]) a_inscrire.update(tf[2]["moduleimpls_%s" % ue_id])
@ -526,7 +527,7 @@ def do_moduleimpl_incription_options(
) )
if not inscr: if not inscr:
raise ScoValueError( raise ScoValueError(
"pas inscrit a ce module ! (etudid=%s, moduleimpl_id=%)" "pas inscrit a ce module ! (etudid=%s, moduleimpl_id=%s)"
% (etudid, moduleimpl_id) % (etudid, moduleimpl_id)
) )
oid = inscr[0]["moduleimpl_inscription_id"] oid = inscr[0]["moduleimpl_inscription_id"]

View File

@ -28,7 +28,6 @@
"""Une classe "vecteur" pour les formules utilisateurs de calcul des moyennes """Une classe "vecteur" pour les formules utilisateurs de calcul des moyennes
""" """
from sets import Set
import operator import operator
import traceback import traceback
from types import FloatType, IntType, LongType, StringType from types import FloatType, IntType, LongType, StringType
@ -174,8 +173,7 @@ formula_builtins = {
def eval_user_expression(context, expression, variables): def eval_user_expression(context, expression, variables):
"""Evalue l'expression (formule utilisateur) avec les variables (dict) données. """Evalue l'expression (formule utilisateur) avec les variables (dict) données."""
"""
variables["__builtins__"] = formula_builtins variables["__builtins__"] = formula_builtins
# log('Evaluating %s with %s' % (expression, variables)) # log('Evaluating %s with %s' % (expression, variables))
# may raise exception if user expression is invalid # may raise exception if user expression is invalid

View File

@ -28,7 +28,6 @@
"""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.
""" """
from sets import Set
from gen_tables import GenTable from gen_tables import GenTable
@ -117,8 +116,7 @@ def list_inscrits(context, formsemestre_id, with_dems=False):
def list_etuds_from_sem(context, src, dst): def list_etuds_from_sem(context, src, dst):
"""Liste des etudiants du semestre src qui sont autorisés à passer dans le semestre dst. """Liste des etudiants du semestre src qui sont autorisés à passer dans le semestre dst."""
"""
target = dst["semestre_id"] target = dst["semestre_id"]
dpv = sco_pvjury.dict_pvjury(context, src["formsemestre_id"]) dpv = sco_pvjury.dict_pvjury(context, src["formsemestre_id"])
if not dpv: if not dpv:
@ -274,7 +272,7 @@ def formsemestre_inscr_passage(
- on peut choisir les groupes TD, TP, TA - on peut choisir les groupes TD, TP, TA
- seuls les etudiants non inscrits changent (de groupe) - seuls les etudiants non inscrits changent (de groupe)
- les etudiants inscrit qui se trouvent décochés sont désinscrits - les etudiants inscrit qui se trouvent décochés sont désinscrits
- Confirmation: indiquer les étudiants inscrits et ceux désinscrits, le total courant. - Confirmation: indiquer les étudiants inscrits et ceux désinscrits, le total courant.
""" """
inscrit_groupes = int(inscrit_groupes) inscrit_groupes = int(inscrit_groupes)
@ -292,11 +290,11 @@ def formsemestre_inscr_passage(
etuds = etuds.split(",") # vient du form de confirmation etuds = etuds.split(",") # vient du form de confirmation
auth_etuds_by_sem, inscrits, candidats = list_authorized_etuds_by_sem(context, sem) auth_etuds_by_sem, inscrits, candidats = list_authorized_etuds_by_sem(context, sem)
etuds_set = Set(etuds) etuds_set = set(etuds)
candidats_set = Set(candidats) candidats_set = set(candidats)
inscrits_set = Set(inscrits) inscrits_set = set(inscrits)
candidats_non_inscrits = candidats_set - inscrits_set candidats_non_inscrits = candidats_set - inscrits_set
inscrits_ailleurs = Set(list_inscrits_date(context, sem)) inscrits_ailleurs = set(list_inscrits_date(context, sem))
def set_to_sorted_etud_list(etudset): def set_to_sorted_etud_list(etudset):
etuds = [candidats[etudid] for etudid in etudset] etuds = [candidats[etudid] for etudid in etudset]
@ -489,7 +487,7 @@ def etuds_select_boxes(
"""Boites pour selection étudiants par catégorie """Boites pour selection étudiants par catégorie
auth_etuds_by_cat = { category : { 'info' : {}, 'etuds' : ... } auth_etuds_by_cat = { category : { 'info' : {}, 'etuds' : ... }
inscrits_ailleurs = inscrits_ailleurs =
sel_inscrits= sel_inscrits=
export_cat_xls = export_cat_xls =
""" """
if export_cat_xls: if export_cat_xls:
@ -619,11 +617,8 @@ 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", "sexe", "nom", "prenom", "etape"]
titles = {} titles = {x: x for x in columns_ids}
map(
lambda x, titles=titles: titles.__setitem__(x[0], x[1]),
zip(columns_ids, columns_ids),
)
# Ajoute colonne paiement inscription # Ajoute colonne paiement inscription
columns_ids.append("paiementinscription_str") columns_ids.append("paiementinscription_str")
titles["paiementinscription_str"] = "paiement inscription" titles["paiementinscription_str"] = "paiement inscription"

View File

@ -41,14 +41,12 @@ import sco_excel
from gen_tables import GenTable from gen_tables import GenTable
from htmlutils import histogram_notes from htmlutils import histogram_notes
from sets import Set
def do_evaluation_listenotes(context, REQUEST): def do_evaluation_listenotes(context, REQUEST):
""" """
Affichage des notes d'une évaluation Affichage des notes d'une évaluation
args: evaluation_id args: evaluation_id
""" """
cnx = context.GetDBConnexion() cnx = context.GetDBConnexion()
mode = None mode = None
@ -267,8 +265,8 @@ def _make_table_notes(
"prenom": "Prénom", "prenom": "Prénom",
"nomprenom": "Nom", "nomprenom": "Nom",
"expl_key": "Rem.", "expl_key": "Rem.",
"email" : "e-mail", "email": "e-mail",
"emailperso" : "e-mail perso" "emailperso": "e-mail perso",
} }
rows = [] rows = []
@ -323,8 +321,8 @@ def _make_table_notes(
"prenom": strcapitalize(strlower(etud["prenom"])), "prenom": strcapitalize(strlower(etud["prenom"])),
"nomprenom": etud["nomprenom"], "nomprenom": etud["nomprenom"],
"group": grc, "group": grc,
"email" : etud["email"], "email": etud["email"],
"emailperso" : etud["emailperso"], "emailperso": etud["emailperso"],
"_css_row_class": css_row_class or "", "_css_row_class": css_row_class or "",
} }
) )
@ -381,7 +379,7 @@ def _make_table_notes(
# Si module, ajoute moyenne du module: # Si module, ajoute moyenne du module:
if len(evals) > 1: if len(evals) > 1:
notes = _add_moymod_column( _add_moymod_column(
context, context,
sem["formsemestre_id"], sem["formsemestre_id"],
e, e,
@ -397,7 +395,7 @@ def _make_table_notes(
# Ajoute colonnes emails tout à droite: # Ajoute colonnes emails tout à droite:
if with_emails: if with_emails:
columns_ids += [ "email", "emailperso" ] columns_ids += ["email", "emailperso"]
# Ajoute lignes en tête et moyennes # Ajoute lignes en tête et moyennes
if len(evals) > 0: if len(evals) > 0:
rows = [coefs, note_max] + rows rows = [coefs, note_max] + rows
@ -646,6 +644,7 @@ def _add_moymod_column(
note_sur_20, note_sur_20,
keep_numeric, keep_numeric,
): ):
"""Ajoute la colonne moymod à rows"""
col_id = "moymod" col_id = "moymod"
nt = context._getNotesCache().get_NotesTable( nt = context._getNotesCache().get_NotesTable(
context, formsemestre_id context, formsemestre_id
@ -701,7 +700,7 @@ def _eval_demijournee(E):
def evaluation_check_absences(context, evaluation_id): def evaluation_check_absences(context, evaluation_id):
"""Vérifie les absences au moment de cette évaluation. """Vérifie les absences au moment de cette évaluation.
Cas incohérents que l'on peut rencontrer pour chaque étudiant: Cas incohérents que l'on peut rencontrer pour chaque étudiant:
note et absent note et absent
ABS et pas noté absent ABS et pas noté absent
ABS et absent justifié ABS et absent justifié
EXC et pas noté absent EXC et pas noté absent
@ -722,13 +721,13 @@ def evaluation_check_absences(context, evaluation_id):
# 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(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(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 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
# Les notes: # Les notes:
NotesDB = context._notes_getall(evaluation_id) NotesDB = context._notes_getall(evaluation_id)
@ -860,8 +859,7 @@ def evaluation_check_absences_html(
def formsemestre_check_absences_html(context, formsemestre_id, REQUEST=None): def formsemestre_check_absences_html(context, formsemestre_id, REQUEST=None):
"""Affiche etat verification absences pour toutes les evaluations du semestre ! """Affiche etat verification absences pour toutes les evaluations du semestre !"""
"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
H = [ H = [
context.html_sem_header( context.html_sem_header(

View File

@ -27,7 +27,6 @@
"""Tableau de bord module """Tableau de bord module
""" """
from sets import Set
from notesdb import * from notesdb import *
from sco_utils import * from sco_utils import *

View File

@ -80,8 +80,7 @@ class DecisionSem:
def SituationEtudParcours(context, etud, formsemestre_id): def SituationEtudParcours(context, etud, formsemestre_id):
"""renvoie une instance de SituationEtudParcours (ou sous-classe spécialisée) """renvoie une instance de SituationEtudParcours (ou sous-classe spécialisée)"""
"""
nt = context._getNotesCache().get_NotesTable( nt = context._getNotesCache().get_NotesTable(
context, formsemestre_id context, formsemestre_id
) # > get_etud_decision_sem, get_etud_moy_gen, get_ues, get_etud_ue_status, etud_check_conditions_ues ) # > get_etud_decision_sem, get_etud_moy_gen, get_ues, get_etud_ue_status, etud_check_conditions_ues
@ -248,7 +247,7 @@ class SituationEtudParcoursGeneric:
decision = self.nt.get_etud_decision_sem(self.etudid) decision = self.nt.get_etud_decision_sem(self.etudid)
return decision and code_semestre_validant(decision["code"]) return decision and code_semestre_validant(decision["code"])
else: else:
to_validate = Set( to_validate = set(
range(1, self.parcours.NB_SEM + 1) range(1, self.parcours.NB_SEM + 1)
) # ensemble des indices à valider ) # ensemble des indices à valider
if exclude_current and self.sem["semestre_id"] in to_validate: if exclude_current and self.sem["semestre_id"] in to_validate:
@ -652,8 +651,7 @@ class SituationEtudParcoursGeneric:
class SituationEtudParcoursECTS(SituationEtudParcoursGeneric): class SituationEtudParcoursECTS(SituationEtudParcoursGeneric):
"""Gestion parcours basés sur ECTS """Gestion parcours basés sur ECTS"""
"""
def __init__(self, context, etud, formsemestre_id, nt): def __init__(self, context, etud, formsemestre_id, nt):
SituationEtudParcoursGeneric.__init__(self, context, etud, formsemestre_id, nt) SituationEtudParcoursGeneric.__init__(self, context, etud, formsemestre_id, nt)
@ -663,7 +661,7 @@ class SituationEtudParcoursECTS(SituationEtudParcoursGeneric):
def get_possible_choices(self, assiduite=True): def get_possible_choices(self, assiduite=True):
"""Listes de décisions "recommandées" (hors décisions manuelles) """Listes de décisions "recommandées" (hors décisions manuelles)
Dans ce type de parcours, on n'utilise que ADM, AJ, et ADJ (?). Dans ce type de parcours, on n'utilise que ADM, AJ, et ADJ (?).
""" """
etud_moy_infos = self.nt.get_etud_moy_infos(self.etudid) etud_moy_infos = self.nt.get_etud_moy_infos(self.etudid)
@ -939,8 +937,7 @@ def do_formsemestre_validate_ue(
semestre_id=None, semestre_id=None,
is_external=0, is_external=0,
): ):
"""Ajoute ou change validation UE """Ajoute ou change validation UE"""
"""
args = { args = {
"formsemestre_id": formsemestre_id, "formsemestre_id": formsemestre_id,
"etudid": etudid, "etudid": etudid,
@ -1026,17 +1023,17 @@ def formsemestre_get_autorisation_inscription(context, etudid, origin_formsemest
def formsemestre_get_etud_capitalisation(context, sem, etudid): def formsemestre_get_etud_capitalisation(context, sem, etudid):
"""Liste des UE capitalisées (ADM) correspondant au semestre sem et à l'étudiant. """Liste des UE capitalisées (ADM) correspondant au semestre sem et à l'étudiant.
Recherche dans les semestres de la même formation (code) avec le même Recherche dans les semestres de la même formation (code) avec le même
semestre_id et une date de début antérieure à celle du semestre mentionné. semestre_id et une date de début antérieure à celle du semestre mentionné.
Et aussi les UE externes validées. Et aussi les UE externes validées.
Resultat: [ { 'formsemestre_id' : Resultat: [ { 'formsemestre_id' :
'ue_id' : ue_id dans le semestre origine 'ue_id' : ue_id dans le semestre origine
'ue_code' : 'ue_code' :
'moy_ue' : 'moy_ue' :
'event_date' : 'event_date' :
'is_external' 'is_external'
} ] } ]
""" """
cnx = context.GetDBConnexion() cnx = context.GetDBConnexion()

View File

@ -28,7 +28,16 @@
"""Liaison avec le portail ENT (qui donne accès aux infos Apogée) """Liaison avec le portail ENT (qui donne accès aux infos Apogée)
""" """
from sco_utils import * import os, time
import urllib
import xml
import xml.sax.saxutils
import xml.dom.minidom
import datetime
import sco_utils
from sco_utils import ScoEtudInscrit, log, ScoValueError, DictDefault
from sco_utils import SCO_TMPDIR, SCO_ENCODING
SCO_CACHE_ETAPE_FILENAME = os.path.join(SCO_TMPDIR, "last_etapes.xml") SCO_CACHE_ETAPE_FILENAME = os.path.join(SCO_TMPDIR, "last_etapes.xml")
@ -153,7 +162,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 = query_portal(req, timeout=actual_timeout) doc = sco_utils.query_portal(req, timeout=actual_timeout)
if doc: if doc:
break break
if not doc: if not doc:
@ -194,7 +203,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 = query_portal(req, timeout=portal_timeout) # sco_utils doc = sco_utils.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)
@ -250,7 +259,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(suppression_diacritics(unom)) nom_noaccents = str(sco_utils.suppression_diacritics(unom))
nom_utf8 = unom.encode("utf-8") nom_utf8 = unom.encode("utf-8")
else: else:
nom_noaccents = nom nom_noaccents = nom
@ -258,7 +267,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(suppression_diacritics(uprenom)) prenom_noaccents = str(sco_utils.suppression_diacritics(uprenom))
prenom_utf8 = uprenom.encode("utf-8") prenom_utf8 = uprenom.encode("utf-8")
else: else:
prenom_noaccents = prenom prenom_noaccents = prenom
@ -314,7 +323,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 = query_portal(req, timeout=portal_timeout) doc = sco_utils.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
@ -378,7 +387,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 = query_portal(etapes_url, timeout=portal_timeout) doc = sco_utils.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)
@ -473,7 +482,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"] = (
strlower(infos["paiementinscription"]) == "true" sco_utils.strlower(infos["paiementinscription"]) == "true"
) )
if infos["paiementinscription"]: if infos["paiementinscription"]:
infos["paiementinscription_str"] = "ok" infos["paiementinscription_str"] = "ok"
@ -508,7 +517,7 @@ def check_paiement_etuds(context, etuds):
Seuls les etudiants avec code NIP sont renseignés. Seuls les etudiants avec code NIP sont renseignés.
Renseigne l'attribut booleen 'paiementinscription' dans chaque etud, ainsi que l'étape. Renseigne l'attribut booleen 'paiementinscription' dans chaque etud.
En sortie: modif les champs de chaque etud En sortie: modif les champs de chaque etud
'paiementinscription' : True, False ou None 'paiementinscription' : True, False ou None
@ -553,5 +562,5 @@ def get_maquette_apogee(context, etape="", annee_scolaire=""):
+ "?" + "?"
+ urllib.urlencode((("etape", etape), ("annee", annee_scolaire))) + urllib.urlencode((("etape", etape), ("annee", annee_scolaire)))
) )
doc = query_portal(req, timeout=portal_timeout) doc = sco_utils.query_portal(req, timeout=portal_timeout)
return doc return doc

View File

@ -35,6 +35,7 @@ import sco_evaluations
import sco_formsemestre import sco_formsemestre
import sco_formsemestre_status import sco_formsemestre_status
import sco_bulletins_xml import sco_bulletins_xml
import sco_bulletins_json
import sco_codes_parcours import sco_codes_parcours
import sco_bac import sco_bac
@ -71,7 +72,7 @@ def formsemestre_recapcomplet(
else: else:
hidebac = int(hidebac) hidebac = int(hidebac)
xml_with_decisions = int(xml_with_decisions) xml_with_decisions = int(xml_with_decisions)
isFile = tabformat in ("csv", "xls", "xml", "xlsall") isFile = tabformat in ("csv", "xls", "xml", "xlsall", "json")
H = [] H = []
if not isFile: if not isFile:
H += [ H += [
@ -103,6 +104,7 @@ def formsemestre_recapcomplet(
("xlsall", "Fichier tableur avec toutes les évals"), ("xlsall", "Fichier tableur avec toutes les évals"),
("csv", "Fichier tableur (CSV)"), ("csv", "Fichier tableur (CSV)"),
("xml", "Fichier XML"), ("xml", "Fichier XML"),
("json", "JSON"),
): ):
if format == tabformat: if format == tabformat:
selected = " selected" selected = " selected"
@ -129,8 +131,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", "text/xml") REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE)
H.append( H.append(
do_formsemestre_recapcomplet( do_formsemestre_recapcomplet(
context, context,
@ -181,7 +182,7 @@ def do_formsemestre_recapcomplet(
context=None, context=None,
REQUEST=None, REQUEST=None,
formsemestre_id=None, formsemestre_id=None,
format="html", # html, xml, xls, xlsall format="html", # html, xml, xls, xlsall, json
hidemodules=False, # ne pas montrer les modules (ignoré en XML) hidemodules=False, # ne pas montrer les modules (ignoré en XML)
hidebac=False, # pas de colonne Bac (ignoré en XML) hidebac=False, # pas de colonne Bac (ignoré en XML)
xml_nodate=False, # format XML sans dates (sert pour debug cache: comparaison de XML) xml_nodate=False, # format XML sans dates (sert pour debug cache: comparaison de XML)
@ -191,8 +192,7 @@ def do_formsemestre_recapcomplet(
disable_etudlink=False, disable_etudlink=False,
rank_partition_id=None, # si None, calcul rang global rank_partition_id=None, # si None, calcul rang global
): ):
"""Calcule et renvoie le tableau récapitulatif. """Calcule et renvoie le tableau récapitulatif."""
"""
data, filename, format = make_formsemestre_recapcomplet(**vars()) data, filename, format = make_formsemestre_recapcomplet(**vars())
if format == "xml" or format == "html": if format == "xml" or format == "html":
return data return data
@ -200,6 +200,8 @@ def do_formsemestre_recapcomplet(
return sendCSVFile(REQUEST, data, filename) return 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":
return sendJSON(REQUEST, data)
else: else:
raise ValueError("unknown format %s" % format) raise ValueError("unknown format %s" % format)
@ -208,7 +210,7 @@ def make_formsemestre_recapcomplet(
context=None, context=None,
REQUEST=None, REQUEST=None,
formsemestre_id=None, formsemestre_id=None,
format="html", # html, xml, xls, xlsall format="html", # html, xml, xls, xlsall, json
hidemodules=False, # ne pas montrer les modules (ignoré en XML) hidemodules=False, # ne pas montrer les modules (ignoré en XML)
hidebac=False, # pas de colonne Bac (ignoré en XML) hidebac=False, # pas de colonne Bac (ignoré en XML)
xml_nodate=False, # format XML sans dates (sert pour debug cache: comparaison de XML) xml_nodate=False, # format XML sans dates (sert pour debug cache: comparaison de XML)
@ -226,6 +228,10 @@ def make_formsemestre_recapcomplet(
return _formsemestre_recapcomplet_xml( return _formsemestre_recapcomplet_xml(
context, formsemestre_id, xml_nodate, xml_with_decisions=xml_with_decisions context, formsemestre_id, xml_nodate, xml_with_decisions=xml_with_decisions
) )
elif format == "json":
return _formsemestre_recapcomplet_json(
context, formsemestre_id, xml_nodate, xml_with_decisions=xml_with_decisions
)
if format[:3] == "xls": if format[:3] == "xls":
keep_numeric = True # pas de conversion des notes en strings keep_numeric = True # pas de conversion des notes en strings
else: else:
@ -261,7 +267,7 @@ def make_formsemestre_recapcomplet(
else: else:
rank_partition = sco_groups.get_default_partition(context, formsemestre_id) rank_partition = sco_groups.get_default_partition(context, formsemestre_id)
rank_label = "Rg" rank_label = "Rg"
T = nt.get_table_moyennes_triees() T = nt.get_table_moyennes_triees()
if not T: if not T:
return "", "", format return "", "", format
@ -556,19 +562,18 @@ def make_formsemestre_recapcomplet(
cls = "recap_tit_ue" cls = "recap_tit_ue"
else: else:
cls = "recap_tit" cls = "recap_tit"
if i == 0 or F[0][i] == "classement": # Rang: force tri numerique pour sortable if (
i == 0 or F[0][i] == "classement"
): # Rang: force tri numerique pour sortable
cls = cls + " sortnumeric" cls = cls + " sortnumeric"
if cod2mod.has_key(F[0][i]): # lien vers etat module if cod2mod.has_key(F[0][i]): # lien vers etat module
mod = cod2mod[F[0][i]] mod = cod2mod[F[0][i]]
cells += ( cells += '<td class="%s"><a href="moduleimpl_status?moduleimpl_id=%s" title="%s (%s)">%s</a></td>' % (
'<td class="%s"><a href="moduleimpl_status?moduleimpl_id=%s" title="%s (%s)">%s</a></td>' cls,
% ( mod["moduleimpl_id"],
cls, mod["module"]["titre"],
mod["moduleimpl_id"], context.Users.user_info(mod["responsable_id"])["nomcomplet"],
mod["module"]["titre"], F[0][i],
context.Users.user_info(mod["responsable_id"])["nomcomplet"],
F[0][i],
)
) )
else: else:
cells += '<td class="%s">%s</td>' % (cls, F[0][i]) cells += '<td class="%s">%s</td>' % (cls, F[0][i])
@ -788,8 +793,7 @@ def _list_notes_evals_stats(context, evals, key):
def _formsemestre_recapcomplet_xml( def _formsemestre_recapcomplet_xml(
context, formsemestre_id, xml_nodate, xml_with_decisions=False context, formsemestre_id, xml_nodate, xml_with_decisions=False
): ):
"XML export: liste tous les bulletins XML" "XML export: liste tous les bulletins XML."
# REQUEST.RESPONSE.setHeader('content-type', XML_MIMETYPE)
nt = context._getNotesCache().get_NotesTable( nt = context._getNotesCache().get_NotesTable(
context, formsemestre_id context, formsemestre_id
@ -827,3 +831,42 @@ def _formsemestre_recapcomplet_xml(
) )
doc._pop() doc._pop()
return repr(doc), "", "xml" return repr(doc), "", "xml"
def _formsemestre_recapcomplet_json(
context, formsemestre_id, xml_nodate, xml_with_decisions=False
):
"JSON export: liste tous les bulletins JSON"
if xml_nodate:
docdate = ""
else:
docdate = datetime.datetime.now().isoformat()
evals = sco_evaluations.do_evaluation_etat_in_sem(context, formsemestre_id)
J = {
"docdate": docdate,
"formsemestre_id": formsemestre_id,
"evals_info": {
"nb_evals_completes": evals["nb_evals_completes"],
"nb_evals_en_cours": evals["nb_evals_en_cours"],
"nb_evals_vides": evals["nb_evals_vides"],
"date_derniere_note": evals["last_modif"],
},
"bulletins": [],
}
bulletins = J["bulletins"]
nt = context._getNotesCache().get_NotesTable(
context, formsemestre_id
) # > get_table_moyennes_triees
T = nt.get_table_moyennes_triees()
for t in T:
etudid = t[-1]
bulletins.append(
sco_bulletins_json.formsemestre_bulletinetud_published_dict(
context,
formsemestre_id,
etudid,
force_publishing=True,
xml_with_decisions=xml_with_decisions,
)
)
return J, "", "json"

View File

@ -29,8 +29,8 @@
- statistiques decisions - statistiques decisions
- suivi cohortes - suivi cohortes
""" """
from mx.DateTime import DateTime as mxDateTime
import mx.DateTime import mx.DateTime
from mx.DateTime import DateTime as mxDateTime
import tempfile, urllib, re import tempfile, urllib, re
@ -396,12 +396,12 @@ def table_suivi_cohorte(
logt("A: orig etuds set") logt("A: orig etuds set")
S = {formsemestre_id: sem} # ensemble de formsemestre_id S = {formsemestre_id: sem} # ensemble de formsemestre_id
orig_set = Set() # ensemble d'etudid du semestre d'origine orig_set = set() # ensemble d'etudid du semestre d'origine
bacs = Set() bacs = set()
bacspecialites = Set() bacspecialites = set()
annee_bacs = Set() annee_bacs = set()
sexes = Set() sexes = 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]
bacspe = etud["bac"] + " / " + etud["specialite"] bacspe = etud["bac"] + " / " + etud["specialite"]
@ -429,7 +429,7 @@ def table_suivi_cohorte(
# 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) s["date_debut_mx"] = mxDateTime(y, m, d) # pylint: disable=not-callable
sems.sort(lambda x, y: cmp(x["date_debut_mx"], y["date_debut_mx"])) sems.sort(lambda x, y: cmp(x["date_debut_mx"], y["date_debut_mx"]))
# 2-- Pour chaque semestre, trouve l'ensemble des etudiants venant de sem # 2-- Pour chaque semestre, trouve l'ensemble des etudiants venant de sem
@ -439,7 +439,7 @@ def table_suivi_cohorte(
ins = context.do_formsemestre_inscription_list( ins = context.do_formsemestre_inscription_list(
args={"formsemestre_id": s["formsemestre_id"]} args={"formsemestre_id": s["formsemestre_id"]}
) # sans dems ) # sans dems
inset = Set([i["etudid"] for i in ins]) inset = set([i["etudid"] for i in ins])
s["members"] = orig_set.intersection(inset) s["members"] = orig_set.intersection(inset)
nb_dipl = 0 # combien de diplomes dans ce semestre ? nb_dipl = 0 # combien de diplomes dans ce semestre ?
if s["semestre_id"] == nt.parcours.NB_SEM: if s["semestre_id"] == nt.parcours.NB_SEM:
@ -461,7 +461,7 @@ 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) porigin.datedebut = mxDateTime(y, m, d) # pylint: disable=not-callable
porigin.sems = [sem] porigin.sems = [sem]
# #
@ -480,7 +480,7 @@ def table_suivi_cohorte(
P.append(p) P.append(p)
# 4-- regroupe par indice de semestre S_i # 4-- regroupe par indice de semestre S_i
indices_sems = list(Set([s["semestre_id"] for s in sems])) indices_sems = list(set([s["semestre_id"] for s in sems]))
indices_sems.sort() indices_sems.sort()
for p in P: for p in P:
p.nb_etuds = 0 # nombre total d'etudiants dans la periode p.nb_etuds = 0 # nombre total d'etudiants dans la periode
@ -518,7 +518,7 @@ def table_suivi_cohorte(
d = {"row_title": "Autre semestre"} d = {"row_title": "Autre semestre"}
for p in P: for p in P:
etuds_period = Set() etuds_period = set()
for s in p.sems: for s in p.sems:
if s["semestre_id"] == idx_sem: if s["semestre_id"] == idx_sem:
etuds_period = etuds_period.union(s["members"]) etuds_period = etuds_period.union(s["members"])
@ -533,8 +533,8 @@ def table_suivi_cohorte(
logt("D: cout dems reos") logt("D: cout dems reos")
sem["dems"], sem["reos"] = _count_dem_reo(context, formsemestre_id, sem["members"]) sem["dems"], sem["reos"] = _count_dem_reo(context, formsemestre_id, sem["members"])
for p in P: for p in P:
p.dems = Set() p.dems = set()
p.reos = Set() p.reos = set()
for s in p.sems: for s in p.sems:
d, r = _count_dem_reo(context, s["formsemestre_id"], s["members"]) d, r = _count_dem_reo(context, s["formsemestre_id"], s["members"])
p.dems.update(d) p.dems.update(d)
@ -879,8 +879,8 @@ def _count_dem_reo(context, formsemestre_id, etudids):
nt = context._getNotesCache().get_NotesTable( nt = context._getNotesCache().get_NotesTable(
context, formsemestre_id context, formsemestre_id
) # > get_etud_etat, get_etud_decision_sem ) # > get_etud_etat, get_etud_decision_sem
dems = Set() dems = set()
reos = Set() reos = set()
for etudid in etudids: for etudid in etudids:
if nt.get_etud_etat(etudid) == "D": if nt.get_etud_etat(etudid) == "D":
dems.add(etudid) dems.add(etudid)
@ -994,11 +994,11 @@ def tsp_etud_list(
) # > get_etudids, ) # > get_etudids,
etudids = nt.get_etudids() etudids = nt.get_etudids()
etuds = [] etuds = []
bacs = Set() bacs = set()
bacspecialites = Set() bacspecialites = set()
annee_bacs = Set() annee_bacs = set()
sexes = Set() sexes = 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]
bacspe = etud["bac"] + " / " + etud["specialite"] bacspe = etud["bac"] + " / " + etud["specialite"]
@ -1228,25 +1228,25 @@ def graph_parcours(
if not etuds: if not etuds:
return "", etuds, bacs, bacspecialites, annee_bacs, sexes, statuts return "", etuds, bacs, bacspecialites, annee_bacs, sexes, statuts
edges = DictDefault( edges = DictDefault(
defaultvalue=Set() defaultvalue=set()
) # {(formsemestre_id_origin, formsemestre_id_dest) : etud_set} ) # {(formsemestre_id_origin, formsemestre_id_dest) : etud_set}
sems = {} sems = {}
effectifs = DictDefault(defaultvalue=Set()) # formsemestre_id : etud_set effectifs = DictDefault(defaultvalue=set()) # formsemestre_id : etud_set
decisions = DictDefault(defaultvalue={}) # formsemestre_id : { code : nb_etud } decisions = DictDefault(defaultvalue={}) # formsemestre_id : { code : nb_etud }
isolated_nodes = [] isolated_nodes = []
connected_nodes = Set() connected_nodes = set()
diploma_nodes = [] diploma_nodes = []
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:
next = None nxt = None
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(
context, s["formsemestre_id"] context, s["formsemestre_id"]
) # > get_etud_decision_sem, get_etud_etat ) # > get_etud_decision_sem, get_etud_etat
dec = nt.get_etud_decision_sem(etudid) dec = nt.get_etud_decision_sem(etudid)
if next: if nxt:
if ( if (
s["semestre_id"] == nt.parcours.NB_SEM s["semestre_id"] == nt.parcours.NB_SEM
and dec and dec
@ -1255,17 +1255,17 @@ def graph_parcours(
): ):
# cas particulier du diplome puis poursuite etude # cas particulier du diplome puis poursuite etude
edges[ edges[
("_dipl_" + s["formsemestre_id"], next["formsemestre_id"]) ("_dipl_" + s["formsemestre_id"], nxt["formsemestre_id"])
].add(etudid) ].add(etudid)
else: else:
edges[(s["formsemestre_id"], next["formsemestre_id"])].add(etudid) edges[(s["formsemestre_id"], nxt["formsemestre_id"])].add(etudid)
connected_nodes.add(s["formsemestre_id"]) connected_nodes.add(s["formsemestre_id"])
connected_nodes.add(next["formsemestre_id"]) connected_nodes.add(nxt["formsemestre_id"])
else: else:
isolated_nodes.append(s["formsemestre_id"]) isolated_nodes.append(s["formsemestre_id"])
sems[s["formsemestre_id"]] = s sems[s["formsemestre_id"]] = s
effectifs[s["formsemestre_id"]].add(etudid) effectifs[s["formsemestre_id"]].add(etudid)
next = s nxt = s
# Compte decisions jury de chaque semestres: # Compte decisions jury de chaque semestres:
dc = decisions[s["formsemestre_id"]] dc = decisions[s["formsemestre_id"]]
if dec: if dec:

View File

@ -29,8 +29,8 @@
""" """
from sco_utils import * from sco_utils import ScoEtudInscrit, annee_scolaire_debut, log, ScoValueError
from notesdb import * from notesdb import ScoDocCursor
import sco_portal_apogee import sco_portal_apogee
import sco_inscr_passage import sco_inscr_passage
@ -698,7 +698,7 @@ def do_import_etud_admission(
log("do_import_etud_admission: etud=%s" % etud) log("do_import_etud_admission: etud=%s" % etud)
al = scolars.admission_list(cnx, args={"etudid": etudid}) al = scolars.admission_list(cnx, args={"etudid": etudid})
if not al: if not al:
adm_id = scolars.admission_create(cnx, args) scolars.admission_create(cnx, args) # -> adm_id
else: else:
# existing data: merge # existing data: merge
e = al[0] e = al[0]

View File

@ -61,8 +61,6 @@ except ImportError:
# fallback for very old ScoDoc instances # fallback for very old ScoDoc instances
STRING_TYPES = StringType STRING_TYPES = StringType
from sets import Set
from PIL import Image as PILImage from PIL import Image as PILImage
# XML generation package (apt-get install jaxml) # XML generation package (apt-get install jaxml)
@ -215,6 +213,7 @@ if SCO_SRCDIR:
SCO_SRCDIR += "/" SCO_SRCDIR += "/"
else: else:
SCO_SRCDIR = "/opt/scodoc/Products/ScoDoc/" # debug mode SCO_SRCDIR = "/opt/scodoc/Products/ScoDoc/" # debug mode
CONFIG = None
try: try:
_config_filename = SCO_SRCDIR + "config/scodoc_config.py" _config_filename = SCO_SRCDIR + "config/scodoc_config.py"
_config_text = open(_config_filename).read() _config_text = open(_config_filename).read()
@ -512,7 +511,7 @@ def make_filename(name):
VALID_CARS = ( VALID_CARS = (
"-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.!" # no / ! "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.!" # no / !
) )
VALID_CARS_SET = Set(VALID_CARS) VALID_CARS_SET = set(VALID_CARS)
VALID_EXP = re.compile("^[" + VALID_CARS + "]+$") VALID_EXP = re.compile("^[" + VALID_CARS + "]+$")
@ -558,12 +557,14 @@ def sendPDFFile(REQUEST, data, filename):
class ScoDocJSONEncoder(json.JSONEncoder): class ScoDocJSONEncoder(json.JSONEncoder):
def default(self, o): def default(self, o): # pylint: disable=E0202
import sco_formsemestre import sco_formsemestre
# horrible hack pour encoder les dates # horrible hack pour encoder les dates mx
if str(type(o)) == "<type 'mx.DateTime.DateTime'>": if str(type(o)) == "<type 'mx.DateTime.DateTime'>":
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)):
return o.isoformat()
elif isinstance(o, sco_formsemestre.ApoEtapeVDI): elif isinstance(o, sco_formsemestre.ApoEtapeVDI):
return str(o) return str(o)
else: else: