Up-to-date with 7.20a
This commit is contained in:
commit
aec2d58dbf
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
# SCODOC - gestion de la scolarité
|
||||
|
||||
(c) Emmanuel Viennet 1999 - 2020 (voir LICENCE.txt)
|
||||
(c) Emmanuel Viennet 1999 - 2021 (voir LICENCE.txt)
|
||||
|
||||
|
||||
Installation: voir instructions à jour sur <https://scodoc.org>
|
||||
|
@ -8,6 +8,7 @@ SCONAME = "ScoDoc"
|
||||
SCONEWS = """
|
||||
<h4>Année 2020</h4>
|
||||
<ul>
|
||||
<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>Enregistrement de semestres extérieurs</li>
|
||||
<li>Améliorations PV de Jury</li>
|
||||
|
265
ZAbsences.py
265
ZAbsences.py
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -45,17 +45,20 @@ L'API de plus bas niveau est en gros:
|
||||
"""
|
||||
|
||||
import urllib
|
||||
import datetime
|
||||
import jaxml
|
||||
import cgi
|
||||
|
||||
# ---------------
|
||||
from sco_zope import *
|
||||
|
||||
# ---------------
|
||||
|
||||
from notesdb import *
|
||||
import sco_utils as scu
|
||||
import notesdb
|
||||
from notes_log import log
|
||||
from scolog import logdb
|
||||
from sco_utils import *
|
||||
|
||||
# import notes_users
|
||||
from sco_permissions import ScoAbsAddBillet, ScoAbsChange, ScoView
|
||||
from sco_exceptions import ScoValueError, ScoInvalidDateError
|
||||
from TrivialFormulator import TrivialFormulator, TF
|
||||
from gen_tables import GenTable
|
||||
import scolars
|
||||
@ -201,7 +204,7 @@ class ddmmyyyy:
|
||||
return self.prev(self.weekday)
|
||||
|
||||
def __cmp__(self, other):
|
||||
"""return a negative integer if self < other,
|
||||
"""return a negative integer if self < other,
|
||||
zero if self == other, a positive integer if self > other"""
|
||||
return int(self.time - other.time)
|
||||
|
||||
@ -356,7 +359,7 @@ class ZAbsences(
|
||||
estjust = _toboolean(estjust)
|
||||
matin = _toboolean(matin)
|
||||
cnx = self.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
cursor.execute(
|
||||
"insert into absences (etudid,jour,estabs,estjust,matin,description, moduleimpl_id) values (%(etudid)s, %(jour)s, TRUE, %(estjust)s, %(matin)s, %(description)s, %(moduleimpl_id)s )",
|
||||
vars(),
|
||||
@ -380,7 +383,7 @@ class ZAbsences(
|
||||
raise ScoValueError("date justificatif trop loin dans le futur !")
|
||||
matin = _toboolean(matin)
|
||||
cnx = self.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
cursor.execute(
|
||||
"insert into absences (etudid,jour,estabs,estjust,matin, description) values (%(etudid)s,%(jour)s, FALSE, TRUE, %(matin)s, %(description)s )",
|
||||
vars(),
|
||||
@ -402,7 +405,7 @@ class ZAbsences(
|
||||
# unpublished
|
||||
matin = _toboolean(matin)
|
||||
cnx = self.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
req = "delete from absences where jour=%(jour)s and matin=%(matin)s and etudid=%(etudid)s and estabs"
|
||||
if moduleimpl_id:
|
||||
req += " and moduleimpl_id=%(moduleimpl_id)s"
|
||||
@ -423,7 +426,7 @@ class ZAbsences(
|
||||
# unpublished
|
||||
matin = _toboolean(matin)
|
||||
cnx = self.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
cursor.execute(
|
||||
"delete from absences where jour=%(jour)s and matin=%(matin)s and etudid=%(etudid)s and ESTJUST AND NOT ESTABS",
|
||||
vars(),
|
||||
@ -450,7 +453,7 @@ class ZAbsences(
|
||||
# """
|
||||
# # unpublished
|
||||
# cnx = self.GetDBConnexion()
|
||||
# cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
# cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
# # supr les absences non justifiees
|
||||
# cursor.execute("delete from absences where etudid=%(etudid)s and (not estjust) and moduleimpl_id=(moduleimpl_id)s and jour BETWEEN %(datedebut)s AND %(datefin)s",
|
||||
# vars() )
|
||||
@ -487,7 +490,7 @@ class ZAbsences(
|
||||
self._AnnuleAbsence(etudid, jour, matin, moduleimpl_id, REQUEST)
|
||||
return
|
||||
cnx = self.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
# supr les absences non justifiees
|
||||
for date in dates:
|
||||
cursor.execute(
|
||||
@ -534,7 +537,7 @@ class ZAbsences(
|
||||
else:
|
||||
modul = ""
|
||||
cnx = self.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
cursor.execute(
|
||||
"""SELECT COUNT(*) AS NbAbs FROM (
|
||||
SELECT DISTINCT A.JOUR, A.MATIN
|
||||
@ -565,7 +568,7 @@ class ZAbsences(
|
||||
else:
|
||||
modul = ""
|
||||
cnx = self.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
cursor.execute(
|
||||
"""SELECT COUNT(*) AS NbAbsJust FROM (
|
||||
SELECT DISTINCT A.JOUR, A.MATIN
|
||||
@ -588,7 +591,7 @@ class ZAbsences(
|
||||
def _ListeAbsDate(self, etudid, beg_date, end_date):
|
||||
# Liste des absences et justifs entre deux dates
|
||||
cnx = self.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
cursor.execute(
|
||||
"""SELECT jour, matin, estabs, estjust, description FROM ABSENCES A
|
||||
WHERE A.ETUDID = %(etudid)s
|
||||
@ -598,7 +601,6 @@ class ZAbsences(
|
||||
vars(),
|
||||
)
|
||||
Abs = cursor.dictfetchall()
|
||||
# log('ListeAbsDate: abs=%s' % Abs)
|
||||
# remove duplicates
|
||||
A = {} # { (jour, matin) : abs }
|
||||
for a in Abs:
|
||||
@ -625,7 +627,6 @@ class ZAbsences(
|
||||
# sort
|
||||
R = A.values()
|
||||
R.sort(key=lambda x: (x["begin"]))
|
||||
# log('R=%s' % R)
|
||||
return R
|
||||
|
||||
security.declareProtected(ScoView, "ListeAbsJust")
|
||||
@ -633,7 +634,7 @@ class ZAbsences(
|
||||
def ListeAbsJust(self, etudid, datedebut):
|
||||
"Liste des absences justifiees (par ordre chronologique)"
|
||||
cnx = self.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
cursor.execute(
|
||||
"""SELECT DISTINCT A.ETUDID, A.JOUR, A.MATIN FROM ABSENCES A, ABSENCES B
|
||||
WHERE A.ETUDID = %(etudid)s
|
||||
@ -654,7 +655,7 @@ class ZAbsences(
|
||||
def ListeAbsNonJust(self, etudid, datedebut):
|
||||
"Liste des absences NON justifiees (par ordre chronologique)"
|
||||
cnx = self.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
cursor.execute(
|
||||
"""SELECT ETUDID, JOUR, MATIN FROM ABSENCES A
|
||||
WHERE A.ETUDID = %(etudid)s
|
||||
@ -680,7 +681,7 @@ class ZAbsences(
|
||||
Si only_no_abs: seulement les justificatifs correspondant aux jours sans absences relevées.
|
||||
"""
|
||||
cnx = self.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
req = """SELECT DISTINCT ETUDID, JOUR, MATIN FROM ABSENCES A
|
||||
WHERE A.ETUDID = %(etudid)s
|
||||
AND A.ESTJUST
|
||||
@ -704,7 +705,7 @@ class ZAbsences(
|
||||
"Description associee a l'absence"
|
||||
if not cursor:
|
||||
cnx = self.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
a = a.copy()
|
||||
# a['jour'] = a['jour'].date()
|
||||
if a["matin"]: # devrait etre booleen... :-(
|
||||
@ -732,7 +733,6 @@ class ZAbsences(
|
||||
|
||||
if desc:
|
||||
return "(%s) %s" % (desc, module)
|
||||
return desc
|
||||
if module:
|
||||
return module
|
||||
return ""
|
||||
@ -745,7 +745,7 @@ class ZAbsences(
|
||||
is_just: idem
|
||||
"""
|
||||
cnx = self.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
req = """SELECT DISTINCT etudid, jour, matin FROM ABSENCES A
|
||||
WHERE A.jour = %(date)s
|
||||
"""
|
||||
@ -769,7 +769,7 @@ class ZAbsences(
|
||||
def ListeAbsNonJustJour(self, date, am=True, pm=True):
|
||||
"Liste des absences non justifiees ce jour"
|
||||
cnx = self.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
reqa = ""
|
||||
if not am:
|
||||
reqa += " AND NOT matin "
|
||||
@ -849,7 +849,7 @@ class ZAbsences(
|
||||
def CalSelectWeek(self, year=None, REQUEST=None):
|
||||
"display calendar allowing week selection"
|
||||
if not year:
|
||||
year = AnneeScolaire(REQUEST)
|
||||
year = scu.AnneeScolaire(REQUEST)
|
||||
sems = sco_formsemestre.do_formsemestre_list(self)
|
||||
if not sems:
|
||||
js = ""
|
||||
@ -886,10 +886,9 @@ class ZAbsences(
|
||||
security.declareProtected(ScoView, "ListMondays")
|
||||
|
||||
def ListMondays(self, year=None, REQUEST=None):
|
||||
"""return list of mondays (ISO dates), from september to june
|
||||
"""
|
||||
"""return list of mondays (ISO dates), from september to june"""
|
||||
if not year:
|
||||
year = AnneeScolaire(REQUEST)
|
||||
year = scu.AnneeScolaire(REQUEST)
|
||||
d = ddmmyyyy("1/9/%d" % year, work_saturday=self.is_work_saturday())
|
||||
while d.weekday != 0:
|
||||
d = d.next()
|
||||
@ -934,7 +933,7 @@ class ZAbsences(
|
||||
):
|
||||
"Saisie hebdomadaire des absences"
|
||||
if not moduleimpl_id:
|
||||
moduleimp_id = None
|
||||
moduleimpl_id = None
|
||||
|
||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
||||
self, group_ids, REQUEST=REQUEST
|
||||
@ -953,20 +952,32 @@ class ZAbsences(
|
||||
)
|
||||
|
||||
formsemestre_id = groups_infos.formsemestre_id
|
||||
require_module = self.get_preference("abs_require_module", formsemestre_id)
|
||||
etuds = [
|
||||
self.getEtudInfo(etudid=m["etudid"], filled=True)[0]
|
||||
for m in groups_infos.members
|
||||
]
|
||||
# Restreint aux inscrits au module sélectionné
|
||||
if moduleimpl_id:
|
||||
mod_inscrits = set(
|
||||
[
|
||||
x["etudid"]
|
||||
for x in self.Notes.do_moduleimpl_inscription_list(
|
||||
moduleimpl_id=moduleimpl_id
|
||||
)
|
||||
]
|
||||
)
|
||||
etuds = [e for e in etuds if e["etudid"] in mod_inscrits]
|
||||
nt = self.Notes._getNotesCache().get_NotesTable(self.Notes, formsemestre_id)
|
||||
sem = sco_formsemestre.do_formsemestre_list(
|
||||
self, {"formsemestre_id": formsemestre_id}
|
||||
)[0]
|
||||
|
||||
# calcule dates jours de cette semaine
|
||||
datessem = [DateDMYtoISO(datelundi)]
|
||||
for jour in self.day_names()[1:]:
|
||||
# liste de dates iso "yyyy-mm-dd"
|
||||
datessem = [notesdb.DateDMYtoISO(datelundi)]
|
||||
for _ in self.day_names()[1:]:
|
||||
datessem.append(self.NextISODay(datessem[-1]))
|
||||
|
||||
#
|
||||
if groups_infos.tous_les_etuds_du_sem:
|
||||
gr_tit = "en"
|
||||
@ -1045,7 +1056,7 @@ class ZAbsences(
|
||||
)
|
||||
|
||||
H += self._gen_form_saisie_groupe(
|
||||
etuds, self.day_names(), datessem, destination, None, moduleimpl_id
|
||||
etuds, datessem, destination, moduleimpl_id, require_module
|
||||
)
|
||||
|
||||
H.append(self.sco_footer(REQUEST))
|
||||
@ -1063,8 +1074,7 @@ class ZAbsences(
|
||||
moduleimpl_id=None,
|
||||
REQUEST=None,
|
||||
):
|
||||
"""Saisie des absences sur une journée sur un semestre (ou intervalle de dates) entier
|
||||
"""
|
||||
"""Saisie des absences sur une journée sur un semestre (ou intervalle de dates) entier"""
|
||||
# log('SignaleAbsenceGrSemestre: moduleimpl_id=%s destination=%s' % (moduleimpl_id, destination))
|
||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
||||
self, group_ids, REQUEST=REQUEST
|
||||
@ -1075,23 +1085,30 @@ class ZAbsences(
|
||||
+ "<h3>Aucun étudiant !</h3>"
|
||||
+ self.sco_footer(REQUEST)
|
||||
)
|
||||
|
||||
formsemestre_id = groups_infos.formsemestre_id
|
||||
require_module = self.get_preference("abs_require_module", formsemestre_id)
|
||||
etuds = [
|
||||
self.getEtudInfo(etudid=m["etudid"], filled=True)[0]
|
||||
for m in groups_infos.members
|
||||
]
|
||||
|
||||
if not moduleimpl_id:
|
||||
moduleimp_id = None
|
||||
base_url_noweeks = (
|
||||
"SignaleAbsenceGrSemestre?datedebut=%s&datefin=%s&%s&destination=%s"
|
||||
% (
|
||||
datedebut,
|
||||
datefin,
|
||||
groups_infos.groups_query_args,
|
||||
urllib.quote(destination),
|
||||
# Restreint aux inscrits au module sélectionné
|
||||
if moduleimpl_id:
|
||||
mod_inscrits = set(
|
||||
[
|
||||
x["etudid"]
|
||||
for x in self.Notes.do_moduleimpl_inscription_list(
|
||||
moduleimpl_id=moduleimpl_id
|
||||
)
|
||||
]
|
||||
)
|
||||
etuds = [e for e in etuds if e["etudid"] in mod_inscrits]
|
||||
if not moduleimpl_id:
|
||||
moduleimpl_id = None
|
||||
base_url_noweeks = "SignaleAbsenceGrSemestre?datedebut=%s&datefin=%s&%s&destination=%s" % (
|
||||
datedebut,
|
||||
datefin,
|
||||
groups_infos.groups_query_args,
|
||||
urllib.quote(destination),
|
||||
)
|
||||
base_url = (
|
||||
base_url_noweeks + "&nbweeks=%s" % nbweeks
|
||||
@ -1139,7 +1156,6 @@ class ZAbsences(
|
||||
if moduleimpl_id:
|
||||
url_link_semaines += "&moduleimpl_id=" + moduleimpl_id
|
||||
#
|
||||
colnames = [str(x) for x in dates]
|
||||
dates = [x.ISO() for x in dates]
|
||||
dayname = self.day_names()[jourdebut.weekday]
|
||||
|
||||
@ -1147,9 +1163,9 @@ class ZAbsences(
|
||||
gr_tit = "en"
|
||||
else:
|
||||
if len(groups_infos.group_ids) > 1:
|
||||
p = "des groupes"
|
||||
p = "des groupes "
|
||||
else:
|
||||
p = "du groupe"
|
||||
p = "du groupe "
|
||||
gr_tit = (
|
||||
p + '<span class="fontred">' + groups_infos.groups_titles + "</span>"
|
||||
)
|
||||
@ -1209,26 +1225,45 @@ class ZAbsences(
|
||||
sel = "selected" # aucun module specifie
|
||||
H.append(
|
||||
"""<p>
|
||||
Module concerné par ces absences (optionnel): <select id="moduleimpl_id" name="moduleimpl_id" onchange="document.location='%(url)s&moduleimpl_id='+document.getElementById('moduleimpl_id').value">
|
||||
Module concerné par ces absences (%(optionel_txt)s):
|
||||
<select id="moduleimpl_id" name="moduleimpl_id"
|
||||
onchange="document.location='%(url)s&moduleimpl_id='+document.getElementById('moduleimpl_id').value">
|
||||
<option value="" %(sel)s>non spécifié</option>
|
||||
%(menu_module)s
|
||||
</select>
|
||||
</p>"""
|
||||
% {"menu_module": menu_module, "url": base_url, "sel": sel}
|
||||
% {
|
||||
"menu_module": menu_module,
|
||||
"url": base_url,
|
||||
"sel": sel,
|
||||
"optionel_txt": '<span class="redboldtext">requis</span>'
|
||||
if require_module
|
||||
else "optionnel",
|
||||
}
|
||||
)
|
||||
|
||||
H += self._gen_form_saisie_groupe(
|
||||
etuds, colnames, dates, destination, dayname, moduleimpl_id
|
||||
etuds, dates, destination, moduleimpl_id, require_module
|
||||
)
|
||||
H.append(self.sco_footer(REQUEST))
|
||||
return "\n".join(H)
|
||||
|
||||
def _gen_form_saisie_groupe(
|
||||
self, etuds, colnames, dates, destination="", dayname="", moduleimpl_id=None
|
||||
self, etuds, dates, destination="", moduleimpl_id=None, require_module=False
|
||||
):
|
||||
"""Formulaire saisie absences
|
||||
|
||||
Args:
|
||||
etuds: liste des étudiants
|
||||
dates: liste de dates iso, par exemple: [ '2020-12-24', ... ]
|
||||
moduleimpl_id: optionnel, module concerné.
|
||||
"""
|
||||
H = [
|
||||
"""
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
$(".abs_form_table input").prop( "disabled", %s );
|
||||
});
|
||||
function colorize(obj) {
|
||||
if (obj.checked) {
|
||||
obj.parentNode.className = 'absent';
|
||||
@ -1250,27 +1285,34 @@ class ZAbsences(
|
||||
<table rules="cols" frame="box" class="abs_form_table">
|
||||
<tr><th class="formabs_contetud">%d étudiants</th>
|
||||
"""
|
||||
% len(etuds)
|
||||
% (
|
||||
"true" if (require_module and not moduleimpl_id) else "false",
|
||||
len(etuds),
|
||||
)
|
||||
]
|
||||
# Dates
|
||||
odates = [datetime.date(*[int(x) for x in d.split("-")]) for d in dates]
|
||||
# Titres colonnes
|
||||
if dayname:
|
||||
for jour in colnames:
|
||||
H.append(
|
||||
'<th colspan="2" width="100px" style="padding-left: 5px; padding-right: 5px;">'
|
||||
+ dayname
|
||||
+ "</th>"
|
||||
)
|
||||
H.append("</tr><tr><td> </td>")
|
||||
|
||||
for jour in colnames:
|
||||
noms_jours = [] # eg [ "Lundi", "mardi", "Samedi", ... ]
|
||||
jn = self.day_names()
|
||||
for d in odates:
|
||||
idx_jour = d.weekday()
|
||||
noms_jours.append(jn[idx_jour])
|
||||
for jour in noms_jours:
|
||||
H.append(
|
||||
'<th colspan="2" width="100px" style="padding-left: 5px; padding-right: 5px;">'
|
||||
+ jour
|
||||
+ "</th>"
|
||||
)
|
||||
|
||||
H.append("</tr><tr><td> </td>")
|
||||
H.append("<th>AM</th><th>PM</th>" * len(colnames))
|
||||
for d in odates:
|
||||
H.append(
|
||||
'<th colspan="2" width="100px" style="padding-left: 5px; padding-right: 5px;">'
|
||||
+ d.strftime("%d/%m/%Y")
|
||||
+ "</th>"
|
||||
)
|
||||
H.append("</tr><tr><td> </td>")
|
||||
H.append("<th>AM</th><th>PM</th>" * len(dates))
|
||||
H.append("</tr>")
|
||||
#
|
||||
if not etuds:
|
||||
@ -1309,17 +1351,26 @@ class ZAbsences(
|
||||
checked = "checked"
|
||||
else:
|
||||
checked = ""
|
||||
# bulle lors du passage souris
|
||||
coljour = DAYNAMES[
|
||||
(calendar.weekday(int(date[:4]), int(date[5:7]), int(date[8:])))
|
||||
]
|
||||
datecol = coljour + " " + date[8:] + "/" + date[5:7] + "/" + date[:4]
|
||||
bulle_am = '"' + etud["nomprenom"] + " - " + datecol + ' (matin)"'
|
||||
bulle_pm = '"' + etud["nomprenom"] + " - " + datecol + ' (ap.midi)"'
|
||||
|
||||
H.append(
|
||||
'<td class="%s"><input type="checkbox" name="abslist:list" value="%s" %s onclick="on_toggled(this, \'%s\', \'%s\')"/></td>'
|
||||
'<td class="%s"><a title=%s><input type="checkbox" name="abslist:list" value="%s" %s onclick="on_toggled(this, \'%s\', \'%s\')"/></a></td>'
|
||||
% (
|
||||
td_matin_class,
|
||||
bulle_am,
|
||||
etudid + ":" + date + ":" + "am",
|
||||
checked,
|
||||
etudid,
|
||||
date + ":am",
|
||||
)
|
||||
)
|
||||
# apres midi
|
||||
# après-midi
|
||||
if self.CountAbs(
|
||||
etudid, date, date, False, moduleimpl_id=moduleimpl_id
|
||||
):
|
||||
@ -1327,8 +1378,14 @@ class ZAbsences(
|
||||
else:
|
||||
checked = ""
|
||||
H.append(
|
||||
'<td><input type="checkbox" name="abslist:list" value="%s" %s onclick="on_toggled(this, \'%s\', \'%s\')"/></td>'
|
||||
% (etudid + ":" + date + ":" + "pm", checked, etudid, date + ":pm")
|
||||
'<td><a title=%s><input type="checkbox" name="abslist:list" value="%s" %s onclick="on_toggled(this, \'%s\', \'%s\')"/></a></td>'
|
||||
% (
|
||||
bulle_pm,
|
||||
etudid + ":" + date + ":" + "pm",
|
||||
checked,
|
||||
etudid,
|
||||
date + ":pm",
|
||||
)
|
||||
)
|
||||
H.append("</tr>")
|
||||
H.append("</table>")
|
||||
@ -1373,14 +1430,13 @@ class ZAbsences(
|
||||
absjust_only=0,
|
||||
REQUEST=None,
|
||||
):
|
||||
"""Tables des absences justifiees et non justifiees d'un étudiant sur l'année en cours
|
||||
"""
|
||||
"""Tables des absences justifiees et non justifiees d'un étudiant sur l'année en cours"""
|
||||
absjust = self.ListeAbsJust(etudid=etudid, datedebut=datedebut)
|
||||
absnonjust = self.ListeAbsNonJust(etudid=etudid, datedebut=datedebut)
|
||||
# examens ces jours là ?
|
||||
if with_evals:
|
||||
cnx = self.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor = cnx.cursor(cursor_factory=notesdb.ScoDocCursor)
|
||||
for a in absnonjust + absjust:
|
||||
cursor.execute(
|
||||
"""select eval.*
|
||||
@ -1407,7 +1463,7 @@ class ZAbsences(
|
||||
if x:
|
||||
return "matin"
|
||||
else:
|
||||
return "après midi"
|
||||
return "après-midi"
|
||||
|
||||
def descr_exams(a):
|
||||
if not a.has_key("evals"):
|
||||
@ -1499,10 +1555,9 @@ class ZAbsences(
|
||||
format="html",
|
||||
REQUEST=None,
|
||||
):
|
||||
"""Liste les absences de groupes
|
||||
"""
|
||||
datedebut = DateDMYtoISO(debut)
|
||||
datefin = DateDMYtoISO(fin)
|
||||
"""Liste les absences de groupes"""
|
||||
datedebut = notesdb.DateDMYtoISO(debut)
|
||||
datefin = notesdb.DateDMYtoISO(fin)
|
||||
# Informations sur les groupes à afficher:
|
||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
||||
self, group_ids, REQUEST=REQUEST
|
||||
@ -1603,7 +1658,7 @@ class ZAbsences(
|
||||
base_url="%s&formsemestre_id=%s&debut=%s&fin=%s"
|
||||
% (groups_infos.base_url, formsemestre_id, debut, fin),
|
||||
filename="etat_abs_"
|
||||
+ make_filename(
|
||||
+ scu.make_filename(
|
||||
"%s de %s" % (groups_infos.groups_filename, sem["titreannee"])
|
||||
),
|
||||
caption=title,
|
||||
@ -1632,26 +1687,20 @@ ou entrez une date pour visualiser les absents un jour donné :
|
||||
def EtatAbsencesDate(
|
||||
self, group_ids=[], date=None, REQUEST=None # list of groups to display
|
||||
):
|
||||
"""Etat des absences pour un groupe à une date donnée
|
||||
"""
|
||||
"""Etat des absences pour un groupe à une date donnée"""
|
||||
# Informations sur les groupes à afficher:
|
||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
||||
self, group_ids, REQUEST=REQUEST
|
||||
)
|
||||
formsemestre_id = groups_infos.formsemestre_id
|
||||
sem = sco_formsemestre.do_formsemestre_list(
|
||||
self, {"formsemestre_id": formsemestre_id}
|
||||
)[0]
|
||||
H = [self.sco_header(page_title="Etat des absences", REQUEST=REQUEST)]
|
||||
if date:
|
||||
dateiso = DateDMYtoISO(date)
|
||||
dateiso = notesdb.DateDMYtoISO(date)
|
||||
nbetud = 0
|
||||
t_nbabsjustam = 0
|
||||
t_nbabsam = 0
|
||||
t_nbabsjustpm = 0
|
||||
t_nbabspm = 0
|
||||
etuds = self.getEtudInfoGroupes(groups_infos.group_ids)
|
||||
H.append("<h2>Etat des absences le %s</h2>" % date)
|
||||
H.append("<h2>État des absences le %s</h2>" % date)
|
||||
H.append(
|
||||
"""<table border="0" cellspacing="4" cellpadding="0">
|
||||
<tr><th> </th>
|
||||
@ -1738,7 +1787,7 @@ ou entrez une date pour visualiser les absents un jour donné :
|
||||
etudid=etudid, code_nip=code_nip, REQUEST=REQUEST, filled=True
|
||||
)
|
||||
if not etuds:
|
||||
return log_unknown_etud(self, REQUEST=REQUEST)
|
||||
return scu.log_unknown_etud(self, REQUEST=REQUEST)
|
||||
etud = etuds[0]
|
||||
# check dates
|
||||
begin_date = ParseDateTimeUTC(begin) # may raises ValueError
|
||||
@ -1763,7 +1812,7 @@ ou entrez une date pour visualiser les absents un jour donné :
|
||||
if xml_reply:
|
||||
# Renvoie le nouveau billet en XML
|
||||
if REQUEST:
|
||||
REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE)
|
||||
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
|
||||
|
||||
billets = billet_absence_list(cnx, {"billet_id": billet_id})
|
||||
tab = self._tableBillets(billets, etud=etud)
|
||||
@ -1827,12 +1876,12 @@ ou entrez une date pour visualiser les absents un jour donné :
|
||||
if b["abs_begin"].hour < 12:
|
||||
m = " matin"
|
||||
else:
|
||||
m = " après midi"
|
||||
m = " après-midi"
|
||||
b["abs_begin_str"] = b["abs_begin"].strftime("%d/%m/%Y") + m
|
||||
if b["abs_end"].hour < 12:
|
||||
m = " matin"
|
||||
else:
|
||||
m = " après midi"
|
||||
m = " après-midi"
|
||||
b["abs_end_str"] = b["abs_end"].strftime("%d/%m/%Y") + m
|
||||
if b["etat"] == 0:
|
||||
if b["justified"] == 0:
|
||||
@ -1884,11 +1933,10 @@ ou entrez une date pour visualiser les absents un jour donné :
|
||||
security.declareProtected(ScoView, "listeBilletsEtud")
|
||||
|
||||
def listeBilletsEtud(self, etudid=False, REQUEST=None, format="html"):
|
||||
"""Liste billets pour un etudiant
|
||||
"""
|
||||
"""Liste billets pour un etudiant"""
|
||||
etuds = self.getEtudInfo(etudid=etudid, filled=1, REQUEST=REQUEST)
|
||||
if not etuds:
|
||||
return log_unknown_etud(self, format=format, REQUEST=REQUEST)
|
||||
return scu.log_unknown_etud(self, format=format, REQUEST=REQUEST)
|
||||
|
||||
etud = etuds[0]
|
||||
cnx = self.GetDBConnexion()
|
||||
@ -1899,8 +1947,7 @@ ou entrez une date pour visualiser les absents un jour donné :
|
||||
security.declareProtected(ScoView, "XMLgetBilletsEtud")
|
||||
|
||||
def XMLgetBilletsEtud(self, etudid=False, REQUEST=None):
|
||||
"""Liste billets pour un etudiant
|
||||
"""
|
||||
"""Liste billets pour un etudiant"""
|
||||
if not self.get_preference("handle_billets_abs"):
|
||||
return ""
|
||||
t0 = time.time()
|
||||
@ -1937,8 +1984,7 @@ ou entrez une date pour visualiser les absents un jour donné :
|
||||
security.declareProtected(ScoAbsChange, "deleteBilletAbsence")
|
||||
|
||||
def deleteBilletAbsence(self, billet_id, REQUEST=None, dialog_confirmed=False):
|
||||
"""Supprime un billet.
|
||||
"""
|
||||
"""Supprime un billet."""
|
||||
cnx = self.GetDBConnexion()
|
||||
billets = billet_absence_list(cnx, {"billet_id": billet_id})
|
||||
if not billets:
|
||||
@ -1962,7 +2008,7 @@ ou entrez une date pour visualiser les absents un jour donné :
|
||||
def _ProcessBilletAbsence(self, billet, estjust, description, REQUEST):
|
||||
"""Traite un billet: ajoute absence(s) et éventuellement justificatifs,
|
||||
et change l'état du billet à 1.
|
||||
NB: actuellement, les heures ne sont utilisées que pour déterminer si matin et/ou après midi.
|
||||
NB: actuellement, les heures ne sont utilisées que pour déterminer si matin et/ou après-midi.
|
||||
"""
|
||||
cnx = self.GetDBConnexion()
|
||||
if billet["etat"] != 0:
|
||||
@ -1974,7 +2020,7 @@ ou entrez une date pour visualiser les absents un jour donné :
|
||||
datedebut = billet["abs_begin"].strftime("%d/%m/%Y")
|
||||
datefin = billet["abs_end"].strftime("%d/%m/%Y")
|
||||
dates = self.DateRangeISO(datedebut, datefin)
|
||||
# commence apres midi ?
|
||||
# commence après-midi ?
|
||||
if dates and billet["abs_begin"].hour > 11:
|
||||
self._AddAbsence(
|
||||
billet["etudid"], dates[0], 0, estjust, REQUEST, description=description
|
||||
@ -2107,8 +2153,8 @@ ou entrez une date pour visualiser les absents un jour donné :
|
||||
|
||||
Abs = self._ListeAbsDate(etud["etudid"], beg_date, end_date)
|
||||
|
||||
REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE)
|
||||
doc = jaxml.XML_document(encoding=SCO_ENCODING)
|
||||
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
|
||||
doc = jaxml.XML_document(encoding=scu.SCO_ENCODING)
|
||||
doc.absences(etudid=etud["etudid"], beg_date=beg_date, end_date=end_date)
|
||||
doc._push()
|
||||
for a in Abs:
|
||||
@ -2126,7 +2172,7 @@ ou entrez une date pour visualiser les absents un jour donné :
|
||||
return repr(doc)
|
||||
|
||||
|
||||
_billet_absenceEditor = EditableTable(
|
||||
_billet_absenceEditor = notesdb.EditableTable(
|
||||
"billet_absence",
|
||||
"billet_id",
|
||||
(
|
||||
@ -2210,7 +2256,6 @@ def MonthTableTail():
|
||||
def MonthTableBody(
|
||||
month, year, events=[], halfday=0, trattributes="", work_saturday=False, pad_width=8
|
||||
):
|
||||
# log('XXX events=%s' % events)
|
||||
firstday, nbdays = calendar.monthrange(year, month)
|
||||
localtime = time.localtime()
|
||||
current_weeknum = time.strftime("%U", localtime)
|
||||
@ -2270,7 +2315,7 @@ def MonthTableBody(
|
||||
if href:
|
||||
href = 'href="%s"' % href
|
||||
if descr:
|
||||
descr = 'title="%s"' % descr
|
||||
descr = 'title="%s"' % cgi.escape(descr, quote=True)
|
||||
if href or descr:
|
||||
cc.append("<a %s %s>" % (href, descr))
|
||||
|
||||
@ -2362,7 +2407,7 @@ def MonthTableBody(
|
||||
if href:
|
||||
href = 'href="%s"' % href
|
||||
if descr:
|
||||
descr = 'title="%s"' % descr
|
||||
descr = 'title="%s"' % cgi.escape(descr, quote=True)
|
||||
if href or descr:
|
||||
cc.append("<a %s %s>" % (href, descr))
|
||||
if legend or d == 1:
|
||||
@ -2443,8 +2488,8 @@ class CAbsSemEtud:
|
||||
self.sem = sco_formsemestre.get_formsemestre(
|
||||
self.context, self.sem["formsemestre_id"]
|
||||
)
|
||||
debut_sem = DateDMYtoISO(self.sem["date_debut"])
|
||||
fin_sem = DateDMYtoISO(self.sem["date_fin"])
|
||||
debut_sem = notesdb.DateDMYtoISO(self.sem["date_debut"])
|
||||
fin_sem = notesdb.DateDMYtoISO(self.sem["date_fin"])
|
||||
|
||||
self._CountAbs = self.context.Absences.CountAbs(
|
||||
etudid=self.etudid, debut=debut_sem, fin=fin_sem
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
11
ZNotes.py
11
ZNotes.py
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -1531,6 +1531,8 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
|
||||
)
|
||||
|
||||
_expr_help = """<p class="help">Expérimental: formule de calcul de la moyenne %(target)s</p>
|
||||
<p class="help">Attention: l'utilisation de formules ralenti considérablement
|
||||
les traitements. A utiliser uniquement dans els cas ne pouvant pas être traités autrement.</p>
|
||||
<p class="help">Dans la formule, les variables suivantes sont définies:</p>
|
||||
<ul class="help">
|
||||
<li><tt>moy</tt> la moyenne, calculée selon la règle standard (moyenne pondérée)</li>
|
||||
@ -1542,8 +1544,9 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
|
||||
<li>Nombre d'absences: <tt>nb_abs</tt>, <tt>nb_abs_just</tt>, <tt>nb_abs_nojust</tt> (en demi-journées)</li>
|
||||
</ul>
|
||||
<p class="help">Les éléments des vecteurs sont ordonnés dans l'ordre des %(objs)s%(ordre)s.</p>
|
||||
<p class="help">Les fonctions suivantes sont utilisables: <tt>abs, cmp, dot, len, map, max, min, pow, reduce, round, sum, ifelse</tt></p>
|
||||
<p class="help">La notation <tt>V(1,2,3)</tt> représente un vecteur <tt>(1,2,3)</tt></p>
|
||||
<p class="help">Les fonctions suivantes sont utilisables: <tt>abs, cmp, dot, len, map, max, min, pow, reduce, round, sum, ifelse</tt>.</p>
|
||||
<p class="help">La notation <tt>V(1,2,3)</tt> représente un vecteur <tt>(1,2,3)</tt>.</p>
|
||||
<p class="help"></p>Pour indiquer que la note calculée n'existe pas, utiliser la chaîne <tt>'NA'</tt>.</p>
|
||||
<p class="help">Vous pouvez désactiver la formule (et revenir au mode de calcul "classique")
|
||||
en supprimant le texte ou en faisant précéder la première ligne par <tt>#</tt></p>
|
||||
"""
|
||||
@ -1617,7 +1620,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
|
||||
security.declareProtected(ScoView, "view_module_abs")
|
||||
|
||||
def view_module_abs(self, REQUEST, moduleimpl_id, format="html"):
|
||||
"""Visulalisation des absences a un module"""
|
||||
"""Visualisation des absences a un module"""
|
||||
M = self.do_moduleimpl_withmodule_list(moduleimpl_id=moduleimpl_id)[0]
|
||||
sem = sco_formsemestre.get_formsemestre(self, M["formsemestre_id"])
|
||||
debut_sem = DateDMYtoISO(sem["date_debut"])
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -308,6 +308,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
|
||||
raise ValueError("nom de departement invalide")
|
||||
if not pass2:
|
||||
# 1- Creation de repertoire Dept
|
||||
log("creating Zope folder " + DeptId)
|
||||
add_method = self.manage_addProduct["OFSP"].manage_addFolder
|
||||
add_method(DeptId, title="Site dept. " + DeptId)
|
||||
|
||||
@ -315,10 +316,12 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
|
||||
|
||||
if not pass2:
|
||||
# 2- Creation du repertoire Fotos
|
||||
log("creating Zope folder %s/Fotos" % DeptId)
|
||||
add_method = DeptFolder.manage_addProduct["OFSP"].manage_addFolder
|
||||
add_method("Fotos", title="Photos identites " + DeptId)
|
||||
|
||||
# 3- Creation instance ScoDoc
|
||||
log("creating Zope ZScolar instance")
|
||||
add_method = DeptFolder.manage_addProduct["ScoDoc"].manage_addZScolarForm
|
||||
return add_method(DeptId, REQUEST=REQUEST)
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -277,7 +277,7 @@ class ZScoUsers(
|
||||
|
||||
def user_info(self, user_name=None, user=None):
|
||||
"""Donne infos sur l'utilisateur (qui peut ne pas etre dans notre base).
|
||||
Si user_name est specifie, interroge la BD. Sinon, user doit etre un dict.
|
||||
Si user_name est specifie, interroge la BD. Sinon, user doit etre un dict.
|
||||
"""
|
||||
if user_name:
|
||||
infos = self._user_list(args={"user_name": user_name})
|
||||
@ -919,7 +919,7 @@ class ZScoUsers(
|
||||
self, edit, user_name="", nom="", prenom="", email="", roles=[]
|
||||
):
|
||||
"""Vérifie que et utilisateur peut etre crée (edit=0) ou modifié (edit=1)
|
||||
Cherche homonymes.
|
||||
Cherche homonymes.
|
||||
returns (ok, msg)
|
||||
- ok : si vrai, peut continuer avec ces parametres
|
||||
(si ok est faux, l'utilisateur peut quand même forcer la creation)
|
||||
@ -1252,8 +1252,7 @@ class ZScoUsers(
|
||||
security.declareProtected(ScoView, "get_user_name_from_nomplogin")
|
||||
|
||||
def get_user_name_from_nomplogin(self, nomplogin):
|
||||
"""Returns user_name (login) from nomplogin
|
||||
"""
|
||||
"""Returns user_name (login) from nomplogin"""
|
||||
m = re.match(r".*\((.*)\)", nomplogin.strip())
|
||||
if m:
|
||||
return m.group(1)
|
||||
|
47
ZScolar.py
47
ZScolar.py
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -2037,49 +2037,8 @@ function tweakmenu( gname ) {
|
||||
)
|
||||
|
||||
if not edit:
|
||||
# creation d'un etudiant
|
||||
etudid = scolars.etudident_create(
|
||||
cnx, tf[2], context=self, REQUEST=REQUEST
|
||||
)
|
||||
# crée une adresse vide (chaque etudiant doit etre dans la table "adresse" !)
|
||||
adresse_id = scolars.adresse_create(
|
||||
cnx,
|
||||
{
|
||||
"etudid": etudid,
|
||||
"typeadresse": "domicile",
|
||||
"description": "(creation individuelle)",
|
||||
},
|
||||
)
|
||||
|
||||
# event
|
||||
scolars.scolar_events_create(
|
||||
cnx,
|
||||
args={
|
||||
"etudid": etudid,
|
||||
"event_date": time.strftime("%d/%m/%Y"),
|
||||
"formsemestre_id": None,
|
||||
"event_type": "CREATION",
|
||||
},
|
||||
)
|
||||
# log
|
||||
logdb(
|
||||
REQUEST,
|
||||
cnx,
|
||||
method="etudident_edit_form",
|
||||
etudid=etudid,
|
||||
msg="creation initiale",
|
||||
)
|
||||
etud = scolars.etudident_list(cnx, {"etudid": etudid})[0]
|
||||
self.fillEtudsInfo([etud])
|
||||
etud["url"] = "ficheEtud?etudid=%(etudid)s" % etud
|
||||
sco_news.add(
|
||||
self,
|
||||
REQUEST,
|
||||
typ=NEWS_INSCR,
|
||||
object=None, # pas d'object pour ne montrer qu'un etudiant
|
||||
text='Nouvel étudiant <a href="%(url)s">%(nomprenom)s</a>' % etud,
|
||||
url=etud["url"],
|
||||
)
|
||||
etud = scolars.create_etud(self, cnx, args=tf[2], REQUEST=REQUEST)
|
||||
etudid = etud["etudid"]
|
||||
else:
|
||||
# modif d'un etudiant
|
||||
scolars.etudident_edit(cnx, tf[2], context=self, REQUEST=REQUEST)
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -15,19 +15,37 @@ source utils.sh
|
||||
|
||||
check_uid_root "$0"
|
||||
|
||||
usage() {
|
||||
echo "$0 [-n DEPT]"
|
||||
echo "(default to interactive mode)"
|
||||
exit 1
|
||||
}
|
||||
[ $# = 0 ] || [ $# = 2 ] || usage
|
||||
|
||||
echo -n "Nom du departement (un mot sans ponctuation, exemple \"Info\"): "
|
||||
read -r DEPT
|
||||
if [ "$1" = "-n" ]
|
||||
then
|
||||
interactive=0
|
||||
if [ $# -lt 2 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
DEPT=$2
|
||||
else
|
||||
interactive=1
|
||||
echo -n "Nom du departement (un mot sans ponctuation, exemple \"Info\"): "
|
||||
read -r DEPT
|
||||
fi
|
||||
|
||||
if [[ ! "$DEPT" =~ ^[A-Za-z0-9]+$ ]]
|
||||
then
|
||||
echo 'Nom de departement invalide !'
|
||||
exit 1
|
||||
exit 2
|
||||
fi
|
||||
|
||||
export DEPT
|
||||
|
||||
export db_name=SCO$(to_upper "$DEPT")
|
||||
db_name=SCO$(to_upper "$DEPT")
|
||||
export db_name
|
||||
|
||||
cfg_pathname="${SCODOC_VAR_DIR}/config/depts/$DEPT".cfg
|
||||
|
||||
@ -41,29 +59,39 @@ fi
|
||||
init_postgres_user
|
||||
|
||||
# ----------------------- Create database
|
||||
su -c ./create_database.sh $POSTGRES_SUPERUSER
|
||||
su -c ./create_database.sh "$POSTGRES_SUPERUSER"
|
||||
|
||||
# ----------------------- Create tables
|
||||
# POSTGRES_USER == regular unix user (www-data)
|
||||
su -c ./initialize_database.sh $POSTGRES_USER
|
||||
|
||||
# ----------------------- Enregistre fichier config
|
||||
echo "dbname=$db_name" > "$cfg_pathname"
|
||||
|
||||
# ----------------------- Force mise à jour
|
||||
echo -n "Voulez vous mettre a jour ScoDoc (tres recommande) ? (y/n) [y] "
|
||||
read -r ans
|
||||
if [ "$(norm_ans "$ans")" != 'N' ]
|
||||
if [ "$interactive" = 1 ]
|
||||
then
|
||||
(cd "$SCODOC_DIR/config"; ./upgrade.sh)
|
||||
su -c ./initialize_database.sh "$POSTGRES_USER"
|
||||
else
|
||||
su -c ./initialize_database.sh "$POSTGRES_USER" > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# -----------------------
|
||||
echo
|
||||
echo " Departement $DEPT cree"
|
||||
echo
|
||||
echo " Attention: la base de donnees n'a pas de copies de sauvegarde"
|
||||
echo
|
||||
echo " Maintenant, vous pouvez ajouter le departement via l'application web"
|
||||
echo " en suivant le lien \"Administration de ScoDoc\" sur la page d'accueil."
|
||||
echo
|
||||
|
||||
|
||||
# ----------------------- Enregistre fichier config
|
||||
echo "dbname=${db_name}" > "$cfg_pathname"
|
||||
|
||||
|
||||
if [ "$interactive" = 1 ]
|
||||
then
|
||||
# ----------------------- Force mise à jour
|
||||
echo -n "Voulez vous mettre a jour ScoDoc (tres recommande) ? (y/n) [y] "
|
||||
read -r ans
|
||||
if [ "$(norm_ans "$ans")" != 'N' ]
|
||||
then
|
||||
(cd "$SCODOC_DIR/config" || terminate "no config directory"; ./upgrade.sh)
|
||||
fi
|
||||
# -----------------------
|
||||
echo
|
||||
echo " Departement $DEPT cree"
|
||||
echo
|
||||
echo " Attention: la base de donnees n'a pas de copies de sauvegarde"
|
||||
echo
|
||||
echo " Maintenant, vous pouvez ajouter le departement via l'application web"
|
||||
echo " en suivant le lien \"Administration de ScoDoc\" sur la page d'accueil."
|
||||
echo
|
||||
fi
|
||||
|
@ -17,23 +17,38 @@
|
||||
source config.sh
|
||||
source utils.sh
|
||||
|
||||
check_uid_root "$0"
|
||||
|
||||
echo
|
||||
echo "Ce script supprime la base de donnees ScoDoc d'un departement"
|
||||
echo
|
||||
echo "Attention: le departement doit au prealable avoir ete supprime via l'interface web !"
|
||||
echo "faites le AVANT d'executer ce script !!!"
|
||||
echo
|
||||
echo -n "Nom du departement a supprimer (un mot sans ponctuation, exemple \"Info\"): "
|
||||
read -r DEPT
|
||||
check_uid_root $0
|
||||
usage() {
|
||||
echo "$0 [-n DEPT]"
|
||||
echo "(default to interactive mode)"
|
||||
exit 1
|
||||
}
|
||||
[ $# = 0 ] || [ $# = 2 ] || usage
|
||||
if [ "$1" = "-n" ]
|
||||
then
|
||||
interactive=0
|
||||
if [ $# -lt 2 ]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
DEPT=$2
|
||||
else
|
||||
interactive=1
|
||||
echo
|
||||
echo "Ce script supprime la base de donnees ScoDoc d'un departement"
|
||||
echo
|
||||
echo "Attention: le departement doit au prealable avoir ete supprime via l'interface web !"
|
||||
echo "faites le AVANT d'executer ce script !!!"
|
||||
echo
|
||||
echo -n "Nom du departement a supprimer (un mot sans ponctuation, exemple \"Info\"): "
|
||||
read -r DEPT
|
||||
fi
|
||||
|
||||
if [[ ! "$DEPT" =~ ^[A-Za-z0-9]+$ ]]
|
||||
then
|
||||
echo "Nom de departement invalide !"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export DEPT
|
||||
|
||||
cfg_pathname="${SCODOC_VAR_DIR}/config/depts/$DEPT".cfg
|
||||
@ -50,11 +65,14 @@ then
|
||||
# suppression du fichier de config
|
||||
/bin/rm -f "$cfg_pathname" || terminate "ne peux supprimer $cfg_pathname"
|
||||
# relance ScoDoc
|
||||
echo -n "Demarrer le serveur ScoDoc ? (y/n) [n]"
|
||||
read -r ans
|
||||
if [ "$(norm_ans "$ans")" = 'Y' ]
|
||||
if [ "$interactive" = 1 ]
|
||||
then
|
||||
scodocctl start
|
||||
echo -n "Demarrer le serveur ScoDoc ? (y/n) [n]"
|
||||
read -r ans
|
||||
if [ "$(norm_ans "$ans")" = 'Y' ]
|
||||
then
|
||||
scodocctl start
|
||||
fi
|
||||
fi
|
||||
exit 0
|
||||
else
|
||||
|
0
config/migre-7-a-8.sh
Executable file → Normal file
0
config/migre-7-a-8.sh
Executable file → Normal file
@ -57,7 +57,7 @@ then
|
||||
echo "Opening tgz archive..."
|
||||
tmp=$(mktemp -d)
|
||||
chmod a+rx "$tmp"
|
||||
cd "$tmp" || { echo "Fatal error: directory not available"; exit 1; }
|
||||
cd "$tmp" || terminate "directory error"
|
||||
tar xfz "$SRC"
|
||||
SRC=$(ls -1d "$tmp"/*)
|
||||
IS_TMP=1
|
||||
@ -83,18 +83,18 @@ su -c "$SCODOC_DIR/config/psql_restore_databases.sh $PG_DUMPFILE" postgres
|
||||
#
|
||||
echo Copying data files...
|
||||
|
||||
rm -rf "$INSTANCE_DIR/var"
|
||||
rm -rf "${INSTANCE_DIR:?}/var"
|
||||
$COPY "$SRC/var" "$INSTANCE_DIR"
|
||||
|
||||
if [ ! -e "${SCODOC_VAR_DIR}/config/" ]
|
||||
if [ ! -e "${SCODOC_VAR_DIR:?}/config/" ]
|
||||
then
|
||||
mkdir "${SCODOC_VAR_DIR}/config/"
|
||||
chown www-data.www-data "${SCODOC_VAR_DIR}/config/"
|
||||
chmod 775 "${SCODOC_VAR_DIR}/config/"
|
||||
mkdir "${SCODOC_VAR_DIR:?}/config/"
|
||||
chown www-data.www-data "${SCODOC_VAR_DIR:?}/config/"
|
||||
chmod 775 "${SCODOC_VAR_DIR:?}/config/"
|
||||
fi
|
||||
|
||||
rm -rf "$SCODOC_DIR/config/depts"
|
||||
if [ -e "$SRC/depts" ]
|
||||
rm -rf "${SCODOC_DIR:?}/config/depts"
|
||||
if [ -e "${SRC:?}/depts" ]
|
||||
then
|
||||
# legacy depts => move them to var
|
||||
$COPY "$SRC/depts" "${SCODOC_VAR_DIR}/config/"
|
||||
@ -107,7 +107,7 @@ then
|
||||
$COPY "$SRC/photos" "${SCODOC_VAR_DIR}/"
|
||||
fi
|
||||
|
||||
rm -rf "$SCODOC_DIR/logos"
|
||||
rm -rf "${SCODOC_DIR:?}/logos"
|
||||
$COPY "$SRC/logos" "$SCODOC_DIR/"
|
||||
|
||||
mv "$SCODOC_DIR/config/scodoc_config.py" "$SCODOC_DIR/config/scodoc_config.py.$(date +%Y%m%d-%H%M%S)"
|
||||
@ -119,7 +119,7 @@ then
|
||||
iconv -f iso8859-15 -t utf-8 "$SCODOC_DIR/config/scodoc_config.py.orig" > "$SCODOC_DIR/config/scodoc_config.py"
|
||||
fi
|
||||
|
||||
rm -rf "$INSTANCE_DIR/log"
|
||||
rm -rf "${INSTANCE_DIR:?}/log"
|
||||
$COPY "$SRC/log" "$INSTANCE_DIR/"
|
||||
|
||||
# Fix file ownership and access rights
|
||||
@ -130,13 +130,13 @@ chown -R www-data.root "$SCODOC_DIR"
|
||||
chmod -R 775 "$SCODOC_DIR"
|
||||
|
||||
# Remove tmp directory
|
||||
if [ $IS_TMP = "1" ]
|
||||
if [ "$IS_TMP" = "1" ]
|
||||
then
|
||||
rm -rf "$tmp"
|
||||
rm -rf "${tmp}"
|
||||
fi
|
||||
|
||||
# Mise a jour BD ScoDoc
|
||||
cd "$SCODOC_DIR"/config || { echo "Fatal error: invalid directory"; exit 2; }
|
||||
cd ${SCODOC_DIR:?}/config || terminate "no config directory"
|
||||
./upgrade.sh
|
||||
|
||||
#
|
||||
|
@ -36,6 +36,12 @@ fi
|
||||
INSTANCE_DIR=/opt/scodoc
|
||||
SCODOC_DIR="$INSTANCE_DIR/Products/ScoDoc"
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
source utils.sh
|
||||
check_uid_root "$0"
|
||||
|
||||
>>>>>>> e2a2b0f0836fc6de922c35b77b236379783e7590
|
||||
echo "Stopping ScoDoc..."
|
||||
scodocctl stop
|
||||
|
||||
@ -43,9 +49,13 @@ scodocctl stop
|
||||
echo "Dumping SQL database..."
|
||||
chown postgres "$DEST"
|
||||
su -c "pg_dumpall > \"$DEST\"/scodoc.dump.txt" postgres
|
||||
if [ ! $? -eq 0 ]
|
||||
if [ ! "$?" -eq 0 ]
|
||||
then
|
||||
<<<<<<< HEAD
|
||||
printf "Error dumping postgresql database\nPlease check that SQL server is running\nAborting.\n"
|
||||
=======
|
||||
printf "Error dumping postgresql database\nPlease check that SQL server is running\nAborting."
|
||||
>>>>>>> e2a2b0f0836fc6de922c35b77b236379783e7590
|
||||
exit 1
|
||||
fi
|
||||
chown root "$DEST"
|
||||
@ -85,6 +95,6 @@ cp -rp "$INSTANCE_DIR/log" "$DEST"
|
||||
echo
|
||||
echo "Archiving backup files in a $DEST.tgz..."
|
||||
base=$(basename "$DEST")
|
||||
(cd "$DEST"/..; tar cfz "$DEST".tgz "$base")
|
||||
(cd "$DEST"/.. || terminate "directory error"; tar cfz "$DEST".tgz "$base")
|
||||
|
||||
echo "Done (you can copy " "$DEST"".tgz to destination machine)."
|
||||
|
@ -6,7 +6,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
6
debug.py
6
debug.py
@ -31,6 +31,8 @@ nt = context.Notes._getNotesCache().get_NotesTable(context.Notes, formsemestre_i
|
||||
|
||||
|
||||
"""
|
||||
import pdb
|
||||
|
||||
from notesdb import *
|
||||
from notes_log import log
|
||||
from sco_utils import *
|
||||
@ -78,6 +80,9 @@ class FakeUser:
|
||||
def has_permission(self, op, context):
|
||||
return True
|
||||
|
||||
def has_role(self, role):
|
||||
return True
|
||||
|
||||
|
||||
class DummyResponse:
|
||||
"""Emulation vide de Reponse http Zope"""
|
||||
@ -104,6 +109,7 @@ class DummyRequest:
|
||||
self.URL1 = self.URL
|
||||
self.URL0 = self.URL
|
||||
self.BASE0 = "localhost"
|
||||
self.REMOTE_HOST = "localhost"
|
||||
self.REMOTE_ADDR = "127.0.0.1"
|
||||
self.HTTP_REFERER = ""
|
||||
self.REQUEST_METHOD = "get"
|
||||
|
22
dutrules.py
22
dutrules.py
@ -4,7 +4,27 @@
|
||||
#
|
||||
# Command: ./csv2rules.py misc/parcoursDUT.csv
|
||||
#
|
||||
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 = "misc/parcoursDUT.csv"
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -45,9 +45,20 @@ from collections import OrderedDict
|
||||
|
||||
# XML generation package (apt-get install jaxml)
|
||||
import jaxml
|
||||
import json
|
||||
|
||||
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Frame, PageBreak
|
||||
from reportlab.platypus import Table, TableStyle, Image, KeepInFrame
|
||||
from reportlab.lib.colors import Color
|
||||
from reportlab.lib import styles
|
||||
from reportlab.lib.units import inch, cm, mm
|
||||
from reportlab.rl_config import defaultPageSize # pylint: disable=no-name-in-module
|
||||
|
||||
import sco_utils as scu
|
||||
import sco_excel
|
||||
from sco_pdf import *
|
||||
import sco_pdf
|
||||
from sco_pdf import SU
|
||||
from notes_log import log
|
||||
|
||||
|
||||
def mark_paras(L, tags):
|
||||
@ -280,7 +291,7 @@ class GenTable:
|
||||
if not row:
|
||||
return "<tr></tr>" # empty row
|
||||
|
||||
if self.html_col_width: # XXXX Obsolete ?
|
||||
if self.html_col_width:
|
||||
std = ' style="width:%s;"' % self.html_col_width
|
||||
else:
|
||||
std = ""
|
||||
@ -382,10 +393,6 @@ class GenTable:
|
||||
else:
|
||||
cls = ""
|
||||
|
||||
if self.html_col_width:
|
||||
std = ' style="width:%s;"' % self.html_col_width
|
||||
else:
|
||||
std = ""
|
||||
H = [self.html_before_table, "<table%s%s>" % (hid, cls)]
|
||||
|
||||
line_num = 0
|
||||
@ -438,14 +445,14 @@ class GenTable:
|
||||
if self.xls_link:
|
||||
H.append(
|
||||
' <a href="%s&format=xls">%s</a>'
|
||||
% (self.base_url, ICON_XLS)
|
||||
% (self.base_url, scu.ICON_XLS)
|
||||
)
|
||||
if self.xls_link and self.pdf_link:
|
||||
H.append(" ")
|
||||
if self.pdf_link:
|
||||
H.append(
|
||||
' <a href="%s&format=pdf">%s</a>'
|
||||
% (self.base_url, ICON_PDF)
|
||||
% (self.base_url, scu.ICON_PDF)
|
||||
)
|
||||
H.append("</p>")
|
||||
|
||||
@ -483,10 +490,10 @@ class GenTable:
|
||||
"PDF representation: returns a ReportLab's platypus Table instance"
|
||||
r = []
|
||||
try:
|
||||
PDFLOCK.acquire()
|
||||
sco_pdf.PDFLOCK.acquire()
|
||||
r = self._pdf()
|
||||
finally:
|
||||
PDFLOCK.release()
|
||||
sco_pdf.PDFLOCK.release()
|
||||
return r
|
||||
|
||||
def _pdf(self):
|
||||
@ -513,7 +520,7 @@ class GenTable:
|
||||
CellStyle.leading = 1.0 * self.preferences["SCOLAR_FONT_SIZE"] # vertical space
|
||||
LINEWIDTH = 0.5
|
||||
#
|
||||
titles = ["<para><b>%s</b></para>" % x for x in self.get_titles_list()]
|
||||
# titles = ["<para><b>%s</b></para>" % x for x in self.get_titles_list()]
|
||||
pdf_style_list = []
|
||||
Pt = [
|
||||
[Paragraph(SU(str(x)), CellStyle) for x in line]
|
||||
@ -530,10 +537,10 @@ class GenTable:
|
||||
# log('len(Pt)=%s' % len(Pt))
|
||||
# log( 'line lens=%s' % [ len(x) for x in Pt ] )
|
||||
# log( 'style=\n%s' % pdf_style_list)
|
||||
col_min = min([x[1][0] for x in pdf_style_list])
|
||||
col_max = max([x[2][0] for x in pdf_style_list])
|
||||
lin_min = min([x[1][1] for x in pdf_style_list])
|
||||
lin_max = max([x[2][1] for x in pdf_style_list])
|
||||
# col_min = min([x[1][0] for x in pdf_style_list])
|
||||
# col_max = max([x[2][0] for x in pdf_style_list])
|
||||
# lin_min = min([x[1][1] for x in pdf_style_list])
|
||||
# lin_max = max([x[2][1] for x in pdf_style_list])
|
||||
# log('col_min=%s col_max=%s lin_min=%s lin_max=%s' % (col_min, col_max, lin_min, lin_max))
|
||||
T = Table(Pt, repeatRows=1, colWidths=self.pdf_col_widths, style=pdf_style_list)
|
||||
|
||||
@ -559,7 +566,7 @@ class GenTable:
|
||||
The tag names <table> and <row> can be changed using
|
||||
xml_outer_tag and xml_row_tag
|
||||
"""
|
||||
doc = jaxml.XML_document(encoding=SCO_ENCODING)
|
||||
doc = jaxml.XML_document(encoding=scu.SCO_ENCODING)
|
||||
getattr(doc, self.xml_outer_tag)(
|
||||
id=self.table_id, origin=self.origin or "", caption=self.caption or ""
|
||||
)
|
||||
@ -593,7 +600,7 @@ class GenTable:
|
||||
v = str(v)
|
||||
r[cid] = v
|
||||
d.append(r)
|
||||
return json.dumps(d, encoding=SCO_ENCODING)
|
||||
return json.dumps(d, encoding=scu.SCO_ENCODING)
|
||||
|
||||
def make_page(
|
||||
self,
|
||||
@ -637,11 +644,11 @@ class GenTable:
|
||||
return "\n".join(H)
|
||||
elif format == "pdf":
|
||||
objects = self.pdf()
|
||||
doc = pdf_basic_page(
|
||||
doc = sco_pdf.pdf_basic_page(
|
||||
objects, title=title, preferences=self.preferences, context=context
|
||||
)
|
||||
if publish:
|
||||
return sendPDFFile(REQUEST, doc, filename + ".pdf")
|
||||
return scu.sendPDFFile(REQUEST, doc, filename + ".pdf")
|
||||
else:
|
||||
return doc
|
||||
elif format == "xls":
|
||||
@ -653,16 +660,16 @@ class GenTable:
|
||||
elif format == "text":
|
||||
return self.text()
|
||||
elif format == "csv":
|
||||
return sendCSVFile(REQUEST, self.text(), filename + ".csv")
|
||||
return scu.sendCSVFile(REQUEST, self.text(), filename + ".csv")
|
||||
elif format == "xml":
|
||||
xml = self.xml()
|
||||
if REQUEST and publish:
|
||||
REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE)
|
||||
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
|
||||
return xml
|
||||
elif format == "json":
|
||||
js = self.json()
|
||||
if REQUEST and publish:
|
||||
REQUEST.RESPONSE.setHeader("content-type", JSON_MIMETYPE)
|
||||
REQUEST.RESPONSE.setHeader("content-type", scu.JSON_MIMETYPE)
|
||||
return js
|
||||
else:
|
||||
log("make_page: format=%s" % format)
|
||||
@ -687,7 +694,7 @@ class SeqGenTable:
|
||||
def excel(self):
|
||||
"""Export des genTables dans un unique fichier excel avec plusieurs feuilles tagguées"""
|
||||
book = sco_excel.Workbook() # Le fichier xls en devenir
|
||||
for (name, gt) in self.genTables.items():
|
||||
for (_, gt) in self.genTables.items():
|
||||
gt.excel(wb=book) # Ecrit dans un fichier excel
|
||||
return book.savetostr()
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -257,6 +257,5 @@ def sco_header(
|
||||
|
||||
|
||||
def sco_footer(context, REQUEST=None):
|
||||
"""Main HTMl pages footer
|
||||
"""
|
||||
"""Main HTMl pages footer"""
|
||||
return """</div><!-- /gtrcontent -->""" + CUSTOM_HTML_FOOTER + """</body></html>"""
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -158,8 +158,7 @@ def sidebar(context, REQUEST=None):
|
||||
|
||||
|
||||
def sidebar_dept(context, REQUEST=None):
|
||||
"""Partie supérieure de la marge de gauche
|
||||
"""
|
||||
"""Partie supérieure de la marge de gauche"""
|
||||
infos = {
|
||||
"BASE0": REQUEST.BASE0,
|
||||
"DeptIntranetTitle": context.get_preference("DeptIntranetTitle"),
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -49,7 +49,7 @@ def histogram_notes(notes):
|
||||
"HTML code drawing histogram"
|
||||
if not notes:
|
||||
return ""
|
||||
bins, H = listhistogram.ListHistogram(notes, 21, minmax=(0, 20))
|
||||
_, H = listhistogram.ListHistogram(notes, 21, minmax=(0, 20))
|
||||
D = ['<ul id="vhist-q-graph"><li class="vhist-qtr" id="vhist-q1"><ul>']
|
||||
left = 5
|
||||
colwidth = 16 # must match #q-graph li.bar width in stylesheet
|
||||
|
100
intervals.py
100
intervals.py
@ -10,53 +10,53 @@ from itertools import izip
|
||||
|
||||
class intervalmap(object):
|
||||
"""
|
||||
This class maps a set of intervals to a set of values.
|
||||
|
||||
>>> i = intervalmap()
|
||||
>>> i[0:5] = '0-5'
|
||||
>>> i[8:12] = '8-12'
|
||||
>>> print i[2]
|
||||
0-5
|
||||
>>> print i[10]
|
||||
8-12
|
||||
>>> print repr(i[-1])
|
||||
None
|
||||
>>> print repr(i[17])
|
||||
None
|
||||
>>> i[4:9] = '4-9'
|
||||
>>> print [(j,i[j]) for j in range(6)]
|
||||
[(0, '0-5'), (1, '0-5'), (2, '0-5'), (3, '0-5'), (4, '4-9'), (5, '4-9')]
|
||||
>>> print list(i.items())
|
||||
[((0, 4), '0-5'), ((4, 9), '4-9'), ((9, 12), '8-12')]
|
||||
>>> i[:0] = 'less than 0'
|
||||
>>> i[-5]
|
||||
'less than 0'
|
||||
>>> i[0]
|
||||
'0-5'
|
||||
>>> print list(i.items())
|
||||
[((None, 0), 'less than 0'), ((0, 4), '0-5'), ((4, 9), '4-9'), ((9, 12), '8-12')]
|
||||
>>> i[21:] = 'more than twenty'
|
||||
>>> i[42]
|
||||
'more than twenty'
|
||||
>>> i[10.5:15.5] = '10.5-15.5'
|
||||
>>> i[11.5]
|
||||
'10.5-15.5'
|
||||
>>> i[0.5]
|
||||
'0-5'
|
||||
>>> print list(i.items())
|
||||
[((None, 0),... ((9, 10.5), '8-12'), ((10.5, 15.5), '10.5-15.5'), ((21, None),...
|
||||
>>> i = intervalmap()
|
||||
>>> i[0:2] = 1
|
||||
>>> i[2:8] = 2
|
||||
>>> i[4:] = 3
|
||||
>>> i[5:6] = 4
|
||||
>>> i
|
||||
{[0, 2] => 1, [2, 4] => 2, [4, 5] => 3, [5, 6] => 4, [6, None] => 3}
|
||||
This class maps a set of intervals to a set of values.
|
||||
|
||||
>>> i = intervalmap()
|
||||
>>> i[0:5] = '0-5'
|
||||
>>> i[8:12] = '8-12'
|
||||
>>> print i[2]
|
||||
0-5
|
||||
>>> print i[10]
|
||||
8-12
|
||||
>>> print repr(i[-1])
|
||||
None
|
||||
>>> print repr(i[17])
|
||||
None
|
||||
>>> i[4:9] = '4-9'
|
||||
>>> print [(j,i[j]) for j in range(6)]
|
||||
[(0, '0-5'), (1, '0-5'), (2, '0-5'), (3, '0-5'), (4, '4-9'), (5, '4-9')]
|
||||
>>> print list(i.items())
|
||||
[((0, 4), '0-5'), ((4, 9), '4-9'), ((9, 12), '8-12')]
|
||||
>>> i[:0] = 'less than 0'
|
||||
>>> i[-5]
|
||||
'less than 0'
|
||||
>>> i[0]
|
||||
'0-5'
|
||||
>>> print list(i.items())
|
||||
[((None, 0), 'less than 0'), ((0, 4), '0-5'), ((4, 9), '4-9'), ((9, 12), '8-12')]
|
||||
>>> i[21:] = 'more than twenty'
|
||||
>>> i[42]
|
||||
'more than twenty'
|
||||
>>> i[10.5:15.5] = '10.5-15.5'
|
||||
>>> i[11.5]
|
||||
'10.5-15.5'
|
||||
>>> i[0.5]
|
||||
'0-5'
|
||||
>>> print list(i.items())
|
||||
[((None, 0),... ((9, 10.5), '8-12'), ((10.5, 15.5), '10.5-15.5'), ((21, None),...
|
||||
>>> i = intervalmap()
|
||||
>>> i[0:2] = 1
|
||||
>>> i[2:8] = 2
|
||||
>>> i[4:] = 3
|
||||
>>> i[5:6] = 4
|
||||
>>> i
|
||||
{[0, 2] => 1, [2, 4] => 2, [4, 5] => 3, [5, 6] => 4, [6, None] => 3}
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Initializes an empty intervalmap.
|
||||
Initializes an empty intervalmap.
|
||||
"""
|
||||
self._bounds = []
|
||||
self._items = []
|
||||
@ -64,7 +64,7 @@ class intervalmap(object):
|
||||
|
||||
def __setitem__(self, _slice, _value):
|
||||
"""
|
||||
Sets an interval mapping.
|
||||
Sets an interval mapping.
|
||||
"""
|
||||
assert isinstance(_slice, slice), "The key must be a slice object"
|
||||
|
||||
@ -112,7 +112,7 @@ class intervalmap(object):
|
||||
|
||||
def __getitem__(self, _point):
|
||||
"""
|
||||
Gets a value from the mapping.
|
||||
Gets a value from the mapping.
|
||||
"""
|
||||
assert not isinstance(_point, slice), "The key cannot be a slice object"
|
||||
|
||||
@ -124,9 +124,9 @@ class intervalmap(object):
|
||||
|
||||
def items(self):
|
||||
"""
|
||||
Returns an iterator with each item being
|
||||
((low_bound,high_bound), value). The items are returned
|
||||
in order.
|
||||
Returns an iterator with each item being
|
||||
((low_bound,high_bound), value). The items are returned
|
||||
in order.
|
||||
"""
|
||||
previous_bound = None
|
||||
for b, v in izip(self._bounds, self._items):
|
||||
@ -138,8 +138,8 @@ class intervalmap(object):
|
||||
|
||||
def values(self):
|
||||
"""
|
||||
Returns an iterator with each item being a stored value. The items
|
||||
are returned in order.
|
||||
Returns an iterator with each item being a stored value. The items
|
||||
are returned in order.
|
||||
"""
|
||||
for v in self._items:
|
||||
if v is not None:
|
||||
|
@ -394,7 +394,7 @@ CREATE TABLE notes_formsemestre (
|
||||
elt_annee_apo text -- code element annee Apogee, eg VRT1A ou V2INLA,V2INCA
|
||||
) WITH OIDS;
|
||||
|
||||
-- id des utilsateurs responsables (aka directeurs des etudes) du semestre:
|
||||
-- id des utilisateurs responsables (aka directeurs des etudes) du semestre:
|
||||
CREATE TABLE notes_formsemestre_responsables (
|
||||
formsemestre_id text REFERENCES notes_formsemestre(formsemestre_id) ON DELETE CASCADE,
|
||||
responsable_id text NOT NULL,
|
||||
|
@ -51,5 +51,5 @@ telephone; text; adresse; 1; num. telephone (fixe)
|
||||
telephonemobile; text; adresse; 1; num. telephone (mobile)
|
||||
#
|
||||
# Pas tout à fait admission:
|
||||
debouche;text; admissions;1;situation APRES être passé par chez nous;
|
||||
debouche;text; admissions;1;(OBSOLETE, ne plus utiliser) situation APRES être passé par chez nous;
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -61,5 +61,5 @@ class CacheFunc:
|
||||
|
||||
def inval_cache(self): # >
|
||||
"clear whole cache"
|
||||
log("inval_cache %s(%s)" % (str(self.func), str(args))) # >
|
||||
log("inval_cache %s" % (str(self.func))) # >
|
||||
self.cache = {}
|
||||
|
@ -35,7 +35,7 @@ class _logguer:
|
||||
if LOG_FILENAME:
|
||||
path = os.path.join(self.directory, LOG_FILENAME)
|
||||
self.file = open(path, "a")
|
||||
self("new _logguer")
|
||||
self("new _logguer (%s)" % path)
|
||||
else:
|
||||
self.file = None # logging disabled
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -51,7 +51,7 @@ BONUS_TWO_ARGS = len(inspect.getargspec(CONFIG.compute_bonus)[0]) == 2
|
||||
|
||||
|
||||
def comp_ranks(T):
|
||||
"""Calcul rangs à partir d'une liste ordonnée de tuples [ (valeur, ..., etudid) ]
|
||||
"""Calcul rangs à partir d'une liste ordonnée de tuples [ (valeur, ..., etudid) ]
|
||||
(valeur est une note numérique), en tenant compte des ex-aequos
|
||||
Le resultat est: { etudid : rang } où rang est une chaine decrivant le rang
|
||||
"""
|
||||
@ -135,8 +135,8 @@ class NotesTable:
|
||||
- inscrlist: étudiants inscrits à ce semestre, par ordre alphabétique (avec demissions)
|
||||
- identdict: { etudid : ident }
|
||||
- sem : le formsemestre
|
||||
get_table_moyennes_triees: [ (moy_gen, moy_ue1, moy_ue2, ... moy_ues, moy_mod1, ..., moy_modn, etudid) ]
|
||||
(où toutes les valeurs sont soit des nombrs soit des chaines spéciales comme 'NA', 'NI'),
|
||||
get_table_moyennes_triees: [ (moy_gen, moy_ue1, moy_ue2, ... moy_ues, moy_mod1, ..., moy_modn, etudid) ]
|
||||
(où toutes les valeurs sont soit des nombrs soit des chaines spéciales comme 'NA', 'NI'),
|
||||
incluant les UE de sport
|
||||
|
||||
- bonus[etudid] : valeur du bonus "sport".
|
||||
@ -145,7 +145,7 @@ class NotesTable:
|
||||
- _modmoys : { moduleimpl_id : { etudid: note_moyenne_dans_ce_module } }
|
||||
- _ues : liste des UE de ce semestre (hors capitalisees)
|
||||
- _matmoys : { matiere_id : { etudid: note moyenne dans cette matiere } }
|
||||
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, context, formsemestre_id):
|
||||
@ -408,7 +408,7 @@ class NotesTable:
|
||||
|
||||
def get_ues(self, filter_sport=False, filter_non_inscrit=False, etudid=None):
|
||||
"""liste des ue, ordonnée par numero.
|
||||
Si filter_non_inscrit, retire les UE dans lesquelles l'etudiant n'est
|
||||
Si filter_non_inscrit, retire les UE dans lesquelles l'etudiant n'est
|
||||
inscrit à aucun module.
|
||||
Si filter_sport, retire les UE de type SPORT
|
||||
"""
|
||||
@ -580,11 +580,11 @@ class NotesTable:
|
||||
return matmoy.get(etudid, "NA")
|
||||
|
||||
def comp_etud_moy_ue(self, etudid, ue_id=None, cnx=None):
|
||||
"""Calcule moyenne gen. pour un etudiant dans une UE
|
||||
"""Calcule moyenne gen. pour un etudiant dans une UE
|
||||
Ne prend en compte que les evaluations où toutes les notes sont entrées
|
||||
Return a dict(moy, nb_notes, nb_missing, sum_coefs)
|
||||
Si pas de notes, moy == 'NA' et sum_coefs==0
|
||||
Si non inscrit, moy == 'NI' et sum_coefs==0
|
||||
Si non inscrit, moy == 'NI' et sum_coefs==0
|
||||
"""
|
||||
assert ue_id
|
||||
modimpls = self.get_modimpls(ue_id)
|
||||
@ -608,7 +608,6 @@ class NotesTable:
|
||||
est_inscrit = False # inscrit à l'un des modules de cette UE ?
|
||||
|
||||
for modimpl in modimpls:
|
||||
mod_ue_id = modimpl["ue"]["ue_id"]
|
||||
# module ne faisant pas partie d'une UE capitalisee
|
||||
val = self._modmoys[modimpl["moduleimpl_id"]].get(etudid, "NI")
|
||||
# si 'NI', etudiant non inscrit a ce module
|
||||
@ -711,7 +710,7 @@ class NotesTable:
|
||||
def comp_etud_moy_gen(self, etudid, cnx):
|
||||
"""Calcule moyenne gen. pour un etudiant
|
||||
Return a dict:
|
||||
moy : moyenne générale
|
||||
moy : moyenne générale
|
||||
nb_notes, nb_missing, sum_coefs
|
||||
ects_pot : (float) nb de crédits ECTS qui seraient validés (sous réserve de validation par le jury),
|
||||
ects_pot_fond: (float) nb d'ECTS issus d'UE fondamentales (non électives)
|
||||
@ -721,14 +720,14 @@ class NotesTable:
|
||||
'est_inscrit' : True si étudiant inscrit à au moins un module de cette UE
|
||||
'moy' : moyenne, avec capitalisation eventuelle
|
||||
'coef_ue' : coef de l'UE utilisé pour le calcul de la moyenne générale
|
||||
(la somme des coefs des modules, ou le coef d'UE capitalisée,
|
||||
(la somme des coefs des modules, ou le coef d'UE capitalisée,
|
||||
ou encore le coef d'UE si l'option use_ue_coefs est active)
|
||||
'cur_moy_ue' : moyenne de l'UE en cours (sans considérer de capitalisation)
|
||||
'cur_coef_ue': coefficient de l'UE courante
|
||||
'is_capitalized' : True|False,
|
||||
'ects_pot' : (float) nb de crédits ECTS qui seraient validés (sous réserve de validation par le jury),
|
||||
'ects_pot_fond': 0. si UE non fondamentale, = ects_pot sinon,
|
||||
'ects_pot_pro' : 0 si UE non pro, = ects_pot sinon,
|
||||
'ects_pot_fond': 0. si UE non fondamentale, = ects_pot sinon,
|
||||
'ects_pot_pro' : 0 si UE non pro, = ects_pot sinon,
|
||||
'formsemestre_id' : (si capitalisee),
|
||||
'event_date' : (si capitalisee)
|
||||
}
|
||||
@ -760,7 +759,6 @@ class NotesTable:
|
||||
sem_ects_pot_pro = 0.0
|
||||
|
||||
for ue in self.get_ues():
|
||||
ue_id = ue["ue_id"]
|
||||
# - On calcule la moyenne d'UE courante:
|
||||
if not block_computation:
|
||||
mu = self.comp_etud_moy_ue(etudid, ue_id=ue["ue_id"], cnx=cnx)
|
||||
@ -956,10 +954,10 @@ class NotesTable:
|
||||
Ne considère que les UE ayant des notes (moyenne calculée).
|
||||
(les UE sans notes ne sont pas comptées comme sous la barre)
|
||||
Prend en compte les éventuelles UE capitalisées.
|
||||
|
||||
|
||||
Pour les parcours habituels, cela revient à vérifier que
|
||||
les moyennes d'UE sont toutes > à leur barre (sauf celles sans notes)
|
||||
|
||||
|
||||
Pour les parcours non standards (LP2014), cela peut être plus compliqué.
|
||||
|
||||
Return: True|False, message explicatif
|
||||
@ -1000,8 +998,7 @@ class NotesTable:
|
||||
)
|
||||
|
||||
def get_table_moyennes_dict(self):
|
||||
"""{ etudid : (liste des moyennes) } comme get_table_moyennes_triees
|
||||
"""
|
||||
"""{ etudid : (liste des moyennes) } comme get_table_moyennes_triees"""
|
||||
D = {}
|
||||
for t in self.T:
|
||||
D[t[-1]] = t
|
||||
@ -1209,13 +1206,13 @@ class NotesTable:
|
||||
# return sum(c_list)
|
||||
|
||||
def get_etud_ue_cap_coef(self, etudid, ue, ue_cap, cnx=None):
|
||||
"""Calcule le coefficient d'une UE capitalisée, pour cet étudiant,
|
||||
"""Calcule le coefficient d'une UE capitalisée, pour cet étudiant,
|
||||
injectée dans le semestre courant.
|
||||
|
||||
ue : ue du semestre courant
|
||||
|
||||
|
||||
ue_cap = resultat de formsemestre_get_etud_capitalisation
|
||||
{ 'ue_id' (dans le semestre source),
|
||||
{ 'ue_id' (dans le semestre source),
|
||||
'ue_code', 'moy', 'event_date','formsemestre_id' }
|
||||
"""
|
||||
# log("get_etud_ue_cap_coef\nformsemestre_id='%s'\netudid='%s'\nue=%s\nue_cap=%s\n" % (self.formsemestre_id, etudid, ue, ue_cap))
|
||||
@ -1291,8 +1288,7 @@ class NotesTable:
|
||||
return len(cursor.fetchall()) > 0
|
||||
|
||||
def get_evaluations_etats(self): # evaluation_list_in_sem
|
||||
"""[ {...evaluation et son etat...} ]
|
||||
"""
|
||||
"""[ {...evaluation et son etat...} ]"""
|
||||
if self._evaluations_etats is None:
|
||||
self._evaluations_etats = sco_evaluations.do_evaluation_list_in_sem(
|
||||
self.context, self.formsemestre_id
|
||||
@ -1301,13 +1297,11 @@ class NotesTable:
|
||||
return self._evaluations_etats
|
||||
|
||||
def get_sem_evaluation_etat_list(self):
|
||||
"""Liste des evaluations de ce semestre, avec leur etat
|
||||
"""
|
||||
"""Liste des evaluations de ce semestre, avec leur etat"""
|
||||
return self.get_evaluations_etats()
|
||||
|
||||
def get_mod_evaluation_etat_list(self, moduleimpl_id):
|
||||
"""Liste des évaluations de ce module
|
||||
"""
|
||||
"""Liste des évaluations de ce module"""
|
||||
return [
|
||||
e
|
||||
for e in self.get_evaluations_etats()
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -248,8 +248,7 @@ def DBDelete(cnx, table, colid, val, commit=False):
|
||||
|
||||
|
||||
class EditableTable:
|
||||
""" --- generic class: SQL table with create/edit/list/delete
|
||||
"""
|
||||
"""--- generic class: SQL table with create/edit/list/delete"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -377,7 +376,11 @@ class EditableTable:
|
||||
# format value
|
||||
for title in vals.keys():
|
||||
if self.input_formators.has_key(title):
|
||||
vals[title] = self.input_formators[title](vals[title])
|
||||
try:
|
||||
vals[title] = self.input_formators[title](vals[title])
|
||||
except:
|
||||
log("exception while converting %s=%s" % (title, vals[title]))
|
||||
raise
|
||||
DBUpdateArgs(
|
||||
cnx,
|
||||
self.table_name,
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
36
pe_jurype.py
36
pe_jurype.py
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -88,7 +88,7 @@ class JuryPE:
|
||||
{'etudid : { 'nom', 'prenom', 'sexe', 'diplome', '', }}
|
||||
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
|
||||
|
||||
|
||||
|
||||
Note (EV:): les attributs sont des chaines encodées (utf8), comme dans ScoDoc (pas des unicodes)
|
||||
"""
|
||||
@ -210,8 +210,7 @@ class JuryPE:
|
||||
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
def get_zipped_data(self):
|
||||
"""returns zipped data with all generated (CSV) files
|
||||
"""
|
||||
"""returns zipped data with all generated (CSV) files"""
|
||||
if self.zipfile:
|
||||
self.zipfile.close()
|
||||
self.zipfile = None
|
||||
@ -366,7 +365,7 @@ class JuryPE:
|
||||
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
def add_etudiants(self, etudid):
|
||||
""" Ajoute un étudiant (via son etudid) au dictionnaire de synthèse jurydict.
|
||||
"""Ajoute un étudiant (via son etudid) au dictionnaire de synthèse jurydict.
|
||||
L'ajout consiste à :
|
||||
> insérer une entrée pour l'étudiant en mémorisant ses infos (get_etudInfo),
|
||||
avec son nom, prénom, etc...
|
||||
@ -479,7 +478,7 @@ class JuryPE:
|
||||
pour autant avoir été indiqué NAR ou DEM ; recherche son dernier semestre validé et regarde s'il
|
||||
n'existe pas parmi les semestres existants dans scodoc un semestre postérieur (en terme de date de
|
||||
début) de n° au moins égal à celui de son dernier semestre valide dans lequel il aurait pu
|
||||
s'inscrire mais ne l'a pas fait. """
|
||||
s'inscrire mais ne l'a pas fait."""
|
||||
sessems = self.get_semestresDUT_d_un_etudiant(
|
||||
etudid
|
||||
) # les semestres de l'étudiant
|
||||
@ -868,9 +867,7 @@ class JuryPE:
|
||||
return semDeb["annee_debut"]
|
||||
|
||||
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]
|
||||
sems = self.get_semestresDUT_d_un_etudiant(etudid)
|
||||
|
||||
@ -934,7 +931,7 @@ class JuryPE:
|
||||
|
||||
def get_allTagForAggregat(self, nom_aggregat):
|
||||
"""Extrait du dictionnaire syntheseJury la liste des tags d'un semestre ou
|
||||
d'un aggrégat donné par son nom (S1, S2, S3 ou S4, 1A, ...). Renvoie [] si aucun tag."""
|
||||
d'un aggrégat donné par son nom (S1, S2, S3 ou S4, 1A, ...). Renvoie [] si aucun tag."""
|
||||
taglist = set()
|
||||
for etudid in self.get_etudids_du_jury():
|
||||
taglist = taglist.union(
|
||||
@ -1127,10 +1124,9 @@ class JuryPE:
|
||||
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
def get_cache_notes_d_un_semestre(
|
||||
cls, context, formsemestre_id
|
||||
self, context, formsemestre_id
|
||||
): # inutile en realité !
|
||||
"""Charge la table des notes d'un formsemestre
|
||||
"""
|
||||
"""Charge la table des notes d'un formsemestre"""
|
||||
return context.Notes._getNotesCache().get_NotesTable(
|
||||
context.Notes, formsemestre_id
|
||||
)
|
||||
@ -1196,7 +1192,7 @@ class JuryPE:
|
||||
|
||||
# ----------------------------------------------------------------------------------------
|
||||
def get_annee_diplome_semestre(sem):
|
||||
""" Pour un semestre donne, décrit par le biais du dictionnaire sem usuel :
|
||||
"""Pour un semestre donne, décrit par le biais du dictionnaire sem usuel :
|
||||
sem = {'formestre_id': ..., 'semestre_id': ..., 'annee_debut': ...},
|
||||
à condition qu'il soit un semestre de formation DUT,
|
||||
predit l'annee à laquelle sera remis le diplome DUT des etudiants scolarisés dans le semestre
|
||||
@ -1230,12 +1226,12 @@ def get_annee_diplome_semestre(sem):
|
||||
|
||||
# ----------------------------------------------------------------------------------
|
||||
def get_cosemestres_diplomants(context, semBase, avec_meme_formation=False):
|
||||
""" Partant d'un semestre de Base = {'formsemestre_id': ..., 'semestre_id': ..., 'annee_debut': ...},
|
||||
renvoie la liste de tous ses co-semestres (lui-meme inclus)
|
||||
Par co-semestre, s'entend les semestres :
|
||||
> dont l'annee predite pour la remise du diplome DUT est la meme
|
||||
> dont la formation est la même (optionnel)
|
||||
> ne prenant en compte que les etudiants sans redoublement
|
||||
"""Partant d'un semestre de Base = {'formsemestre_id': ..., 'semestre_id': ..., 'annee_debut': ...},
|
||||
renvoie la liste de tous ses co-semestres (lui-meme inclus)
|
||||
Par co-semestre, s'entend les semestres :
|
||||
> dont l'annee predite pour la remise du diplome DUT est la meme
|
||||
> dont la formation est la même (optionnel)
|
||||
> ne prenant en compte que les etudiants sans redoublement
|
||||
"""
|
||||
tousLesSems = (
|
||||
context.Notes.formsemestre_list()
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -144,8 +144,7 @@ class SetTag(pe_tagtable.TableTag):
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------------------
|
||||
def do_tagdict(self):
|
||||
"""Synthétise la liste des modules pris en compte dans le calcul d'un tag (pour analyse des résultats)
|
||||
"""
|
||||
"""Synthétise la liste des modules pris en compte dans le calcul d'un tag (pour analyse des résultats)"""
|
||||
self.tagdict = {}
|
||||
for semtag in self.SemTagDict.values():
|
||||
for tag in semtag.get_all_tags():
|
||||
@ -208,8 +207,8 @@ class SetTag(pe_tagtable.TableTag):
|
||||
|
||||
class SetTagInterClasse(pe_tagtable.TableTag):
|
||||
"""Récupère les moyennes de SetTag aggrégant un même parcours (par ex un ['S1', 'S2'] n'ayant pas fini au même S2
|
||||
pour fournir un interclassement sur un groupe d'étudiant => seul compte alors la promo
|
||||
nom_combinaison = 'S1' ou '1A'
|
||||
pour fournir un interclassement sur un groupe d'étudiant => seul compte alors la promo
|
||||
nom_combinaison = 'S1' ou '1A'
|
||||
"""
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -95,7 +95,7 @@ class TableTag:
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
def get_coeff_from_resultats(self, tag, etudid):
|
||||
"""Renvoie la somme des coeffs de pondération normalisée utilisés dans le calcul de la moyenne à un tag d'un étudiant
|
||||
"""Renvoie la somme des coeffs de pondération normalisée utilisés dans le calcul de la moyenne à un tag d'un étudiant
|
||||
au regard du format de self.resultats.
|
||||
"""
|
||||
return (
|
||||
@ -329,7 +329,7 @@ def moyenne_ponderee_terme_a_terme(notes, coeffs=None, force=False):
|
||||
|
||||
# -------------------------------------------------------------------------------------------
|
||||
def conversionDate_StrToDate(date_fin):
|
||||
""" Conversion d'une date fournie sous la forme d'une chaine de caractère de
|
||||
"""Conversion d'une date fournie sous la forme d'une chaine de caractère de
|
||||
type 'jj/mm/aaaa' en un objet date du package datetime.
|
||||
Fonction servant au tri des semestres par date
|
||||
"""
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -89,7 +89,7 @@ def pe_view_sem_recap(
|
||||
REQUEST=None,
|
||||
):
|
||||
"""Génération des avis de poursuite d'étude
|
||||
|
||||
|
||||
mode_debug = Pour "squeezer" le calcul du jury pe (long)
|
||||
et debugger uniquement la partie avis latex
|
||||
"""
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
111
sco_abs_views.py
111
sco_abs_views.py
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -53,8 +53,7 @@ def doSignaleAbsence(
|
||||
description=None,
|
||||
REQUEST=None,
|
||||
): # etudid implied
|
||||
"""Signalement d'une absence
|
||||
"""
|
||||
"""Signalement d'une absence"""
|
||||
etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0]
|
||||
etudid = etud["etudid"]
|
||||
|
||||
@ -124,21 +123,51 @@ def doSignaleAbsence(
|
||||
|
||||
|
||||
def SignaleAbsenceEtud(context, REQUEST=None): # etudid implied
|
||||
"""Formulaire individuel simple de signalement d'une absence
|
||||
"""
|
||||
"""Formulaire individuel simple de signalement d'une absence"""
|
||||
# brute-force portage from very old dtml code ...
|
||||
etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0]
|
||||
etudid = etud["etudid"]
|
||||
disabled = False
|
||||
if not etud["cursem"]:
|
||||
menu_module = ""
|
||||
require_module = context.get_preference(
|
||||
"abs_require_module"
|
||||
) # on utilise la pref globale car pas de sem courant
|
||||
if require_module:
|
||||
menu_module = """<div class="ue_warning">Pas inscrit dans un semestre courant,
|
||||
et l'indication du module est requise. Donc pas de saisie d'absence possible !</div>"""
|
||||
disabled = True
|
||||
else:
|
||||
menu_module = ""
|
||||
else:
|
||||
formsemestre_id = etud["cursem"]["formsemestre_id"]
|
||||
require_module = context.get_preference("abs_require_module", formsemestre_id)
|
||||
nt = context.Notes._getNotesCache().get_NotesTable(
|
||||
context.Notes, formsemestre_id
|
||||
)
|
||||
ues = nt.get_ues(etudid=etudid)
|
||||
menu_module = """<p><select name="moduleimpl_id">
|
||||
<option value="NULL" selected>(Module)</option>"""
|
||||
if require_module:
|
||||
menu_module = """
|
||||
<script type="text/javascript">
|
||||
function form_enable_disable() {
|
||||
if ( $("select#sel_moduleimpl_id").val() == "NULL" ) {
|
||||
$("#butsubmit").prop("disabled", true);
|
||||
} else {
|
||||
$("#butsubmit").prop("disabled", false);
|
||||
};
|
||||
}
|
||||
$(document).ready(function() {
|
||||
form_enable_disable();
|
||||
});
|
||||
</script>
|
||||
<p>Module:
|
||||
<select id="sel_moduleimpl_id" name="moduleimpl_id"
|
||||
onChange="form_enable_disable();">"""
|
||||
else:
|
||||
menu_module = (
|
||||
"""<p>Module: <select id="sel_moduleimpl_id" name="moduleimpl_id">"""
|
||||
)
|
||||
menu_module += """<option value="NULL" selected>(Module)</option>"""
|
||||
|
||||
for ue in ues:
|
||||
modimpls = nt.get_modimpls(ue_id=ue["ue_id"])
|
||||
for modimpl in modimpls:
|
||||
@ -162,7 +191,10 @@ def SignaleAbsenceEtud(context, REQUEST=None): # etudid implied
|
||||
% etud,
|
||||
"""<a href="%s/ficheEtud?etudid=%s">""" % (context.ScoURL(), etud["etudid"]),
|
||||
sco_photos.etud_photo_html(
|
||||
context, etudid=etudid, title="fiche de " + etud["nomprenom"], REQUEST=REQUEST
|
||||
context,
|
||||
etudid=etudid,
|
||||
title="fiche de " + etud["nomprenom"],
|
||||
REQUEST=REQUEST,
|
||||
),
|
||||
"""</a></td></tr></table>""",
|
||||
"""
|
||||
@ -170,35 +202,40 @@ def SignaleAbsenceEtud(context, REQUEST=None): # etudid implied
|
||||
<input type="hidden" name="etudid" value="%(etudid)s">
|
||||
<p>
|
||||
<table><tr>
|
||||
<td>Date début : </td>
|
||||
<td>Date début : </td>
|
||||
<td><input type="text" name="datedebut" size="10" class="datepicker"/> <em>j/m/a</em></td>
|
||||
<td> Date Fin (optionnel):</td>
|
||||
<td> Date fin (optionnelle):</td>
|
||||
<td><input type="text" name="datefin" size="10" class="datepicker"/> <em>j/m/a</em></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
<input type="radio" name="demijournee" value="2" checked>journée(s)
|
||||
<input type="radio" name="demijournee" value="2" checked>Journée(s)
|
||||
<input type="radio" name="demijournee" value="1">Matin(s)
|
||||
<input type="radio" name="demijournee" value="0">Après midi
|
||||
<input type="radio" name="demijournee" value="0">Après-midi
|
||||
|
||||
%(menu_module)s
|
||||
|
||||
<p>
|
||||
<input type="checkbox" name="estjust"/>Absence justifiée.
|
||||
<input type="checkbox" name="estjust"/>Absence justifiée.
|
||||
<br/>
|
||||
Raison: <input type="text" name="description" size="42"/> (optionnel)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input type="submit" value="Envoyer"/>
|
||||
<input id="butsubmit" type="submit" value="Envoyer" disable="%(disabled)s"/>
|
||||
<em>
|
||||
<p>Seuls les modules du semestre en cours apparaissent.</p><p> Evitez de saisir une absence pour un module qui n'est pas en place à cette date.</p>
|
||||
<p>Toutes les dates sont au format jour/mois/annee</p>
|
||||
<p>Seuls les modules du semestre en cours apparaissent.</p>
|
||||
<p>Évitez de saisir une absence pour un module qui n'est pas en place à cette date.</p>
|
||||
<p>Toutes les dates sont au format jour/mois/annee.</p>
|
||||
</em>
|
||||
|
||||
</form>
|
||||
"""
|
||||
% {"etudid": etud["etudid"], "menu_module": menu_module},
|
||||
% {
|
||||
"etudid": etud["etudid"],
|
||||
"menu_module": menu_module,
|
||||
"disabled": "disabled" if disabled else "",
|
||||
},
|
||||
context.sco_footer(REQUEST),
|
||||
]
|
||||
return "\n".join(H)
|
||||
@ -207,8 +244,7 @@ Raison: <input type="text" name="description" size="42"/> (optionnel)
|
||||
def doJustifAbsence(
|
||||
context, datedebut, datefin, demijournee, description=None, REQUEST=None
|
||||
): # etudid implied
|
||||
"""Justification d'une absence
|
||||
"""
|
||||
"""Justification d'une absence"""
|
||||
etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0]
|
||||
etudid = etud["etudid"]
|
||||
description_abs = description
|
||||
@ -274,8 +310,7 @@ def doJustifAbsence(
|
||||
|
||||
|
||||
def JustifAbsenceEtud(context, REQUEST=None): # etudid implied
|
||||
"""Formulaire individuel simple de justification d'une absence
|
||||
"""
|
||||
"""Formulaire individuel simple de justification d'une absence"""
|
||||
# brute-force portage from very old dtml code ...
|
||||
etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0]
|
||||
etudid = etud["etudid"]
|
||||
@ -290,7 +325,10 @@ def JustifAbsenceEtud(context, REQUEST=None): # etudid implied
|
||||
% etud,
|
||||
"""<a href="%s/ficheEtud?etudid=%s">""" % (context.ScoURL(), etud["etudid"]),
|
||||
sco_photos.etud_photo_html(
|
||||
context, etudid=etudid, title="fiche de " + etud["nomprenom"], REQUEST=REQUEST
|
||||
context,
|
||||
etudid=etudid,
|
||||
title="fiche de " + etud["nomprenom"],
|
||||
REQUEST=REQUEST,
|
||||
),
|
||||
"""</a></td></tr></table>""",
|
||||
"""
|
||||
@ -309,7 +347,7 @@ def JustifAbsenceEtud(context, REQUEST=None): # etudid implied
|
||||
</table>
|
||||
<br/>
|
||||
|
||||
<input type="radio" name="demijournee" value="2" checked>journée(s)
|
||||
<input type="radio" name="demijournee" value="2" checked>Journée(s)
|
||||
<input type="radio" name="demijournee" value="1">Matin(s)
|
||||
<input type="radio" name="demijournee" value="0">Après midi
|
||||
|
||||
@ -329,8 +367,7 @@ Raison: <input type="text" name="description" size="42"/> (optionnel)
|
||||
def doAnnuleAbsence(
|
||||
context, datedebut, datefin, demijournee, REQUEST=None
|
||||
): # 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]
|
||||
etudid = etud["etudid"]
|
||||
|
||||
@ -378,8 +415,7 @@ autre absence pour <b>%(nomprenom)s</b></a></li>
|
||||
|
||||
|
||||
def AnnuleAbsenceEtud(context, REQUEST=None): # etudid implied
|
||||
"""Formulaire individuel simple d'annulation d'une absence
|
||||
"""
|
||||
"""Formulaire individuel simple d'annulation d'une absence"""
|
||||
# brute-force portage from very old dtml code ...
|
||||
etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0]
|
||||
etudid = etud["etudid"]
|
||||
@ -395,7 +431,10 @@ def AnnuleAbsenceEtud(context, REQUEST=None): # etudid implied
|
||||
% etud, # "
|
||||
"""<a href="%s/ficheEtud?etudid=%s">""" % (context.ScoURL(), etud["etudid"]),
|
||||
sco_photos.etud_photo_html(
|
||||
context, etudid=etudid, title="fiche de " + etud["nomprenom"], REQUEST=REQUEST
|
||||
context,
|
||||
etudid=etudid,
|
||||
title="fiche de " + etud["nomprenom"],
|
||||
REQUEST=REQUEST,
|
||||
),
|
||||
"""</a></td></tr></table>""",
|
||||
"""<p>A n'utiliser que suite à une erreur de saisie ou lorsqu'il s'avère que l'étudiant était en fait présent. </p>
|
||||
@ -464,14 +503,13 @@ def AnnuleAbsenceEtud(context, REQUEST=None): # etudid implied
|
||||
def doAnnuleJustif(
|
||||
context, datedebut0, datefin0, demijournee, REQUEST=None
|
||||
): # etudid implied
|
||||
"""Annulation d'une justification
|
||||
"""
|
||||
"""Annulation d'une justification"""
|
||||
etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0]
|
||||
etudid = etud["etudid"]
|
||||
dates = context.DateRangeISO(datedebut0, datefin0)
|
||||
nbadded = 0
|
||||
for jour in dates:
|
||||
# Attention: supprime matin et après midi
|
||||
# Attention: supprime matin et après-midi
|
||||
if demijournee == "2":
|
||||
context._AnnuleJustif(etudid, jour, False, REQUEST=REQUEST)
|
||||
context._AnnuleJustif(etudid, jour, True, REQUEST=REQUEST)
|
||||
@ -551,7 +589,6 @@ def formChoixSemestreGroupe(context, all=False):
|
||||
if not sems:
|
||||
raise ScoValueError("aucun semestre !")
|
||||
H = ['<select name="group_ids">']
|
||||
nbgroups = 0
|
||||
for sem in sems:
|
||||
for p in sco_groups.get_partitions_list(context, sem["formsemestre_id"]):
|
||||
for group in sco_groups.get_partition_groups(context, p):
|
||||
@ -569,8 +606,7 @@ def formChoixSemestreGroupe(context, all=False):
|
||||
|
||||
|
||||
def CalAbs(context, REQUEST=None): # etud implied
|
||||
"""Calendrier des absences d un etudiant
|
||||
"""
|
||||
"""Calendrier des absences d un etudiant"""
|
||||
# crude portage from 1999 DTML
|
||||
etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0]
|
||||
etudid = etud["etudid"]
|
||||
@ -621,7 +657,10 @@ def CalAbs(context, REQUEST=None): # etud implied
|
||||
context.ScoURL(),
|
||||
etudid,
|
||||
sco_photos.etud_photo_html(
|
||||
context, etudid=etudid, title="fiche de " + etud["nomprenom"], REQUEST=REQUEST
|
||||
context,
|
||||
etudid=etudid,
|
||||
title="fiche de " + etud["nomprenom"],
|
||||
REQUEST=REQUEST,
|
||||
),
|
||||
),
|
||||
CalHTML,
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -62,8 +62,7 @@ _help_txt = """
|
||||
|
||||
|
||||
def apo_compare_csv_form(context, REQUEST=None):
|
||||
"""Form: submit 2 CSV files to compare them.
|
||||
"""
|
||||
"""Form: submit 2 CSV files to compare them."""
|
||||
H = [
|
||||
context.sco_header(REQUEST, page_title="Comparaison de fichiers Apogée"),
|
||||
"""<h2>Comparaison de fichiers Apogée</h2>
|
||||
@ -90,8 +89,7 @@ def apo_compare_csv_form(context, REQUEST=None):
|
||||
|
||||
|
||||
def apo_compare_csv(context, A_file, B_file, autodetect=True, REQUEST=None):
|
||||
"""Page comparing 2 Apogee CSV files
|
||||
"""
|
||||
"""Page comparing 2 Apogee CSV files"""
|
||||
A = _load_apo_data(A_file, autodetect=autodetect)
|
||||
B = _load_apo_data(B_file, autodetect=autodetect)
|
||||
|
||||
@ -182,7 +180,11 @@ def _apo_compare_csv(context, A, B, REQUEST=None):
|
||||
elts_only_B = B_elts - A_elts.intersection(B_elts)
|
||||
L.append(
|
||||
'<span class="val_dif">différents (%d en commun, %d seulement dans A, %d seulement dans B)</span>'
|
||||
% (len(elts_communs), len(elts_only_A), len(elts_only_B),)
|
||||
% (
|
||||
len(elts_communs),
|
||||
len(elts_only_A),
|
||||
len(elts_only_B),
|
||||
)
|
||||
)
|
||||
if elts_only_A:
|
||||
L.append(
|
||||
@ -244,8 +246,7 @@ def _apo_compare_csv(context, A, B, REQUEST=None):
|
||||
|
||||
|
||||
def apo_table_compare_etud_results(context, A, B, REQUEST=None):
|
||||
"""
|
||||
"""
|
||||
""""""
|
||||
D = compare_etuds_res(A, B)
|
||||
T = GenTable(
|
||||
rows=D,
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -112,8 +112,7 @@ APO_NEWLINE = "\r\n"
|
||||
|
||||
|
||||
def code_scodoc_to_apo(code):
|
||||
"""Conversion code jury ScoDoc en code Apogée
|
||||
"""
|
||||
"""Conversion code jury ScoDoc en code Apogée"""
|
||||
return {
|
||||
ATT: "AJAC",
|
||||
ATB: "AJAC",
|
||||
@ -159,7 +158,7 @@ def fix_data_encoding(
|
||||
text, default_source_encoding=APO_INPUT_ENCODING, dest_encoding=APO_INPUT_ENCODING
|
||||
):
|
||||
"""Try to ensure that text is using dest_encoding
|
||||
returns converted text, and a message describing the conversion.
|
||||
returns converted text, and a message describing the conversion.
|
||||
"""
|
||||
message = ""
|
||||
detected_encoding = guess_data_encoding(text)
|
||||
@ -241,8 +240,7 @@ VOID_APO_RES = dict(N="", B="", J="", R="", M="")
|
||||
|
||||
|
||||
class ApoEtud(dict):
|
||||
"""Etudiant Apogee:
|
||||
"""
|
||||
"""Etudiant Apogee:"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -361,7 +359,7 @@ class ApoEtud(dict):
|
||||
Autres éléments: résultats du semestre ou de l'année scolaire:
|
||||
=> VRTW1: code additionnel au semestre ("code élement semestre", elt_sem_apo)
|
||||
=> VRT1A: le même que le VET: ("code élement annuel", elt_annee_apo)
|
||||
Attention, si le semestre couvre plusieurs étapes, indiquer les codes des éléments,
|
||||
Attention, si le semestre couvre plusieurs étapes, indiquer les codes des éléments,
|
||||
séparés par des virgules.
|
||||
|
||||
Args:
|
||||
@ -369,7 +367,7 @@ class ApoEtud(dict):
|
||||
sem (dict): semestre dans lequel on cherche l'élément
|
||||
cur_sem (dict): semestre "courant" pour résultats annuels (VET)
|
||||
autre_sem (dict): autre semestre utilisé pour calculé les résultats annuels (VET)
|
||||
|
||||
|
||||
Returns:
|
||||
dict: with N, B, J, R keys, ou None si elt non trouvé
|
||||
"""
|
||||
@ -701,8 +699,7 @@ class ApoData:
|
||||
self.periode = periode
|
||||
|
||||
def setup(self, context):
|
||||
"""Recherche semestres ScoDoc concernés
|
||||
"""
|
||||
"""Recherche semestres ScoDoc concernés"""
|
||||
self.context = context
|
||||
self.sems_etape = comp_apo_sems(context, self.etape_apogee, self.annee_scolaire)
|
||||
self.etape_formsemestre_ids = {s["formsemestre_id"] for s in self.sems_etape}
|
||||
@ -803,7 +800,7 @@ class ApoData:
|
||||
Clé: id apogée, eg 'V1RT', 'V1GE2201', ...
|
||||
Valeur: ApoElt, avec les attributs code, type_objet
|
||||
|
||||
Si les id Apogée ne sont pas uniques (ce n'est pas garanti), garde le premier
|
||||
Si les id Apogée ne sont pas uniques (ce n'est pas garanti), garde le premier
|
||||
"""
|
||||
elts = collections.OrderedDict()
|
||||
for col_id in sorted(cols.keys(), reverse=True):
|
||||
@ -849,8 +846,7 @@ class ApoData:
|
||||
return L
|
||||
|
||||
def get_etape_apogee(self):
|
||||
"""Le code etape: 'V1RT', donné par le code de l'élément VET
|
||||
"""
|
||||
"""Le code etape: 'V1RT', donné par le code de l'élément VET"""
|
||||
for elt in self.apo_elts.values():
|
||||
if elt.type_objet == "VET":
|
||||
return elt.code
|
||||
@ -893,8 +889,7 @@ class ApoData:
|
||||
f.write(self.column_titles)
|
||||
|
||||
def write_etuds(self, f):
|
||||
"""write apo CSV etuds on f
|
||||
"""
|
||||
"""write apo CSV etuds on f"""
|
||||
for e in self.etuds:
|
||||
fs = [] # e['nip'], e['nom'], e['prenom'], e['naissance'] ]
|
||||
for col_id in self.col_ids:
|
||||
@ -983,8 +978,7 @@ class ApoData:
|
||||
return codes_by_sem
|
||||
|
||||
def build_cr_table(self):
|
||||
"""Table compte rendu des décisions
|
||||
"""
|
||||
"""Table compte rendu des décisions"""
|
||||
CR = [] # tableau compte rendu des decisions
|
||||
for e in self.etuds:
|
||||
cr = {
|
||||
@ -1015,14 +1009,14 @@ class ApoData:
|
||||
|
||||
|
||||
def _apo_read_cols(f):
|
||||
"""Lecture colonnes apo :
|
||||
"""Lecture colonnes apo :
|
||||
Démarre après la balise XX-APO_COLONNES-XX
|
||||
et s'arrête après la balise APO_COL_VAL_FIN
|
||||
|
||||
Colonne Apogee: les champs sont données par la ligne
|
||||
apoL_a01_code de la section XX-APO_COLONNES-XX
|
||||
apoL_a01_code de la section XX-APO_COLONNES-XX
|
||||
col_id est apoL_c0001, apoL_c0002, ...
|
||||
|
||||
|
||||
:return: { col_id : { title : value } }
|
||||
Example: { 'apoL_c0001' : { 'Type Objet' : 'VET', 'Code' : 'V1IN', ... }, ... }
|
||||
"""
|
||||
@ -1116,8 +1110,7 @@ def comp_apo_sems(context, etape_apogee, annee_scolaire):
|
||||
|
||||
|
||||
def nar_etuds_table(context, apo_data, NAR_Etuds):
|
||||
"""Liste les NAR -> excel table
|
||||
"""
|
||||
"""Liste les NAR -> excel table"""
|
||||
code_etape = apo_data.etape_apogee
|
||||
today = datetime.datetime.today().strftime("%d/%m/%y")
|
||||
L = []
|
||||
@ -1186,7 +1179,7 @@ def export_csv_to_apogee(
|
||||
export_res_rat=True,
|
||||
REQUEST=None,
|
||||
):
|
||||
"""Genere un fichier CSV Apogée
|
||||
"""Genere un fichier CSV Apogée
|
||||
à partir d'un fichier CSV Apogée vide (ou partiellement rempli)
|
||||
et des résultats ScoDoc.
|
||||
Si dest_zip, ajoute les fichiers générés à ce zip
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -49,14 +49,12 @@ EtudsArchive = EtudsArchiver()
|
||||
|
||||
|
||||
def can_edit_etud_archive(context, authuser):
|
||||
"""True si l'utilisateur peut modifier les archives etudiantes
|
||||
"""
|
||||
"""True si l'utilisateur peut modifier les archives etudiantes"""
|
||||
return authuser.has_permission(ScoEtudAddAnnotations, context)
|
||||
|
||||
|
||||
def etud_list_archives_html(context, REQUEST, etudid):
|
||||
"""HTML snippet listing archives
|
||||
"""
|
||||
"""HTML snippet listing archives"""
|
||||
can_edit = can_edit_etud_archive(context, REQUEST.AUTHENTICATED_USER)
|
||||
L = []
|
||||
for archive_id in EtudsArchive.list_obj_archives(context, etudid):
|
||||
@ -122,8 +120,7 @@ def add_archives_info_to_etud_list(context, etuds):
|
||||
|
||||
|
||||
def etud_upload_file_form(context, REQUEST, etudid):
|
||||
"""Page with a form to choose and upload a file, with a description.
|
||||
"""
|
||||
"""Page with a form to choose and upload a file, with a description."""
|
||||
# check permission
|
||||
if not can_edit_etud_archive(context, REQUEST.AUTHENTICATED_USER):
|
||||
raise AccessDenied(
|
||||
@ -178,8 +175,7 @@ def etud_upload_file_form(context, REQUEST, etudid):
|
||||
def _store_etud_file_to_new_archive(
|
||||
context, REQUEST, etudid, data, filename, description=""
|
||||
):
|
||||
"""Store data to new archive.
|
||||
"""
|
||||
"""Store data to new archive."""
|
||||
filesize = len(data)
|
||||
if filesize < 10 or filesize > CONFIG.ETUD_MAX_FILE_SIZE:
|
||||
return 0, "Fichier image de taille invalide ! (%d)" % filesize
|
||||
@ -188,8 +184,7 @@ def _store_etud_file_to_new_archive(
|
||||
|
||||
|
||||
def etud_delete_archive(context, REQUEST, etudid, archive_name, dialog_confirmed=False):
|
||||
"""Delete an archive
|
||||
"""
|
||||
"""Delete an archive"""
|
||||
# check permission
|
||||
if not can_edit_etud_archive(context, REQUEST.AUTHENTICATED_USER):
|
||||
raise AccessDenied(
|
||||
@ -218,8 +213,7 @@ def etud_delete_archive(context, REQUEST, etudid, archive_name, dialog_confirmed
|
||||
|
||||
|
||||
def etud_get_archived_file(context, REQUEST, etudid, archive_name, filename):
|
||||
"""Send file to client.
|
||||
"""
|
||||
"""Send file to client."""
|
||||
return EtudsArchive.get_archived_file(
|
||||
context, REQUEST, etudid, archive_name, filename
|
||||
)
|
||||
@ -227,8 +221,7 @@ def etud_get_archived_file(context, REQUEST, etudid, archive_name, filename):
|
||||
|
||||
# --- Upload d'un ensemble de fichiers (pour un groupe d'étudiants)
|
||||
def etudarchive_generate_excel_sample(context, group_id=None, REQUEST=None):
|
||||
"""Feuille excel pour import fichiers etudiants (utilisé pour admissions)
|
||||
"""
|
||||
"""Feuille excel pour import fichiers etudiants (utilisé pour admissions)"""
|
||||
fmt = ImportScolars.sco_import_format()
|
||||
data = ImportScolars.sco_import_generate_excel_sample(
|
||||
fmt,
|
||||
@ -249,8 +242,7 @@ def etudarchive_generate_excel_sample(context, group_id=None, REQUEST=None):
|
||||
|
||||
|
||||
def etudarchive_import_files_form(context, group_id, REQUEST=None):
|
||||
"""Formualaire pour importation fichiers d'un groupe
|
||||
"""
|
||||
"""Formualaire pour importation fichiers d'un groupe"""
|
||||
H = [
|
||||
context.sco_header(
|
||||
REQUEST, page_title="Import de fichiers associés aux étudiants"
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -162,4 +162,4 @@ class Baccalaureat:
|
||||
return self.type() == "G"
|
||||
|
||||
def is_techno(self):
|
||||
return selt.type() == "T"
|
||||
return self.type() == "T"
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -435,8 +435,15 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
|
||||
if mod["mod_moy_txt"][:2] == "NA":
|
||||
mod["mod_moy_txt"] = "-"
|
||||
if is_malus:
|
||||
mod["mod_moy_txt"] = ""
|
||||
mod["mod_coef_txt"] = ""
|
||||
if mod_moy > 0:
|
||||
mod["mod_moy_txt"] = fmt_note(mod_moy)
|
||||
mod["mod_coef_txt"] = "Malus"
|
||||
elif mod_moy < 0:
|
||||
mod["mod_moy_txt"] = fmt_note(-mod_moy)
|
||||
mod["mod_coef_txt"] = "Bonus"
|
||||
else:
|
||||
mod["mod_moy_txt"] = "-"
|
||||
mod["mod_coef_txt"] = "-"
|
||||
else:
|
||||
mod["mod_coef_txt"] = fmt_coef(modimpl["module"]["coefficient"])
|
||||
if mod["mod_moy_txt"] != "NI": # ne montre pas les modules 'non inscrit'
|
||||
@ -517,7 +524,7 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
|
||||
if val == "NP":
|
||||
e["note_txt"] = "nd"
|
||||
e["note_html"] = '<span class="note_nd">nd</span>'
|
||||
e["coef_txt"] = ""
|
||||
e["coef_txt"] = fmt_coef(e["coefficient"])
|
||||
else:
|
||||
# (-0.15) s'affiche "bonus de 0.15"
|
||||
if is_malus:
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -80,8 +80,7 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
|
||||
return [self.buildTableObject(P, pdfTableStyle, colWidths)]
|
||||
|
||||
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
|
||||
authuser = self.authuser
|
||||
@ -130,13 +129,10 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
|
||||
continue # saute les modules où on n'est pas inscrit
|
||||
H.append('<tr class="notes_bulletin_row_mod%s">' % rowstyle)
|
||||
if context.get_preference("bul_show_minmax_mod", formsemestre_id):
|
||||
rang_minmax = (
|
||||
'%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>'
|
||||
% (
|
||||
mod["mod_rang_txt"],
|
||||
fmt_note(mod["stats"]["min"]),
|
||||
fmt_note(mod["stats"]["max"]),
|
||||
)
|
||||
rang_minmax = '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' % (
|
||||
mod["mod_rang_txt"],
|
||||
fmt_note(mod["stats"]["min"]),
|
||||
fmt_note(mod["stats"]["max"]),
|
||||
)
|
||||
else:
|
||||
rang_minmax = mod["mod_rang_txt"] # vide si pas option rang
|
||||
@ -386,8 +382,7 @@ sco_bulletins_generator.register_bulletin_class(BulletinGeneratorLegacy)
|
||||
|
||||
|
||||
class BulTableStyle:
|
||||
"""Construction du style de tables reportlab platypus pour les bulletins "classiques"
|
||||
"""
|
||||
"""Construction du style de tables reportlab platypus pour les bulletins "classiques" """
|
||||
|
||||
LINEWIDTH = 0.5
|
||||
LINECOLOR = Color(0, 0, 0)
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -57,8 +57,7 @@ import os
|
||||
|
||||
|
||||
def form_change_bul_sig(context, side, formsemestre_id=None, REQUEST=None):
|
||||
"""Change pdf signature
|
||||
"""
|
||||
"""Change pdf signature"""
|
||||
filename = _get_sig_existing_filename(
|
||||
context, side, formsemestre_id=formsemestre_id
|
||||
)
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -48,10 +48,22 @@ Balises img: actuellement interdites.
|
||||
"""
|
||||
import traceback, re
|
||||
|
||||
import sco_utils as scu
|
||||
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
|
||||
from notes_log import log
|
||||
from sco_permissions import ScoEtudInscrit
|
||||
from sco_codes_parcours import (
|
||||
UE_COLORS,
|
||||
UE_DEFAULT_COLOR,
|
||||
UE_ELECTIVE,
|
||||
UE_SPORT,
|
||||
UE_STANDARD,
|
||||
)
|
||||
import sco_bulletins_generator
|
||||
import sco_bulletins_pdf
|
||||
import sco_groups
|
||||
@ -271,7 +283,6 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
|
||||
context = self.context
|
||||
P = [] # elems pour générer table avec gen_table (liste de dicts)
|
||||
formsemestre_id = I["formsemestre_id"]
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
prefs = context.get_preferences(formsemestre_id)
|
||||
|
||||
# Colonnes à afficher:
|
||||
@ -328,8 +339,8 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
|
||||
linktmpl = (
|
||||
'<span onclick="toggle_vis_ue(this);" class="toggle_ue">%s</span> '
|
||||
)
|
||||
minuslink = linktmpl % icontag("minus_img", border="0", alt="-")
|
||||
pluslink = linktmpl % icontag("plus_img", border="0", alt="+")
|
||||
minuslink = linktmpl % scu.icontag("minus_img", border="0", alt="-")
|
||||
pluslink = linktmpl % scu.icontag("plus_img", border="0", alt="+")
|
||||
|
||||
# 1er ligne titres
|
||||
t = {
|
||||
@ -384,9 +395,7 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
|
||||
P.append(t)
|
||||
|
||||
# Rangs dans les partitions:
|
||||
partitions, partitions_etud_groups = sco_groups.get_formsemestre_groups(
|
||||
context, formsemestre_id
|
||||
)
|
||||
partitions, _ = sco_groups.get_formsemestre_groups(context, formsemestre_id)
|
||||
for partition in partitions:
|
||||
if partition["bul_show_rank"]:
|
||||
partition_id = partition["partition_id"]
|
||||
@ -486,16 +495,16 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
|
||||
t["_css_row_class"] += " notes_bulletin_row_ue_cur"
|
||||
t["_titre_help"] = "(en cours, non prise en compte)"
|
||||
if prefs["bul_show_minmax"]:
|
||||
t["min"] = fmt_note(ue["min"])
|
||||
t["max"] = fmt_note(ue["max"])
|
||||
t["min"] = scu.fmt_note(ue["min"])
|
||||
t["max"] = scu.fmt_note(ue["max"])
|
||||
if prefs["bul_show_moypromo"]:
|
||||
t["moy"] = fmt_note(ue["moy"]).replace("NA", "-")
|
||||
t["moy"] = scu.fmt_note(ue["moy"]).replace("NA", "-")
|
||||
# Cas particulier des UE sport (bonus)
|
||||
if ue["type"] == UE_SPORT and not ue_descr:
|
||||
del t["module"]
|
||||
del t["coef"]
|
||||
t["_pdf_style"].append(("SPAN", (colidx["note"], 0), (-1, 0)))
|
||||
# t["_module_colspan"] = 3 # non car bug si aucune colonne additionnelle
|
||||
# t["_module_colspan"] = 3 # non car bug si aucune colonne additionnelle
|
||||
# UE électives
|
||||
if ue["type"] == UE_ELECTIVE:
|
||||
t["module"] += " <i>(élective)</i>"
|
||||
@ -544,8 +553,7 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
|
||||
rowstyle="",
|
||||
hidden=False,
|
||||
):
|
||||
"""Liste dans la table les descriptions des modules et, si version != short, des évaluations.
|
||||
"""
|
||||
"""Liste dans la table les descriptions des modules et, si version != short, des évaluations."""
|
||||
if ue_type == "cur": # UE courante non prise en compte (car capitalisee)
|
||||
pdf_style_bg = [("BACKGROUND", (0, 0), (-1, 0), self.PDF_UE_CUR_BG)]
|
||||
else:
|
||||
@ -596,10 +604,10 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
|
||||
"_pdf_style": pdf_style,
|
||||
}
|
||||
if prefs["bul_show_minmax_mod"]:
|
||||
t["min"] = fmt_note(mod["stats"]["min"])
|
||||
t["max"] = fmt_note(mod["stats"]["max"])
|
||||
t["min"] = scu.fmt_note(mod["stats"]["min"])
|
||||
t["max"] = scu.fmt_note(mod["stats"]["max"])
|
||||
if prefs["bul_show_moypromo"]:
|
||||
t["moy"] = fmt_note(mod["stats"]["moy"]).replace("NA", "-")
|
||||
t["moy"] = scu.fmt_note(mod["stats"]["moy"]).replace("NA", "-")
|
||||
P.append(t)
|
||||
|
||||
if self.version != "short":
|
||||
@ -660,12 +668,15 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
|
||||
t["note"] = "<i>" + e["note_txt"] + "</i>"
|
||||
else:
|
||||
t["_module_colspan"] = 2
|
||||
if prefs["bul_show_minmax_eval"]:
|
||||
if prefs["bul_show_minmax_eval"] or prefs["bul_show_moypromo"]:
|
||||
etat = sco_evaluations.do_evaluation_etat(
|
||||
self.context, e["evaluation_id"]
|
||||
)
|
||||
t["min"] = fmt_note(etat["mini"])
|
||||
t["max"] = fmt_note(etat["maxi"])
|
||||
if prefs["bul_show_minmax_eval"]:
|
||||
t["min"] = scu.fmt_note(etat["mini"])
|
||||
t["max"] = scu.fmt_note(etat["maxi"])
|
||||
if prefs["bul_show_moypromo"]:
|
||||
t["moy"] = scu.fmt_note(etat["moy"])
|
||||
P.append(t)
|
||||
nbeval += 1
|
||||
return nbeval
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -305,5 +305,4 @@ sco_bulletins_generator.register_bulletin_class(BulletinGeneratorUCAC)
|
||||
|
||||
|
||||
def bulletin_table_ucac(context, I, version=None):
|
||||
"""
|
||||
"""
|
||||
""""""
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -230,6 +230,7 @@ def make_xml_formsemestre_bulletinetud(
|
||||
value=mod_moy,
|
||||
min=fmt_note(modstat["min"]),
|
||||
max=fmt_note(modstat["max"]),
|
||||
moy=fmt_note(modstat["moy"]),
|
||||
)
|
||||
doc._pop()
|
||||
if context.get_preference("bul_show_mod_rangs", formsemestre_id):
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -35,6 +35,7 @@ import thread, time
|
||||
# Cache data
|
||||
class simpleCache:
|
||||
def __init__(self):
|
||||
self.cache = {}
|
||||
self.inval_cache() # >
|
||||
|
||||
def inval_cache(self, key=None): # >
|
||||
@ -56,7 +57,7 @@ class simpleCache:
|
||||
class expiringCache(simpleCache):
|
||||
"""A simple cache wich cache data for a most "duration" seconds.
|
||||
|
||||
This is used for users (which may be updated from external
|
||||
This is used for users (which may be updated from external
|
||||
information systems)
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -315,7 +315,7 @@ def do_moduleimpl_moyennes(context, nt, mod):
|
||||
notes.append(0.0)
|
||||
coefs.append(0.0)
|
||||
coefs_mask.append(0)
|
||||
if nb_notes > 0:
|
||||
if nb_notes > 0 or formula_use_abs:
|
||||
user_moy = compute_user_formula(
|
||||
context,
|
||||
sem,
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -28,12 +28,14 @@
|
||||
"""
|
||||
Rapport (table) avec dernier semestre fréquenté et débouché de chaque étudiant
|
||||
"""
|
||||
|
||||
from types import StringType
|
||||
import safehtml
|
||||
|
||||
from notesdb import *
|
||||
from sco_utils import *
|
||||
import sco_utils as scu
|
||||
import notesdb
|
||||
from notes_log import log
|
||||
import VERSION
|
||||
from sco_exceptions import AccessDenied
|
||||
from scolog import logdb
|
||||
from gen_tables import GenTable
|
||||
import sco_formsemestre
|
||||
@ -42,8 +44,7 @@ import sco_tag_module
|
||||
|
||||
|
||||
def report_debouche_date(context, start_year=None, format="html", REQUEST=None):
|
||||
"""Rapport (table) pour les débouchés des étudiants sortis à partir de l'année indiquée.
|
||||
"""
|
||||
"""Rapport (table) pour les débouchés des étudiants sortis à partir de l'année indiquée."""
|
||||
if not start_year:
|
||||
return report_debouche_ask_date(context, REQUEST=REQUEST)
|
||||
if format == "xls":
|
||||
@ -54,8 +55,8 @@ def report_debouche_date(context, start_year=None, format="html", REQUEST=None):
|
||||
etudids = get_etudids_with_debouche(context, start_year)
|
||||
tab = table_debouche_etudids(context, etudids, keep_numeric=keep_numeric)
|
||||
|
||||
tab.filename = make_filename("debouche_scodoc_%s" % start_year)
|
||||
tab.origin = "Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + ""
|
||||
tab.filename = scu.make_filename("debouche_scodoc_%s" % start_year)
|
||||
tab.origin = "Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + ""
|
||||
tab.caption = "Récapitulatif débouchés à partir du 1/1/%s." % start_year
|
||||
tab.base_url = "%s?start_year=%s" % (REQUEST.URL0, start_year)
|
||||
return tab.make_page(
|
||||
@ -77,7 +78,7 @@ def get_etudids_with_debouche(context, start_year):
|
||||
start_date = str(start_year) + "-01-01"
|
||||
# Recupere tous les etudid avec un debouché renseigné et une inscription dans un semestre
|
||||
# posterieur à la date de depart:
|
||||
# r = SimpleDictFetch(context,
|
||||
# r = notesdb.SimpleDictFetch(context,
|
||||
# """SELECT DISTINCT i.etudid
|
||||
# FROM notes_formsemestre_inscription i, admissions adm, notes_formsemestre s
|
||||
# WHERE adm.debouche is not NULL
|
||||
@ -86,7 +87,7 @@ def get_etudids_with_debouche(context, start_year):
|
||||
# """,
|
||||
# {'start_date' : start_date })
|
||||
|
||||
r = SimpleDictFetch(
|
||||
r = notesdb.SimpleDictFetch(
|
||||
context,
|
||||
"""SELECT DISTINCT i.etudid
|
||||
FROM notes_formsemestre_inscription i, notes_formsemestre s, itemsuivi it
|
||||
@ -100,8 +101,7 @@ def get_etudids_with_debouche(context, start_year):
|
||||
|
||||
|
||||
def table_debouche_etudids(context, etudids, keep_numeric=True):
|
||||
"""Rapport pour ces etudiants
|
||||
"""
|
||||
"""Rapport pour ces etudiants"""
|
||||
L = []
|
||||
for etudid in etudids:
|
||||
etud = context.getEtudInfo(filled=1, etudid=etudid)[0]
|
||||
@ -122,7 +122,7 @@ def table_debouche_etudids(context, etudids, keep_numeric=True):
|
||||
"_prenom_target": "ficheEtud?etudid=" + etud["etudid"],
|
||||
"_nom_td_attrs": 'id="%s" class="etudinfo"' % (etud["etudid"]),
|
||||
# 'debouche' : etud['debouche'],
|
||||
"moy": fmt_note(nt.get_etud_moy_gen(etudid), keep_numeric=keep_numeric),
|
||||
"moy": scu.fmt_note(nt.get_etud_moy_gen(etudid), keep_numeric=keep_numeric),
|
||||
"rang": nt.get_etud_rang(etudid),
|
||||
"effectif": len(nt.T),
|
||||
"semestre_id": last_sem["semestre_id"],
|
||||
@ -189,8 +189,7 @@ def table_debouche_etudids(context, etudids, keep_numeric=True):
|
||||
|
||||
|
||||
def report_debouche_ask_date(context, REQUEST=None):
|
||||
"""Formulaire demande date départ
|
||||
"""
|
||||
"""Formulaire demande date départ"""
|
||||
return (
|
||||
context.sco_header(REQUEST)
|
||||
+ """<form method="GET">
|
||||
@ -223,14 +222,17 @@ def report_debouche_ask_date(context, REQUEST=None):
|
||||
# admission_edit(cnx, adm)
|
||||
|
||||
|
||||
_itemsuiviEditor = EditableTable(
|
||||
_itemsuiviEditor = notesdb.EditableTable(
|
||||
"itemsuivi",
|
||||
"itemsuivi_id",
|
||||
("itemsuivi_id", "etudid", "item_date", "situation"),
|
||||
sortkey="item_date desc",
|
||||
convert_null_outputs_to_empty=True,
|
||||
output_formators={"situation": safehtml.HTML2SafeHTML, "item_date": DateISOtoDMY},
|
||||
input_formators={"item_date": DateDMYtoISO},
|
||||
output_formators={
|
||||
"situation": safehtml.HTML2SafeHTML,
|
||||
"item_date": notesdb.DateISOtoDMY,
|
||||
},
|
||||
input_formators={"item_date": notesdb.DateDMYtoISO},
|
||||
)
|
||||
|
||||
_itemsuivi_create = _itemsuiviEditor.create
|
||||
@ -240,8 +242,7 @@ _itemsuivi_edit = _itemsuiviEditor.edit
|
||||
|
||||
|
||||
class ItemSuiviTag(sco_tag_module.ScoTag):
|
||||
"""Les tags sur les items
|
||||
"""
|
||||
"""Les tags sur les items"""
|
||||
|
||||
tag_table = "itemsuivi_tags" # table (tag_id, title)
|
||||
assoc_table = "itemsuivi_tags_assoc" # table (tag_id, object_id)
|
||||
@ -259,8 +260,7 @@ def itemsuivi_get(cnx, itemsuivi_id, ignore_errors=False):
|
||||
|
||||
|
||||
def itemsuivi_suppress(context, itemsuivi_id, REQUEST=None):
|
||||
"""Suppression d'un item
|
||||
"""
|
||||
"""Suppression d'un item"""
|
||||
if not context.can_edit_suivi(REQUEST):
|
||||
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
||||
cnx = context.GetDBConnexion()
|
||||
@ -285,7 +285,7 @@ def itemsuivi_create(
|
||||
log("created itemsuivi %s for %s" % (itemsuivi_id, etudid))
|
||||
item = itemsuivi_get(cnx, itemsuivi_id)
|
||||
if format == "json":
|
||||
return sendJSON(REQUEST, item)
|
||||
return scu.sendJSON(REQUEST, item)
|
||||
return item
|
||||
|
||||
|
||||
@ -313,7 +313,7 @@ def itemsuivi_set_situation(context, object, value, REQUEST=None):
|
||||
item = itemsuivi_get(cnx, itemsuivi_id)
|
||||
item["situation"] = situation
|
||||
_itemsuivi_edit(cnx, item)
|
||||
return situation or IT_SITUATION_MISSING_STR
|
||||
return situation or scu.IT_SITUATION_MISSING_STR
|
||||
|
||||
|
||||
def itemsuivi_list_etud(context, etudid, format=None, REQUEST=None):
|
||||
@ -323,13 +323,13 @@ def itemsuivi_list_etud(context, etudid, format=None, REQUEST=None):
|
||||
for it in items:
|
||||
it["tags"] = ", ".join(itemsuivi_tag_list(context, it["itemsuivi_id"]))
|
||||
if format == "json":
|
||||
return sendJSON(REQUEST, items)
|
||||
return scu.sendJSON(REQUEST, items)
|
||||
return items
|
||||
|
||||
|
||||
def itemsuivi_tag_list(context, itemsuivi_id):
|
||||
"""les noms de tags associés à cet item"""
|
||||
r = SimpleDictFetch(
|
||||
r = notesdb.SimpleDictFetch(
|
||||
context,
|
||||
"""SELECT t.title
|
||||
FROM itemsuivi_tags_assoc a, itemsuivi_tags t
|
||||
@ -344,17 +344,17 @@ def itemsuivi_tag_list(context, itemsuivi_id):
|
||||
def itemsuivi_tag_search(context, term, REQUEST=None):
|
||||
"""List all used tag names (for auto-completion)"""
|
||||
# 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 = []
|
||||
else:
|
||||
r = SimpleDictFetch(
|
||||
r = notesdb.SimpleDictFetch(
|
||||
context,
|
||||
"SELECT title FROM itemsuivi_tags WHERE title LIKE %(term)s",
|
||||
{"term": term + "%"},
|
||||
)
|
||||
data = [x["title"] for x in r]
|
||||
|
||||
return sendJSON(REQUEST, data)
|
||||
return scu.sendJSON(REQUEST, data)
|
||||
|
||||
|
||||
def itemsuivi_tag_set(context, itemsuivi_id="", taglist=[], REQUEST=None):
|
||||
@ -372,7 +372,7 @@ def itemsuivi_tag_set(context, itemsuivi_id="", taglist=[], REQUEST=None):
|
||||
# log('itemsuivi_tag_set: itemsuivi_id=%s taglist=%s' % (itemsuivi_id, taglist))
|
||||
# Sanity check:
|
||||
cnx = context.GetDBConnexion()
|
||||
item = itemsuivi_get(cnx, itemsuivi_id)
|
||||
_ = itemsuivi_get(cnx, itemsuivi_id)
|
||||
|
||||
newtags = set(taglist)
|
||||
oldtags = set(itemsuivi_tag_list(context, itemsuivi_id))
|
||||
|
16
sco_dept.py
16
sco_dept.py
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -43,8 +43,9 @@ def index_html(context, REQUEST=None, showcodes=0, showsemtable=0):
|
||||
H = []
|
||||
|
||||
# News:
|
||||
rssicon = icontag("rssscodoc_img", title="Flux RSS", border="0")
|
||||
H.append(sco_news.scolar_news_summary_html(context, rssicon=rssicon))
|
||||
# 2020-12-30: abandonne l'icon rss
|
||||
# rssicon = icontag("rssscodoc_img", title="Flux RSS", border="0")
|
||||
H.append(sco_news.scolar_news_summary_html(context)) # , rssicon=rssicon))
|
||||
|
||||
# Avertissement de mise à jour:
|
||||
H.append(sco_up_to_date.html_up_to_date_box(context))
|
||||
@ -169,8 +170,7 @@ Chercher étape courante: <input name="etape_apo" type="text" size="8"></input>
|
||||
|
||||
|
||||
def _sem_table(context, sems):
|
||||
"""Affiche liste des semestres, utilisée pour semestres en cours
|
||||
"""
|
||||
"""Affiche liste des semestres, utilisée pour semestres en cours"""
|
||||
tmpl = """<tr class="%(trclass)s">%(tmpcode)s
|
||||
<td class="semicon">%(lockimg)s <a href="Notes/formsemestre_status?formsemestre_id=%(formsemestre_id)s#groupes">%(groupicon)s</a></td>
|
||||
<td class="datesem">%(mois_debut)s</td><td class="datesem"><a title="%(session_id)s">-</a> %(mois_fin)s</td>
|
||||
@ -202,8 +202,7 @@ def _sem_table(context, sems):
|
||||
|
||||
|
||||
def _sem_table_gt(context, sems, showcodes=False):
|
||||
"""Nouvelle version de la table des semestres
|
||||
"""
|
||||
"""Nouvelle version de la table des semestres"""
|
||||
_style_sems(context, sems)
|
||||
columns_ids = (
|
||||
"lockimg",
|
||||
@ -241,8 +240,7 @@ def _sem_table_gt(context, sems, showcodes=False):
|
||||
|
||||
|
||||
def _style_sems(context, sems):
|
||||
"""ajoute quelques attributs de présentation pour la table
|
||||
"""
|
||||
"""ajoute quelques attributs de présentation pour la table"""
|
||||
for sem in sems:
|
||||
sem["_groupicon_target"] = (
|
||||
"Notes/formsemestre_status?formsemestre_id=%(formsemestre_id)s" % sem
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -114,8 +114,7 @@ def sco_dump_and_send_db(context, REQUEST=None):
|
||||
|
||||
finally:
|
||||
# Drop anonymized database
|
||||
_drop_ano_db(ano_db_name)
|
||||
|
||||
# XXX _drop_ano_db(ano_db_name)
|
||||
# Remove lock
|
||||
fcntl.flock(x, fcntl.LOCK_UN)
|
||||
|
||||
@ -153,7 +152,7 @@ def _anonymize_db(ano_db_name):
|
||||
cmd = os.path.join(SCO_TOOLS_DIR, "anonymize_db.py")
|
||||
log("_anonymize_db: {}".format(cmd))
|
||||
try:
|
||||
out = subprocess.check_output([cmd, ano_db_name])
|
||||
subprocess.check_output([cmd, ano_db_name])
|
||||
except subprocess.CalledProcessError as e:
|
||||
log("sco_dump_and_send_db: exception in anonymisation: {}".format(e))
|
||||
raise ScoValueError(
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -37,8 +37,7 @@ import sco_formsemestre
|
||||
|
||||
|
||||
def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST=None):
|
||||
"""Delete a formation
|
||||
"""
|
||||
"""Delete a formation"""
|
||||
F = context.formation_list(args={"formation_id": formation_id})
|
||||
if not F:
|
||||
raise ScoValueError("formation inexistante !")
|
||||
@ -89,14 +88,12 @@ def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST
|
||||
|
||||
|
||||
def formation_create(context, REQUEST=None):
|
||||
"""Creation d'une formation
|
||||
"""
|
||||
"""Creation d'une formation"""
|
||||
return formation_edit(context, create=True, REQUEST=REQUEST)
|
||||
|
||||
|
||||
def formation_edit(context, formation_id=None, create=False, REQUEST=None):
|
||||
"""Edit or create a formation
|
||||
"""
|
||||
"""Edit or create a formation"""
|
||||
if create:
|
||||
H = [
|
||||
context.sco_header(REQUEST, page_title="Création d'une formation"),
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -36,8 +36,7 @@ import sco_formsemestre
|
||||
|
||||
|
||||
def matiere_create(context, ue_id=None, REQUEST=None):
|
||||
"""Creation d'une matiere
|
||||
"""
|
||||
"""Creation d'une matiere"""
|
||||
UE = context.do_ue_list(args={"ue_id": ue_id})[0]
|
||||
H = [
|
||||
context.sco_header(REQUEST, page_title="Création d'une matière"),
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -55,8 +55,7 @@ saisir et modifier les notes de ce module.
|
||||
|
||||
|
||||
def module_create(context, matiere_id=None, REQUEST=None):
|
||||
"""Creation d'un module
|
||||
"""
|
||||
"""Creation d'un module"""
|
||||
if not matiere_id:
|
||||
raise ScoValueError("invalid matiere !")
|
||||
M = context.do_matiere_list(args={"matiere_id": matiere_id})[0]
|
||||
@ -436,8 +435,7 @@ def module_list(context, formation_id, REQUEST=None):
|
||||
|
||||
|
||||
def formation_add_malus_modules(context, formation_id, titre=None, REQUEST=None):
|
||||
"""Création d'un module de "malus" dans chaque UE d'une formation
|
||||
"""
|
||||
"""Création d'un module de "malus" dans chaque UE d'une formation"""
|
||||
ue_list = context.do_ue_list(args={"formation_id": formation_id})
|
||||
|
||||
for ue in ue_list:
|
||||
@ -457,8 +455,7 @@ def formation_add_malus_modules(context, formation_id, titre=None, REQUEST=None)
|
||||
|
||||
|
||||
def ue_add_malus_module(context, ue_id, titre=None, code=None, REQUEST=None):
|
||||
"""Add a malus module in this ue
|
||||
"""
|
||||
"""Add a malus module in this ue"""
|
||||
ue = context.do_ue_list(args={"ue_id": ue_id})[0]
|
||||
|
||||
if titre is None:
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -41,14 +41,12 @@ import sco_tag_module
|
||||
|
||||
|
||||
def ue_create(context, formation_id=None, REQUEST=None):
|
||||
"""Creation d'une UE
|
||||
"""
|
||||
"""Creation d'une UE"""
|
||||
return ue_edit(context, create=True, formation_id=formation_id, REQUEST=REQUEST)
|
||||
|
||||
|
||||
def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None):
|
||||
"""Modification ou creation d'une UE
|
||||
"""
|
||||
"""Modification ou creation d'une UE"""
|
||||
create = int(create)
|
||||
if not create:
|
||||
U = context.do_ue_list(args={"ue_id": ue_id})
|
||||
@ -227,7 +225,7 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None):
|
||||
|
||||
def _add_ue_semestre_id(context, ue_list):
|
||||
"""ajoute semestre_id dans les ue, en regardant le premier module de chacune.
|
||||
Les UE sans modules se voient attribuer le numero UE_SEM_DEFAULT (1000000),
|
||||
Les UE sans modules se voient attribuer le numero UE_SEM_DEFAULT (1000000),
|
||||
qui les place à la fin de la liste.
|
||||
"""
|
||||
for ue in ue_list:
|
||||
@ -281,7 +279,7 @@ def ue_delete(
|
||||
|
||||
|
||||
def ue_list(context, formation_id=None, msg="", REQUEST=None):
|
||||
"""Liste des matières et modules d'une formation, avec liens pour
|
||||
"""Liste des matières et modules d'une formation, avec liens pour
|
||||
editer (si non verrouillée).
|
||||
"""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
@ -781,8 +779,7 @@ def edit_ue_set_code_apogee(context, id=None, value=None, REQUEST=None):
|
||||
|
||||
# ---- Table recap formation
|
||||
def formation_table_recap(context, formation_id, format="html", REQUEST=None):
|
||||
"""
|
||||
"""
|
||||
""""""
|
||||
F = context.formation_list(args={"formation_id": formation_id})
|
||||
if not F:
|
||||
raise ScoValueError("invalid formation_id")
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -67,8 +67,7 @@ def formsemestre_get_ics_url(context, sem):
|
||||
|
||||
|
||||
def formsemestre_load_ics(context, sem):
|
||||
"""Load ics data, from our cache or, when necessary, from external provider
|
||||
"""
|
||||
"""Load ics data, from our cache or, when necessary, from external provider"""
|
||||
# TODO: cacher le résultat
|
||||
ics_url = formsemestre_get_ics_url(context, sem)
|
||||
if not ics_url:
|
||||
@ -86,15 +85,13 @@ def formsemestre_load_ics(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'emplois du temps publié"""
|
||||
cal = formsemestre_load_ics(context, sem)
|
||||
return {e["X-GROUP-ID"].decode("utf8") for e in events}
|
||||
|
||||
|
||||
def get_edt_transcodage_groups(context, formsemestre_id):
|
||||
""" -> { nom_groupe_edt : nom_groupe_scodoc }
|
||||
"""
|
||||
"""-> { nom_groupe_edt : nom_groupe_scodoc }"""
|
||||
# TODO: valider ces données au moment où on enregistre les préférences
|
||||
edt2sco = {}
|
||||
sco2edt = {}
|
||||
@ -161,8 +158,7 @@ for e in events:
|
||||
|
||||
|
||||
def experimental_calendar(context, group_id=None, formsemestre_id=None, REQUEST=None):
|
||||
"""experimental page
|
||||
"""
|
||||
"""experimental page"""
|
||||
return "\n".join(
|
||||
[
|
||||
context.sco_header(
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -190,8 +190,7 @@ def apo_csv_list_stored_etapes(context, annee_scolaire, sem_id=None, etapes=None
|
||||
|
||||
|
||||
def apo_csv_delete(context, archive_id):
|
||||
"""Delete archived CSV
|
||||
"""
|
||||
"""Delete archived CSV"""
|
||||
ApoCSVArchive.delete_archive(archive_id)
|
||||
|
||||
|
||||
@ -224,19 +223,18 @@ def apo_csv_get(context, etape_apo="", annee_scolaire="", sem_id=""):
|
||||
|
||||
|
||||
def apo_get_sem_etapes(context, sem):
|
||||
"""Etapes de ce semestre: pour l'instant, celles déclarées
|
||||
Dans une future version, on pourrait aussi utiliser les étapes
|
||||
d'inscription des étudiants, recupérées via le portail,
|
||||
"""Etapes de ce semestre: pour l'instant, celles déclarées
|
||||
Dans une future version, on pourrait aussi utiliser les étapes
|
||||
d'inscription des étudiants, recupérées via le portail,
|
||||
voir check_paiement_etuds().
|
||||
|
||||
|
||||
:return: list of etape_apo (ApoEtapeVDI instances)
|
||||
"""
|
||||
return sem["etapes"]
|
||||
|
||||
|
||||
def apo_csv_check_etape(context, semset, set_nips, etape_apo):
|
||||
"""Check etape vs set of sems
|
||||
"""
|
||||
"""Check etape vs set of sems"""
|
||||
# Etudiants dans la maquette CSV:
|
||||
csv_data = apo_csv_get(
|
||||
context, etape_apo, semset["annee_scolaire"], semset["sem_id"]
|
||||
@ -254,7 +252,10 @@ def apo_csv_check_etape(context, semset, set_nips, etape_apo):
|
||||
|
||||
return nips_ok, apo_nips, nips_no_apo, nips_no_sco, maq_elems, sem_elems
|
||||
|
||||
def apo_csv_semset_check(context, semset, allow_missing_apo=False, allow_missing_csv=False): # was apo_csv_check
|
||||
|
||||
def apo_csv_semset_check(
|
||||
context, semset, allow_missing_apo=False, allow_missing_csv=False
|
||||
): # was apo_csv_check
|
||||
"""
|
||||
check students in stored maqs vs students in semset
|
||||
Cas à détecter:
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -58,9 +58,7 @@ def apo_semset_maq_status(
|
||||
block_export_res_sdj=True,
|
||||
REQUEST=None,
|
||||
):
|
||||
"""Page statut / tableau de bord
|
||||
|
||||
"""
|
||||
"""Page statut / tableau de bord"""
|
||||
if not semset_id:
|
||||
raise ValueError("invalid null semset_id")
|
||||
semset = sco_semset.SemSet(context, semset_id=semset_id)
|
||||
@ -91,7 +89,9 @@ def apo_semset_maq_status(
|
||||
apo_dups,
|
||||
maq_elems,
|
||||
sem_elems,
|
||||
) = sco_etape_apogee.apo_csv_semset_check(context, semset, allow_missing_apo, allow_missing_csv)
|
||||
) = sco_etape_apogee.apo_csv_semset_check(
|
||||
context, semset, allow_missing_apo, allow_missing_csv
|
||||
)
|
||||
|
||||
if not allow_missing_decisions:
|
||||
ok_for_export &= semset["jury_ok"]
|
||||
@ -265,9 +265,7 @@ def apo_semset_maq_status(
|
||||
)
|
||||
if allow_missing_csv:
|
||||
H.append("checked")
|
||||
H.append(
|
||||
""" >autoriser export même si étapes sans maquettes</input></div>"""
|
||||
)
|
||||
H.append(""" >autoriser export même si étapes sans maquettes</input></div>""")
|
||||
H.append("""</form>""")
|
||||
|
||||
if semset and ok_for_export:
|
||||
@ -295,7 +293,9 @@ def apo_semset_maq_status(
|
||||
H.append(
|
||||
"""<div><label><input type="checkbox" name="block_export_res_etape" value="1" %s %s>%s</input></label></div>"""
|
||||
% checked(
|
||||
block_export_res_etape, "export_res_etape", "résultat de l'étape (VET), sauf si diplôme"
|
||||
block_export_res_etape,
|
||||
"export_res_etape",
|
||||
"résultat de l'étape (VET), sauf si diplôme",
|
||||
)
|
||||
)
|
||||
H.append(
|
||||
@ -424,8 +424,7 @@ def apo_semset_maq_status(
|
||||
|
||||
|
||||
def table_apo_csv_list(context, semset, REQUEST=None):
|
||||
"""Table des archives (triée par date d'archivage)
|
||||
"""
|
||||
"""Table des archives (triée par date d'archivage)"""
|
||||
annee_scolaire = semset["annee_scolaire"]
|
||||
sem_id = semset["sem_id"]
|
||||
|
||||
@ -481,8 +480,7 @@ def table_apo_csv_list(context, semset, REQUEST=None):
|
||||
|
||||
|
||||
def view_apo_etuds(context, semset_id, title="", nips=[], format="html", REQUEST=None):
|
||||
"""Table des étudiants Apogée par nips
|
||||
"""
|
||||
"""Table des étudiants Apogée par nips"""
|
||||
if not semset_id:
|
||||
raise ValueError("invalid null semset_id")
|
||||
semset = sco_semset.SemSet(context, semset_id=semset_id)
|
||||
@ -520,8 +518,7 @@ def view_apo_etuds(context, semset_id, title="", nips=[], format="html", REQUEST
|
||||
def view_scodoc_etuds(
|
||||
context, semset_id, title="", etudids=None, nips=None, format="html", REQUEST=None
|
||||
):
|
||||
"""Table des étudiants ScoDoc par nips ou etudids
|
||||
"""
|
||||
"""Table des étudiants ScoDoc par nips ou etudids"""
|
||||
if etudids is not None:
|
||||
if type(etudids) != type([]):
|
||||
etudids = [etudids]
|
||||
@ -636,8 +633,7 @@ def view_apo_csv_store(
|
||||
|
||||
|
||||
def view_apo_csv_download_and_store(context, etape_apo="", semset_id="", REQUEST=None):
|
||||
"""Download maquette and store it
|
||||
"""
|
||||
"""Download maquette and store it"""
|
||||
if not semset_id:
|
||||
raise ValueError("invalid null semset_id")
|
||||
semset = sco_semset.SemSet(context, semset_id=semset_id)
|
||||
@ -656,8 +652,7 @@ def view_apo_csv_download_and_store(context, etape_apo="", semset_id="", REQUEST
|
||||
def view_apo_csv_delete(
|
||||
context, etape_apo="", semset_id="", dialog_confirmed=False, REQUEST=None
|
||||
):
|
||||
"""Delete CSV file
|
||||
"""
|
||||
"""Delete CSV file"""
|
||||
if not semset_id:
|
||||
raise ValueError("invalid null semset_id")
|
||||
semset = sco_semset.SemSet(context, semset_id=semset_id)
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2019 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -27,15 +27,23 @@
|
||||
|
||||
"""Evaluations
|
||||
"""
|
||||
import time
|
||||
import urllib
|
||||
import operator
|
||||
import datetime
|
||||
|
||||
from notes_log import log, logCallStack
|
||||
from sco_utils import *
|
||||
from notesdb import *
|
||||
import sco_utils as scu
|
||||
from notesdb import ScoDocCursor
|
||||
from sco_exceptions import AccessDenied, ScoValueError
|
||||
import VERSION
|
||||
from gen_tables import GenTable
|
||||
from TrivialFormulator import TrivialFormulator
|
||||
import sco_news
|
||||
import sco_formsemestre
|
||||
import sco_groups
|
||||
import ZAbsences
|
||||
import sco_evaluations
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
#
|
||||
@ -47,7 +55,7 @@ def notes_moyenne_median_mini_maxi(notes):
|
||||
notes = [
|
||||
x
|
||||
for x in notes
|
||||
if (x != None) and (x != NOTES_NEUTRALISE) and (x != NOTES_ATTENTE)
|
||||
if (x != None) and (x != scu.NOTES_NEUTRALISE) and (x != scu.NOTES_ATTENTE)
|
||||
]
|
||||
n = len(notes)
|
||||
if not n:
|
||||
@ -136,8 +144,8 @@ def do_evaluation_etat(
|
||||
NotesDB = context._notes_getall(evaluation_id) # { etudid : value }
|
||||
notes = [x["value"] for x in NotesDB.values()]
|
||||
nb_abs = len([x for x in notes if x is None])
|
||||
nb_neutre = len([x for x in notes if x == NOTES_NEUTRALISE])
|
||||
nb_att = len([x for x in notes if x == NOTES_ATTENTE])
|
||||
nb_neutre = len([x for x in notes if x == scu.NOTES_NEUTRALISE])
|
||||
nb_att = len([x for x in notes if x == scu.NOTES_ATTENTE])
|
||||
moy_num, median_num, mini_num, maxi_num = notes_moyenne_median_mini_maxi(notes)
|
||||
if moy_num is None:
|
||||
median, moy = "", ""
|
||||
@ -145,10 +153,10 @@ def do_evaluation_etat(
|
||||
mini, maxi = "", ""
|
||||
mini_num, maxi_num = None, None
|
||||
else:
|
||||
median = fmt_note(median_num)
|
||||
moy = fmt_note(moy_num)
|
||||
mini = fmt_note(mini_num)
|
||||
maxi = fmt_note(maxi_num)
|
||||
median = scu.fmt_note(median_num)
|
||||
moy = scu.fmt_note(moy_num)
|
||||
mini = scu.fmt_note(mini_num)
|
||||
maxi = scu.fmt_note(maxi_num)
|
||||
# cherche date derniere modif note
|
||||
if len(NotesDB):
|
||||
t = [x["date"] for x in NotesDB.values()]
|
||||
@ -159,7 +167,7 @@ def do_evaluation_etat(
|
||||
E = context.do_evaluation_list(args={"evaluation_id": evaluation_id})[0]
|
||||
M = context.do_moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0]
|
||||
Mod = context.do_module_list(args={"module_id": M["module_id"]})[0]
|
||||
is_malus = Mod["module_type"] == MODULE_MALUS # True si module de malus
|
||||
is_malus = Mod["module_type"] == scu.MODULE_MALUS # True si module de malus
|
||||
formsemestre_id = M["formsemestre_id"]
|
||||
# Si partition_id is None, prend 'all' ou bien la premiere:
|
||||
if partition_id is None:
|
||||
@ -186,8 +194,8 @@ def do_evaluation_etat(
|
||||
|
||||
# On considere une note "manquante" lorsqu'elle n'existe pas
|
||||
# ou qu'elle est en attente (ATT)
|
||||
GrNbMissing = DictDefault() # group_id : nb notes manquantes
|
||||
GrNotes = DictDefault(defaultvalue=[]) # group_id: liste notes valides
|
||||
GrNbMissing = scu.DictDefault() # group_id : nb notes manquantes
|
||||
GrNotes = scu.DictDefault(defaultvalue=[]) # group_id: liste notes valides
|
||||
TotalNbMissing = 0
|
||||
TotalNbAtt = 0
|
||||
groups = {} # group_id : group
|
||||
@ -201,14 +209,14 @@ def do_evaluation_etat(
|
||||
isMissing = False
|
||||
if NotesDB.has_key(i["etudid"]):
|
||||
val = NotesDB[i["etudid"]]["value"]
|
||||
if val == NOTES_ATTENTE:
|
||||
if val == scu.NOTES_ATTENTE:
|
||||
isMissing = True
|
||||
TotalNbAtt += 1
|
||||
if group:
|
||||
GrNotes[group["group_id"]].append(val)
|
||||
else:
|
||||
if group:
|
||||
junk = GrNotes[group["group_id"]] # create group
|
||||
_ = GrNotes[group["group_id"]] # create group
|
||||
isMissing = True
|
||||
if isMissing:
|
||||
TotalNbMissing += 1
|
||||
@ -219,7 +227,7 @@ def do_evaluation_etat(
|
||||
gr_incomplets.sort()
|
||||
if (
|
||||
(TotalNbMissing > 0)
|
||||
and (E["evaluation_type"] != EVALUATION_RATTRAPAGE)
|
||||
and (E["evaluation_type"] != scu.EVALUATION_RATTRAPAGE)
|
||||
and not is_malus
|
||||
):
|
||||
complete = False
|
||||
@ -244,15 +252,15 @@ def do_evaluation_etat(
|
||||
"group_id": group_id,
|
||||
"group_name": groups[group_id]["group_name"],
|
||||
"gr_moy_num": gr_moy,
|
||||
"gr_moy": fmt_note(gr_moy),
|
||||
"gr_moy": scu.fmt_note(gr_moy),
|
||||
"gr_median_num": gr_median,
|
||||
"gr_median": fmt_note(gr_median),
|
||||
"gr_mini": fmt_note(gr_mini),
|
||||
"gr_maxi": fmt_note(gr_maxi),
|
||||
"gr_mini": gr_mini,
|
||||
"gr_maxi": gr_maxi,
|
||||
"gr_median": scu.fmt_note(gr_median),
|
||||
"gr_mini": scu.fmt_note(gr_mini),
|
||||
"gr_maxi": scu.fmt_note(gr_maxi),
|
||||
"gr_mini_num": gr_mini,
|
||||
"gr_maxi_num": gr_maxi,
|
||||
"gr_nb_notes": len(notes),
|
||||
"gr_nb_att": len([x for x in notes if x == NOTES_ATTENTE]),
|
||||
"gr_nb_att": len([x for x in notes if x == scu.NOTES_ATTENTE]),
|
||||
}
|
||||
)
|
||||
gr_moyennes.sort(key=operator.itemgetter("group_name"))
|
||||
@ -337,7 +345,7 @@ def do_evaluation_list_in_sem(context, formsemestre_id):
|
||||
'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 order by moduleimpl_id, numero desc, jour desc, heure_debut desc"
|
||||
cnx = context.GetDBConnexion()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor.execute(req, {"formsemestre_id": formsemestre_id})
|
||||
@ -380,7 +388,7 @@ def _eval_etat(evals):
|
||||
nb_evals_en_cours += 1
|
||||
dates.append(e["etat"]["last_modif"])
|
||||
|
||||
dates = sort_dates(dates)
|
||||
dates = scu.sort_dates(dates)
|
||||
|
||||
if len(dates):
|
||||
last_modif = dates[-1] # date de derniere modif d'une note dans un module
|
||||
@ -511,18 +519,18 @@ def evaluation_date_first_completion(context, evaluation_id):
|
||||
if not etat["evalcomplete"]:
|
||||
return None
|
||||
|
||||
E = context.do_evaluation_list(args={"evaluation_id": evaluation_id})[0]
|
||||
M = context.do_moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0]
|
||||
formsemestre_id = M["formsemestre_id"]
|
||||
|
||||
# XXX inachevé ou à revoir ?
|
||||
# Il faut considerer les inscriptions au semestre
|
||||
# (pour avoir l'etat et le groupe) et aussi les inscriptions
|
||||
# au module (pour gerer les modules optionnels correctement)
|
||||
insem = context.do_formsemestre_inscription_listinscrits(formsemestre_id)
|
||||
insmod = context.do_moduleimpl_inscription_list(moduleimpl_id=E["moduleimpl_id"])
|
||||
insmodset = set([x["etudid"] for x in insmod])
|
||||
# E = context.do_evaluation_list(args={"evaluation_id": evaluation_id})[0]
|
||||
# M = context.do_moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0]
|
||||
# formsemestre_id = M["formsemestre_id"]
|
||||
# insem = context.do_formsemestre_inscription_listinscrits(formsemestre_id)
|
||||
# insmod = context.do_moduleimpl_inscription_list(moduleimpl_id=E["moduleimpl_id"])
|
||||
# insmodset = set([x["etudid"] for x in insmod])
|
||||
# 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]
|
||||
|
||||
notes = context._notes_getall(evaluation_id, filter_suppressed=False).values()
|
||||
notes_log = context._notes_getall(
|
||||
@ -560,8 +568,8 @@ def formsemestre_evaluations_delai_correction(
|
||||
for e in evals:
|
||||
M = context.do_moduleimpl_list(moduleimpl_id=e["moduleimpl_id"])[0]
|
||||
Mod = context.do_module_list(args={"module_id": M["module_id"]})[0]
|
||||
if (e["evaluation_type"] != EVALUATION_NORMALE) or (
|
||||
Mod["module_type"] == MODULE_MALUS
|
||||
if (e["evaluation_type"] != scu.EVALUATION_NORMALE) or (
|
||||
Mod["module_type"] == scu.MODULE_MALUS
|
||||
):
|
||||
continue
|
||||
e["date_first_complete"] = evaluation_date_first_completion(
|
||||
@ -612,8 +620,8 @@ def formsemestre_evaluations_delai_correction(
|
||||
caption="Correction des évaluations du semestre",
|
||||
preferences=context.get_preferences(formsemestre_id),
|
||||
base_url="%s?formsemestre_id=%s" % (REQUEST.URL0, formsemestre_id),
|
||||
origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "",
|
||||
filename=make_filename("evaluations_delais_" + sem["titreannee"]),
|
||||
origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "",
|
||||
filename=scu.make_filename("evaluations_delais_" + sem["titreannee"]),
|
||||
)
|
||||
return tab.make_page(context, format=format, REQUEST=REQUEST)
|
||||
|
||||
@ -727,7 +735,6 @@ def evaluation_describe(context, evaluation_id="", edit_in_place=True, REQUEST=N
|
||||
M = context.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0]
|
||||
Mod = context.do_module_list(args={"module_id": M["module_id"]})[0]
|
||||
formsemestre_id = M["formsemestre_id"]
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
u = context.Users.user_info(M["responsable_id"])
|
||||
resp = u["prenomnom"]
|
||||
nomcomplet = u["nomcomplet"]
|
||||
@ -747,13 +754,13 @@ def evaluation_describe(context, evaluation_id="", edit_in_place=True, REQUEST=N
|
||||
etit = E["description"] or ""
|
||||
if etit:
|
||||
etit = ' "' + etit + '"'
|
||||
if Mod["module_type"] == MODULE_MALUS:
|
||||
if Mod["module_type"] == scu.MODULE_MALUS:
|
||||
etit += ' <span class="eval_malus">(points de malus)</span>'
|
||||
H = [
|
||||
'<span class="eval_title">Evaluation%s</span><p><b>Module : %s</b></p>'
|
||||
% (etit, mod_descr)
|
||||
]
|
||||
if Mod["module_type"] == MODULE_MALUS:
|
||||
if Mod["module_type"] == scu.MODULE_MALUS:
|
||||
# Indique l'UE
|
||||
ue = context.do_ue_list(args={"ue_id": Mod["ue_id"]})[0]
|
||||
H.append("<p><b>UE : %(acronyme)s</b></p>" % ue)
|
||||
@ -804,9 +811,9 @@ def evaluation_create_form(
|
||||
moduleimpl_id = the_eval["moduleimpl_id"]
|
||||
#
|
||||
M = context.do_moduleimpl_withmodule_list(moduleimpl_id=moduleimpl_id)[0]
|
||||
is_malus = M["module"]["module_type"] == MODULE_MALUS # True si module de malus
|
||||
is_malus = M["module"]["module_type"] == scu.MODULE_MALUS # True si module de malus
|
||||
formsemestre_id = M["formsemestre_id"]
|
||||
min_note_max = NOTES_PRECISION # le plus petit bareme possible
|
||||
min_note_max = scu.NOTES_PRECISION # le plus petit bareme possible
|
||||
if not readonly:
|
||||
try:
|
||||
context._evaluation_check_write_access(REQUEST, moduleimpl_id=moduleimpl_id)
|
||||
@ -853,17 +860,16 @@ def evaluation_create_form(
|
||||
# Note maximale actuelle dans cette eval ?
|
||||
etat = do_evaluation_etat(context, evaluation_id)
|
||||
if etat["maxi_num"] is not None:
|
||||
min_note_max = max(NOTES_PRECISION, etat["maxi_num"])
|
||||
min_note_max = max(scu.NOTES_PRECISION, etat["maxi_num"])
|
||||
else:
|
||||
min_note_max = NOTES_PRECISION
|
||||
min_note_max = scu.NOTES_PRECISION
|
||||
#
|
||||
if min_note_max > NOTES_PRECISION:
|
||||
min_note_max_str = fmt_note(min_note_max)
|
||||
if min_note_max > scu.NOTES_PRECISION:
|
||||
min_note_max_str = scu.fmt_note(min_note_max)
|
||||
else:
|
||||
min_note_max_str = "0"
|
||||
#
|
||||
Mod = context.do_module_list(args={"module_id": M["module_id"]})[0]
|
||||
sem = sco_formsemestre.get_formsemestre(context, M["formsemestre_id"])
|
||||
#
|
||||
help = """<div class="help"><p class="help">
|
||||
Le coefficient d'une évaluation n'est utilisé que pour pondérer les évaluations au sein d'un module.
|
||||
@ -973,7 +979,7 @@ def evaluation_create_form(
|
||||
"title": "Notes de 0 à",
|
||||
"explanation": "barème (note max actuelle: %s)" % min_note_max_str,
|
||||
"allow_null": False,
|
||||
"max_value": NOTES_MAX,
|
||||
"max_value": scu.NOTES_MAX,
|
||||
"min_value": min_note_max,
|
||||
},
|
||||
),
|
||||
@ -1008,7 +1014,7 @@ def evaluation_create_form(
|
||||
{
|
||||
"input_type": "menu",
|
||||
"title": "Modalité",
|
||||
"allowed_values": (EVALUATION_NORMALE, EVALUATION_RATTRAPAGE),
|
||||
"allowed_values": (scu.EVALUATION_NORMALE, scu.EVALUATION_RATTRAPAGE),
|
||||
"type": "int",
|
||||
"labels": ("Normale", "Rattrapage"),
|
||||
},
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -237,8 +237,7 @@ class ScoExcelSheet:
|
||||
|
||||
|
||||
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
|
||||
wb = Workbook()
|
||||
ws0 = wb.add_sheet(SheetName.decode(SCO_ENCODING))
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -201,8 +201,7 @@ def _build_results_list(context, dpv_by_sem, etuds_infos):
|
||||
|
||||
|
||||
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(
|
||||
context,
|
||||
"SELECT formsemestre_id FROM notes_formsemestre WHERE date_debut >= %(start_date)s AND date_fin <= %(end_date)s",
|
||||
@ -216,7 +215,7 @@ def scodoc_table_results(
|
||||
):
|
||||
"""Page affichant la table des résultats
|
||||
Les dates sont en dd/mm/yyyy (datepicker javascript)
|
||||
types_parcours est la liste des types de parcours à afficher
|
||||
types_parcours est la liste des types de parcours à afficher
|
||||
(liste de chaines, eg ['100', '210'] )
|
||||
"""
|
||||
log("scodoc_table_results: start_date=%s" % (start_date,)) # XXX
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -216,7 +216,7 @@ def search_etud_in_dept(
|
||||
# Was chercheEtudsInfo()
|
||||
def search_etuds_infos(context, expnom=None, code_nip=None, REQUEST=None):
|
||||
"""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)
|
||||
cnx = context.GetDBConnexion()
|
||||
@ -286,8 +286,7 @@ def search_etud_by_name(context, term, REQUEST=None):
|
||||
|
||||
|
||||
def form_search_etud_in_accessible_depts(context, REQUEST):
|
||||
"""Form recherche etudiants pour page accueil ScoDoc
|
||||
"""
|
||||
"""Form recherche etudiants pour page accueil ScoDoc"""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
# present form only to authenticated users
|
||||
if not authuser.has_role("Authenticated"):
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -644,6 +644,12 @@ def formsemestre_description_table(
|
||||
ModInscrits = context.do_moduleimpl_inscription_list(
|
||||
moduleimpl_id=M["moduleimpl_id"]
|
||||
)
|
||||
enseignants = ", ".join(
|
||||
[
|
||||
context.Users.user_info(m["ens_id"], REQUEST)["nomprenom"]
|
||||
for m in M["ens"]
|
||||
]
|
||||
)
|
||||
l = {
|
||||
"UE": M["ue"]["acronyme"],
|
||||
"Code": M["module"]["code"],
|
||||
@ -652,6 +658,8 @@ def formsemestre_description_table(
|
||||
"Inscrits": len(ModInscrits),
|
||||
"Responsable": context.Users.user_info(M["responsable_id"])["nomprenom"],
|
||||
"_Responsable_class": "scotext",
|
||||
"Enseignants": enseignants,
|
||||
"_Enseignants_class": "scotext",
|
||||
"Coef.": M["module"]["coefficient"],
|
||||
# 'ECTS' : M['module']['ects'],
|
||||
# Lien sur titre -> module
|
||||
@ -689,7 +697,7 @@ def formsemestre_description_table(
|
||||
columns_ids = ["UE", "Code", "Module", "Coef."]
|
||||
if context.get_preference("bul_show_ects", formsemestre_id):
|
||||
columns_ids += ["ects"]
|
||||
columns_ids += ["Inscrits", "Responsable"]
|
||||
columns_ids += ["Inscrits", "Responsable", "Enseignants"]
|
||||
if with_evals:
|
||||
columns_ids += [
|
||||
"jour",
|
||||
@ -899,6 +907,12 @@ def formsemestre_status(context, formsemestre_id=None, REQUEST=None):
|
||||
<th class="resp">Responsable</th>
|
||||
<th class="evals">Evaluations</th></tr>"""
|
||||
)
|
||||
mails_enseignants = set(
|
||||
[
|
||||
context.Users.user_info(ens_id, REQUEST)["email"]
|
||||
for ens_id in sem["responsables"]
|
||||
]
|
||||
) # adr. mail des enseignants
|
||||
for M in Mlist:
|
||||
Mod = M["module"]
|
||||
ModDescr = (
|
||||
@ -915,6 +929,12 @@ def formsemestre_status(context, formsemestre_id=None, REQUEST=None):
|
||||
ModInscrits = context.do_moduleimpl_inscription_list(
|
||||
moduleimpl_id=M["moduleimpl_id"]
|
||||
)
|
||||
mails_enseignants.add(
|
||||
context.Users.user_info(M["responsable_id"], REQUEST)["email"]
|
||||
)
|
||||
mails_enseignants |= set(
|
||||
[context.Users.user_info(m["ens_id"], REQUEST)["email"] for m in M["ens"]]
|
||||
)
|
||||
ue = M["ue"]
|
||||
if prev_ue_id != ue["ue_id"]:
|
||||
prev_ue_id = ue["ue_id"]
|
||||
@ -1039,5 +1059,11 @@ def formsemestre_status(context, formsemestre_id=None, REQUEST=None):
|
||||
)
|
||||
# --- LISTE DES ETUDIANTS
|
||||
H += ['<div id="groupes">', context.make_listes_sem(sem, REQUEST), "</div>"]
|
||||
|
||||
# --- Lien mail enseignants:
|
||||
adrlist = list(mails_enseignants - set([""]))
|
||||
if adrlist:
|
||||
H.append(
|
||||
'<p><a class="stdlink" href="mailto:?cc=%s">Courrier aux %d enseignants du semestre</a></p>'
|
||||
% (",".join(adrlist), len(adrlist))
|
||||
)
|
||||
return "".join(H) + context.sco_footer(REQUEST)
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -480,7 +480,7 @@ def formsemestre_recap_parcours_table(
|
||||
show_details=False,
|
||||
):
|
||||
"""Tableau HTML recap parcours
|
||||
Si with_links, ajoute liens pour modifier decisions (colonne de droite)
|
||||
Si with_links, ajoute liens pour modifier decisions (colonne de droite)
|
||||
sem_info = { formsemestre_id : txt } permet d'ajouter des informations associées à chaque semestre
|
||||
with_all_columns: si faux, pas de colonne "assiduité".
|
||||
"""
|
||||
@ -690,8 +690,7 @@ def formsemestre_recap_parcours_table(
|
||||
def form_decision_manuelle(
|
||||
context, Se, formsemestre_id, etudid, desturl="", sortcol=None
|
||||
):
|
||||
"""Formulaire pour saisie décision manuelle
|
||||
"""
|
||||
"""Formulaire pour saisie décision manuelle"""
|
||||
H = [
|
||||
"""
|
||||
<script type="text/javascript">
|
||||
@ -1033,8 +1032,7 @@ def formsemestre_fix_validation_ues(context, formsemestre_id, REQUEST=None):
|
||||
|
||||
|
||||
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))
|
||||
cnx = context.GetDBConnexion(autocommit=False)
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
@ -1064,7 +1062,7 @@ def formsemestre_validation_suppress_etud(context, formsemestre_id, etudid):
|
||||
|
||||
|
||||
def formsemestre_validate_previous_ue(context, formsemestre_id, etudid, REQUEST=None):
|
||||
"""Form. saisie UE validée hors ScoDoc
|
||||
"""Form. saisie UE validée hors ScoDoc
|
||||
(pour étudiants arrivant avec un UE antérieurement validée).
|
||||
"""
|
||||
etud = context.getEtudInfo(etudid=etudid, filled=True)[0]
|
||||
@ -1205,7 +1203,7 @@ def do_formsemestre_validate_previous_ue(
|
||||
REQUEST=None,
|
||||
):
|
||||
"""Enregistre (ou modifie) validation d'UE (obtenue hors ScoDoc).
|
||||
Si le coefficient est spécifié, modifie le coefficient de
|
||||
Si le coefficient est spécifié, modifie le coefficient de
|
||||
cette UE (utile seulement pour les semestres extérieurs).
|
||||
"""
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
@ -1265,8 +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):
|
||||
"""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(
|
||||
context,
|
||||
"""SELECT SFV.* FROM scolar_formsemestre_validation SFV
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -431,10 +431,10 @@ def groups_table(
|
||||
format: csv, json, xml, xls, allxls, xlsappel, moodlecsv, pdf
|
||||
Si with_codes, ajoute 4 colonnes avec les codes etudid, NIP, INE et etape
|
||||
"""
|
||||
log(
|
||||
"enter groups_table %s: %s"
|
||||
% (groups_infos.members[0]["nom"], groups_infos.members[0].get("etape", "-"))
|
||||
)
|
||||
# log(
|
||||
# "enter groups_table %s: %s"
|
||||
# % (groups_infos.members[0]["nom"], groups_infos.members[0].get("etape", "-"))
|
||||
# )
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
|
||||
with_codes = int(with_codes)
|
||||
@ -798,6 +798,11 @@ def tab_absences_html(context, groups_infos, etat=None, REQUEST=None):
|
||||
"<h3>Absences</h3>",
|
||||
'<ul class="ul_abs">',
|
||||
"<li>",
|
||||
form_choix_saisie_semaine(
|
||||
context, groups_infos, REQUEST=REQUEST
|
||||
), # Ajout Le Havre
|
||||
"</li>",
|
||||
"<li>",
|
||||
form_choix_jour_saisie_hebdo(context, groups_infos, REQUEST=REQUEST),
|
||||
"</li>",
|
||||
"""<li><a class="stdlink" href="Absences/EtatAbsencesGr?%s&debut=%s&fin=%s">Etat des absences du groupe</a></li>"""
|
||||
@ -888,6 +893,37 @@ def form_choix_jour_saisie_hebdo(context, groups_infos, REQUEST=None):
|
||||
return "\n".join(FA)
|
||||
|
||||
|
||||
# Ajout Le Havre
|
||||
# Formulaire saisie absences semaine
|
||||
def form_choix_saisie_semaine(context, groups_infos, REQUEST=None):
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
if not authuser.has_permission(ScoAbsChange, context):
|
||||
return ""
|
||||
sem = groups_infos.formsemestre
|
||||
# construit l'URL "destination"
|
||||
# (a laquelle on revient apres saisie absences)
|
||||
query_args = cgi.parse_qs(REQUEST.QUERY_STRING)
|
||||
moduleimpl_id = query_args.get("moduleimpl_id", [""])[0]
|
||||
if "head_message" in query_args:
|
||||
del query_args["head_message"]
|
||||
destination = "%s?%s" % (REQUEST.URL, urllib.urlencode(query_args, True))
|
||||
destination = destination.replace(
|
||||
"%", "%%"
|
||||
) # car ici utilisee dans un format string !
|
||||
|
||||
DateJour = time.strftime("%d/%m/%Y")
|
||||
datelundi = ZAbsences.ddmmyyyy(DateJour).prev_monday()
|
||||
FA = [] # formulaire avec menu saisi hebdo des absences
|
||||
FA.append('<form action="Absences/SignaleAbsenceGrHebdo" method="get">')
|
||||
FA.append('<input type="hidden" name="datelundi" value="%s"/>' % datelundi)
|
||||
FA.append('<input type="hidden" name="moduleimpl_id" value="%s"/>' % moduleimpl_id)
|
||||
FA.append('<input type="hidden" name="destination" value="%s"/>' % destination)
|
||||
FA.append(groups_infos.get_form_elem())
|
||||
FA.append('<input type="submit" class="button" value="Saisie à la semaine" />')
|
||||
FA.append("</form>")
|
||||
return "\n".join(FA)
|
||||
|
||||
|
||||
def export_groups_as_moodle_csv(context, formsemestre_id=None, REQUEST=None):
|
||||
"""Export all students/groups, in a CSV format suitable for Moodle
|
||||
Each (student,group) will be listed on a separate line
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -45,8 +45,7 @@ import sco_formsemestre
|
||||
def formsemestre_table_etuds_lycees(
|
||||
context, formsemestre_id, group_lycees=True, only_primo=False
|
||||
):
|
||||
"""Récupère liste d'etudiants avec etat et decision.
|
||||
"""
|
||||
"""Récupère liste d'etudiants avec etat et decision."""
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
etuds = sco_report.tsp_etud_list(context, formsemestre_id, only_primo=only_primo)[0]
|
||||
if only_primo:
|
||||
@ -60,8 +59,7 @@ def formsemestre_table_etuds_lycees(
|
||||
|
||||
|
||||
def scodoc_table_etuds_lycees(context, format="html", REQUEST=None):
|
||||
"""Table avec _tous_ les étudiants des semestres non verrouillés de _tous_ les départements.
|
||||
"""
|
||||
"""Table avec _tous_ les étudiants des semestres non verrouillés de _tous_ les départements."""
|
||||
semdepts = sco_formsemestre.scodoc_get_all_unlocked_sems(context)
|
||||
etuds = []
|
||||
for (sem, deptcontext) in semdepts:
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -41,8 +41,7 @@ import sco_codes_parcours
|
||||
|
||||
|
||||
def list_formsemestres_modalites(context, sems):
|
||||
"""Liste ordonnée des modalités présentes dans ces formsemestres
|
||||
"""
|
||||
"""Liste ordonnée des modalités présentes dans ces formsemestres"""
|
||||
modalites = {}
|
||||
for sem in sems:
|
||||
if sem["modalite"] not in modalites:
|
||||
@ -86,8 +85,7 @@ _modaliteEditor = EditableTable(
|
||||
|
||||
|
||||
def do_modalite_list(context, *args, **kw):
|
||||
"""Liste des modalites
|
||||
"""
|
||||
"""Liste des modalites"""
|
||||
cnx = context.GetDBConnexion()
|
||||
return _modaliteEditor.list(cnx, *args, **kw)
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -46,11 +46,11 @@ def moduleimpl_inscriptions_edit(
|
||||
* Gestion des inscriptions
|
||||
Nom TD TA TP (triable)
|
||||
[x] M. XXX YYY - - -
|
||||
|
||||
|
||||
|
||||
|
||||
ajouter TD A, TD B, TP 1, TP 2 ...
|
||||
supprimer TD A, TD B, TP 1, TP 2 ...
|
||||
|
||||
|
||||
* Si pas les droits: idem en readonly
|
||||
"""
|
||||
M = context.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0]
|
||||
@ -131,10 +131,10 @@ def moduleimpl_inscriptions_edit(
|
||||
"""
|
||||
% M
|
||||
)
|
||||
H.append('<table><tr>')
|
||||
H.append("<table><tr>")
|
||||
H.append(_make_menu(context, partitions, "Ajouter", "true"))
|
||||
H.append(_make_menu(context, partitions, "Enlever", "false"))
|
||||
H.append('</tr></table>')
|
||||
H.append("</tr></table>")
|
||||
H.append(
|
||||
"""
|
||||
<p><br/></p>
|
||||
@ -217,14 +217,10 @@ def _make_menu_old_xxx(context, partitions, title="", check="true"):
|
||||
|
||||
return "".join(H)
|
||||
|
||||
|
||||
def _make_menu(context, partitions, title="", check="true"):
|
||||
"""Menu with list of all groups"""
|
||||
items = [
|
||||
{
|
||||
"title" : "Tous",
|
||||
"attr" : "onclick=\"group_select('', -1, %s)\"" % check
|
||||
}
|
||||
]
|
||||
items = [{"title": "Tous", "attr": "onclick=\"group_select('', -1, %s)\"" % check}]
|
||||
p_idx = 0
|
||||
for partition in partitions:
|
||||
if partition["partition_name"] != None:
|
||||
@ -232,12 +228,18 @@ def _make_menu(context, partitions, title="", check="true"):
|
||||
for group in sco_groups.get_partition_groups(context, partition):
|
||||
items.append(
|
||||
{
|
||||
"title" : "%s %s" % (partition["partition_name"], group["group_name"]),
|
||||
"attr" : "onclick=\"group_select('%s', %s, %s)\"" % (
|
||||
group["group_name"], p_idx, check)
|
||||
"title": "%s %s"
|
||||
% (partition["partition_name"], group["group_name"]),
|
||||
"attr": "onclick=\"group_select('%s', %s, %s)\""
|
||||
% (group["group_name"], p_idx, check),
|
||||
}
|
||||
)
|
||||
return '<td class="inscr_addremove_menu">' + makeMenu( title, items, base_url=context.absolute_url(), alone=True ) + "</td>"
|
||||
return (
|
||||
'<td class="inscr_addremove_menu">'
|
||||
+ makeMenu(title, items, base_url=context.absolute_url(), alone=True)
|
||||
+ "</td>"
|
||||
)
|
||||
|
||||
|
||||
def moduleimpl_inscriptions_stats(context, formsemestre_id, REQUEST=None):
|
||||
"""Affiche quelques informations sur les inscriptions
|
||||
@ -257,7 +259,7 @@ def moduleimpl_inscriptions_stats(context, formsemestre_id, REQUEST=None):
|
||||
groupes de TD A, B et C
|
||||
tous sauf groupe de TP Z (?)
|
||||
tous sauf <liste d'au plus 7 noms>
|
||||
|
||||
|
||||
"""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
|
||||
@ -278,7 +280,7 @@ def moduleimpl_inscriptions_stats(context, formsemestre_id, REQUEST=None):
|
||||
commons = [] # modules communs a tous les etuds du semestre
|
||||
options = [] # modules ou seuls quelques etudiants sont inscrits
|
||||
for mod in Mlist:
|
||||
all, nb_inscrits, descr = descr_inscrs_module(
|
||||
tous_inscrits, nb_inscrits, descr = descr_inscrs_module(
|
||||
context,
|
||||
sem,
|
||||
mod["moduleimpl_id"],
|
||||
@ -286,7 +288,7 @@ def moduleimpl_inscriptions_stats(context, formsemestre_id, REQUEST=None):
|
||||
partitions,
|
||||
partitions_etud_groups,
|
||||
)
|
||||
if all:
|
||||
if tous_inscrits:
|
||||
commons.append(mod)
|
||||
else:
|
||||
mod["descri"] = descr
|
||||
@ -420,8 +422,7 @@ def moduleimpl_inscriptions_stats(context, formsemestre_id, REQUEST=None):
|
||||
def descr_inscrs_module(
|
||||
context, sem, moduleimpl_id, set_all, partitions, partitions_etud_groups
|
||||
):
|
||||
"""returns All, nb_inscrits, descr All true si tous inscrits
|
||||
"""
|
||||
"""returns tous_inscrits, nb_inscrits, descr"""
|
||||
ins = context.do_moduleimpl_inscription_list(moduleimpl_id=moduleimpl_id)
|
||||
set_m = set([x["etudid"] for x in ins]) # ens. des inscrits au module
|
||||
non_inscrits = set_all - set_m
|
||||
@ -523,8 +524,7 @@ def is_inscrit_ue(context, etudid, formsemestre_id, ue_id):
|
||||
|
||||
|
||||
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()
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor.execute(
|
||||
@ -558,8 +558,7 @@ def do_etud_desinscrit_ue(context, etudid, formsemestre_id, ue_id, REQUEST=None)
|
||||
|
||||
|
||||
def do_etud_inscrit_ue(context, etudid, formsemestre_id, ue_id, REQUEST=None):
|
||||
"""Incrit l'etudiant de tous les modules de cette UE dans ce semestre.
|
||||
"""
|
||||
"""Incrit l'etudiant de tous les modules de cette UE dans ce semestre."""
|
||||
# Verifie qu'il est bien inscrit au semestre
|
||||
insem = context.do_formsemestre_inscription_list(
|
||||
args={"formsemestre_id": formsemestre_id, "etudid": etudid}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -262,7 +262,11 @@ def moduleimpl_status(context, moduleimpl_id=None, partition_id=None, REQUEST=No
|
||||
H.append(
|
||||
"""Afficher les groupes de <select name="partition_id" onchange="document.f.submit();">"""
|
||||
)
|
||||
been_selected = False
|
||||
for partition in partitions:
|
||||
if not partition_id and not been_selected:
|
||||
selected = "selected"
|
||||
been_selected = True
|
||||
if partition["partition_id"] == partition_id:
|
||||
selected = "selected"
|
||||
else:
|
||||
@ -337,12 +341,11 @@ def moduleimpl_status(context, moduleimpl_id=None, partition_id=None, REQUEST=No
|
||||
% etat["last_modif"].strftime("%d/%m/%Y à %Hh%M")
|
||||
)
|
||||
H.append('<span class="evalindex_cont">')
|
||||
if has_expression:
|
||||
if has_expression or True:
|
||||
H.append(
|
||||
"""<span class="evalindex" title="Indice dans les vecteurs (formules)">%02d</span>"""
|
||||
"""<span class="evalindex" title="Indice dans les vecteurs (formules)">%2d</span>"""
|
||||
% eval_index
|
||||
)
|
||||
|
||||
# Fleches:
|
||||
H.append('<span class="eval_arrows_chld">')
|
||||
if eval_index != (len(ModEvals) - 1) and caneditevals:
|
||||
|
11
sco_news.py
11
sco_news.py
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -37,7 +37,7 @@ from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from email.header import Header
|
||||
|
||||
from notesdb import *
|
||||
from notesdb import * # pylint: disable=unused-wildcard-import
|
||||
from notes_log import log
|
||||
import scolars
|
||||
from sco_utils import SCO_ENCODING, SCO_ANNONCES_WEBSITE
|
||||
@ -127,7 +127,6 @@ def scolar_news_summary(context, n=5):
|
||||
news = news[:n]
|
||||
# mimic EditableTable.list output formatting:
|
||||
for n in news:
|
||||
d = n["date"]
|
||||
n["date822"] = n["date"].strftime("%a, %d %b %Y %H:%M:%S %z")
|
||||
# heure
|
||||
n["hm"] = n["date"].strftime("%Hh%M")
|
||||
@ -194,7 +193,7 @@ def scolar_news_summary_html(context, n=5, rssicon=None):
|
||||
if not news:
|
||||
return ""
|
||||
H = ['<div class="news"><span class="newstitle">Dernières opérations']
|
||||
if rssicon:
|
||||
if rssicon: # 2020-12-30 plus utilisé
|
||||
H.append('<a href="rssnews">' + rssicon + "</a>")
|
||||
H.append('</span><ul class="newslist">')
|
||||
|
||||
@ -262,8 +261,10 @@ def _send_news_by_mail(context, n):
|
||||
#
|
||||
txt = n["text"]
|
||||
if infos:
|
||||
txt += "\n\nSemestre %(titremois)s\n\n" % infos["sem"]
|
||||
txt += (
|
||||
'\n\nSemestre <a href="Notes/formsemestre_status?formsemestre_id=%(formsemestre_id)s">%(descr_sem)s</a>)'
|
||||
"""<a href="Notes/formsemestre_status?formsemestre_id=%(formsemestre_id)s">%(descr_sem)s</a>
|
||||
"""
|
||||
% infos
|
||||
)
|
||||
txt += "\n\nEffectué par: %(nomcomplet)s\n" % n["user_info"]
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -273,18 +273,17 @@ def ficheEtud(context, etudid=None, REQUEST=None):
|
||||
if not context.canSuppressAnnotation(a["id"], REQUEST):
|
||||
a["dellink"] = ""
|
||||
else:
|
||||
a["dellink"] = (
|
||||
'<td class="annodel"><a href="doSuppressAnnotation?etudid=%s&annotation_id=%s">%s</a></td>'
|
||||
% (
|
||||
etudid,
|
||||
a["id"],
|
||||
icontag(
|
||||
"delete_img",
|
||||
border="0",
|
||||
alt="suppress",
|
||||
title="Supprimer cette annotation",
|
||||
),
|
||||
)
|
||||
a[
|
||||
"dellink"
|
||||
] = '<td class="annodel"><a href="doSuppressAnnotation?etudid=%s&annotation_id=%s">%s</a></td>' % (
|
||||
etudid,
|
||||
a["id"],
|
||||
icontag(
|
||||
"delete_img",
|
||||
border="0",
|
||||
alt="suppress",
|
||||
title="Supprimer cette annotation",
|
||||
),
|
||||
)
|
||||
alist.append(
|
||||
'<tr><td><span class="annodate">Le %(date)s par %(zope_authenticated_user)s : </span><span class="annoc">%(comment)s</span></td>%(dellink)s</tr>'
|
||||
@ -486,8 +485,7 @@ def ficheEtud(context, etudid=None, REQUEST=None):
|
||||
|
||||
|
||||
def menus_etud(context, REQUEST=None):
|
||||
"""Menu etudiant (operations sur l'etudiant)
|
||||
"""
|
||||
"""Menu etudiant (operations sur l'etudiant)"""
|
||||
if not REQUEST.form.has_key("etudid"):
|
||||
return ""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -41,7 +41,7 @@ from reportlab.platypus import Table, TableStyle, Image, KeepInFrame
|
||||
from reportlab.platypus.flowables import Flowable
|
||||
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
|
||||
from reportlab.lib.styles import getSampleStyleSheet
|
||||
from reportlab.rl_config import defaultPageSize
|
||||
from reportlab.rl_config import defaultPageSize # pylint: disable=no-name-in-module
|
||||
from reportlab.lib.units import inch, cm, mm
|
||||
from reportlab.lib.colors import pink, black, red, blue, green, magenta, red
|
||||
from reportlab.lib.colors import Color
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2020 Emmanuel Viennet. All rights reserved.
|
||||
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -197,16 +197,18 @@ def do_placement_selectetuds(context, REQUEST):
|
||||
numbering = tf[2]["numbering"]
|
||||
if columns in ("3", "4", "5", "6", "7", "8"):
|
||||
gs = [("group_ids%3Alist=" + urllib.quote_plus(x)) for x in group_ids]
|
||||
query = "evaluation_id=%s&placement_method=%s&teachers=%s&building=%s&room=%s&columns=%s&numbering=%s&" % (
|
||||
evaluation_id,
|
||||
placement_method,
|
||||
teachers,
|
||||
building,
|
||||
room,
|
||||
columns,
|
||||
numbering,
|
||||
) + "&".join(
|
||||
gs
|
||||
query = (
|
||||
"evaluation_id=%s&placement_method=%s&teachers=%s&building=%s&room=%s&columns=%s&numbering=%s&"
|
||||
% (
|
||||
evaluation_id,
|
||||
placement_method,
|
||||
teachers,
|
||||
building,
|
||||
room,
|
||||
columns,
|
||||
numbering,
|
||||
)
|
||||
+ "&".join(gs)
|
||||
)
|
||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "/do_placement?" + query)
|
||||
else:
|
||||
@ -385,8 +387,7 @@ def do_placement(context, REQUEST):
|
||||
|
||||
|
||||
def placement_eval_selectetuds(context, evaluation_id, REQUEST=None):
|
||||
"""Dialogue placement etudiants: choix methode et localisation
|
||||
"""
|
||||
"""Dialogue placement etudiants: choix methode et localisation"""
|
||||
evals = context.do_evaluation_list({"evaluation_id": evaluation_id})
|
||||
if not evals:
|
||||
raise ScoValueError("invalid evaluation_id")
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user