diff --git a/ImportScolars.py b/ImportScolars.py index 8713ac3cd..c264e9d4c 100644 --- a/ImportScolars.py +++ b/ImportScolars.py @@ -28,10 +28,16 @@ """ Importation des etudiants à partir de fichiers CSV """ -import os, sys, time, pdb +import os +import sys +import time +import pdb +import collections +import types +import re -from sco_utils import * -from notesdb import * +import sco_utils as scu +import notesdb as ndb from notes_log import log import scolars import sco_formsemestre @@ -42,6 +48,15 @@ import sco_news from sco_news import NEWS_INSCR, NEWS_NOTE, NEWS_FORM, NEWS_SEM, NEWS_MISC from sco_formsemestre_inscriptions import do_formsemestre_inscription_with_modules from gen_tables import GenTable +from sco_exceptions import ( + AccessDenied, + FormatError, + ScoException, + ScoValueError, + ScoInvalidDateError, + ScoLockedFormError, + ScoGenError, +) # format description (relative to Product directory)) FORMAT_FILE = "misc/format_import_etudiants.txt" @@ -93,7 +108,7 @@ ADMISSION_MODIFIABLE_FIELDS = ( def sco_import_format(with_codesemestre=True): "returns tuples (Attribut, Type, Table, AllowNulls, Description)" r = [] - for l in open(SCO_SRCDIR + "/" + FORMAT_FILE): + for l in open(scu.SCO_SRCDIR + "/" + FORMAT_FILE): l = l.strip() if l and l[0] != "#": fs = l.split(";") @@ -152,10 +167,10 @@ def sco_import_generate_excel_sample( titles = [] titlesStyles = [] for l in fmt: - name = strlower(l[0]) + name = scu.strlower(l[0]) if (not with_codesemestre) and name == "codesemestre": continue # pas de colonne codesemestre - if only_tables is not None and strlower(l[2]) not in only_tables: + if only_tables is not None and scu.strlower(l[2]) not in only_tables: continue # table non demandée if name in exclude_cols: continue # colonne exclue @@ -192,7 +207,7 @@ def sco_import_generate_excel_sample( ) l.append(etud["partitionsgroupes"]) else: - key = strlower(field).split()[0] + key = scu.strlower(field).split()[0] l.append(etud.get(key, "")) lines.append(l) else: @@ -224,7 +239,7 @@ def students_import_excel( if formsemestre_id: dest = "formsemestre_status?formsemestre_id=%s" % formsemestre_id else: - dest = REQUEST.URL1 + dest = context.NotesURL() H = [context.sco_header(REQUEST, page_title="Import etudiants")] H.append("
') - 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(" | ") - if month == lastmonth: - break - month = month + 1 - if month > 12: - month = 1 - year = year + 1 - T.append("
- Saisie des absences %s %s, - semaine du lundi %s- - - -- Module concerné par ces absences (%(optionel_txt)s): @@ -1255,7 +1055,7 @@ class ZAbsences( Args: etuds: liste des étudiants - dates: liste de dates iso, par exemple: [ '2020-12-24', ... ] + dates: liste ordonnée de dates iso, par exemple: [ '2020-12-24', ... ] moduleimpl_id: optionnel, module concerné. """ H = [ @@ -1292,9 +1092,11 @@ class ZAbsences( ] # Dates odates = [datetime.date(*[int(x) for x in d.split("-")]) for d in dates] + begin = dates[0] + end = dates[-1] # Titres colonnes noms_jours = [] # eg [ "Lundi", "mardi", "Samedi", ... ] - jn = self.day_names() + jn = sco_abs.day_names(self) for d in odates: idx_jour = d.weekday() noms_jours.append(jn[idx_jour]) @@ -1320,6 +1122,8 @@ class ZAbsences( ' Aucun étudiant inscrit ! | %s%s | '
% (tr_class, etudid, etudid, etud["nomprenom"], capstr)
)
- for date in dates:
+ etud_abs = self.ListAbsInRange(
+ etudid, begin, end, moduleimpl_id=moduleimpl_id, cursor=cursor
+ )
+ for d in odates:
+ date = d.strftime("%Y-%m-%d")
# matin
- if self.CountAbs(etudid, date, date, True, moduleimpl_id=moduleimpl_id):
+ is_abs = {"jour": d, "matin": True} in etud_abs
+ if is_abs:
checked = "checked"
else:
checked = ""
# bulle lors du passage souris
- coljour = DAYNAMES[
- (calendar.weekday(int(date[:4]), int(date[5:7]), int(date[8:])))
- ]
- datecol = coljour + " " + date[8:] + "/" + date[5:7] + "/" + date[:4]
+ coljour = sco_abs.DAYNAMES[(calendar.weekday(d.year, d.month, d.day))]
+ datecol = coljour + " " + d.strftime("%d/%m/%Y")
bulle_am = '"' + etud["nomprenom"] + " - " + datecol + ' (matin)"'
bulle_pm = '"' + etud["nomprenom"] + " - " + datecol + ' (ap.midi)"'
@@ -1371,9 +1178,8 @@ class ZAbsences(
)
)
# après-midi
- if self.CountAbs(
- etudid, date, date, False, moduleimpl_id=moduleimpl_id
- ):
+ is_abs = {"jour": d, "matin": False} in etud_abs
+ if is_abs:
checked = "checked"
else:
checked = ""
@@ -1470,8 +1276,8 @@ class ZAbsences(
return ""
ex = []
for ev in a["evals"]:
- mod = self.Notes.do_moduleimpl_withmodule_list(
- moduleimpl_id=ev["moduleimpl_id"]
+ mod = sco_moduleimpl.do_moduleimpl_withmodule_list(
+ self.Notes, moduleimpl_id=ev["moduleimpl_id"]
)[0]
if format == "html":
ex.append(
@@ -1487,8 +1293,8 @@ class ZAbsences(
def descr_abs(a):
ex = []
for ev in a.get("absent", []):
- mod = self.Notes.do_moduleimpl_withmodule_list(
- moduleimpl_id=ev["moduleimpl_id"]
+ mod = sco_moduleimpl.do_moduleimpl_withmodule_list(
+ self.Notes, moduleimpl_id=ev["moduleimpl_id"]
)[0]
if format == "html":
ex.append(
@@ -1507,7 +1313,7 @@ class ZAbsences(
if with_evals:
a["exams"] = descr_exams(a)
a["datedmy"] = a["jour"].strftime("%d/%m/%Y")
- a["matin_o"] = int(a["matin"])
+ a["ampm"] = int(a["matin"])
a["matin"] = matin(a["matin"])
index = a["description"].find(")")
if index != -1:
@@ -1521,8 +1327,8 @@ class ZAbsences(
for a in absnonjust:
a["justlink"] = "justifier"
a["_justlink_target"] = (
- "doJustifAbsence?etudid=%s&datedebut=%s&datefin=%s&demijournee=%s"
- % (etudid, a["datedmy"], a["datedmy"], a["matin_o"])
+ "doJustifAbsence?etudid=%s&datedebut=%s&datefin=%s&demijournee=%s"
+ % (etudid, a["datedmy"], a["datedmy"], a["ampm"])
)
#
titles = {
@@ -1534,6 +1340,8 @@ class ZAbsences(
"motif": "Motif",
}
columns_ids = ["datedmy", "matin"]
+ if format in ("json", "xml"):
+ columns_ids += ["jour", "ampm"]
if with_evals:
columns_ids.append("exams")
@@ -1627,7 +1435,7 @@ class ZAbsences(
gr_tit = p + h
title = "Etat des absences %s" % gr_tit
- if format == "xls" or format == "xml":
+ if format == "xls" or format == "xml" or format == "json":
columns_ids = ["etudid"] + columns_ids
tab = GenTable(
columns_ids=columns_ids,
@@ -1655,7 +1463,7 @@ class ZAbsences(
)
+ "Période du %s au %s (nombre de demi-journées) Billets déclarés par %s' % (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) @@ -2170,392 +1978,3 @@ ou entrez une date pour visualiser les absents un jour donné : doc._pop() log("XMLgetAbsEtud (%gs)" % (time.time() - t0)) 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évrier", - "Mars", - "Avril", - "Mai", - "Juin", - "Juillet", - "Aout", - "Septembre", - "Octobre", - "Novembre", - "Décembre", -) - -MONTHNAMES_ABREV = ( - "Jan.", - "Fév.", - "Mars", - "Avr.", - "Mai ", - "Juin", - "Juil", - "Aout", - "Sept", - "Oct.", - "Nov.", - "Dé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 """
' % color)
- else:
- cc.append(' | ')
-
- if href:
- href = 'href="%s"' % href
- if descr:
- descr = 'title="%s"' % cgi.escape(descr, quote=True)
- if href or descr:
- cc.append("" % (href, descr))
-
- if legend or d == 1:
- if pad_width != None:
- n = pad_width - len(legend) # pad to 8 cars
- if n > 0:
- legend = " " * (n / 2) + legend + " " * ((n + 1) / 2)
- else:
- legend = " " # empty cell
- cc.append(legend)
- if href or descr:
- cc.append("")
- cc.append(" | ")
- 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(
- '%d%s | %s%d%s | '
- % (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('' % (color))
- else:
- cc.append(' | ')
- if href:
- href = 'href="%s"' % href
- if descr:
- descr = 'title="%s"' % cgi.escape(descr, quote=True)
- if href or descr:
- cc.append("" % (href, descr))
- if legend or d == 1:
- n = 3 - len(legend) # pad to 3 cars
- if n > 0:
- legend = " " * (n / 2) + legend + " " * ((n + 1) / 2)
- else:
- legend = " " # empty cell
- cc.append(legend)
- if href or descr:
- cc.append("")
- cc.append(" | \n")
- T.append(string.join(cc, "") + "'
+ + prev_lnk
+ + ''
+ + next_lnk
+ + " "
+ )
+ # Ajout des liens sur la table:
+ for e in entreprises:
+ e["_nom_target"] = "entreprise_edit?entreprise_id=%(entreprise_id)s" % e
+ e["correspondants"] = sco_entreprises.do_entreprise_correspondant_list(
+ self, args={"entreprise_id": e["entreprise_id"]}
+ )
+ e["nbcorr"] = "%d corr." % len(e["correspondants"])
+ e["_nbcorr_target"] = (
+ "entreprise_correspondant_list?entreprise_id=%(entreprise_id)s" % e
+ )
+ e["contacts"] = sco_entreprises.do_entreprise_contact_list(
+ self, args={"entreprise_id": e["entreprise_id"]}
+ )
+ e["nbcontact"] = "%d contacts." % len(e["contacts"])
+ e["_nbcontact_target"] = (
+ "entreprise_contact_list?entreprise_id=%(entreprise_id)s" % e
+ )
+ tab = GenTable(
+ rows=entreprises,
+ columns_ids=("nom", "ville", "secteur", "nbcorr", "nbcontact"),
+ titles={
+ "nom": "Entreprise",
+ "ville": "Ville",
+ "secteur": "Secteur",
+ "nbcorr": "Corresp.",
+ "contacts": "Contacts",
+ },
+ origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr(),
+ filename=scu.make_filename(
+ "entreprises_%s" % self.get_preference("DeptName")
+ ),
+ caption="Entreprises du département %s" % self.get_preference("DeptName"),
+ html_sortable=True,
+ html_class="entreprise_list table_leftalign",
+ html_with_td_classes=True,
+ html_next_section=table_navigation,
+ base_url=REQUEST.URL0 + "?",
+ preferences=self.get_preferences(),
+ )
+ if format != "html":
+ return tab.make_page(self, format=format, REQUEST=REQUEST)
+ else:
+ H = [
+ entreprise_header(
+ self, REQUEST=REQUEST, page_title="Suivi entreprises"
+ ),
+ """Suivi relations entreprises""", + """""",
+ tab.html(),
+ """ """,
+ entreprise_footer(self, REQUEST),
+ ]
+ return "\n".join(H)
security.declareProtected(ScoEntrepriseView, "entreprise_contact_list")
- entreprise_contact_list = DTMLFile(
- "dtml/entreprises/entreprise_contact_list", globals()
- )
- security.declareProtected(ScoEntrepriseView, "entreprise_correspondant_list")
- entreprise_correspondant_list = DTMLFile(
- "dtml/entreprises/entreprise_correspondant_list", globals()
- )
- # les methodes "edit" sont aussi en ScoEntrepriseView car elles permettent
- # la visualisation (via variable _read_only positionnee dans entreprise_header)
- security.declareProtected(ScoEntrepriseView, "entreprise_contact_edit")
- entreprise_contact_edit = DTMLFile(
- "dtml/entreprises/entreprise_contact_edit", globals()
- )
- security.declareProtected(ScoEntrepriseView, "entreprise_correspondant_edit")
- entreprise_correspondant_edit = DTMLFile(
- "dtml/entreprises/entreprise_correspondant_edit", globals()
- )
- # Acces en modification:
- security.declareProtected(ScoEntrepriseChange, "entreprise_contact_create")
- entreprise_contact_create = DTMLFile(
- "dtml/entreprises/entreprise_contact_create", globals()
- )
- security.declareProtected(ScoEntrepriseChange, "entreprise_contact_delete")
- entreprise_contact_delete = DTMLFile(
- "dtml/entreprises/entreprise_contact_delete", globals()
- )
- security.declareProtected(ScoEntrepriseChange, "entreprise_correspondant_create")
- entreprise_correspondant_create = DTMLFile(
- "dtml/entreprises/entreprise_correspondant_create", globals()
- )
- security.declareProtected(ScoEntrepriseChange, "entreprise_correspondant_delete")
- entreprise_correspondant_delete = DTMLFile(
- "dtml/entreprises/entreprise_correspondant_delete", globals()
- )
- security.declareProtected(ScoEntrepriseChange, "entreprise_delete")
- entreprise_delete = DTMLFile("dtml/entreprises/entreprise_delete", globals())
-
- # --------------------------------------------------------------------
- #
- # Entreprises : Methodes en Python
- #
- # --------------------------------------------------------------------
- security.declareProtected(ScoEntrepriseChange, "do_entreprise_create")
-
- def do_entreprise_create(self, args):
- "entreprise_create"
- cnx = self.GetDBConnexion()
- r = _entreprisesEditor.create(cnx, args)
- return r
-
- security.declareProtected(ScoEntrepriseChange, "do_entreprise_delete")
-
- def do_entreprise_delete(self, oid):
- "entreprise_delete"
- cnx = self.GetDBConnexion()
- _entreprisesEditor.delete(cnx, oid)
-
- security.declareProtected(ScoEntrepriseView, "do_entreprise_list")
-
- def do_entreprise_list(self, **kw):
- "entreprise_list"
- cnx = self.GetDBConnexion()
- kw["ZEntrepriseInstance"] = self
- return _entreprisesEditor.list(cnx, **kw)
-
- security.declareProtected(ScoEntrepriseView, "do_entreprise_list_by_etud")
-
- def do_entreprise_list_by_etud(self, **kw):
- "entreprise_list_by_etud"
- cnx = self.GetDBConnexion()
- return _entreprisesEditor.list_by_etud(cnx, **kw)
-
- security.declareProtected(ScoEntrepriseView, "do_entreprise_edit")
-
- def do_entreprise_edit(self, *args, **kw):
- "entreprise_edit"
- cnx = self.GetDBConnexion()
- _entreprisesEditor.edit(cnx, *args, **kw)
-
- security.declareProtected(ScoEntrepriseChange, "do_entreprise_correspondant_create")
-
- def do_entreprise_correspondant_create(self, args):
- "entreprise_correspondant_create"
- cnx = self.GetDBConnexion()
- r = _entreprise_correspEditor.create(cnx, args)
- return r
-
- security.declareProtected(ScoEntrepriseChange, "do_entreprise_correspondant_delete")
-
- def do_entreprise_correspondant_delete(self, oid):
- "entreprise_correspondant_delete"
- cnx = self.GetDBConnexion()
- _entreprise_correspEditor.delete(cnx, oid)
-
- security.declareProtected(ScoEntrepriseView, "do_entreprise_correspondant_list")
-
- def do_entreprise_correspondant_list(self, **kw):
- "entreprise_correspondant_list"
- cnx = self.GetDBConnexion()
- return _entreprise_correspEditor.list(cnx, **kw)
-
- security.declareProtected(ScoEntrepriseView, "do_entreprise_correspondant_edit")
-
- def do_entreprise_correspondant_edit(self, *args, **kw):
- "entreprise_correspondant_edit"
- cnx = self.GetDBConnexion()
- _entreprise_correspEditor.edit(cnx, *args, **kw)
-
- 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
- ]
-
- security.declareProtected(ScoEntrepriseChange, "do_entreprise_contact_create")
-
- def do_entreprise_contact_create(self, args):
- "entreprise_contact_create"
- cnx = self.GetDBConnexion()
- r = _entreprise_contactEditor.create(cnx, args)
- return r
-
- security.declareProtected(ScoEntrepriseChange, "do_entreprise_contact_delete")
-
- def do_entreprise_contact_delete(self, oid):
- "entreprise_contact_delete"
- cnx = self.GetDBConnexion()
- _entreprise_contactEditor.delete(cnx, oid)
-
- security.declareProtected(ScoEntrepriseView, "do_entreprise_contact_list")
-
- def do_entreprise_contact_list(self, **kw):
- "entreprise_contact_list"
- cnx = self.GetDBConnexion()
- return _entreprise_contactEditor.list(cnx, **kw)
-
- security.declareProtected(ScoEntrepriseView, "do_entreprise_contact_edit")
-
- def do_entreprise_contact_edit(self, *args, **kw):
- "entreprise_contact_edit"
- cnx = self.GetDBConnexion()
- _entreprise_contactEditor.edit(cnx, *args, **kw)
-
- #
- security.declareProtected(ScoEntrepriseView, "do_entreprise_check_etudiant")
-
- def do_entreprise_check_etudiant(self, etudiant):
- """Si etudiant est vide, ou un ETUDID valide, ou un nom unique,
- retourne (1, ETUDID).
- Sinon, retourne (0, 'message explicatif')
- """
- etudiant = etudiant.strip().translate(
- None, "'()"
- ) # suppress parens and quote from name
- if not etudiant:
- return 1, None
- cnx = self.GetDBConnexion()
- cursor = cnx.cursor(cursor_factory=ScoDocCursor)
- cursor.execute(
- "select etudid, nom, prenom from identite where upper(nom) ~ upper(%(etudiant)s) or etudid=%(etudiant)s",
- {"etudiant": etudiant},
- )
- r = cursor.fetchall()
- if len(r) < 1:
- return 0, 'Aucun etudiant ne correspond à "%s"' % etudiant
- elif len(r) > 10:
- return (
- 0,
- "%d etudiants correspondent à ce nom (utilisez le code)"
- % len(r),
+ def entreprise_contact_list(self, entreprise_id=None, format="html", REQUEST=None):
+ """Liste des contacts de l'entreprise"""
+ H = [entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises")]
+ if entreprise_id:
+ E = sco_entreprises.do_entreprise_list(
+ self, args={"entreprise_id": entreprise_id}
+ )[0]
+ C = sco_entreprises.do_entreprise_contact_list(
+ self, args={"entreprise_id": entreprise_id}
)
- elif len(r) > 1:
- e = ['
Listes des contacts avec l'entreprise %(nom)s+ """ + % E ) - else: # une seule reponse ! - return 1, r[0][0].strip() - - security.declareProtected(ScoEntrepriseView, "do_entreprise_list_by_contact") - - def do_entreprise_list_by_contact( - self, args={}, operator="and", test="=", sortkey=None - ): - """Recherche dans entreprises, avec date de contact""" - # (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, + C = sco_entreprises.do_entreprise_contact_list(self, args={}) + H.append( + """Listes des contacts+ """ + ) + for c in C: + c[ + "_date_target" + ] = "%s/entreprise_contact_edit?entreprise_contact_id=%s" % ( + self.EntreprisesURL(), + c["entreprise_contact_id"], + ) + c["entreprise"] = sco_entreprises.do_entreprise_list( + self, args={"entreprise_id": c["entreprise_id"]} + )[0] + if c["etudid"]: + c["etud"] = self.getEtudInfo(etudid=c["etudid"], filled=1)[0] + c["etudnom"] = c["etud"]["nomprenom"] + c["_etudnom_target"] = "%s/ficheEtud?etudid=%s" % ( + self.ScoURL(), + c["etudid"], + ) + else: + c["etud"] = None + c["etudnom"] = "" + + tab = GenTable( + rows=C, + columns_ids=("date", "type_contact", "etudnom", "description"), + titles={ + "date": "Date", + "type_contact": "Object", + "etudnom": "Étudiant", + "description": "Description", + }, + origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr(), + filename=scu.make_filename("contacts_%s" % self.get_preference("DeptName")), + caption="", + html_sortable=True, + html_class="contact_list table_leftalign", + html_with_td_classes=True, + base_url=REQUEST.URL0 + "?", + preferences=self.get_preferences(), ) - 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 + if format != "html": + return tab.make_page(self, format=format, REQUEST=REQUEST) + + H.append(tab.html()) + + if REQUEST.AUTHENTICATED_USER.has_permission(ScoEntrepriseChange, self): + if entreprise_id: + H.append( + """ + """ + % E + ) + + H.append(entreprise_footer(self, REQUEST)) + return "\n".join(H) + + security.declareProtected(ScoEntrepriseView, "entreprise_correspondant_list") + + def entreprise_correspondant_list( + self, + entreprise_id=None, + format="html", + REQUEST=None, + ): + """Liste des correspondants de l'entreprise""" + E = sco_entreprises.do_entreprise_list( + self, args={"entreprise_id": entreprise_id} + )[0] + H = [ + entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), + """ +Listes des correspondants dans l'entreprise %(nom)s+ """ + % E, + ] + correspondants = sco_entreprises.do_entreprise_correspondant_list( + self, args={"entreprise_id": entreprise_id} + ) + for c in correspondants: + c["nomprenom"] = c["nom"].upper() + " " + c["nom"].capitalize() + c[ + "_nomprenom_target" + ] = "%s/entreprise_correspondant_edit?entreprise_corresp_id=%s" % ( + self.EntreprisesURL(), + c["entreprise_corresp_id"], + ) + + c["nom_entreprise"] = E["nom"] + l = [] + if c["phone1"]: + l.append(c["phone1"]) + if c["phone2"]: + l.append(c["phone2"]) + if c["mobile"]: + l.append(c["mobile"]) + c["telephones"] = " / ".join(l) + c["mails"] = " ".join( + [ + '%s' % (c["mail1"], c["mail1"]) + if c["mail1"] + else "", + '%s' % (c["mail2"], c["mail2"]) + if c["mail2"] + else "", + ] + ) + c["modifier"] = ( + 'modifier' + % c["entreprise_corresp_id"] + ) + c["supprimer"] = ( + 'supprimer' + % c["entreprise_corresp_id"] + ) + tab = GenTable( + rows=correspondants, + columns_ids=( + "nomprenom", + "nom_entreprise", + "fonction", + "telephones", + "mails", + "note", + "modifier", + "supprimer", + ), + titles={ + "nomprenom": "Nom", + "nom_entreprise": "Entreprise", + "fonction": "Fonction", + "telephones": "Téléphone", + "mails": "Mail", + "note": "Note", + "modifier": "", + "supprimer": "", + }, + origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr(), + filename=scu.make_filename( + "correspondants_%s_%s" % (E["nom"], self.get_preference("DeptName")) + ), + caption="", + html_sortable=True, + html_class="contact_list table_leftalign", + html_with_td_classes=True, + base_url=REQUEST.URL0 + "?", + preferences=self.get_preferences(), + ) + if format != "html": + return tab.make_page(self, format=format, REQUEST=REQUEST) + + H.append(tab.html()) + + if REQUEST.AUTHENTICATED_USER.has_permission(ScoEntrepriseChange, self): + H.append( + """Ajouter un correspondant dans l'entreprise %(nom)s + """ + % E + ) + + H.append(entreprise_footer(self, REQUEST)) + return "\n".join(H) + + security.declareProtected(ScoEntrepriseView, "entreprise_contact_edit") + + def entreprise_contact_edit(self, entreprise_contact_id, REQUEST=None): + """Form edit contact""" + c = sco_entreprises.do_entreprise_contact_list( + self, args={"entreprise_contact_id": entreprise_contact_id} + )[0] + link_create_corr = ( + 'créer un nouveau correspondant' + % (self.EntreprisesURL(), c["entreprise_id"]) + ) + E = sco_entreprises.do_entreprise_list( + self, args={"entreprise_id": c["entreprise_id"]} + )[0] + correspondants = sco_entreprises.do_entreprise_correspondant_listnames( + self, args={"entreprise_id": c["entreprise_id"]} + ) + [("inconnu", "")] + + H = [ + entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), + """Suivi entreprises+Contact avec entreprise %(nom)s""" + % E, + ] + tf = TrivialFormulator( + REQUEST.URL0, + REQUEST.form, + ( + ( + "entreprise_contact_id", + {"default": entreprise_contact_id, "input_type": "hidden"}, + ), + ( + "entreprise_id", + {"input_type": "hidden", "default": c["entreprise_id"]}, + ), + ( + "type_contact", + { + "input_type": "menu", + "title": "Objet", + "allowed_values": ( + "Prospection", + "Stage étudiant", + "Contrat Apprentissage", + "Projet", + "Autre", + ), + }, + ), + ( + "date", + { + "size": 12, + "title": "Date du contact (j/m/a)", + "allow_null": False, + }, + ), + ( + "entreprise_corresp_id", + { + "input_type": "menu", + "title": "Correspondant entreprise", + "explanation": link_create_corr, + "allow_null": True, + "labels": [x[0] for x in correspondants], + "allowed_values": [x[1] for x in correspondants], + }, + ), + ( + "etudiant", + { + "size": 16, + "title": "Etudiant concerné", + "allow_null": True, + "default": c["etudid"], + "explanation": "nom (si pas ambigu) ou code", + }, + ), + ( + "enseignant", + {"size": 16, "title": "Enseignant (tuteur)", "allow_null": True}, + ), + ( + "description", + { + "input_type": "textarea", + "rows": 3, + "cols": 40, + "title": "Description", + }, + ), + ), + cancelbutton="Annuler", + initvalues=c, + submitlabel="Modifier les valeurs", + readonly=not REQUEST.AUTHENTICATED_USER.has_permission( + ScoEntrepriseChange, self + ), + ) + + if tf[0] == 0: + H.append(tf[1]) + if REQUEST.AUTHENTICATED_USER.has_permission(ScoEntrepriseChange, self): + H.append( + """""" + % entreprise_contact_id + ) + elif tf[0] == -1: + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + else: + etudok = sco_entreprises.do_entreprise_check_etudiant( + self, tf[2]["etudiant"] + ) + if etudok[0] == 0: + H.append("""%s """ % etudok[1]) + else: + tf[2].update({"etudid": etudok[1]}) + sco_entreprises.do_entreprise_contact_edit(self, tf[2]) + return REQUEST.RESPONSE.redirect( + self.EntreprisesURL() + + "/entreprise_contact_list?entreprise_id=" + + str(c["entreprise_id"]) + ) + H.append(entreprise_footer(self, REQUEST)) + return "\n".join(H) + + security.declareProtected(ScoEntrepriseView, "entreprise_correspondant_edit") + + def entreprise_correspondant_edit(self, entreprise_corresp_id, REQUEST=None): + """Form édition d'un correspondant""" + c = sco_entreprises.do_entreprise_correspondant_list( + self, args={"entreprise_corresp_id": entreprise_corresp_id} + )[0] + H = [ + entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), + """Édition contact entreprise""", + ] + tf = TrivialFormulator( + REQUEST.URL0, + REQUEST.form, + ( + ( + "entreprise_corresp_id", + {"default": entreprise_corresp_id, "input_type": "hidden"}, + ), + ( + "civilite", + { + "input_type": "menu", + "labels": ["M.", "Mme"], + "allowed_values": ["M.", "Mme"], + }, + ), + ("nom", {"size": 25, "title": "Nom", "allow_null": False}), + ("prenom", {"size": 25, "title": "Prénom"}), + ( + "fonction", + { + "input_type": "menu", + "allowed_values": ( + "Directeur", + "RH", + "Resp. Administratif", + "Tuteur", + "Autre", + ), + "explanation": "fonction via à vis de l'IUT", + }, + ), + ( + "phone1", + { + "size": 14, + "title": "Téléphone 1", + }, + ), + ( + "phone2", + { + "size": 14, + "title": "Téléphone 2", + }, + ), + ( + "mobile", + { + "size": 14, + "title": "Tél. mobile", + }, + ), + ( + "fax", + { + "size": 14, + "title": "Fax", + }, + ), + ( + "mail1", + { + "size": 25, + "title": "e-mail", + }, + ), + ( + "mail2", + { + "size": 25, + "title": "e-mail 2", + }, + ), + ( + "note", + {"input_type": "textarea", "rows": 3, "cols": 40, "title": "Note"}, + ), + ), + cancelbutton="Annuler", + initvalues=c, + submitlabel="Modifier les valeurs", + readonly=not REQUEST.AUTHENTICATED_USER.has_permission( + ScoEntrepriseChange, self + ), + ) + if tf[0] == 0: + H.append(tf[1]) + elif tf[0] == -1: + return REQUEST.RESPONSE.redirect( + "%s/entreprise_correspondant_list?entreprise_id=%s" + % (self.EntreprisesURL(), c["entreprise_id"]) + ) + else: + sco_entreprises.do_entreprise_correspondant_edit(self, tf[2]) + return REQUEST.RESPONSE.redirect( + "%s/entreprise_correspondant_list?entreprise_id=%s" + % (self.EntreprisesURL(), c["entreprise_id"]) + ) + H.append(entreprise_footer(self, REQUEST)) + return "\n".join(H) + + security.declareProtected(ScoEntrepriseChange, "entreprise_contact_create") + + def entreprise_contact_create(self, entreprise_id, REQUEST=None): + """Form création contact""" + E = sco_entreprises.do_entreprise_list( + self, args={"entreprise_id": entreprise_id} + )[0] + correspondants = sco_entreprises.do_entreprise_correspondant_listnames( + self, args={"entreprise_id": entreprise_id} + ) + if not correspondants: + correspondants = [("inconnu", "")] + curtime = time.strftime("%d/%m/%Y") + link_create_corr = ( + 'créer un nouveau correspondant' + % (self.EntreprisesURL(), entreprise_id) + ) + H = [ + entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), + """Nouveau "contact" avec l'entreprise %(nom)s""" + % E, + ] + tf = TrivialFormulator( + REQUEST.URL0, + REQUEST.form, + ( + ("entreprise_id", {"input_type": "hidden", "default": entreprise_id}), + ( + "type_contact", + { + "input_type": "menu", + "title": "Objet", + "allowed_values": ( + "Prospection", + "Stage étudiant", + "Contrat Apprentissage DUT GTR1", + "Contrat Apprentissage DUT GTR2", + "Contrat Apprentissage Licence SQRT", + "Projet", + "Autre", + ), + "default": "Stage étudiant", + }, + ), + ( + "date", + { + "size": 12, + "title": "Date du contact (j/m/a)", + "allow_null": False, + "default": curtime, + }, + ), + ( + "entreprise_corresp_id", + { + "input_type": "menu", + "title": "Correspondant entreprise", + "explanation": link_create_corr, + "allow_null": True, + "labels": [x[0] for x in correspondants], + "allowed_values": [x[1] for x in correspondants], + }, + ), + ( + "etudiant", + { + "size": 16, + "title": "Etudiant concerné", + "allow_null": True, + "explanation": "nom (si pas ambigu) ou code", + }, + ), + ( + "enseignant", + {"size": 16, "title": "Enseignant (tuteur)", "allow_null": True}, + ), + ( + "description", + { + "input_type": "textarea", + "rows": 3, + "cols": 40, + "title": "Description", + }, + ), + ), + cancelbutton="Annuler", + submitlabel="Ajouter ce contact", + readonly=not REQUEST.AUTHENTICATED_USER.has_permission( + ScoEntrepriseChange, self + ), + ) + if tf[0] == 0: + H.append(tf[1]) + elif tf[0] == -1: + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + else: + etudok = sco_entreprises.do_entreprise_check_etudiant( + self, tf[2]["etudiant"] + ) + if etudok[0] == 0: + H.append("""%s """ % etudok[1]) + else: + tf[2].update({"etudid": etudok[1]}) + sco_entreprises.do_entreprise_contact_create(self, tf[2]) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + H.append(entreprise_footer(self, REQUEST)) + return "\n".join(H) + + security.declareProtected(ScoEntrepriseChange, "entreprise_contact_delete") + + def entreprise_contact_delete(self, entreprise_contact_id, REQUEST=None): + """Form delete contact""" + c = sco_entreprises.do_entreprise_contact_list( + self, args={"entreprise_contact_id": entreprise_contact_id} + )[0] + H = [ + entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), + """Suppression du contact""", + ] + tf = TrivialFormulator( + REQUEST.URL0, + REQUEST.form, + (("entreprise_contact_id", {"input_type": "hidden"}),), + initvalues=c, + submitlabel="Confirmer la suppression", + cancelbutton="Annuler", + readonly=not REQUEST.AUTHENTICATED_USER.has_permission( + ScoEntrepriseChange, self + ), + ) + if tf[0] == 0: + H.append(tf[1]) + elif tf[0] == -1: + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + else: + sco_entreprises.do_entreprise_contact_delete( + self, c["entreprise_contact_id"] + ) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + H.append(entreprise_footer(self, REQUEST)) + return "\n".join(H) + + security.declareProtected(ScoEntrepriseChange, "entreprise_correspondant_create") + + def entreprise_correspondant_create(self, entreprise_id, REQUEST=None): + """Form création correspondant""" + E = sco_entreprises.do_entreprise_list( + self, args={"entreprise_id": entreprise_id} + )[0] + H = [ + entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), + """Nouveau correspondant l'entreprise %(nom)s""" + % E, + ] + tf = TrivialFormulator( + REQUEST.URL0, + REQUEST.form, + ( + ("entreprise_id", {"input_type": "hidden", "default": entreprise_id}), + ( + "civilite", + { + "input_type": "menu", + "labels": ["M.", "Mme"], + "allowed_values": ["M.", "Mme"], + }, + ), + ("nom", {"size": 25, "title": "Nom", "allow_null": False}), + ("prenom", {"size": 25, "title": "Prénom"}), + ( + "fonction", + { + "input_type": "menu", + "allowed_values": ( + "Directeur", + "RH", + "Resp. Administratif", + "Tuteur", + "Autre", + ), + "default": "Tuteur", + "explanation": "fonction via à vis de l'IUT", + }, + ), + ( + "phone1", + { + "size": 14, + "title": "Téléphone 1", + }, + ), + ( + "phone2", + { + "size": 14, + "title": "Téléphone 2", + }, + ), + ( + "mobile", + { + "size": 14, + "title": "Tél. mobile", + }, + ), + ( + "fax", + { + "size": 14, + "title": "Fax", + }, + ), + ( + "mail1", + { + "size": 25, + "title": "e-mail", + }, + ), + ( + "mail2", + { + "size": 25, + "title": "e-mail 2", + }, + ), + ( + "note", + {"input_type": "textarea", "rows": 3, "cols": 40, "title": "Note"}, + ), + ), + cancelbutton="Annuler", + submitlabel="Ajouter ce correspondant", + readonly=not REQUEST.AUTHENTICATED_USER.has_permission( + ScoEntrepriseChange, self + ), + ) + if tf[0] == 0: + H.append(tf[1]) + elif tf[0] == -1: + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + else: + sco_entreprises.do_entreprise_correspondant_create(self, tf[2]) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + H.append(entreprise_footer(self, REQUEST)) + return "\n".join(H) + + security.declareProtected(ScoEntrepriseChange, "entreprise_correspondant_delete") + + def entreprise_correspondant_delete(self, entreprise_corresp_id, REQUEST=None): + """Form delete correspondant""" + c = sco_entreprises.do_entreprise_correspondant_list( + self, args={"entreprise_corresp_id": entreprise_corresp_id} + )[0] + H = [ + entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), + """Suppression du correspondant %(nom)s %(prenom)s""" % c, + ] + tf = TrivialFormulator( + REQUEST.URL0, + REQUEST.form, + (("entreprise_corresp_id", {"input_type": "hidden"}),), + initvalues=c, + submitlabel="Confirmer la suppression", + cancelbutton="Annuler", + readonly=not REQUEST.AUTHENTICATED_USER.has_permission( + ScoEntrepriseChange, self + ), + ) + if tf[0] == 0: + H.append(tf[1]) + elif tf[0] == -1: + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + else: + sco_entreprises.do_entreprise_correspondant_delete( + self, c["entreprise_corresp_id"] + ) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + H.append(entreprise_footer(self, REQUEST)) + return "\n".join(H) + + security.declareProtected(ScoEntrepriseChange, "entreprise_delete") + + def entreprise_delete(self, entreprise_id, REQUEST=None): + """Form delete entreprise""" + E = sco_entreprises.do_entreprise_list( + self, args={"entreprise_id": entreprise_id} + )[0] + H = [ + entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), + """Suppression de l'entreprise %(nom)s+Attention: supression définitive de l'entreprise, de ses correspondants et contacts. + """ + % E, + ] + Cl = sco_entreprises.do_entreprise_correspondant_list( + self, args={"entreprise_id": entreprise_id} + ) + if Cl: + H.append( + """Correspondants dans l'entreprise qui seront supprimés:
Contacts avec l'entreprise qui seront supprimés:
Création d'une entreprise""", ] tf = TrivialFormulator( @@ -658,26 +1113,29 @@ class ZEntreprises( ), cancelbutton="Annuler", submitlabel="Ajouter cette entreprise", - readonly=REQUEST["_read_only"], + readonly=not REQUEST.AUTHENTICATED_USER.has_permission( + ScoEntrepriseChange, self + ), ) if tf[0] == 0: - return "\n".join(H) + tf[1] + context.entreprise_footer(REQUEST) + return "\n".join(H) + tf[1] + entreprise_footer(self, REQUEST) elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) else: - self.do_entreprise_create(tf[2]) - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + sco_entreprises.do_entreprise_create(self, tf[2]) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) security.declareProtected(ScoEntrepriseView, "entreprise_edit") def entreprise_edit(self, entreprise_id, REQUEST=None, start=1): """Form. edit entreprise""" - context = self authuser = REQUEST.AUTHENTICATED_USER readonly = not authuser.has_permission(ScoEntrepriseChange, self) - F = self.do_entreprise_list(args={"entreprise_id": entreprise_id})[0] + F = sco_entreprises.do_entreprise_list( + self, args={"entreprise_id": entreprise_id} + )[0] H = [ - self.entreprise_header(REQUEST, page_title="Entreprise"), + entreprise_header(self, REQUEST, page_title="Entreprise"), """%(nom)s""" % F, ] tf = TrivialFormulator( @@ -762,17 +1220,17 @@ class ZEntreprises( if tf[0] == 0: H.append(tf[1]) - Cl = self.do_entreprise_correspondant_list( - args={"entreprise_id": F["entreprise_id"]} + Cl = sco_entreprises.do_entreprise_correspondant_list( + self, args={"entreprise_id": F["entreprise_id"]} ) - Cts = self.do_entreprise_contact_list( - args={"entreprise_id": F["entreprise_id"]} + Cts = sco_entreprises.do_entreprise_contact_list( + self, args={"entreprise_id": F["entreprise_id"]} ) if not readonly: H.append( """""" % ( - icontag("delete_img", title="delete", border="0"), + scu.icontag("delete_img", title="delete", border="0"), F["entreprise_id"], ) ) @@ -835,64 +1293,9 @@ class ZEntreprises( H.append("(%s)" % c["description"]) H.append("") H.append("") - return "\n".join(H) + context.entreprise_footer(REQUEST) + return "\n".join(H) + entreprise_footer(self, REQUEST) elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "?start=" + start) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL() + "?start=" + start) else: - self.do_entreprise_edit(tf[2]) - return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "?start=" + start) - - # --- Misc tools.... ------------------ - security.declareProtected(ScoEntrepriseView, "str_abbrev") - - def str_abbrev(self, s, maxlen): - "abreviation" - if s == None: - return "?" - if len(s) < maxlen: - return s - return s[: maxlen - 3] + "..." - - security.declareProtected(ScoEntrepriseView, "setPageSizeCookie") - - def setPageSizeCookie(self, REQUEST=None): - "set page size cookie" - RESPONSE = REQUEST.RESPONSE - # - if REQUEST.form.has_key("entreprise_page_size"): - RESPONSE.setCookie( - "entreprise_page_size", - REQUEST.form["entreprise_page_size"], - path="/", - expires="Wed, 31-Dec-2025 23:55:00 GMT", - ) - RESPONSE.redirect(REQUEST.form["target_url"]) - - security.declareProtected(ScoEntrepriseView, "make_link_create_corr") - - def make_link_create_corr(self, entreprise_id): - "yet another stupid code snippet" - return ( - 'créer un nouveau correspondant' - ) - - -# -------------------------------------------------------------------- -# -# Zope Product Administration -# -# -------------------------------------------------------------------- -def manage_addZEntreprises( - self, id="id_ZEntreprises", title="The Title for ZEntreprises Object", REQUEST=None -): - "Add a ZEntreprises instance to a folder." - self._setObject(id, ZEntreprises(id, title)) - 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()) + sco_entreprises.do_entreprise_edit(self, tf[2]) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL() + "?start=" + start) diff --git a/ZNotes.py b/ZNotes.py index ae180b3e4..f454d2e04 100644 --- a/ZNotes.py +++ b/ZNotes.py @@ -27,16 +27,38 @@ """Interface Zope <-> Notes """ +import time +import datetime +import jaxml +import pprint -from sco_zope import * +from sco_zope import * # pylint: disable=unused-wildcard-import # --------------- - -from notesdb import * +import sco_utils as scu +import notesdb as ndb from notes_log import log, sendAlarm import scolog from scolog import logdb -from sco_utils import * +from sco_permissions import ( + ScoView, + ScoEnsView, + ScoImplement, + ScoChangeFormation, + ScoObservateur, + ScoEtudInscrit, + ScoEtudChangeGroups, + ScoEtudChangeAdr, + ScoEtudSupprAnnotations, + ScoEditAllEvals, + ScoEditAllNotes, + ScoEditFormationTags, + ScoEditApo, + ScoSuperAdmin, +) +from sco_exceptions import ScoValueError, ScoLockedFormError, ScoGenError, AccessDenied + +from TrivialFormulator import TrivialFormulator import htmlutils import sco_excel @@ -52,6 +74,7 @@ import sco_formsemestre_edit import sco_formsemestre_status import sco_formsemestre_inscriptions import sco_formsemestre_custommenu +import sco_moduleimpl import sco_moduleimpl_status import sco_moduleimpl_inscriptions import sco_evaluations @@ -63,6 +86,7 @@ import sco_edit_module import sco_tag_module import sco_bulletins import sco_bulletins_pdf +import sco_compute_moy import sco_recapcomplet import sco_liste_notes import sco_saisie_notes @@ -93,7 +117,8 @@ import sco_export_results import sco_formsemestre_exterieurs from sco_pdf import PDFLOCK -from notes_table import * +import notes_table +from notes_table import NOTES_CACHE_INST, CacheNotesTable import VERSION # @@ -138,11 +163,13 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl self.title = title # The form used to edit this object + security.declareProtected(ScoView, "manage_editZNotes") + def manage_editZNotes(self, title, RESPONSE=None): "Changes the instance values" self.title = title self._p_changed = 1 - RESPONSE.redirect("manage_editForm") + return RESPONSE.redirect("manage_editForm") def _getNotesCache(self): "returns CacheNotesTable instance for us" @@ -164,15 +191,13 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl # Affecte aussi cache inscriptions self.get_formsemestre_inscription_cache().inval_cache( key=formsemestre_id - ) # > + ) else: self._getNotesCache().inval_cache( self, formsemestre_id=formsemestre_id, pdfonly=pdfonly - ) # > + ) # Affecte aussi cache inscriptions - self.get_formsemestre_inscription_cache().inval_cache( - key=formsemestre_id - ) # > + self.get_formsemestre_inscription_cache().inval_cache(key=formsemestre_id) security.declareProtected(ScoView, "clearcache") @@ -219,7 +244,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl "essai gloups" return "" # return pdfbulletins.essaipdf(REQUEST) - # return sendPDFFile(REQUEST, pdfbulletins.pdftrombino(0,0), 'toto.pdf' ) + # return scu.sendPDFFile(REQUEST, pdfbulletins.pdftrombino(0,0), 'toto.pdf' ) # Python methods: security.declareProtected(ScoView, "formsemestre_status") @@ -230,10 +255,12 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl sco_formsemestre_edit.formsemestre_createwithmodules ) - security.declareProtected(ScoView, "formsemestre_editwithmodules") + security.declareProtected( + ScoView, "formsemestre_editwithmodules" + ) # controle d'acces specifique pour dir. etud formsemestre_editwithmodules = sco_formsemestre_edit.formsemestre_editwithmodules - security.declareProtected(ScoView, "formsemestre_clone") + security.declareProtected(ScoImplement, "formsemestre_clone") formsemestre_clone = sco_formsemestre_edit.formsemestre_clone security.declareProtected(ScoChangeFormation, "formsemestre_associate_new_version") @@ -335,15 +362,6 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl def index_html(self, REQUEST=None): "Page accueil formations" - lockicon = icontag( - "lock32_img", title="Comporte des semestres verrouillés", border="0" - ) - suppricon = icontag( - "delete_small_img", border="0", alt="supprimer", title="Supprimer" - ) - editicon = icontag( - "edit_img", border="0", alt="modifier", title="Modifier titres et code" - ) editable = REQUEST.AUTHENTICATED_USER.has_permission(ScoChangeFormation, self) @@ -358,7 +376,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl if editable: H.append( - """ + """Une "formation" est un programme pédagogique structuré en UE, matières et modules. Chaque semestre se réfère à une formation. La modification d'une formation affecte tous les semestres qui s'y réfèrent. """ @@ -374,7 +392,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl # -------------------------------------------------------------------- # --- Formations - _formationEditor = EditableTable( + _formationEditor = ndb.EditableTable( "notes_formations", "formation_id", ( @@ -461,7 +479,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl cnx = self.GetDBConnexion() r = self._formationEditor.list(cnx, args=args) # log('%d formations found' % len(r)) - return sendResult(REQUEST, r, name="formation", format=format) + return scu.sendResult(REQUEST, r, name="formation", format=format) security.declareProtected(ScoView, "formation_export") @@ -503,11 +521,9 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl if tf[0] == 0: return "\n".join(H) + tf[1] + footer elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect(self.NotesURL()) else: - formation_id, junk, junk = self.formation_import_xml( - tf[2]["xmlfile"], REQUEST - ) + formation_id, _, _ = self.formation_import_xml(tf[2]["xmlfile"], REQUEST) return ( "\n".join(H) @@ -538,13 +554,13 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl ) if redirect: return REQUEST.RESPONSE.redirect( - "ue_list?formation_id=" + new_id + "&msg=Nouvelle version !" + "ue_list?formation_id=" + new_id + "&msg=Nouvelle version !" ) else: return new_id, modules_old2new, ues_old2new # --- UE - _ueEditor = EditableTable( + _ueEditor = ndb.EditableTable( "notes_ue", "ue_id", ( @@ -561,11 +577,11 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl "coefficient", ), sortkey="numero", - input_formators={"type": int_null_is_zero}, + input_formators={"type": ndb.int_null_is_zero}, output_formators={ - "numero": int_null_is_zero, - "ects": float_null_is_null, - "coefficient": float_null_is_zero, + "numero": ndb.int_null_is_zero, + "ects": ndb.float_null_is_null, + "coefficient": ndb.float_null_is_zero, }, ) @@ -625,7 +641,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl ) if delete_validations: log("deleting all validations of UE %s" % ue_id) - SimpleQuery( + ndb.SimpleQuery( self, "DELETE FROM scolar_formsemestre_validation WHERE ue_id=%(ue_id)s", {"ue_id": ue_id}, @@ -636,12 +652,12 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl for mat in mats: self.do_matiere_delete(mat["matiere_id"], REQUEST) # delete uecoef and events - SimpleQuery( + ndb.SimpleQuery( self, "DELETE FROM notes_formsemestre_uecoef WHERE ue_id=%(ue_id)s", {"ue_id": ue_id}, ) - SimpleQuery( + ndb.SimpleQuery( self, "DELETE FROM scolar_events WHERE ue_id=%(ue_id)s", {"ue_id": ue_id} ) cnx = self.GetDBConnexion() @@ -659,7 +675,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl # if not force: return REQUEST.RESPONSE.redirect( - REQUEST.URL1 + "/ue_list?formation_id=" + str(ue["formation_id"]) + self.NotesURL() + "/ue_list?formation_id=" + str(ue["formation_id"]) ) else: return None @@ -672,12 +688,12 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl return self._ueEditor.list(cnx, *args, **kw) # --- Matieres - _matiereEditor = EditableTable( + _matiereEditor = ndb.EditableTable( "notes_matieres", "matiere_id", ("matiere_id", "ue_id", "numero", "titre"), sortkey="numero", - output_formators={"numero": int_null_is_zero}, + output_formators={"numero": ndb.int_null_is_zero}, ) security.declareProtected(ScoChangeFormation, "do_matiere_create") @@ -746,7 +762,6 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl cnx = self.GetDBConnexion() # check mat = self.do_matiere_list({"matiere_id": args[0]["matiere_id"]})[0] - ue = self.do_ue_list({"ue_id": mat["ue_id"]})[0] if self.matiere_is_locked(mat["matiere_id"]): raise ScoLockedFormError() # edit @@ -758,7 +773,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl def do_matiere_formation_id(self, matiere_id): "get formation_id from matiere" cnx = self.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( "select UE.formation_id from notes_matieres M, notes_ue UE where M.matiere_id = %(matiere_id)s and M.ue_id = UE.ue_id", {"matiere_id": matiere_id}, @@ -767,7 +782,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl return res[0][0] # --- Modules - _moduleEditor = EditableTable( + _moduleEditor = ndb.EditableTable( "notes_modules", "module_id", ( @@ -790,13 +805,13 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl ), sortkey="numero, code, titre", output_formators={ - "heures_cours": float_null_is_zero, - "heures_td": float_null_is_zero, - "heures_tp": float_null_is_zero, - "numero": int_null_is_zero, - "coefficient": float_null_is_zero, - "module_type": int_null_is_zero - #'ects' : float_null_is_null + "heures_cours": ndb.float_null_is_zero, + "heures_td": ndb.float_null_is_zero, + "heures_tp": ndb.float_null_is_zero, + "numero": ndb.int_null_is_zero, + "coefficient": ndb.float_null_is_zero, + "module_type": ndb.int_null_is_zero + #'ects' : ndb.float_null_is_null }, ) @@ -828,7 +843,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl raise ScoLockedFormError() # S'il y a des moduleimpls, on ne peut pas detruire le module ! - mods = self.do_moduleimpl_list(module_id=oid) + mods = sco_moduleimpl.do_moduleimpl_list(self, module_id=oid) if mods: err_page = self.confirmDialog( message="""Destruction du module impossible car il est utilisé dans des semestres existants !""", @@ -906,7 +921,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl def module_count_moduleimpls(self, module_id): "Number of moduleimpls using this module" - mods = self.do_moduleimpl_list(module_id=module_id) + mods = sco_moduleimpl.do_moduleimpl_list(self, module_id=module_id) return len(mods) security.declareProtected(ScoView, "module_is_locked") @@ -915,7 +930,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl """True if UE should not be modified (used in a locked formsemestre) """ - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( self, """SELECT mi.* from notes_modules mod, notes_formsemestre sem, notes_moduleimpl mi WHERE mi.module_id = mod.module_id AND mi.formsemestre_id = sem.formsemestre_id @@ -931,7 +946,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl """True if matiere should not be modified (contains modules used in a locked formsemestre) """ - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( self, """SELECT ma.* from notes_matieres ma, notes_modules mod, notes_formsemestre sem, notes_moduleimpl mi WHERE ma.matiere_id = mod.matiere_id AND mi.module_id = mod.module_id AND mi.formsemestre_id = sem.formsemestre_id @@ -947,7 +962,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl """True if module should not be modified (contains modules used in a locked formsemestre) """ - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( self, """SELECT ue.* FROM notes_ue ue, notes_modules mod, notes_formsemestre sem, notes_moduleimpl mi WHERE ue.ue_id = mod.ue_id @@ -992,6 +1007,8 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl if redirect: return REQUEST.RESPONSE.redirect("ue_list?formation_id=" + formation_id) + security.declareProtected(ScoChangeFormation, "ue_move") + def ue_move(self, ue_id, after=0, REQUEST=None, redirect=1): """Move UE before/after previous one (decrement/increment numero)""" o = self.do_ue_list({"ue_id": ue_id})[0] @@ -1064,6 +1081,8 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl ) return formsemestre_id + security.declareProtected(ScoView, "formsemestre_list") + def formsemestre_list( self, format=None, @@ -1084,7 +1103,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl args[argname] = L[argname] sems = sco_formsemestre.do_formsemestre_list(self, args=args) # log('formsemestre_list: format="%s", %s semestres found' % (format,len(sems))) - return sendResult(REQUEST, sems, name="formsemestre", format=format) + return scu.sendResult(REQUEST, sems, name="formsemestre", format=format) security.declareProtected(ScoView, "XMLgetFormsemestres") @@ -1099,8 +1118,8 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl if formsemestre_id: args["formsemestre_id"] = formsemestre_id if REQUEST: - 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.formsemestrelist() for sem in sco_formsemestre.do_formsemestre_list(self, args=args): doc._push() @@ -1192,158 +1211,12 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl else: return h - # --- Gestion des "Implémentations de Modules" - # Un "moduleimpl" correspond a la mise en oeuvre d'un module - # dans une formation spécifique, à une date spécifique. - _moduleimplEditor = EditableTable( - "notes_moduleimpl", - "moduleimpl_id", - ( - "moduleimpl_id", - "module_id", - "formsemestre_id", - "responsable_id", - "computation_expr", - ), - ) - - _modules_enseignantsEditor = EditableTable( - "notes_modules_enseignants", - "modules_enseignants_id", - ("modules_enseignants_id", "moduleimpl_id", "ens_id"), - ) - - security.declareProtected(ScoImplement, "do_moduleimpl_create") - - def do_moduleimpl_create(self, args): - "create a moduleimpl" - cnx = self.GetDBConnexion() - r = self._moduleimplEditor.create(cnx, args) - self._inval_cache( - formsemestre_id=args["formsemestre_id"] - ) # > creation moduleimpl - return r - - security.declareProtected(ScoImplement, "do_moduleimpl_delete") - - def do_moduleimpl_delete(self, oid, formsemestre_id=None): - "delete moduleimpl (desinscrit tous les etudiants)" - cnx = self.GetDBConnexion() - # --- desinscription des etudiants - cursor = cnx.cursor(cursor_factory=ScoDocCursor) - req = "DELETE FROM notes_moduleimpl_inscription WHERE moduleimpl_id=%(moduleimpl_id)s" - cursor.execute(req, {"moduleimpl_id": oid}) - # --- suppression des enseignants - cursor.execute( - "DELETE FROM notes_modules_enseignants WHERE moduleimpl_id=%(moduleimpl_id)s", - {"moduleimpl_id": oid}, - ) - # --- suppression des references dans les absences - cursor.execute( - "UPDATE absences SET moduleimpl_id=NULL WHERE moduleimpl_id=%(moduleimpl_id)s", - {"moduleimpl_id": oid}, - ) - # --- destruction du moduleimpl - self._moduleimplEditor.delete(cnx, oid) - self._inval_cache(formsemestre_id=formsemestre_id) # > moduleimpl_delete - - security.declareProtected(ScoView, "do_moduleimpl_list") - - def do_moduleimpl_list( - self, moduleimpl_id=None, formsemestre_id=None, module_id=None, REQUEST=None - ): - "list moduleimpls" - args = locals() - cnx = self.GetDBConnexion() - modimpls = self._moduleimplEditor.list(cnx, args) # *args, **kw) - # Ajoute la liste des enseignants - for mo in modimpls: - mo["ens"] = self.do_ens_list(args={"moduleimpl_id": mo["moduleimpl_id"]}) - return return_text_if_published(modimpls, REQUEST) - - security.declareProtected(ScoImplement, "do_moduleimpl_edit") - - def do_moduleimpl_edit(self, args, formsemestre_id=None, cnx=None): - "edit a moduleimpl" - if not cnx: - cnx = self.GetDBConnexion() - self._moduleimplEditor.edit(cnx, args) - - self._inval_cache(formsemestre_id=formsemestre_id) # > modif moduleimpl - - security.declareProtected(ScoView, "do_moduleimpl_withmodule_list") - - def do_moduleimpl_withmodule_list( - self, moduleimpl_id=None, formsemestre_id=None, module_id=None, REQUEST=None - ): - """Liste les moduleimpls et ajoute dans chacun le module correspondant - Tri la liste par semestre/UE/numero_matiere/numero_module - """ - args = locals() - del args["self"] - del args["REQUEST"] - modimpls = self.do_moduleimpl_list(**args) - for mo in modimpls: - mo["module"] = self.do_module_list(args={"module_id": mo["module_id"]})[0] - mo["ue"] = self.do_ue_list(args={"ue_id": mo["module"]["ue_id"]})[0] - mo["matiere"] = self.do_matiere_list( - args={"matiere_id": mo["module"]["matiere_id"]} - )[0] - - # tri par semestre/UE/numero_matiere/numero_module - - extr = lambda x: ( - x["ue"]["numero"], - x["ue"]["ue_id"], - x["matiere"]["numero"], - x["matiere"]["matiere_id"], - x["module"]["numero"], - x["module"]["code"], - ) - - modimpls.sort(lambda x, y: cmp(extr(x), extr(y))) - # log('after sort args=%s' % args) - # log( ',\n'.join( [ str(extr(m)) for m in modimpls ] )) - # log('after sort: Mlist=\n' + ',\n'.join( [ str(m) for m in modimpls ] ) + '\n') - return return_text_if_published(modimpls, REQUEST) - - security.declareProtected(ScoView, "do_ens_list") - - def do_ens_list(self, *args, **kw): - "liste les enseignants d'un moduleimpl (pas le responsable)" - cnx = self.GetDBConnexion() - ens = self._modules_enseignantsEditor.list(cnx, *args, **kw) - return ens - - security.declareProtected(ScoImplement, "do_ens_edit") - - def do_ens_edit(self, *args, **kw): - "edit ens" - cnx = self.GetDBConnexion() - self._modules_enseignantsEditor.edit(cnx, *args, **kw) - - security.declareProtected(ScoImplement, "do_ens_create") - - def do_ens_create(self, args): - "create ens" - cnx = self.GetDBConnexion() - r = self._modules_enseignantsEditor.create(cnx, args) - return r - - security.declareProtected(ScoImplement, "do_ens_delete") - - def do_ens_delete(self, oid): - "delete ens" - cnx = self.GetDBConnexion() - r = self._modules_enseignantsEditor.delete(cnx, oid) - return r - # --- dialogue modif enseignants/moduleimpl security.declareProtected(ScoView, "edit_enseignants_form") def edit_enseignants_form(self, REQUEST, moduleimpl_id): "modif liste enseignants/moduleimpl" - M, sem = self.can_change_ens(REQUEST, moduleimpl_id) + M, sem = sco_moduleimpl.can_change_ens(self, REQUEST, moduleimpl_id) # -- header = self.html_sem_header( REQUEST, @@ -1369,7 +1242,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl ] for ens in M["ens"]: H.append( - 'Pour changer le responsable du module, passez par la - page "Modification du semestre", accessible uniquement au responsable de la formation (chef de département) + page "Modification du semestre", accessible uniquement au responsable de la formation (chef de département) """ % ( sem["formation_id"], @@ -1438,8 +1311,8 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl % ens_id ) else: - self.do_ens_create( - {"moduleimpl_id": moduleimpl_id, "ens_id": ens_id} + sco_moduleimpl.do_ens_create( + self, {"moduleimpl_id": moduleimpl_id, "ens_id": ens_id} ) return REQUEST.RESPONSE.redirect( "edit_enseignants_form?moduleimpl_id=%s" % moduleimpl_id @@ -1452,7 +1325,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl """Changement d'un enseignant responsable de module Accessible par Admin et dir des etud si flag resp_can_change_ens """ - M, sem = self.can_change_module_resp(REQUEST, moduleimpl_id) + M, sem = sco_moduleimpl.can_change_module_resp(self, REQUEST, moduleimpl_id) H = [ self.html_sem_header( REQUEST, @@ -1520,14 +1393,15 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl return REQUEST.RESPONSE.redirect( "moduleimpl_status?moduleimpl_id=" + moduleimpl_id ) - self.do_moduleimpl_edit( + sco_moduleimpl.do_moduleimpl_edit( + self, {"moduleimpl_id": moduleimpl_id, "responsable_id": responsable_id}, formsemestre_id=sem["formsemestre_id"], ) return REQUEST.RESPONSE.redirect( "moduleimpl_status?moduleimpl_id=" + moduleimpl_id - + "&head_message=responsable%20modifié" + + "&head_message=responsable%20modifié" ) _expr_help = """Expérimental: formule de calcul de la moyenne %(target)s @@ -1557,7 +1431,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl """Edition formule calcul moyenne module Accessible par Admin, dir des etud et responsable module """ - M, sem = self.can_change_ens(REQUEST, moduleimpl_id) + M, sem = sco_moduleimpl.can_change_ens(self, REQUEST, moduleimpl_id) H = [ self.html_sem_header( REQUEST, @@ -1601,7 +1475,8 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl "moduleimpl_status?moduleimpl_id=" + moduleimpl_id ) else: - self.do_moduleimpl_edit( + sco_moduleimpl.do_moduleimpl_edit( + self, { "moduleimpl_id": moduleimpl_id, "computation_expr": tf[2]["computation_expr"], @@ -1614,18 +1489,20 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl return REQUEST.RESPONSE.redirect( "moduleimpl_status?moduleimpl_id=" + moduleimpl_id - + "&head_message=règle%20de%20calcul%20modifiée" + + "&head_message=règle%20de%20calcul%20modifiée" ) security.declareProtected(ScoView, "view_module_abs") def view_module_abs(self, REQUEST, moduleimpl_id, format="html"): """Visualisation des absences a un module""" - M = self.do_moduleimpl_withmodule_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_withmodule_list( + self, moduleimpl_id=moduleimpl_id + )[0] sem = sco_formsemestre.get_formsemestre(self, M["formsemestre_id"]) - debut_sem = DateDMYtoISO(sem["date_debut"]) - fin_sem = DateDMYtoISO(sem["date_fin"]) - list_insc = self.do_moduleimpl_listeetuds(moduleimpl_id) + debut_sem = ndb.DateDMYtoISO(sem["date_debut"]) + fin_sem = ndb.DateDMYtoISO(sem["date_fin"]) + list_insc = sco_moduleimpl.do_moduleimpl_listeetuds(self, moduleimpl_id) T = [] for etudid in list_insc: @@ -1677,7 +1554,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl rows=T, html_class="table_leftalign", base_url="%s?moduleimpl_id=%s" % (REQUEST.URL0, moduleimpl_id), - filename="absmodule_" + make_filename(M["module"]["titre"]), + filename="absmodule_" + scu.make_filename(M["module"]["titre"]), caption="Absences dans le module %s" % M["module"]["titre"], preferences=self.get_preferences(), ) @@ -1753,7 +1630,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl return REQUEST.RESPONSE.redirect( "formsemestre_status?formsemestre_id=" + formsemestre_id - + "&head_message=règle%20de%20calcul%20modifiée" + + "&head_message=règle%20de%20calcul%20modifiée" ) security.declareProtected(ScoView, "formsemestre_enseignants_list") @@ -1764,7 +1641,9 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl """ sem = sco_formsemestre.get_formsemestre(self, formsemestre_id) # resp. de modules: - mods = self.do_moduleimpl_withmodule_list(formsemestre_id=formsemestre_id) + mods = sco_moduleimpl.do_moduleimpl_withmodule_list( + self, formsemestre_id=formsemestre_id + ) sem_ens = {} for mod in mods: if not mod["responsable_id"] in sem_ens: @@ -1780,15 +1659,15 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl sem_ens[ensd["ens_id"]]["mods"].append(mod) # compte les absences ajoutées par chacun dans tout le semestre cnx = self.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) for ens in sem_ens: cursor.execute( "select * from scolog L, notes_formsemestre_inscription I where method='AddAbsence' and authenticated_user=%(authenticated_user)s and L.etudid = I.etudid and I.formsemestre_id=%(formsemestre_id)s and date > %(date_debut)s and date < %(date_fin)s", { "authenticated_user": ens, "formsemestre_id": formsemestre_id, - "date_debut": DateDMYtoISO(sem["date_debut"]), - "date_fin": DateDMYtoISO(sem["date_fin"]), + "date_debut": ndb.DateDMYtoISO(sem["date_debut"]), + "date_fin": ndb.DateDMYtoISO(sem["date_fin"]), }, ) @@ -1824,7 +1703,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl rows=sem_ens_list, html_sortable=True, html_class="table_leftalign", - filename=make_filename("Enseignants-" + sem["titreannee"]), + filename=scu.make_filename("Enseignants-" + sem["titreannee"]), html_title=self.html_sem_header( REQUEST, "Enseignants du semestre", sem, with_page_header=False ), @@ -1840,7 +1719,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl def edit_enseignants_form_delete(self, REQUEST, moduleimpl_id, ens_id): "remove ens" - M, sem = self.can_change_ens(REQUEST, moduleimpl_id) + M, _ = sco_moduleimpl.can_change_ens(self, REQUEST, moduleimpl_id) # search ens_id ok = False for ens in M["ens"]: @@ -1849,61 +1728,13 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl break if not ok: raise ScoValueError("invalid ens_id (%s)" % ens_id) - self.do_ens_delete(ens["modules_enseignants_id"]) + sco_moduleimpl.do_ens_delete(self, ens["modules_enseignants_id"]) return REQUEST.RESPONSE.redirect( "edit_enseignants_form?moduleimpl_id=%s" % moduleimpl_id ) - security.declareProtected(ScoView, "can_change_ens") - - def can_change_ens(self, REQUEST, moduleimpl_id, raise_exc=True): - "check if current user can modify ens list (raise exception if not)" - M = self.do_moduleimpl_withmodule_list(moduleimpl_id=moduleimpl_id)[0] - # -- check lock - sem = sco_formsemestre.get_formsemestre(self, M["formsemestre_id"]) - if sem["etat"] != "1": - if raise_exc: - raise ScoValueError("Modification impossible: semestre verrouille") - else: - return False - # -- check access - authuser = REQUEST.AUTHENTICATED_USER - uid = str(authuser) - # admin, resp. module ou resp. semestre - if ( - uid != M["responsable_id"] - and not authuser.has_permission(ScoImplement, self) - and (uid not in sem["responsables"]) - ): - if raise_exc: - raise AccessDenied("Modification impossible pour %s" % uid) - else: - return False - return M, sem - - security.declareProtected(ScoView, "can_change_module_resp") - - def can_change_module_resp(self, REQUEST, moduleimpl_id): - """Check if current user can modify module resp. (raise exception if not). - = Admin, et dir des etud. (si option l'y autorise) - """ - M = self.do_moduleimpl_withmodule_list(moduleimpl_id=moduleimpl_id)[0] - # -- check lock - sem = sco_formsemestre.get_formsemestre(self, M["formsemestre_id"]) - if sem["etat"] != "1": - raise ScoValueError("Modification impossible: semestre verrouille") - # -- check access - authuser = REQUEST.AUTHENTICATED_USER - uid = str(authuser) - # admin ou resp. semestre avec flag resp_can_change_resp - if not authuser.has_permission(ScoImplement, self) and ( - (uid not in sem["responsables"]) or (not sem["resp_can_change_ens"]) - ): - raise AccessDenied("Modification impossible pour %s" % uid) - return M, sem - # --- Gestion des inscriptions aux modules - _formsemestre_inscriptionEditor = EditableTable( + _formsemestre_inscriptionEditor = ndb.EditableTable( "notes_formsemestre_inscription", "formsemestre_inscription_id", ("formsemestre_inscription_id", "etudid", "formsemestre_id", "etat", "etape"), @@ -1974,18 +1805,19 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl security.declareProtected(ScoView, "do_formsemestre_inscription_listinscrits") - def do_formsemestre_inscription_listinscrits(self, formsemestre_id): + def do_formsemestre_inscription_listinscrits( + self, formsemestre_id, format=None, REQUEST=None + ): """Liste les inscrits (état I) à ce semestre et cache le résultat""" cache = self.get_formsemestre_inscription_cache() r = cache.get(formsemestre_id) - if r != None: - return r - # retreive list - r = self.do_formsemestre_inscription_list( - args={"formsemestre_id": formsemestre_id, "etat": "I"} - ) - cache.set(formsemestre_id, r) - return r + if r is None: + # retreive list + r = self.do_formsemestre_inscription_list( + args={"formsemestre_id": formsemestre_id, "etat": "I"} + ) + cache.set(formsemestre_id, r) + return scu.sendResult(REQUEST, r, format=format, name="inscrits") security.declareProtected(ScoImplement, "do_formsemestre_inscription_edit") @@ -1998,7 +1830,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl ) # > modif inscription semestre (demission ?) # Cache inscriptions semestres - def get_formsemestre_inscription_cache(self): + def get_formsemestre_inscription_cache(self, format=None): u = self.GetDBConnexionString() if CACHE_formsemestre_inscription.has_key(u): return CACHE_formsemestre_inscription[u] @@ -2028,7 +1860,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl raise ScoValueError( """Désinscription impossible: l'étudiant a une décision de jury (la supprimer avant si nécessaire: - + supprimer décision jury ) """ @@ -2083,6 +1915,8 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl + self.sco_footer(REQUEST) ) + security.declareProtected(ScoImplement, "do_formsemestre_desinscription") + def do_formsemestre_desinscription(self, etudid, formsemestre_id, REQUEST=None): """Désinscription d'un étudiant. Si semestre extérieur et dernier inscrit, suppression de ce semestre. @@ -2107,7 +1941,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl insem = insem[0] # -- desinscription de tous les modules cnx = self.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( "select moduleimpl_inscription_id from notes_moduleimpl_inscription Im, notes_moduleimpl M where Im.etudid=%(etudid)s and Im.moduleimpl_id = M.moduleimpl_id and M.formsemestre_id = %(formsemestre_id)s", {"etudid": etudid, "formsemestre_id": formsemestre_id}, @@ -2115,8 +1949,8 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl res = cursor.fetchall() moduleimpl_inscription_ids = [x[0] for x in res] for moduleimpl_inscription_id in moduleimpl_inscription_ids: - self.do_moduleimpl_inscription_delete( - moduleimpl_inscription_id, formsemestre_id=formsemestre_id + sco_moduleimpl.do_moduleimpl_inscription_delete( + self, moduleimpl_inscription_id, formsemestre_id=formsemestre_id ) # -- desincription du semestre self.do_formsemestre_inscription_delete( @@ -2147,123 +1981,6 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl commit=False, ) - # --- Inscriptions aux modules - _moduleimpl_inscriptionEditor = EditableTable( - "notes_moduleimpl_inscription", - "moduleimpl_inscription_id", - ("moduleimpl_inscription_id", "etudid", "moduleimpl_id"), - ) - - security.declareProtected(ScoEtudInscrit, "do_moduleimpl_inscription_create") - - def do_moduleimpl_inscription_create( - self, args, REQUEST=None, formsemestre_id=None - ): - "create a moduleimpl_inscription" - cnx = self.GetDBConnexion() - log("do_moduleimpl_inscription_create: " + str(args)) - r = self._moduleimpl_inscriptionEditor.create(cnx, args) - self._inval_cache(formsemestre_id=formsemestre_id) # > moduleimpl_inscription - if REQUEST: - logdb( - REQUEST, - cnx, - method="moduleimpl_inscription", - etudid=args["etudid"], - msg="inscription module %s" % args["moduleimpl_id"], - commit=False, - ) - return r - - security.declareProtected(ScoImplement, "do_moduleimpl_inscription_delete") - - def do_moduleimpl_inscription_delete(self, oid, formsemestre_id=None): - "delete moduleimpl_inscription" - cnx = self.GetDBConnexion() - self._moduleimpl_inscriptionEditor.delete(cnx, oid) - self._inval_cache(formsemestre_id=formsemestre_id) # > moduleimpl_inscription - - security.declareProtected(ScoView, "do_moduleimpl_inscription_list") - - def do_moduleimpl_inscription_list( - self, moduleimpl_id=None, etudid=None, REQUEST=None - ): - "list moduleimpl_inscriptions" - args = locals() - cnx = self.GetDBConnexion() - return return_text_if_published( - self._moduleimpl_inscriptionEditor.list(cnx, args), REQUEST - ) - - security.declareProtected(ScoView, "do_moduleimpl_listeetuds") - - def do_moduleimpl_listeetuds(self, moduleimpl_id): - "retourne liste des etudids inscrits a ce module" - req = "select distinct Im.etudid from notes_moduleimpl_inscription Im, notes_formsemestre_inscription Isem, notes_moduleimpl M where Isem.etudid=Im.etudid and Im.moduleimpl_id=M.moduleimpl_id and M.moduleimpl_id = %(moduleimpl_id)s" - cnx = self.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) - cursor.execute(req, {"moduleimpl_id": moduleimpl_id}) - res = cursor.fetchall() - return [x[0] for x in res] - - security.declareProtected(ScoEtudInscrit, "do_moduleimpl_inscrit_tout_semestre") - - def do_moduleimpl_inscrit_tout_semestre(self, moduleimpl_id, formsemestre_id): - "inscrit tous les etudiants inscrit au semestre a ce module" - cnx = self.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) - req = """INSERT INTO notes_moduleimpl_inscription - (moduleimpl_id, etudid) - SELECT %(moduleimpl_id)s, I.etudid - FROM notes_formsemestre_inscription I - WHERE I.formsemestre_id=%(formsemestre_id)s""" - args = {"moduleimpl_id": moduleimpl_id, "formsemestre_id": formsemestre_id} - cursor.execute(req, args) - - security.declareProtected(ScoEtudInscrit, "do_moduleimpl_inscrit_etuds") - - def do_moduleimpl_inscrit_etuds( - self, moduleimpl_id, formsemestre_id, etudids, reset=False, REQUEST=None - ): - """Inscrit les etudiants (liste d'etudids) a ce module. - Si reset, desinscrit tous les autres. - """ - # Verifie qu'ils sont tous bien inscrits au semestre - for etudid in etudids: - insem = self.do_formsemestre_inscription_list( - args={"formsemestre_id": formsemestre_id, "etudid": etudid} - ) - if not insem: - raise ScoValueError("%s n'est pas inscrit au semestre !" % etudid) - - # Desinscriptions - if reset: - cnx = self.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) - cursor.execute( - "delete from notes_moduleimpl_inscription where moduleimpl_id = %(moduleimpl_id)s", - {"moduleimpl_id": moduleimpl_id}, - ) - # Inscriptions au module: - inmod_set = set( - [ - x["etudid"] - for x in self.do_moduleimpl_inscription_list( - moduleimpl_id=moduleimpl_id - ) - ] - ) - for etudid in etudids: - # deja inscrit ? - if not etudid in inmod_set: - self.do_moduleimpl_inscription_create( - {"moduleimpl_id": moduleimpl_id, "etudid": etudid}, - REQUEST=REQUEST, - formsemestre_id=formsemestre_id, - ) - - self._inval_cache(formsemestre_id=formsemestre_id) # > moduleimpl_inscrit_etuds - security.declareProtected(ScoEtudInscrit, "etud_desinscrit_ue") def etud_desinscrit_ue(self, etudid, formsemestre_id, ue_id, REQUEST=None): @@ -2336,7 +2053,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl ) # --- Evaluations - _evaluationEditor = EditableTable( + _evaluationEditor = ndb.EditableTable( "notes_evaluation", "evaluation_id", ( @@ -2355,15 +2072,15 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl ), sortkey="numero desc, jour desc, heure_debut desc", # plus recente d'abord output_formators={ - "jour": DateISOtoDMY, + "jour": ndb.DateISOtoDMY, "visibulletin": str, "publish_incomplete": str, - "numero": int_null_is_zero, + "numero": ndb.int_null_is_zero, }, input_formators={ - "jour": DateDMYtoISO, - "heure_debut": TimetoISO8601, # converti par do_evaluation_list - "heure_fin": TimetoISO8601, # converti par do_evaluation_list + "jour": ndb.DateDMYtoISO, + "heure_debut": ndb.TimetoISO8601, # converti par do_evaluation_list + "heure_fin": ndb.TimetoISO8601, # converti par do_evaluation_list "visibulletin": int, "publish_incomplete": int, }, @@ -2380,7 +2097,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl raise ValueError("no moduleimpl specified") # bug authuser = REQUEST.AUTHENTICATED_USER uid = str(authuser) - M = self.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_list(self, moduleimpl_id=moduleimpl_id)[0] sem = sco_formsemestre.get_formsemestre(self, M["formsemestre_id"]) if ( @@ -2431,9 +2148,15 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl ) if args["jour"]: next_eval = None - t = (DateDMYtoISO(args["jour"]), TimetoISO8601(args["heure_debut"])) + t = ( + ndb.DateDMYtoISO(args["jour"]), + ndb.TimetoISO8601(args["heure_debut"]), + ) for e in ModEvals: - if (DateDMYtoISO(e["jour"]), TimetoISO8601(e["heure_debut"])) > t: + if ( + ndb.DateDMYtoISO(e["jour"]), + ndb.TimetoISO8601(e["heure_debut"]), + ) > t: next_eval = e break if next_eval: @@ -2456,7 +2179,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl r = self._evaluationEditor.create(cnx, args) # news - M = self.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_list(self, moduleimpl_id=moduleimpl_id)[0] mod = self.do_module_list(args={"module_id": M["module_id"]})[0] mod["moduleimpl_id"] = M["moduleimpl_id"] mod["url"] = "Notes/moduleimpl_status?moduleimpl_id=%(moduleimpl_id)s" % mod @@ -2499,14 +2222,14 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl jour = args.get("jour", None) args["jour"] = jour if jour: - M = self.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_list(self, moduleimpl_id=moduleimpl_id)[0] sem = sco_formsemestre.get_formsemestre(self, M["formsemestre_id"]) d, m, y = [int(x) for x in sem["date_debut"].split("/")] date_debut = datetime.date(y, m, d) d, m, y = [int(x) for x in sem["date_fin"].split("/")] date_fin = datetime.date(y, m, d) - # passe par DateDMYtoISO pour avoir date pivot - y, m, d = [int(x) for x in DateDMYtoISO(jour).split("-")] + # passe par ndb.DateDMYtoISO pour avoir date pivot + y, m, d = [int(x) for x in ndb.DateDMYtoISO(jour).split("-")] jour = datetime.date(y, m, d) if (jour > date_fin) or (jour < date_debut): raise ScoValueError( @@ -2519,7 +2242,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl args["heure_fin"] = heure_fin if jour and ((not heure_debut) or (not heure_fin)): raise ScoValueError("Les heures doivent être précisées") - d = TimeDuration(heure_debut, heure_fin) + d = ndb.TimeDuration(heure_debut, heure_fin) if d and ((d < 0) or (d > 60 * 12)): raise ScoValueError("Heures de l'évaluation incohérentes !") @@ -2531,7 +2254,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl if not El: raise ValueError("Evalution inexistante ! (%s)" % evaluation_id) E = El[0] - M = self.do_moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0] + M = sco_moduleimpl.do_moduleimpl_list(self, moduleimpl_id=E["moduleimpl_id"])[0] Mod = self.do_module_list(args={"module_id": M["module_id"]})[0] tit = "Suppression de l'évaluation %(description)s (%(jour)s)" % E etat = sco_evaluations.do_evaluation_etat(self, evaluation_id) @@ -2619,11 +2342,11 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl 8, 00 ) # au cas ou pas d'heure (note externe?) heure_fin_dt = e["heure_fin"] or datetime.time(8, 00) - e["heure_debut"] = TimefromISO8601(e["heure_debut"]) - e["heure_fin"] = TimefromISO8601(e["heure_fin"]) - e["jouriso"] = DateDMYtoISO(e["jour"]) + e["heure_debut"] = ndb.TimefromISO8601(e["heure_debut"]) + e["heure_fin"] = ndb.TimefromISO8601(e["heure_fin"]) + e["jouriso"] = ndb.DateDMYtoISO(e["jour"]) heure_debut, heure_fin = e["heure_debut"], e["heure_fin"] - d = TimeDuration(heure_debut, heure_fin) + d = ndb.TimeDuration(heure_debut, heure_fin) if d is not None: m = d % 60 e["duree"] = "%dh" % (d / 60) @@ -2653,8 +2376,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl def do_evaluation_list_in_formsemestre(self, formsemestre_id): "list evaluations in this formsemestre" - cnx = self.GetDBConnexion() - mods = self.do_moduleimpl_list(formsemestre_id=formsemestre_id) + mods = sco_moduleimpl.do_moduleimpl_list(self, formsemestre_id=formsemestre_id) evals = [] for mod in mods: evals += self.do_evaluation_list( @@ -2677,7 +2399,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl cnx = self.GetDBConnexion() self._evaluationEditor.edit(cnx, args) # inval cache pour ce semestre - M = self.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_list(self, moduleimpl_id=moduleimpl_id)[0] self._inval_cache( formsemestre_id=M["formsemestre_id"] ) # > evaluation_edit (coef, ...) @@ -2753,42 +2475,6 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl security.declareProtected(ScoView, "evaluation_suppress_alln") evaluation_suppress_alln = sco_saisie_notes.evaluation_suppress_alln - security.declareProtected(ScoView, "can_edit_notes") - - def can_edit_notes(self, authuser, moduleimpl_id, allow_ens=True): - """True if authuser can enter or edit notes in this module. - If allow_ens, grant access to all ens in this module - - Si des décisions de jury ont déjà été saisies dans ce semestre, - seul le directeur des études peut saisir des notes (et il ne devrait pas). - """ - uid = str(authuser) - M = self.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] - sem = sco_formsemestre.get_formsemestre(self, M["formsemestre_id"]) - if sem["etat"] != "1": - return False # semestre verrouillé - - if sco_parcours_dut.formsemestre_has_decisions(self, sem["formsemestre_id"]): - # il y a des décisions de jury dans ce semestre ! - return ( - authuser.has_permission(ScoEditAllNotes, self) - or uid in sem["responsables"] - ) - else: - if ( - (not authuser.has_permission(ScoEditAllNotes, self)) - and uid != M["responsable_id"] - and uid not in sem["responsables"] - ): - # enseignant (chargé de TD) ? - if allow_ens: - for ens in M["ens"]: - if ens["ens_id"] == uid: - return True - return False - else: - return True - security.declareProtected(ScoEditAllNotes, "dummy_ScoEditAllNotes") def dummy_ScoEditAllNotes(self): @@ -2851,7 +2537,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl if r != None: return r cnx = self.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cond = " where evaluation_id=%(evaluation_id)s" if by_uid: cond += " and uid=%(by_uid)s" @@ -2864,7 +2550,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl d = {} if filter_suppressed: for x in res: - if x["value"] != NOTES_SUPPRESS: + if x["value"] != scu.NOTES_SUPPRESS: d[x["etudid"]] = x else: for x in res: @@ -2883,7 +2569,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl pdfdoc, filename = sco_bulletins_pdf.get_formsemestre_bulletins_pdf( self, formsemestre_id, REQUEST, version=version ) - return sendPDFFile(REQUEST, pdfdoc, filename) + return scu.sendPDFFile(REQUEST, pdfdoc, filename) security.declareProtected(ScoView, "etud_bulletins_pdf") @@ -2892,7 +2578,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl pdfdoc, filename = sco_bulletins_pdf.get_etud_bulletins_pdf( self, etudid, REQUEST, version=version ) - return sendPDFFile(REQUEST, pdfdoc, filename) + return scu.sendPDFFile(REQUEST, pdfdoc, filename) security.declareProtected(ScoView, "formsemestre_bulletins_pdf_choice") formsemestre_bulletins_pdf_choice = sco_bulletins.formsemestre_bulletins_pdf_choice @@ -2914,7 +2600,6 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl ): "envoi a chaque etudiant (inscrit et ayant un mail) son bulletin" prefer_mail_perso = int(prefer_mail_perso) - sem = sco_formsemestre.get_formsemestre(self, formsemestre_id) nt = self._getNotesCache().get_NotesTable( self, formsemestre_id ) # > get_etudids @@ -2940,7 +2625,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl # Make each bulletin nb_send = 0 for etudid in etudids: - h, i = sco_bulletins.do_formsemestre_bulletinetud( + h, _ = sco_bulletins.do_formsemestre_bulletinetud( self, formsemestre_id, etudid, @@ -2960,7 +2645,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl + self.sco_footer(REQUEST) ) - security.declareProtected(ScoView, "formsemestre_bulletins_mailetuds") + security.declareProtected(ScoView, "external_ue_create_form") external_ue_create_form = sco_ue_external.external_ue_create_form security.declareProtected(ScoEnsView, "appreciation_add_form") @@ -2997,7 +2682,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl if not can_edit_app: raise AccessDenied("vous n'avez pas le droit d'ajouter une appreciation") # - bull_url = "formsemestre_bulletinetud?formsemestre_id=%s&etudid=%s" % ( + bull_url = "formsemestre_bulletinetud?formsemestre_id=%s&etudid=%s" % ( formsemestre_id, etudid, ) @@ -3071,21 +2756,6 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl ) # > appreciation_add return REQUEST.RESPONSE.redirect(bull_url) - security.declareProtected(ScoView, "can_change_groups") - - def can_change_groups(self, REQUEST, formsemestre_id): - "Vrai si utilisateur peut changer les groupes dans ce semestre" - sem = sco_formsemestre.get_formsemestre(self, formsemestre_id) - if sem["etat"] != "1": - return False # semestre verrouillé - authuser = REQUEST.AUTHENTICATED_USER - if authuser.has_permission(ScoEtudChangeGroups, self): - return True # admin, chef dept - uid = str(authuser) - if uid in sem["responsables"]: - return True - return False - def _can_edit_pv(self, REQUEST, formsemestre_id): "Vrai si utilisateur peut editer un PV de jury de ce semestre" @@ -3282,7 +2952,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl self, formsemestre_id, REQUEST ) - security.declareProtected(ScoView, "formsemestre_validation_auto") + security.declareProtected(ScoView, "do_formsemestre_validation_auto") def do_formsemestre_validation_auto(self, formsemestre_id, REQUEST): "Formulaire saisie automatisee des decisions d'un semestre" @@ -3356,7 +3026,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl OK="Supprimer", dest_url="", REQUEST=REQUEST, - cancel_url="formsemestre_validation_etud_form?formsemestre_id=%s&etudid=%s" + cancel_url="formsemestre_validation_etud_form?formsemestre_id=%s&etudid=%s" % (formsemestre_id, etudid), parameters={"etudid": etudid, "formsemestre_id": formsemestre_id}, ) @@ -3366,7 +3036,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl ) return REQUEST.RESPONSE.redirect( self.ScoURL() - + "/Notes/formsemestre_validation_etud_form?formsemestre_id=%s&etudid=%s&head_message=Décision%%20supprimée" + + "/Notes/formsemestre_validation_etud_form?formsemestre_id=%s&etudid=%s&head_message=Décision%%20supprimée" % (formsemestre_id, etudid) ) @@ -3497,7 +3167,9 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl """ sem = sco_formsemestre.get_formsemestre(self, formsemestre_id) - modimpls = self.do_moduleimpl_list(formsemestre_id=formsemestre_id) + modimpls = sco_moduleimpl.do_moduleimpl_list( + self, formsemestre_id=formsemestre_id + ) bad_ue = [] bad_sem = [] for modimpl in modimpls: @@ -3526,7 +3198,6 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl def check_form_integrity(self, formation_id, fix=False, REQUEST=None): "debug" log("check_form_integrity: formation_id=%s fix=%s" % (formation_id, fix)) - F = self.formation_list(args={"formation_id": formation_id})[0] ues = self.do_ue_list(args={"formation_id": formation_id}) bad = [] for ue in ues: @@ -3571,7 +3242,9 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl # de formations diag = [] - Mlist = self.do_moduleimpl_withmodule_list(formsemestre_id=formsemestre_id) + Mlist = sco_moduleimpl.do_moduleimpl_withmodule_list( + self, formsemestre_id=formsemestre_id + ) for mod in Mlist: if mod["module"]["ue_id"] != mod["matiere"]["ue_id"]: diag.append( @@ -3625,22 +3298,10 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl ) # -------------------------------------------------------------------- + # Support for legacy ScoDoc 7 API + # -------------------------------------------------------------------- + security.declareProtected(ScoView, "do_moduleimpl_list") + do_moduleimpl_list = sco_moduleimpl.do_moduleimpl_list - -# -------------------------------------------------------------------- -# -# Zope Product Administration -# -# -------------------------------------------------------------------- -def manage_addZNotes( - self, id="id_ZNotes", title="The Title for ZNotes Object", REQUEST=None -): - "Add a ZNotes instance to a folder." - self._setObject(id, ZNotes(id, title)) - 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_addZNotesForm = DTMLFile("dtml/manage_addZNotesForm", globals()) + security.declareProtected(ScoView, "do_moduleimpl_withmodule_list") + do_moduleimpl_withmodule_list = sco_moduleimpl.do_moduleimpl_withmodule_list diff --git a/ZScoDoc.py b/ZScoDoc.py index c2c7094cc..3812a004b 100644 --- a/ZScoDoc.py +++ b/ZScoDoc.py @@ -31,35 +31,59 @@ Chaque departement est géré par un ZScolar sous ZScoDoc. """ -import time, string, glob, re, inspect -import urllib, urllib2, cgi, xml +import time +import datetime +import string +import glob +import re +import inspect +import urllib +import urllib2 +import cgi +import xml -try: - from cStringIO import StringIO -except: - from StringIO import StringIO +from cStringIO import StringIO from zipfile import ZipFile -import os.path, glob +import os.path import traceback -from email.MIMEMultipart import MIMEMultipart -from email.MIMEText import MIMEText -from email.MIMEBase import MIMEBase -from email.Header import Header -from email import Encoders +from email.MIMEMultipart import ( # pylint: disable=no-name-in-module,import-error + MIMEMultipart, +) +from email.MIMEText import MIMEText # pylint: disable=no-name-in-module,import-error +from email.MIMEBase import MIMEBase # pylint: disable=no-name-in-module,import-error +from email.Header import Header # pylint: disable=no-name-in-module,import-error +from email import Encoders # pylint: disable=no-name-in-module,import-error -from sco_zope import * +from sco_zope import * # pylint: disable=unused-wildcard-import -# try: import Products.ZPsycopgDA.DA as ZopeDA except: import ZPsycopgDA.DA as ZopeDA # interp.py -from sco_utils import * +import sco_utils as scu +import VERSION from notes_log import log import sco_find_etud -from ZScoUsers import pwdFascistCheck +import sco_users +from sco_permissions import ( + ScoView, + ScoEnsView, + ScoImplement, + ScoChangeFormation, + ScoObservateur, + ScoEtudInscrit, + ScoEtudChangeGroups, + ScoEtudChangeAdr, + ScoEtudSupprAnnotations, + ScoEditAllEvals, + ScoEditAllNotes, + ScoEditFormationTags, + ScoEditApo, + ScoSuperAdmin, +) +from sco_exceptions import ScoValueError, ScoLockedFormError, ScoGenError, AccessDenied class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Implicit): @@ -77,13 +101,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp manage_options = ( ({"label": "Contents", "action": "manage_main"},) + PropertyManager.manage_options # add the 'Properties' tab - + ( - # this line is kept as an example with the files : - # dtml/manage_editZScolarForm.dtml - # html/ZScolar-edit.stx - # {'label': 'Properties', 'action': 'manage_editForm',}, - {"label": "View", "action": "index_html"}, - ) + + ({"label": "View", "action": "index_html"},) + Item.manage_options # add the 'Undo' & 'Owner' tab + RoleManager.manage_options # add the 'Security' tab ) @@ -111,7 +129,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp def _check_users_folder(self, REQUEST=None): """Vérifie UserFolder et le crée s'il le faut""" try: - udb = self.UsersDB + _ = self.UsersDB return "" except: e = self._check_admin_perm(REQUEST) @@ -164,11 +182,11 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp pass # add missing getAuthFailedMessage (bug in exUserFolder ?) try: - x = self.getAuthFailedMessage + _ = self.getAuthFailedMessage except: log("adding getAuthFailedMessage to Zope install") parent = self.aq_parent - from OFS.DTMLMethod import addDTMLMethod + from OFS.DTMLMethod import addDTMLMethod # pylint: disable=import-error addDTMLMethod(parent, "getAuthFailedMessage", file="Identification") @@ -187,7 +205,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp da = ZopeDA.Connection( oid, "Cnx bd utilisateurs", - SCO_DEFAULT_SQL_USERS_CNX, + scu.SCO_DEFAULT_SQL_USERS_CNX, False, check=1, tilevel=2, @@ -207,7 +225,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp raise AccessDenied("vous n'avez pas le droit d'effectuer cette opération") log("trying to change admin password") # 1-- check strong password - if pwdFascistCheck(password) != None: + if not sco_users.is_valid_password(password): log("refusing weak password") return REQUEST.RESPONSE.redirect( "change_admin_user_form?message=Mot%20de%20passe%20trop%20simple,%20recommencez" @@ -255,16 +273,32 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp security.declareProtected("View", "list_depts") - def list_depts(self, REQUEST=None): - """List departments folders - (returns a list of Zope folders containing a ZScolar instance) + def list_depts(self, viewable=True, format=None, REQUEST=None): + """List departments + If viewable, list only depts viewable the current user. """ + authuser = REQUEST.AUTHENTICATED_USER + viewable = int(viewable) + return scu.sendResult( + REQUEST, + [ + d.id + for d in self._list_depts() + if (not viewable) or authuser.has_permission(ScoView, d.Scolarite) + ], + name="depts", + format=format, + ) + + def _list_depts(self, REQUEST=None): # not published + # List departments folders + # (returns a list of Zope folders containing a ZScolar instance) folders = self.objectValues("Folder") # select folders with Scolarite object: r = [] for folder in folders: try: - s = folder.Scolarite + _ = folder.Scolarite r.append(folder) except: pass @@ -309,7 +343,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp if e: return e - if not force and DeptId not in [x.id for x in self.list_depts()]: + if not force and DeptId not in [x.id for x in self._list_depts()]: raise ValueError("nom de departement invalide") self.manage_delObjects(ids=[DeptId]) @@ -317,8 +351,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp return ( "Département " + DeptId - + """ supprimé du serveur web (la base de données n'est pas affectée)! """ - % REQUEST.URL1 + + """ supprimé du serveur web (la base de données n'est pas affectée)!""" ) _top_level_css = """ @@ -362,10 +395,10 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp def scodoc_top_html_header(self, REQUEST, page_title="ScoDoc"): H = [ self._html_begin - % {"page_title": "ScoDoc: bienvenue", "encoding": SCO_ENCODING}, + % {"page_title": "ScoDoc: bienvenue", "encoding": scu.SCO_ENCODING}, self._top_level_css, """""", - CUSTOM_HTML_HEADER_CNX, + scu.CUSTOM_HTML_HEADER_CNX, ] return "\n".join(H) @@ -374,7 +407,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp def index_html(self, REQUEST=None, message=None): """Top level page for ScoDoc""" authuser = REQUEST.AUTHENTICATED_USER - deptList = self.list_depts() + deptList = self._list_depts() self._fix_users_folder() # fix our exUserFolder isAdmin = not self._check_admin_perm(REQUEST) try: @@ -382,14 +415,14 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp except: admin_password_initialized = "0" if isAdmin and admin_password_initialized != "1": - REQUEST.RESPONSE.redirect( + return REQUEST.RESPONSE.redirect( "ScoDoc/change_admin_user_form?message=Le%20mot%20de%20passe%20administrateur%20doit%20etre%20change%20!" ) # Si l'URL indique que l'on est dans un folder, affiche page login du departement try: deptfoldername = REQUEST.URL0.split("ScoDoc")[1].split("/")[1] - if deptfoldername in [x.id for x in self.list_depts()]: + if deptfoldername in [x.id for x in self._list_depts()]: return self.index_dept(deptfoldername=deptfoldername, REQUEST=REQUEST) except: pass @@ -436,7 +469,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp dest_folder = "/Scolarite" else: dest_folder = "" - for deptFolder in self.list_depts(): + for deptFolder in self._list_depts(): if authuser.has_permission(ScoView, deptFolder.Scolarite): link_cls = "link_accessible" else: @@ -471,6 +504,11 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp % REQUEST.BASE0 ) + # Lien expérimental temporaire: + H.append( + 'Version mobile (expérimentale, à vos risques et périls) ' + ) + H.append( """
@@ -478,7 +516,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
E. Viennet (Université Paris 13).
"""
- % (SCO_WEBSITE,)
+ % (scu.SCO_WEBSITE,)
)
H.append(""" |