1
0
forked from ScoDoc/ScoDoc

code refactoring: sco_abs

This commit is contained in:
Emmanuel Viennet 2021-01-10 18:54:39 +01:00
parent 3afec00b5e
commit 0dcb117df0
17 changed files with 699 additions and 651 deletions

View File

@ -48,6 +48,13 @@ import urllib
import datetime
import jaxml
import cgi
import string
import re
import time
import calendar
from mx.DateTime import DateTime as mxDateTime
from mx.DateTime.ISO import ParseDateTimeUTC
# ---------------
from sco_zope import *
@ -68,10 +75,8 @@ import sco_groups_view
import sco_excel
import sco_abs_notification, sco_abs_views
import sco_compute_moy
import string, re
import time, calendar
from mx.DateTime import DateTime as mxDateTime
from mx.DateTime.ISO import ParseDateTimeUTC
import sco_abs
from sco_abs import ddmmyyyy
def _toboolean(x):
@ -84,189 +89,6 @@ def _toboolean(x):
return False
def MonthNbDays(month, year):
"returns nb of days in month"
if month > 7:
month = month + 1
if month % 2:
return 31
elif month == 2:
if calendar.isleap(year):
return 29
else:
return 28
else:
return 30
class ddmmyyyy:
"""immutable dates"""
def __init__(self, date=None, fmt="ddmmyyyy", work_saturday=False):
self.work_saturday = work_saturday
if date is None:
return
try:
if fmt == "ddmmyyyy":
self.day, self.month, self.year = string.split(date, "/")
elif fmt == "iso":
self.year, self.month, self.day = string.split(date, "-")
else:
raise ValueError("invalid format spec. (%s)" % fmt)
self.year = string.atoi(self.year)
self.month = string.atoi(self.month)
self.day = string.atoi(self.day)
except:
raise ScoValueError("date invalide: %s" % date)
# accept years YYYY or YY, uses 1970 as pivot
if self.year < 1970:
if self.year > 100:
raise ScoInvalidDateError("Année invalide: %s" % self.year)
if self.year < 70:
self.year = self.year + 2000
else:
self.year = self.year + 1900
if self.month < 1 or self.month > 12:
raise ScoInvalidDateError("Mois invalide: %s" % self.month)
if self.day < 1 or self.day > MonthNbDays(self.month, self.year):
raise ScoInvalidDateError("Jour invalide: %s" % self.day)
# weekday in 0-6, where 0 is monday
self.weekday = calendar.weekday(self.year, self.month, self.day)
self.time = time.mktime((self.year, self.month, self.day, 0, 0, 0, 0, 0, 0))
def iswork(self):
"returns true if workable day"
if self.work_saturday:
nbdays = 6
else:
nbdays = 5
if (
self.weekday >= 0 and self.weekday < nbdays
): # monday-friday or monday-saturday
return 1
else:
return 0
def __repr__(self):
return "'%02d/%02d/%04d'" % (self.day, self.month, self.year)
def __str__(self):
return "%02d/%02d/%04d" % (self.day, self.month, self.year)
def ISO(self):
"iso8601 representation of the date"
return "%04d-%02d-%02d" % (self.year, self.month, self.day)
def next(self, days=1):
"date for the next day (nota: may be a non workable day)"
day = self.day + days
month = self.month
year = self.year
while day > MonthNbDays(month, year):
day = day - MonthNbDays(month, year)
month = month + 1
if month > 12:
month = 1
year = year + 1
return self.__class__(
"%02d/%02d/%04d" % (day, month, year), work_saturday=self.work_saturday
)
def prev(self, days=1):
"date for previous day"
day = self.day - days
month = self.month
year = self.year
while day <= 0:
month = month - 1
if month == 0:
month = 12
year = year - 1
day = day + MonthNbDays(month, year)
return self.__class__(
"%02d/%02d/%04d" % (day, month, year), work_saturday=self.work_saturday
)
def next_monday(self):
"date of next monday"
return self.next((7 - self.weekday) % 7)
def prev_monday(self):
"date of last monday, but on sunday, pick next monday"
if self.weekday == 6:
return self.next_monday()
else:
return self.prev(self.weekday)
def __cmp__(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)
def __hash__(self):
"we are immutable !"
return hash(self.time) ^ hash(str(self))
# d = ddmmyyyy( '21/12/99' )
def YearTable(
context,
year,
events=[],
firstmonth=9,
lastmonth=7,
halfday=0,
dayattributes="",
pad_width=8,
):
"""Generate a calendar table
events = list of tuples (date, text, color, href [,halfday])
where date is a string in ISO format (yyyy-mm-dd)
halfday is boolean (true: morning, false: afternoon)
text = text to put in calendar (must be short, 1-5 cars) (optional)
if halfday, generate 2 cells per day (morning, afternoon)
"""
T = [
'<table id="maincalendar" class="maincalendar" border="3" cellpadding="1" cellspacing="1" frame="box">'
]
T.append("<tr>")
month = firstmonth
while 1:
T.append('<td valign="top">')
T.append(MonthTableHead(month))
T.append(
MonthTableBody(
month,
year,
events,
halfday,
dayattributes,
context.is_work_saturday(),
pad_width=pad_width,
)
)
T.append(MonthTableTail())
T.append("</td>")
if month == lastmonth:
break
month = month + 1
if month > 12:
month = 1
year = year + 1
T.append("</table>")
return string.join(T, "\n")
# ---------------
class ZAbsences(
ObjectManager, PropertyManager, RoleManager, Item, Persistent, Implicit
):
@ -373,7 +195,7 @@ class ZAbsences(
% vars(),
)
cnx.commit()
invalidateAbsEtudDate(self, etudid, jour)
sco_abs.invalidateAbsEtudDate(self, etudid, jour)
sco_abs_notification.abs_notify(self, etudid, jour)
def _AddJustif(self, etudid, jour, matin, REQUEST, description=None):
@ -396,7 +218,7 @@ class ZAbsences(
msg="JOUR=%(jour)s,MATIN=%(matin)s" % vars(),
)
cnx.commit()
invalidateAbsEtudDate(self, etudid, jour)
sco_abs.invalidateAbsEtudDate(self, etudid, jour)
def _AnnuleAbsence(self, etudid, jour, matin, moduleimpl_id=None, REQUEST=None):
"""Annule une absence ds base
@ -419,7 +241,7 @@ class ZAbsences(
% vars(),
)
cnx.commit()
invalidateAbsEtudDate(self, etudid, jour)
sco_abs.invalidateAbsEtudDate(self, etudid, jour)
def _AnnuleJustif(self, etudid, jour, matin, REQUEST=None):
"Annule un justificatif"
@ -443,7 +265,7 @@ class ZAbsences(
msg="JOUR=%(jour)s,MATIN=%(matin)s" % vars(),
)
cnx.commit()
invalidateAbsEtudDate(self, etudid, jour)
sco_abs.invalidateAbsEtudDate(self, etudid, jour)
# Fonction inutile à supprimer (gestion moduleimpl_id incorrecte):
# def _AnnuleAbsencesPeriodNoJust(self, etudid, datedebut, datefin,
@ -462,8 +284,8 @@ class ZAbsences(
# logdb(REQUEST, cnx, 'AnnuleAbsencesPeriodNoJust', etudid=etudid,
# msg='%(datedebut)s - %(datefin)s - (moduleimpl_id)s'%vars())
# cnx.commit()
# invalidateAbsEtudDate(self, etudid, datedebut)
# invalidateAbsEtudDate(self, etudid, datefin) # si un semestre commence apres datedebut et termine avant datefin, il ne sera pas invalide. Tant pis ;-)
# sco_abs.invalidateAbsEtudDate(self, etudid, datedebut)
# sco_abs.invalidateAbsEtudDate(self, etudid, datefin) # si un semestre commence apres datedebut et termine avant datefin, il ne sera pas invalide. Tant pis ;-)
security.declareProtected(ScoAbsChange, "AnnuleAbsencesDatesNoJust")
@ -497,7 +319,7 @@ class ZAbsences(
"delete from absences where etudid=%(etudid)s and (not estjust) and jour=%(date)s and moduleimpl_id=%(moduleimpl_id)s",
vars(),
)
invalidateAbsEtudDate(self, etudid, date)
sco_abs.invalidateAbsEtudDate(self, etudid, date)
# s'assure que les justificatifs ne sont pas "absents"
for date in dates:
cursor.execute(
@ -855,7 +677,7 @@ class ZAbsences(
js = ""
else:
js = 'onmouseover="highlightweek(this);" onmouseout="deselectweeks();" onclick="wclick(this);"'
C = YearTable(self, int(year), dayattributes=js)
C = sco_abs.YearTable(self, int(year), dayattributes=js)
return C
# --- Misc tools.... ------------------
@ -1352,7 +1174,7 @@ class ZAbsences(
else:
checked = ""
# bulle lors du passage souris
coljour = DAYNAMES[
coljour = sco_abs.DAYNAMES[
(calendar.weekday(int(date[:4]), int(date[5:7]), int(date[8:])))
]
datecol = coljour + " " + date[8:] + "/" + date[5:7] + "/" + date[:4]
@ -1798,7 +1620,7 @@ ou entrez une date pour visualiser les absents un jour donné&nbsp;:
justified = int(justified)
#
cnx = self.GetDBConnexion()
billet_id = billet_absence_create(
billet_id = sco_abs.billet_absence_create(
cnx,
{
"etudid": etud["etudid"],
@ -1814,7 +1636,7 @@ ou entrez une date pour visualiser les absents un jour donné&nbsp;:
if REQUEST:
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
billets = billet_absence_list(cnx, {"billet_id": billet_id})
billets = sco_abs.billet_absence_list(cnx, {"billet_id": billet_id})
tab = self._tableBillets(billets, etud=etud)
log(
"AddBilletAbsence: new billet_id=%s (%gs)"
@ -1940,7 +1762,7 @@ ou entrez une date pour visualiser les absents un jour donné&nbsp;:
etud = etuds[0]
cnx = self.GetDBConnexion()
billets = billet_absence_list(cnx, {"etudid": etud["etudid"]})
billets = sco_abs.billet_absence_list(cnx, {"etudid": etud["etudid"]})
tab = self._tableBillets(billets, etud=etud)
return tab.make_page(self, REQUEST=REQUEST, format=format)
@ -1960,7 +1782,7 @@ ou entrez une date pour visualiser les absents un jour donné&nbsp;:
def listeBillets(self, REQUEST=None):
"""Page liste des billets non traités et formulaire recherche d'un billet"""
cnx = self.GetDBConnexion()
billets = billet_absence_list(cnx, {"etat": 0})
billets = sco_abs.billet_absence_list(cnx, {"etat": 0})
tab = self._tableBillets(billets)
T = tab.html()
H = [
@ -1986,7 +1808,7 @@ ou entrez une date pour visualiser les absents un jour donné&nbsp;:
def deleteBilletAbsence(self, billet_id, REQUEST=None, dialog_confirmed=False):
"""Supprime un billet."""
cnx = self.GetDBConnexion()
billets = billet_absence_list(cnx, {"billet_id": billet_id})
billets = sco_abs.billet_absence_list(cnx, {"billet_id": billet_id})
if not billets:
return REQUEST.RESPONSE.redirect(
"listeBillets?head_message=Billet%%20%s%%20inexistant !" % billet_id
@ -2001,7 +1823,7 @@ ou entrez une date pour visualiser les absents un jour donné&nbsp;:
parameters={"billet_id": billet_id},
)
billet_absence_delete(cnx, billet_id)
sco_abs.billet_absence_delete(cnx, billet_id)
return REQUEST.RESPONSE.redirect("listeBillets?head_message=Billet%20supprimé")
@ -2050,7 +1872,7 @@ ou entrez une date pour visualiser les absents un jour donné&nbsp;:
n += 2
# 2- change etat du billet
billet_absence_edit(cnx, {"billet_id": billet["billet_id"], "etat": 1})
sco_abs.billet_absence_edit(cnx, {"billet_id": billet["billet_id"], "etat": 1})
return n
@ -2059,7 +1881,7 @@ ou entrez une date pour visualiser les absents un jour donné&nbsp;:
def ProcessBilletAbsenceForm(self, billet_id, REQUEST=None):
"""Formulaire traitement d'un billet"""
cnx = self.GetDBConnexion()
billets = billet_absence_list(cnx, {"billet_id": billet_id})
billets = sco_abs.billet_absence_list(cnx, {"billet_id": billet_id})
if not billets:
return REQUEST.RESPONSE.redirect(
"listeBillets?head_message=Billet%%20%s%%20inexistant !" % billet_id
@ -2134,7 +1956,7 @@ ou entrez une date pour visualiser les absents un jour donné&nbsp;:
'</div><p><a class="stdlink" href="listeBillets">Autre billets en attente</a></p><h4>Billets déclarés par %s</h4>'
% (etud["nomprenom"])
)
billets = billet_absence_list(cnx, {"etudid": etud["etudid"]})
billets = sco_abs.billet_absence_list(cnx, {"etudid": etud["etudid"]})
tab = self._tableBillets(billets, etud=etud)
H.append(tab.html())
return "\n".join(H) + self.sco_footer(REQUEST)
@ -2172,258 +1994,6 @@ ou entrez une date pour visualiser les absents un jour donné&nbsp;:
return repr(doc)
_billet_absenceEditor = notesdb.EditableTable(
"billet_absence",
"billet_id",
(
"billet_id",
"etudid",
"abs_begin",
"abs_end",
"description",
"etat",
"entry_date",
"justified",
),
sortkey="entry_date desc",
)
billet_absence_create = _billet_absenceEditor.create
billet_absence_delete = _billet_absenceEditor.delete
billet_absence_list = _billet_absenceEditor.list
billet_absence_edit = _billet_absenceEditor.edit
# ------ HTML Calendar functions (see YearTable function)
# MONTH/DAY NAMES:
MONTHNAMES = (
"Janvier",
"F&eacute;vrier",
"Mars",
"Avril",
"Mai",
"Juin",
"Juillet",
"Aout",
"Septembre",
"Octobre",
"Novembre",
"D&eacute;cembre",
)
MONTHNAMES_ABREV = (
"Jan.",
"F&eacute;v.",
"Mars",
"Avr.",
"Mai&nbsp;",
"Juin",
"Juil",
"Aout",
"Sept",
"Oct.",
"Nov.",
"D&eacute;c.",
)
DAYNAMES = ("Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche")
DAYNAMES_ABREV = ("L", "M", "M", "J", "V", "S", "D")
# COLORS:
WHITE = "#FFFFFF"
GRAY1 = "#EEEEEE"
GREEN3 = "#99CC99"
WEEKDAYCOLOR = GRAY1
WEEKENDCOLOR = GREEN3
def MonthTableHead(month):
color = WHITE
return """<table class="monthcalendar" border="0" cellpadding="0" cellspacing="0" frame="box">
<tr bgcolor="%s"><td class="calcol" colspan="2" align="center">%s</td></tr>\n""" % (
color,
MONTHNAMES_ABREV[month - 1],
)
def MonthTableTail():
return "</table>\n"
def MonthTableBody(
month, year, events=[], halfday=0, trattributes="", work_saturday=False, pad_width=8
):
firstday, nbdays = calendar.monthrange(year, month)
localtime = time.localtime()
current_weeknum = time.strftime("%U", localtime)
current_year = localtime[0]
T = []
# cherche date du lundi de la 1ere semaine de ce mois
monday = ddmmyyyy("1/%d/%d" % (month, year))
while monday.weekday != 0:
monday = monday.prev()
if work_saturday:
weekend = ("D",)
else:
weekend = ("S", "D")
if not halfday:
for d in range(1, nbdays + 1):
weeknum = time.strftime(
"%U", time.strptime("%d/%d/%d" % (d, month, year), "%d/%m/%Y")
)
day = DAYNAMES_ABREV[(firstday + d - 1) % 7]
if day in weekend:
bgcolor = WEEKENDCOLOR
weekclass = "wkend"
attrs = ""
else:
bgcolor = WEEKDAYCOLOR
weekclass = "wk" + str(monday).replace("/", "_")
attrs = trattributes
color = None
legend = ""
href = ""
descr = ""
# event this day ?
# each event is a tuple (date, text, color, href)
# where date is a string in ISO format (yyyy-mm-dd)
for ev in events:
ev_year = int(ev[0][:4])
ev_month = int(ev[0][5:7])
ev_day = int(ev[0][8:10])
if year == ev_year and month == ev_month and ev_day == d:
if ev[1]:
legend = ev[1]
if ev[2]:
color = ev[2]
if ev[3]:
href = ev[3]
if len(ev) > 4 and ev[4]:
descr = ev[4]
#
cc = []
if color != None:
cc.append('<td bgcolor="%s" class="calcell">' % color)
else:
cc.append('<td class="calcell">')
if href:
href = 'href="%s"' % href
if 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:
if pad_width != None:
n = pad_width - len(legend) # pad to 8 cars
if n > 0:
legend = "&nbsp;" * (n / 2) + legend + "&nbsp;" * ((n + 1) / 2)
else:
legend = "&nbsp;" # empty cell
cc.append(legend)
if href or descr:
cc.append("</a>")
cc.append("</td>")
cell = string.join(cc, "")
if day == "D":
monday = monday.next(7)
if (
weeknum == current_weeknum
and current_year == year
and weekclass != "wkend"
):
weekclass += " currentweek"
T.append(
'<tr bgcolor="%s" class="%s" %s><td class="calday">%d%s</td>%s</tr>'
% (bgcolor, weekclass, attrs, d, day, cell)
)
else:
# Calendar with 2 cells / day
for d in range(1, nbdays + 1):
weeknum = time.strftime(
"%U", time.strptime("%d/%d/%d" % (d, month, year), "%d/%m/%Y")
)
day = DAYNAMES_ABREV[(firstday + d - 1) % 7]
if day in weekend:
bgcolor = WEEKENDCOLOR
weekclass = "wkend"
attrs = ""
else:
bgcolor = WEEKDAYCOLOR
weekclass = "wk" + str(monday).replace("/", "_")
attrs = trattributes
if (
weeknum == current_weeknum
and current_year == year
and weekclass != "wkend"
):
weeknum += " currentweek"
if day == "D":
monday = monday.next(7)
T.append(
'<tr bgcolor="%s" class="wk%s" %s><td class="calday">%d%s</td>'
% (bgcolor, weekclass, attrs, d, day)
)
cc = []
for morning in (1, 0):
color = None
legend = ""
href = ""
descr = ""
for ev in events:
ev_year = int(ev[0][:4])
ev_month = int(ev[0][5:7])
ev_day = int(ev[0][8:10])
if ev[4] != None:
ev_half = int(ev[4])
else:
ev_half = 0
if (
year == ev_year
and month == ev_month
and ev_day == d
and morning == ev_half
):
if ev[1]:
legend = ev[1]
if ev[2]:
color = ev[2]
if ev[3]:
href = ev[3]
if len(ev) > 5 and ev[5]:
descr = ev[5]
#
if color != None:
cc.append('<td bgcolor="%s" class="calcell">' % (color))
else:
cc.append('<td class="calcell">')
if href:
href = 'href="%s"' % href
if 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:
n = 3 - len(legend) # pad to 3 cars
if n > 0:
legend = "&nbsp;" * (n / 2) + legend + "&nbsp;" * ((n + 1) / 2)
else:
legend = "&nbsp;&nbsp;&nbsp;" # empty cell
cc.append(legend)
if href or descr:
cc.append("</a>")
cc.append("</td>\n")
T.append(string.join(cc, "") + "</tr>")
return string.join(T, "\n")
# --------------------------------------------------------------------
#
# Zope Product Administration
@ -2441,121 +2011,3 @@ def manage_addZAbsences(
# The form used to get the instance id from the user.
# manage_addZAbsencesForm = DTMLFile('dtml/manage_addZAbsencesForm', globals())
# --------------------------------------------------------------------
#
# Cache absences
#
# On cache simplement (à la demande) le nombre d'absences de chaque etudiant
# dans un semestre donné.
# Toute modification du semestre (invalidation) invalide le cache
# (simple mécanisme de "listener" sur le cache de semestres)
# Toute modification des absences d'un étudiant invalide les caches des semestres
# concernés à cette date (en général un seul semestre)
#
# On ne cache pas la liste des absences car elle est rarement utilisée (calendrier,
# absences à une date donnée).
#
# --------------------------------------------------------------------
class CAbsSemEtud:
"""Comptes d'absences d'un etudiant dans un semestre"""
def __init__(self, context, sem, etudid):
self.context = context
self.sem = sem
self.etudid = etudid
self._loaded = False
formsemestre_id = sem["formsemestre_id"]
context.Notes._getNotesCache().add_listener(
self.invalidate, formsemestre_id, (etudid, formsemestre_id)
)
def CountAbs(self):
if not self._loaded:
self.load()
return self._CountAbs
def CountAbsJust(self):
if not self._loaded:
self.load()
return self._CountAbsJust
def load(self):
"Load state from DB"
# log('loading CAbsEtudSem(%s,%s)' % (self.etudid, self.sem['formsemestre_id']))
# Reload sem, it may have changed
self.sem = sco_formsemestre.get_formsemestre(
self.context, self.sem["formsemestre_id"]
)
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
)
self._CountAbsJust = self.context.Absences.CountAbsJust(
etudid=self.etudid, debut=debut_sem, fin=fin_sem
)
self._loaded = True
def invalidate(self, args=None):
"Notify me that DB has been modified"
# log('invalidate CAbsEtudSem(%s,%s)' % (self.etudid, self.sem['formsemestre_id']))
self._loaded = False
# Accès au cache des absences
ABS_CACHE_INST = {} # { DeptId : { formsemestre_id : { etudid : CAbsEtudSem } } }
def getAbsSemEtud(context, sem, etudid):
AbsSemEtuds = getAbsSemEtuds(context, sem)
if not etudid in AbsSemEtuds:
AbsSemEtuds[etudid] = CAbsSemEtud(context, sem, etudid)
return AbsSemEtuds[etudid]
def getAbsSemEtuds(context, sem):
u = context.GetDBConnexionString() # identifie le dept de facon fiable
if not u in ABS_CACHE_INST:
ABS_CACHE_INST[u] = {}
C = ABS_CACHE_INST[u]
if sem["formsemestre_id"] not in C:
C[sem["formsemestre_id"]] = {}
return C[sem["formsemestre_id"]]
def invalidateAbsEtudDate(context, etudid, date):
"""Doit etre appelé à chaque modification des absences pour cet étudiant et cette date.
Invalide cache absence et PDF bulletins si nécessaire.
date: date au format ISO
"""
# Semestres a cette date:
etud = context.getEtudInfo(etudid=etudid, filled=True)[0]
sems = [
sem
for sem in etud["sems"]
if sem["date_debut_iso"] <= date and sem["date_fin_iso"] >= date
]
# Invalide les PDF et les abscences:
for sem in sems:
# Inval cache bulletin et/ou note_table
if sco_compute_moy.formsemestre_expressions_use_abscounts(
context, sem["formsemestre_id"]
):
pdfonly = False # seules certaines formules utilisent les absences
else:
pdfonly = (
True # efface toujours le PDF car il affiche en général les absences
)
context.Notes._inval_cache(
pdfonly=pdfonly, formsemestre_id=sem["formsemestre_id"]
)
# Inval cache compteurs absences:
AbsSemEtuds = getAbsSemEtuds(context, sem)
if etudid in AbsSemEtuds:
AbsSemEtuds[etudid].invalidate()

View File

@ -107,7 +107,7 @@ class EntreprisesEditor(EditableTable):
"select E.*, I.nom as etud_nom, I.prenom as etud_prenom, C.date from entreprises E, entreprise_contact C, identite I where C.entreprise_id = E.entreprise_id and C.etudid = I.etudid and I.nom ~* %(etud_nom)s ORDER BY E.nom",
args,
)
titles, res = [x[0] for x in cursor.description], cursor.dictfetchall()
_, res = [x[0] for x in cursor.description], cursor.dictfetchall()
R = []
for r in res:
r["etud_prenom"] = r["etud_prenom"] or ""
@ -450,7 +450,6 @@ class ZEntreprises(
def do_entreprise_correspondant_listnames(self, args={}):
"-> liste des noms des correspondants (pour affichage menu)"
cnx = self.GetDBConnexion()
C = self.do_entreprise_correspondant_list(args=args)
return [
(x["prenom"] + " " + x["nom"], str(x["entreprise_corresp_id"])) for x in C
@ -538,43 +537,48 @@ class ZEntreprises(
# (fonction ad-hoc car requete sur plusieurs tables)
raise NotImplementedError
# XXXXX fonction non achevee , non testee...
cnx = self.GetDBConnexion()
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
vals = dictfilter(args, self.dbfields)
# DBSelect
what = ["*"]
operator = " " + operator + " "
cond = " E.entreprise_id = C.entreprise_id "
if vals:
cond += " where " + operator.join(
["%s%s%%(%s)s" % (x, test, x) for x in vals.keys() if vals[x] != None]
)
cnuls = " and ".join(
["%s is NULL" % x for x in vals.keys() if vals[x] is None]
)
if cnuls:
cond = cond + " and " + cnuls
else:
cond += ""
cursor.execute(
"select distinct"
+ ", ".join(what)
+ " from entreprises E, entreprise_contact C "
+ cond
+ orderby,
vals,
)
titles, res = [x[0] for x in cursor.description], cursor.fetchall()
#
R = []
for r in res:
d = {}
for i in range(len(titles)):
v = r[i]
# value not formatted ! (see EditableTable.list())
d[titles[i]] = v
R.append(d)
return R
# cnx = self.GetDBConnexion()
# cursor = cnx.cursor(cursor_factory=ScoDocCursor)
# if sortkey:
# orderby = " order by " + sortkey
# else:
# orderby = ""
# vals = dictfilter(args, self.dbfields)
# # DBSelect
# what = ["*"]
# operator = " " + operator + " "
# cond = " E.entreprise_id = C.entreprise_id "
# if vals:
# cond += " where " + operator.join(
# ["%s%s%%(%s)s" % (x, test, x) for x in vals.keys() if vals[x] != None]
# )
# cnuls = " and ".join(
# ["%s is NULL" % x for x in vals.keys() if vals[x] is None]
# )
# if cnuls:
# cond = cond + " and " + cnuls
# else:
# cond += ""
# cursor.execute(
# "select distinct"
# + ", ".join(what)
# + " from entreprises E, entreprise_contact C "
# + cond
# + orderby,
# vals,
# )
# titles, res = [x[0] for x in cursor.description], cursor.fetchall()
# #
# R = []
# for r in res:
# d = {}
# for i in range(len(titles)):
# v = r[i]
# # value not formatted ! (see EditableTable.list())
# d[titles[i]] = v
# R.append(d)
# return R
# -------- Formulaires: traductions du DTML
security.declareProtected(ScoEntrepriseChange, "entreprise_create")
@ -892,7 +896,3 @@ def manage_addZEntreprises(
if REQUEST is not None:
return self.manage_main(self, REQUEST)
# return self.manage_editForm(self, REQUEST)
# The form used to get the instance id from the user.
# manage_addZAbsencesForm = DTMLFile('dtml/manage_addZAbsencesForm', globals())

View File

@ -89,6 +89,7 @@ import ZEntreprises
import ZScoUsers
import sco_modalites
import ImportScolars
import sco_abs
import sco_portal_apogee
import sco_synchro_etuds
import sco_page_etud
@ -274,13 +275,13 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
</p>
</body>
"""
return (
self.sco_header(REQUEST)
+ """<div class="xp">%s</div>""" % x
+ self.sco_footer(REQUEST)
)
b = "<p>Hello, World !</p><br/>"
raise ValueError("essai exception")
# return (
# self.sco_header(REQUEST)
# + """<div class="xp">%s</div>""" % x
# + self.sco_footer(REQUEST)
# )
# b = "<p>Hello, World !</p><br/>"
# raise ValueError("essai exception")
# raise ScoValueError('essai exception !', dest_url='totoro', REQUEST=REQUEST)
# cursor = cnx.cursor(cursor_factory=ScoDocCursor)
@ -592,7 +593,7 @@ UE11 Découverte métiers <span class="ue_code">(code UCOD46, 16 ECTS, Apo <span
# calcule dates 1er jour semaine pour absences
try:
if with_absences:
first_monday = ZAbsences.ddmmyyyy(sem["date_debut"]).prev_monday()
first_monday = sco_abs.ddmmyyyy(sem["date_debut"]).prev_monday()
FA = [] # formulaire avec menu saisi absences
FA.append(
'<td><form action="Absences/SignaleAbsenceGrSemestre" method="get">'

View File

@ -26,7 +26,7 @@
##############################################################################
from sco_utils import *
from ZAbsences import getAbsSemEtud
from sco_abs import getAbsSemEtud
"""
Génération de la "sidebar" (marge gauche des pages HTML)

595
sco_abs.py Normal file
View File

@ -0,0 +1,595 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# Gestion scolarite IUT
#
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Emmanuel Viennet emmanuel.viennet@viennet.net
#
##############################################################################
"""Fonctions sur les absences
"""
# Anciennement dans ZAbscences.py, séparé pour migration
import string
import datetime
import re
import time
import calendar
import cgi
import notesdb
from sco_exceptions import ScoValueError, ScoInvalidDateError
import sco_formsemestre
import sco_compute_moy
def MonthNbDays(month, year):
"returns nb of days in month"
if month > 7:
month = month + 1
if month % 2:
return 31
elif month == 2:
if calendar.isleap(year):
return 29
else:
return 28
else:
return 30
class ddmmyyyy:
"""immutable dates"""
def __init__(self, date=None, fmt="ddmmyyyy", work_saturday=False):
self.work_saturday = work_saturday
if date is None:
return
try:
if fmt == "ddmmyyyy":
self.day, self.month, self.year = string.split(date, "/")
elif fmt == "iso":
self.year, self.month, self.day = string.split(date, "-")
else:
raise ValueError("invalid format spec. (%s)" % fmt)
self.year = string.atoi(self.year)
self.month = string.atoi(self.month)
self.day = string.atoi(self.day)
except:
raise ScoValueError("date invalide: %s" % date)
# accept years YYYY or YY, uses 1970 as pivot
if self.year < 1970:
if self.year > 100:
raise ScoInvalidDateError("Année invalide: %s" % self.year)
if self.year < 70:
self.year = self.year + 2000
else:
self.year = self.year + 1900
if self.month < 1 or self.month > 12:
raise ScoInvalidDateError("Mois invalide: %s" % self.month)
if self.day < 1 or self.day > MonthNbDays(self.month, self.year):
raise ScoInvalidDateError("Jour invalide: %s" % self.day)
# weekday in 0-6, where 0 is monday
self.weekday = calendar.weekday(self.year, self.month, self.day)
self.time = time.mktime((self.year, self.month, self.day, 0, 0, 0, 0, 0, 0))
def iswork(self):
"returns true if workable day"
if self.work_saturday:
nbdays = 6
else:
nbdays = 5
if (
self.weekday >= 0 and self.weekday < nbdays
): # monday-friday or monday-saturday
return 1
else:
return 0
def __repr__(self):
return "'%02d/%02d/%04d'" % (self.day, self.month, self.year)
def __str__(self):
return "%02d/%02d/%04d" % (self.day, self.month, self.year)
def ISO(self):
"iso8601 representation of the date"
return "%04d-%02d-%02d" % (self.year, self.month, self.day)
def next(self, days=1):
"date for the next day (nota: may be a non workable day)"
day = self.day + days
month = self.month
year = self.year
while day > MonthNbDays(month, year):
day = day - MonthNbDays(month, year)
month = month + 1
if month > 12:
month = 1
year = year + 1
return self.__class__(
"%02d/%02d/%04d" % (day, month, year), work_saturday=self.work_saturday
)
def prev(self, days=1):
"date for previous day"
day = self.day - days
month = self.month
year = self.year
while day <= 0:
month = month - 1
if month == 0:
month = 12
year = year - 1
day = day + MonthNbDays(month, year)
return self.__class__(
"%02d/%02d/%04d" % (day, month, year), work_saturday=self.work_saturday
)
def next_monday(self):
"date of next monday"
return self.next((7 - self.weekday) % 7)
def prev_monday(self):
"date of last monday, but on sunday, pick next monday"
if self.weekday == 6:
return self.next_monday()
else:
return self.prev(self.weekday)
def __cmp__(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)
def __hash__(self):
"we are immutable !"
return hash(self.time) ^ hash(str(self))
# d = ddmmyyyy( '21/12/99' )
def YearTable(
context,
year,
events=[],
firstmonth=9,
lastmonth=7,
halfday=0,
dayattributes="",
pad_width=8,
):
"""Generate a calendar table
events = list of tuples (date, text, color, href [,halfday])
where date is a string in ISO format (yyyy-mm-dd)
halfday is boolean (true: morning, false: afternoon)
text = text to put in calendar (must be short, 1-5 cars) (optional)
if halfday, generate 2 cells per day (morning, afternoon)
"""
T = [
'<table id="maincalendar" class="maincalendar" border="3" cellpadding="1" cellspacing="1" frame="box">'
]
T.append("<tr>")
month = firstmonth
while 1:
T.append('<td valign="top">')
T.append(MonthTableHead(month))
T.append(
MonthTableBody(
month,
year,
events,
halfday,
dayattributes,
context.is_work_saturday(),
pad_width=pad_width,
)
)
T.append(MonthTableTail())
T.append("</td>")
if month == lastmonth:
break
month = month + 1
if month > 12:
month = 1
year = year + 1
T.append("</table>")
return string.join(T, "\n")
# ---- BILLETS
_billet_absenceEditor = notesdb.EditableTable(
"billet_absence",
"billet_id",
(
"billet_id",
"etudid",
"abs_begin",
"abs_end",
"description",
"etat",
"entry_date",
"justified",
),
sortkey="entry_date desc",
)
billet_absence_create = _billet_absenceEditor.create
billet_absence_delete = _billet_absenceEditor.delete
billet_absence_list = _billet_absenceEditor.list
billet_absence_edit = _billet_absenceEditor.edit
# ------ HTML Calendar functions (see YearTable function)
# MONTH/DAY NAMES:
MONTHNAMES = (
"Janvier",
"F&eacute;vrier",
"Mars",
"Avril",
"Mai",
"Juin",
"Juillet",
"Aout",
"Septembre",
"Octobre",
"Novembre",
"D&eacute;cembre",
)
MONTHNAMES_ABREV = (
"Jan.",
"F&eacute;v.",
"Mars",
"Avr.",
"Mai&nbsp;",
"Juin",
"Juil",
"Aout",
"Sept",
"Oct.",
"Nov.",
"D&eacute;c.",
)
DAYNAMES = ("Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche")
DAYNAMES_ABREV = ("L", "M", "M", "J", "V", "S", "D")
# COLORS:
WHITE = "#FFFFFF"
GRAY1 = "#EEEEEE"
GREEN3 = "#99CC99"
WEEKDAYCOLOR = GRAY1
WEEKENDCOLOR = GREEN3
def MonthTableHead(month):
color = WHITE
return """<table class="monthcalendar" border="0" cellpadding="0" cellspacing="0" frame="box">
<tr bgcolor="%s"><td class="calcol" colspan="2" align="center">%s</td></tr>\n""" % (
color,
MONTHNAMES_ABREV[month - 1],
)
def MonthTableTail():
return "</table>\n"
def MonthTableBody(
month, year, events=[], halfday=0, trattributes="", work_saturday=False, pad_width=8
):
firstday, nbdays = calendar.monthrange(year, month)
localtime = time.localtime()
current_weeknum = time.strftime("%U", localtime)
current_year = localtime[0]
T = []
# cherche date du lundi de la 1ere semaine de ce mois
monday = ddmmyyyy("1/%d/%d" % (month, year))
while monday.weekday != 0:
monday = monday.prev()
if work_saturday:
weekend = ("D",)
else:
weekend = ("S", "D")
if not halfday:
for d in range(1, nbdays + 1):
weeknum = time.strftime(
"%U", time.strptime("%d/%d/%d" % (d, month, year), "%d/%m/%Y")
)
day = DAYNAMES_ABREV[(firstday + d - 1) % 7]
if day in weekend:
bgcolor = WEEKENDCOLOR
weekclass = "wkend"
attrs = ""
else:
bgcolor = WEEKDAYCOLOR
weekclass = "wk" + str(monday).replace("/", "_")
attrs = trattributes
color = None
legend = ""
href = ""
descr = ""
# event this day ?
# each event is a tuple (date, text, color, href)
# where date is a string in ISO format (yyyy-mm-dd)
for ev in events:
ev_year = int(ev[0][:4])
ev_month = int(ev[0][5:7])
ev_day = int(ev[0][8:10])
if year == ev_year and month == ev_month and ev_day == d:
if ev[1]:
legend = ev[1]
if ev[2]:
color = ev[2]
if ev[3]:
href = ev[3]
if len(ev) > 4 and ev[4]:
descr = ev[4]
#
cc = []
if color != None:
cc.append('<td bgcolor="%s" class="calcell">' % color)
else:
cc.append('<td class="calcell">')
if href:
href = 'href="%s"' % href
if 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:
if pad_width != None:
n = pad_width - len(legend) # pad to 8 cars
if n > 0:
legend = "&nbsp;" * (n / 2) + legend + "&nbsp;" * ((n + 1) / 2)
else:
legend = "&nbsp;" # empty cell
cc.append(legend)
if href or descr:
cc.append("</a>")
cc.append("</td>")
cell = string.join(cc, "")
if day == "D":
monday = monday.next(7)
if (
weeknum == current_weeknum
and current_year == year
and weekclass != "wkend"
):
weekclass += " currentweek"
T.append(
'<tr bgcolor="%s" class="%s" %s><td class="calday">%d%s</td>%s</tr>'
% (bgcolor, weekclass, attrs, d, day, cell)
)
else:
# Calendar with 2 cells / day
for d in range(1, nbdays + 1):
weeknum = time.strftime(
"%U", time.strptime("%d/%d/%d" % (d, month, year), "%d/%m/%Y")
)
day = DAYNAMES_ABREV[(firstday + d - 1) % 7]
if day in weekend:
bgcolor = WEEKENDCOLOR
weekclass = "wkend"
attrs = ""
else:
bgcolor = WEEKDAYCOLOR
weekclass = "wk" + str(monday).replace("/", "_")
attrs = trattributes
if (
weeknum == current_weeknum
and current_year == year
and weekclass != "wkend"
):
weeknum += " currentweek"
if day == "D":
monday = monday.next(7)
T.append(
'<tr bgcolor="%s" class="wk%s" %s><td class="calday">%d%s</td>'
% (bgcolor, weekclass, attrs, d, day)
)
cc = []
for morning in (1, 0):
color = None
legend = ""
href = ""
descr = ""
for ev in events:
ev_year = int(ev[0][:4])
ev_month = int(ev[0][5:7])
ev_day = int(ev[0][8:10])
if ev[4] != None:
ev_half = int(ev[4])
else:
ev_half = 0
if (
year == ev_year
and month == ev_month
and ev_day == d
and morning == ev_half
):
if ev[1]:
legend = ev[1]
if ev[2]:
color = ev[2]
if ev[3]:
href = ev[3]
if len(ev) > 5 and ev[5]:
descr = ev[5]
#
if color != None:
cc.append('<td bgcolor="%s" class="calcell">' % (color))
else:
cc.append('<td class="calcell">')
if href:
href = 'href="%s"' % href
if 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:
n = 3 - len(legend) # pad to 3 cars
if n > 0:
legend = "&nbsp;" * (n / 2) + legend + "&nbsp;" * ((n + 1) / 2)
else:
legend = "&nbsp;&nbsp;&nbsp;" # empty cell
cc.append(legend)
if href or descr:
cc.append("</a>")
cc.append("</td>\n")
T.append(string.join(cc, "") + "</tr>")
return string.join(T, "\n")
# --------------------------------------------------------------------
#
# Cache absences
#
# On cache simplement (à la demande) le nombre d'absences de chaque etudiant
# dans un semestre donné.
# Toute modification du semestre (invalidation) invalide le cache
# (simple mécanisme de "listener" sur le cache de semestres)
# Toute modification des absences d'un étudiant invalide les caches des semestres
# concernés à cette date (en général un seul semestre)
#
# On ne cache pas la liste des absences car elle est rarement utilisée (calendrier,
# absences à une date donnée).
#
# --------------------------------------------------------------------
class CAbsSemEtud:
"""Comptes d'absences d'un etudiant dans un semestre"""
def __init__(self, context, sem, etudid):
self.context = context
self.sem = sem
self.etudid = etudid
self._loaded = False
formsemestre_id = sem["formsemestre_id"]
context.Notes._getNotesCache().add_listener(
self.invalidate, formsemestre_id, (etudid, formsemestre_id)
)
def CountAbs(self):
if not self._loaded:
self.load()
return self._CountAbs
def CountAbsJust(self):
if not self._loaded:
self.load()
return self._CountAbsJust
def load(self):
"Load state from DB"
# log('loading CAbsEtudSem(%s,%s)' % (self.etudid, self.sem['formsemestre_id']))
# Reload sem, it may have changed
self.sem = sco_formsemestre.get_formsemestre(
self.context, self.sem["formsemestre_id"]
)
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
)
self._CountAbsJust = self.context.Absences.CountAbsJust(
etudid=self.etudid, debut=debut_sem, fin=fin_sem
)
self._loaded = True
def invalidate(self, args=None):
"Notify me that DB has been modified"
# log('invalidate CAbsEtudSem(%s,%s)' % (self.etudid, self.sem['formsemestre_id']))
self._loaded = False
# Accès au cache des absences
ABS_CACHE_INST = {} # { DeptId : { formsemestre_id : { etudid : CAbsEtudSem } } }
def getAbsSemEtud(context, sem, etudid):
AbsSemEtuds = getAbsSemEtuds(context, sem)
if not etudid in AbsSemEtuds:
AbsSemEtuds[etudid] = CAbsSemEtud(context, sem, etudid)
return AbsSemEtuds[etudid]
def getAbsSemEtuds(context, sem):
u = context.GetDBConnexionString() # identifie le dept de facon fiable
if not u in ABS_CACHE_INST:
ABS_CACHE_INST[u] = {}
C = ABS_CACHE_INST[u]
if sem["formsemestre_id"] not in C:
C[sem["formsemestre_id"]] = {}
return C[sem["formsemestre_id"]]
def invalidateAbsEtudDate(context, etudid, date):
"""Doit etre appelé à chaque modification des absences pour cet étudiant et cette date.
Invalide cache absence et PDF bulletins si nécessaire.
date: date au format ISO
"""
# Semestres a cette date:
etud = context.getEtudInfo(etudid=etudid, filled=True)[0]
sems = [
sem
for sem in etud["sems"]
if sem["date_debut_iso"] <= date and sem["date_fin_iso"] >= date
]
# Invalide les PDF et les abscences:
for sem in sems:
# Inval cache bulletin et/ou note_table
if sco_compute_moy.formsemestre_expressions_use_abscounts(
context, sem["formsemestre_id"]
):
pdfonly = False # seules certaines formules utilisent les absences
else:
pdfonly = (
True # efface toujours le PDF car il affiche en général les absences
)
context.Notes._inval_cache(
pdfonly=pdfonly, formsemestre_id=sem["formsemestre_id"]
)
# Inval cache compteurs absences:
AbsSemEtuds = getAbsSemEtuds(context, sem)
if etudid in AbsSemEtuds:
AbsSemEtuds[etudid].invalidate()

View File

@ -40,7 +40,7 @@ import sco_find_etud
import sco_formsemestre
import sco_photos
import ZAbsences
import sco_abs
def doSignaleAbsence(
@ -631,7 +631,7 @@ def CalAbs(context, REQUEST=None): # etud implied
events.append(
(str(a["jour"]), "X", "#8EA2C6", "", a["matin"], a["description"])
)
CalHTML = ZAbsences.YearTable(context, anneescolaire, events=events, halfday=1)
CalHTML = sco_abs.YearTable(context, anneescolaire, events=events, halfday=1)
#
H = [

View File

@ -44,7 +44,7 @@ import sco_groups
import sco_pvjury
import sco_formsemestre_status
import sco_photos
import ZAbsences
import sco_abs
import sco_abs_views
import sco_preferences
import sco_codes_parcours
@ -150,7 +150,7 @@ def formsemestre_bulletinetud_dict(
context, pid
)
# --- Absences
AbsSemEtud = ZAbsences.getAbsSemEtud(context, nt.sem, etudid)
AbsSemEtud = sco_abs.getAbsSemEtud(context, nt.sem, etudid)
I["nbabs"] = AbsSemEtud.CountAbs()
I["nbabsjust"] = AbsSemEtud.CountAbsJust()

View File

@ -34,7 +34,7 @@ from notes_table import *
import sco_formsemestre
import sco_groups
import sco_photos
import ZAbsences
import sco_abs
import sco_bulletins
# -------- Bulletin en JSON
@ -321,7 +321,7 @@ def formsemestre_bulletinetud_published_dict(
if context.get_preference("bul_show_abs", formsemestre_id):
debut_sem = DateDMYtoISO(sem["date_debut"])
fin_sem = DateDMYtoISO(sem["date_fin"])
AbsEtudSem = ZAbsences.getAbsSemEtud(context, sem, etudid)
AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid)
nbabs = AbsEtudSem.CountAbs()
nbabsjust = AbsEtudSem.CountAbsJust()

View File

@ -41,7 +41,7 @@ from notes_table import *
import sco_formsemestre
import sco_groups
import sco_photos
import ZAbsences
import sco_abs
import sco_bulletins
# -------- Bulletin en XML
@ -323,7 +323,7 @@ def make_xml_formsemestre_bulletinetud(
if context.get_preference("bul_show_abs", formsemestre_id):
debut_sem = DateDMYtoISO(sem["date_debut"])
fin_sem = DateDMYtoISO(sem["date_fin"])
AbsEtudSem = ZAbsences.getAbsSemEtud(context, sem, etudid)
AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid)
nbabs = AbsEtudSem.CountAbs()
nbabsjust = AbsEtudSem.CountAbsJust()
doc._push()

View File

@ -37,7 +37,7 @@ import sco_formsemestre
import sco_groups
import sco_evaluations
from sco_formulas import *
import ZAbsences
import sco_abs
def moduleimpl_has_expression(context, mod):
@ -124,7 +124,7 @@ def compute_user_formula(
Retourne moy, et en cas d'erreur met à jour diag_info (msg)
"""
if use_abs:
AbsSemEtud = ZAbsences.getAbsSemEtud(context, sem, etudid)
AbsSemEtud = sco_abs.getAbsSemEtud(context, sem, etudid)
nbabs = AbsSemEtud.CountAbs()
nbabs_just = AbsSemEtud.CountAbsJust()
else:

View File

@ -42,7 +42,7 @@ from TrivialFormulator import TrivialFormulator
import sco_news
import sco_formsemestre
import sco_groups
import ZAbsences
import sco_abs
import sco_evaluations
# --------------------------------------------------------------------
@ -487,7 +487,7 @@ def formsemestre_evaluations_cal(context, formsemestre_id, REQUEST=None):
if day > today:
e[2] = color_futur
CalHTML = ZAbsences.YearTable(
CalHTML = sco_abs.YearTable(
context.Absences, year, events=events.values(), halfday=False, pad_width=None
)

View File

@ -35,7 +35,7 @@ from notes_log import log
from scolog import logdb
from notes_table import *
import notes_table
from ZAbsences import getAbsSemEtud
from sco_abs import getAbsSemEtud
import sco_formsemestre
import sco_formsemestre_edit

View File

@ -35,7 +35,7 @@ from sco_utils import *
import html_sco_header
from gen_tables import GenTable
import scolars
import ZAbsences
import sco_abs
import sco_excel
import sco_formsemestre
import sco_groups
@ -870,7 +870,7 @@ def form_choix_jour_saisie_hebdo(
if not authuser.has_permission(ScoAbsChange, context):
return ""
sem = groups_infos.formsemestre
first_monday = ZAbsences.ddmmyyyy(sem["date_debut"]).prev_monday()
first_monday = sco_abs.ddmmyyyy(sem["date_debut"]).prev_monday()
today_idx = datetime.date.today().weekday()
FA = [] # formulaire avec menu saisi absences
@ -923,7 +923,7 @@ def form_choix_saisie_semaine(context, groups_infos, REQUEST=None):
) # car ici utilisee dans un format string !
DateJour = time.strftime("%d/%m/%Y")
datelundi = ZAbsences.ddmmyyyy(DateJour).prev_monday()
datelundi = sco_abs.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)

View File

@ -43,7 +43,7 @@ import sco_formsemestre
import sco_formsemestre_status
from sco_formsemestre_status import makeMenu
import sco_compute_moy
import ZAbsences
import sco_abs
# ported from old DTML code in oct 2009
@ -241,7 +241,7 @@ def moduleimpl_status(context, moduleimpl_id=None, partition_id=None, REQUEST=No
if authuser.has_permission(
ScoAbsChange, context
) and sco_formsemestre.sem_est_courant(context, sem):
datelundi = ZAbsences.ddmmyyyy(time.strftime("%d/%m/%Y")).prev_monday()
datelundi = sco_abs.ddmmyyyy(time.strftime("%d/%m/%Y")).prev_monday()
H.append(
'<span class="moduleimpl_abs_link"><a class="stdlink" href="Absences/SignaleAbsenceGrHebdo?formsemestre_id=%s&moduleimpl_id=%s&datelundi=%s">Saisie Absences hebdo.</a></span>'
% (formsemestre_id, moduleimpl_id, datelundi)

View File

@ -36,7 +36,7 @@ from notes_log import log
from gen_tables import GenTable
import sco_formsemestre
import sco_groups
import ZAbsences
import sco_abs
from sco_codes_parcours import code_semestre_validant, code_semestre_attente
@ -90,7 +90,7 @@ def etud_get_poursuite_info(context, sem, etud):
rangs.append(["rang_" + codeModule, rangModule])
# Absences
AbsSemEtud = ZAbsences.getAbsSemEtud(context, nt.sem, etudid)
AbsSemEtud = sco_abs.getAbsSemEtud(context, nt.sem, etudid)
NbAbs = AbsSemEtud.CountAbs()
NbAbsJust = AbsSemEtud.CountAbsJust()
if (

View File

@ -38,7 +38,7 @@ import sco_formsemestre
import sco_parcours_dut
import sco_codes_parcours
from scolars import format_nom, format_prenom, format_sexe, format_lycee
from ZAbsences import getAbsSemEtud
from sco_abs import getAbsSemEtud
def feuille_preparation_jury(context, formsemestre_id, REQUEST):

View File

@ -40,7 +40,7 @@ import tempfile
from notes_log import log
from sco_utils import *
import ZAbsences
import sco_abs
import scolars
import sco_photos
import sco_formsemestre
@ -301,9 +301,9 @@ def pdf_feuille_releve_absences(
NB_CELL_PM = context.get_preference("feuille_releve_abs_PM")
COLWIDTH = 0.85 * cm
if context.get_preference("feuille_releve_abs_samedi"):
days = ZAbsences.DAYNAMES[:6] # Lundi, ..., Samedi
days = sco_abs.DAYNAMES[:6] # Lundi, ..., Samedi
else:
days = ZAbsences.DAYNAMES[:5] # Lundi, ..., Vendredi
days = sco_abs.DAYNAMES[:5] # Lundi, ..., Vendredi
nb_days = len(days)
# Informations sur les groupes à afficher: