Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
b2e5fccec1 | |||
1f4a32a485 | |||
97f69ebc7d | |||
d6bf8efdee | |||
8bf2255d82 | |||
4847a2d12b | |||
978d4e64af | |||
7ad2a10894 | |||
dea24d0257 | |||
e7ccdee992 | |||
62a813494c | |||
274d39a3ec | |||
0864917a5f | |||
ea388ea494 | |||
6af4c6a2fd | |||
2b5a470516 | |||
7efe8cd194 | |||
de6d0233ac | |||
fcbbc877bc | |||
2f94c41821 | |||
d386f82146 | |||
ec006442c4 | |||
cf091d2c1a | |||
d6e7bbc713 | |||
7794fff4a5 | |||
65575e3562 | |||
3b75dcfa13 | |||
9b5f766500 |
170
ZAbsences.py
@ -45,17 +45,19 @@ L'API de plus bas niveau est en gros:
|
||||
"""
|
||||
|
||||
import urllib
|
||||
import datetime
|
||||
import jaxml
|
||||
|
||||
# ---------------
|
||||
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
|
||||
@ -356,7 +358,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 +382,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 +404,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 +425,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 +452,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 +489,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 +536,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 +567,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 +590,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 +600,6 @@ class ZAbsences(
|
||||
vars(),
|
||||
)
|
||||
Abs = cursor.dictfetchall()
|
||||
# log('ListeAbsDate: abs=%s' % Abs)
|
||||
# remove duplicates
|
||||
A = {} # { (jour, matin) : abs }
|
||||
for a in Abs:
|
||||
@ -625,7 +626,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 +633,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 +654,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 +680,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 +704,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 +732,6 @@ class ZAbsences(
|
||||
|
||||
if desc:
|
||||
return "(%s) %s" % (desc, module)
|
||||
return desc
|
||||
if module:
|
||||
return module
|
||||
return ""
|
||||
@ -745,7 +744,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 +768,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 +848,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 +885,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 +932,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
|
||||
@ -963,10 +961,10 @@ class ZAbsences(
|
||||
)[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"
|
||||
@ -1044,9 +1042,7 @@ class ZAbsences(
|
||||
% {"menu_module": menu_module, "url": base_url, "sel": sel}
|
||||
)
|
||||
|
||||
H += self._gen_form_saisie_groupe(
|
||||
etuds, self.day_names(), datessem, destination, None, moduleimpl_id
|
||||
)
|
||||
H += self._gen_form_saisie_groupe(etuds, datessem, destination, moduleimpl_id)
|
||||
|
||||
H.append(self.sco_footer(REQUEST))
|
||||
return "\n".join(H)
|
||||
@ -1063,8 +1059,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
|
||||
@ -1083,16 +1078,13 @@ class ZAbsences(
|
||||
]
|
||||
|
||||
if not moduleimpl_id:
|
||||
moduleimp_id = None
|
||||
base_url_noweeks = (
|
||||
"SignaleAbsenceGrSemestre?datedebut=%s&datefin=%s&%s&destination=%s"
|
||||
% (
|
||||
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
|
||||
) # sans le moduleimpl_id
|
||||
@ -1139,7 +1131,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]
|
||||
|
||||
@ -1217,15 +1208,18 @@ class ZAbsences(
|
||||
% {"menu_module": menu_module, "url": base_url, "sel": sel}
|
||||
)
|
||||
|
||||
H += self._gen_form_saisie_groupe(
|
||||
etuds, colnames, dates, destination, dayname, moduleimpl_id
|
||||
)
|
||||
H += self._gen_form_saisie_groupe(etuds, dates, destination, moduleimpl_id)
|
||||
H.append(self.sco_footer(REQUEST))
|
||||
return "\n".join(H)
|
||||
|
||||
def _gen_form_saisie_groupe(
|
||||
self, etuds, colnames, dates, destination="", dayname="", moduleimpl_id=None
|
||||
):
|
||||
def _gen_form_saisie_groupe(self, etuds, dates, destination="", moduleimpl_id=None):
|
||||
"""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">
|
||||
@ -1252,25 +1246,29 @@ class ZAbsences(
|
||||
"""
|
||||
% 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:
|
||||
@ -1373,14 +1371,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.*
|
||||
@ -1499,10 +1496,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 +1599,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 +1628,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 +1728,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 +1753,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)
|
||||
@ -1884,11 +1874,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 +1888,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 +1925,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:
|
||||
@ -2107,8 +2094,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 +2113,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 +2197,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)
|
||||
@ -2443,8 +2429,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
|
||||
|
@ -1617,7 +1617,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"])
|
||||
|
@ -284,6 +284,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)
|
||||
|
||||
@ -291,10 +292,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)
|
||||
|
||||
|
45
ZScolar.py
@ -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)
|
||||
|
@ -13,27 +13,45 @@
|
||||
source config.sh
|
||||
source utils.sh
|
||||
|
||||
check_uid_root $0
|
||||
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 -n "Nom du departement (un mot sans ponctuation, exemple \"Info\"): "
|
||||
read DEPT
|
||||
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
|
||||
|
||||
if [ -e $cfg_pathname ]
|
||||
if [ -e "$cfg_pathname" ]
|
||||
then
|
||||
echo 'Erreur: Il existe deja une configuration pour "'$DEPT'"'
|
||||
echo 'Erreur: Il existe deja une configuration pour "'"$DEPT"'"'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -41,23 +59,32 @@ 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 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
|
||||
|
||||
|
||||
|
||||
# ----------------------- 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"
|
||||
@ -67,3 +94,4 @@ 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
|
||||
|
@ -18,7 +18,22 @@ source config.sh
|
||||
source utils.sh
|
||||
|
||||
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
|
||||
@ -26,38 +41,41 @@ echo "Attention: le departement doit au prealable avoir ete supprime via l'inter
|
||||
echo "faites le AVANT d'executer ce script !!!"
|
||||
echo
|
||||
echo -n "Nom du departement a supprimer (un mot sans ponctuation, exemple \"Info\"): "
|
||||
read DEPT
|
||||
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
|
||||
|
||||
if [ -e $cfg_pathname ]
|
||||
if [ -e "$cfg_pathname" ]
|
||||
then
|
||||
# arret de ScoDoc
|
||||
scodocctl stop
|
||||
|
||||
# suppression de la base postgres
|
||||
db_name=$(cat $cfg_pathname | sed '/^dbname=*/!d; s///;q')
|
||||
db_name=$(cat "$cfg_pathname" | sed '/^dbname=*/!d; s///;q')
|
||||
echo "suppression de la base postgres $db_name"
|
||||
su -c "dropdb $db_name" $POSTGRES_SUPERUSER || terminate "ne peux supprimer base de donnees $db_name"
|
||||
su -c "dropdb $db_name" "$POSTGRES_SUPERUSER" || terminate "ne peux supprimer base de donnees $db_name"
|
||||
# suppression du fichier de config
|
||||
/bin/rm -f $cfg_pathname || terminate "ne peux supprimer $cfg_pathname"
|
||||
/bin/rm -f "$cfg_pathname" || terminate "ne peux supprimer $cfg_pathname"
|
||||
# relance ScoDoc
|
||||
if [ "$interactive" = 1 ]
|
||||
then
|
||||
echo -n "Demarrer le serveur ScoDoc ? (y/n) [n]"
|
||||
read ans
|
||||
read -r ans
|
||||
if [ "$(norm_ans "$ans")" = 'Y' ]
|
||||
then
|
||||
scodocctl start
|
||||
fi
|
||||
fi
|
||||
exit 0
|
||||
else
|
||||
echo 'Erreur: pas de configuration trouvee pour "'$DEPT'"'
|
||||
echo 'Erreur: pas de configuration trouvee pour "'"$DEPT"'"'
|
||||
exit 1
|
||||
fi
|
||||
|
0
config/migre-7-a-8.sh
Executable file → Normal file
@ -15,7 +15,7 @@ SCODOC_DIR="${INSTANCE_DIR}/Products/ScoDoc"
|
||||
SCODOC_VAR_DIR="${INSTANCE_DIR}/var/scodoc"
|
||||
|
||||
source utils.sh
|
||||
check_uid_root $0
|
||||
check_uid_root "$0"
|
||||
|
||||
# Safety check
|
||||
echo "Ce script va remplacer les donnees de votre installation ScoDoc par celles"
|
||||
@ -28,7 +28,7 @@ echo
|
||||
echo "TOUTES LES BASES POSTGRESQL SERONT EFFACEES !!!"
|
||||
echo
|
||||
echo -n "Voulez vous poursuivre cette operation ? (y/n) [n]"
|
||||
read ans
|
||||
read -r ans
|
||||
if [ ! "$(norm_ans "$ans")" = 'Y' ]
|
||||
then
|
||||
echo "Annulation"
|
||||
@ -57,7 +57,7 @@ then
|
||||
echo "Opening tgz archive..."
|
||||
tmp=$(mktemp -d)
|
||||
chmod a+rx "$tmp"
|
||||
cd "$tmp"
|
||||
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
|
||||
cd ${SCODOC_DIR:?}/config || terminate "no config directory"
|
||||
./upgrade.sh
|
||||
|
||||
#
|
||||
|
@ -35,7 +35,7 @@ INSTANCE_DIR=/opt/scodoc
|
||||
SCODOC_DIR="$INSTANCE_DIR/Products/ScoDoc"
|
||||
|
||||
source utils.sh
|
||||
check_uid_root $0
|
||||
check_uid_root "$0"
|
||||
|
||||
echo "Stopping ScoDoc..."
|
||||
scodocctl stop
|
||||
@ -44,9 +44,9 @@ 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
|
||||
echo "Error dumping postgresql database\nPlease check that SQL server is running\nAborting."
|
||||
printf "Error dumping postgresql database\nPlease check that SQL server is running\nAborting."
|
||||
exit 1
|
||||
fi
|
||||
chown root "$DEST"
|
||||
@ -57,7 +57,7 @@ cp -rp "$INSTANCE_DIR/var" "$DEST"
|
||||
|
||||
# Depts db config (now in .../var)
|
||||
shopt -s nullglob
|
||||
if [ ! -z "$(echo ${SCODOC_DIR}/config/depts/*.cfg)" ]
|
||||
if [ -n "$(echo ${SCODOC_DIR}/config/depts/*.cfg)" ]
|
||||
then
|
||||
echo "Copying legacy depts configs..."
|
||||
cp -rp "$SCODOC_DIR/config/depts" "$DEST"
|
||||
@ -86,6 +86,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
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"
|
||||
|
@ -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;
|
||||
|
||||
|
@ -34,7 +34,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
|
||||
|
||||
|
@ -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):
|
||||
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,
|
||||
|
@ -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,8 +123,7 @@ 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"]
|
||||
@ -162,7 +160,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>""",
|
||||
"""
|
||||
@ -207,8 +208,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 +274,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 +289,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>""",
|
||||
"""
|
||||
@ -329,8 +331,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 +379,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 +395,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,8 +467,7 @@ 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)
|
||||
@ -569,8 +571,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 +622,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,
|
||||
|
@ -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'
|
||||
|
@ -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,10 +495,10 @@ 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"]
|
||||
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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))
|
||||
|
@ -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"),
|
||||
},
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -764,12 +764,17 @@ def _list_notes_evals(context, evals, etudid):
|
||||
"""
|
||||
L = []
|
||||
for e in evals:
|
||||
if e["etat"]["evalcomplete"]:
|
||||
if (
|
||||
e["etat"]["evalcomplete"]
|
||||
or e["etat"]["evalattente"]
|
||||
or e["publish_incomplete"]
|
||||
):
|
||||
NotesDB = context._notes_getall(e["evaluation_id"])
|
||||
if NotesDB.has_key(etudid):
|
||||
val = NotesDB[etudid]["value"]
|
||||
else:
|
||||
val = None
|
||||
# Note manquante mais prise en compte immédiate: affiche ATT
|
||||
val = NOTES_ATTENTE
|
||||
val_fmt = fmt_note(val, keep_numeric=True)
|
||||
L.append(val_fmt)
|
||||
return L
|
||||
@ -778,9 +783,15 @@ def _list_notes_evals(context, evals, etudid):
|
||||
def _list_notes_evals_titles(context, codemodule, evals):
|
||||
"""Liste des titres des evals completes"""
|
||||
L = []
|
||||
eval_index = len(evals) - 1
|
||||
for e in evals:
|
||||
if e["etat"]["evalcomplete"]:
|
||||
L.append(codemodule + "-" + DateISOtoDMY(e["jour"]))
|
||||
if (
|
||||
e["etat"]["evalcomplete"]
|
||||
or e["etat"]["evalattente"]
|
||||
or e["publish_incomplete"]
|
||||
):
|
||||
L.append(codemodule + "-" + str(eval_index) + "-" + e["jour"].isoformat())
|
||||
eval_index -= 1
|
||||
return L
|
||||
|
||||
|
||||
@ -788,7 +799,11 @@ def _list_notes_evals_stats(context, evals, key):
|
||||
"""Liste des stats (moy, ou rien!) des evals completes"""
|
||||
L = []
|
||||
for e in evals:
|
||||
if e["etat"]["evalcomplete"]:
|
||||
if (
|
||||
e["etat"]["evalcomplete"]
|
||||
or e["etat"]["evalattente"]
|
||||
or e["publish_incomplete"]
|
||||
):
|
||||
if key == "moy":
|
||||
val = e["etat"]["moy_num"]
|
||||
L.append(fmt_note(val, keep_numeric=True))
|
||||
|
@ -28,6 +28,8 @@
|
||||
"""Synchronisation des listes d'étudiants avec liste portail (Apogée)
|
||||
"""
|
||||
|
||||
import time
|
||||
import pprint
|
||||
|
||||
from sco_utils import ScoEtudInscrit, annee_scolaire_debut, log, ScoValueError
|
||||
from notesdb import ScoDocCursor
|
||||
@ -42,8 +44,6 @@ import sco_formsemestre_inscriptions
|
||||
import sco_formsemestre_status
|
||||
from sco_news import NEWS_INSCR, NEWS_NOTE, NEWS_FORM, NEWS_SEM, NEWS_MISC
|
||||
|
||||
import time
|
||||
|
||||
# Clés utilisées pour la synchro
|
||||
EKEY_APO = "nip"
|
||||
EKEY_SCO = "code_nip"
|
||||
@ -695,7 +695,7 @@ def do_import_etud_admission(
|
||||
"codelycee": get_opt_str(etud, "lycee"),
|
||||
"boursier": get_opt_str(etud, "bourse"),
|
||||
}
|
||||
log("do_import_etud_admission: etud=%s" % etud)
|
||||
log("do_import_etud_admission: etud=%s" % pprint.pformat(etud))
|
||||
al = scolars.admission_list(cnx, args={"etudid": etudid})
|
||||
if not al:
|
||||
scolars.admission_create(cnx, args) # -> adm_id
|
||||
|
57
scolars.py
@ -25,7 +25,7 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
""" Acces donnees etudiants
|
||||
""" Accès donnees etudiants
|
||||
"""
|
||||
|
||||
from sco_utils import *
|
||||
@ -35,7 +35,7 @@ from TrivialFormulator import TrivialFormulator
|
||||
import safehtml
|
||||
from scolog import logdb
|
||||
from notes_table import *
|
||||
|
||||
import sco_news
|
||||
|
||||
# XXXXXXXXX HACK: zope 2.7.7 bug turaround ?
|
||||
import locale
|
||||
@ -618,6 +618,59 @@ def make_etud_args(etudid=None, code_nip=None, REQUEST=None, raise_exc=True):
|
||||
return args
|
||||
|
||||
|
||||
def create_etud(context, cnx, args={}, REQUEST=None):
|
||||
"""Creation d'un étudiant. génère aussi évenement et "news".
|
||||
|
||||
Args:
|
||||
args: dict avec les attributs de l'étudiant
|
||||
|
||||
Returns:
|
||||
etud, l'étudiant créé.
|
||||
"""
|
||||
# creation d'un etudiant
|
||||
etudid = etudident_create(cnx, args, context=context, REQUEST=REQUEST)
|
||||
# crée une adresse vide (chaque etudiant doit etre dans la table "adresse" !)
|
||||
_ = adresse_create(
|
||||
cnx,
|
||||
{
|
||||
"etudid": etudid,
|
||||
"typeadresse": "domicile",
|
||||
"description": "(creation individuelle)",
|
||||
},
|
||||
)
|
||||
|
||||
# event
|
||||
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]
|
||||
context.fillEtudsInfo([etud])
|
||||
etud["url"] = "ficheEtud?etudid=%(etudid)s" % etud
|
||||
sco_news.add(
|
||||
context,
|
||||
REQUEST,
|
||||
typ=sco_news.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"],
|
||||
)
|
||||
return etud
|
||||
|
||||
|
||||
# ---------- "EVENTS"
|
||||
_scolar_eventsEditor = EditableTable(
|
||||
"scolar_events",
|
||||
|
1
scotests/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
#
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |