From d6fa3e57de99c7f0768efd2c3eb0db78ba2d19fb Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sun, 17 Jan 2021 09:37:11 +0100 Subject: [PATCH 1/2] Refactoring: remove useless public zmethods --- ZAbsences.py | 94 +------ ZEntreprises.py | 643 +++++++++++---------------------------------- ZScolar.py | 2 +- sco_abs.py | 40 ++- sco_abs_views.py | 41 ++- sco_entreprises.py | 326 +++++++++++++++++++++++ sco_groups_view.py | 15 +- 7 files changed, 570 insertions(+), 591 deletions(-) create mode 100644 sco_entreprises.py diff --git a/ZAbsences.py b/ZAbsences.py index e10afce5e..ab194f5ab 100644 --- a/ZAbsences.py +++ b/ZAbsences.py @@ -666,21 +666,6 @@ class ZAbsences( if self.CountAbs(etudid, jour, jour, matin, moduleimpl_id) == 0: self._AddAbsence(etudid, jour, matin, 0, REQUEST, "", moduleimpl_id) - # - security.declareProtected(ScoView, "CalSelectWeek") - - def CalSelectWeek(self, year=None, REQUEST=None): - "display calendar allowing week selection" - if not year: - year = scu.AnneeScolaire(REQUEST) - sems = sco_formsemestre.do_formsemestre_list(self) - if not sems: - js = "" - else: - js = 'onmouseover="highlightweek(this);" onmouseout="deselectweeks();" onclick="wclick(this);"' - C = sco_abs.YearTable(self, int(year), dayattributes=js) - return C - # --- Misc tools.... ------------------ def _isFarFutur(self, jour): @@ -691,65 +676,6 @@ class ZAbsences( # 6 mois ~ 182 jours: return j - datetime.date.today() > datetime.timedelta(182) - security.declareProtected(ScoView, "is_work_saturday") - - def is_work_saturday(self): - "Vrai si le samedi est travaillé" - return int(self.get_preference("work_saturday")) - - security.declareProtected(ScoView, "day_names") - - def day_names(self): - """Returns week day names. - If work_saturday property is set, include saturday - """ - if self.is_work_saturday(): - return ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"] - else: - return ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi"] - - security.declareProtected(ScoView, "ListMondays") - - def ListMondays(self, year=None, REQUEST=None): - """return list of mondays (ISO dates), from september to june""" - if not year: - year = scu.AnneeScolaire(REQUEST) - d = ddmmyyyy("1/9/%d" % year, work_saturday=self.is_work_saturday()) - while d.weekday != 0: - d = d.next() - end = ddmmyyyy("1/7/%d" % (year + 1), work_saturday=self.is_work_saturday()) - L = [d] - while d < end: - d = d.next(days=7) - L.append(d) - return map(lambda x: x.ISO(), L) - - security.declareProtected(ScoView, "NextISODay") - - def NextISODay(self, date): - "return date after date" - d = ddmmyyyy(date, fmt="iso", work_saturday=self.is_work_saturday()) - return d.next().ISO() - - security.declareProtected(ScoView, "DateRangeISO") - - def DateRangeISO(self, date_beg, date_end, workable=1): - """returns list of dates in [date_beg,date_end] - workable = 1 => keeps only workable days""" - if not date_beg: - raise ScoValueError("pas de date spécifiée !") - if not date_end: - date_end = date_beg - r = [] - cur = ddmmyyyy(date_beg, work_saturday=self.is_work_saturday()) - end = ddmmyyyy(date_end, work_saturday=self.is_work_saturday()) - while cur <= end: - if (not workable) or cur.iswork(): - r.append(cur) - cur = cur.next() - - return map(lambda x: x.ISO(), r) - # ------------ HTML Interfaces security.declareProtected(ScoAbsChange, "SignaleAbsenceGrHebdo") @@ -801,8 +727,8 @@ class ZAbsences( # calcule dates jours de cette semaine # liste de dates iso "yyyy-mm-dd" datessem = [notesdb.DateDMYtoISO(datelundi)] - for _ in self.day_names()[1:]: - datessem.append(self.NextISODay(datessem[-1])) + for _ in sco_abs.day_names(self)[1:]: + datessem.append(sco_abs.next_iso_day(self, datessem[-1])) # if groups_infos.tous_les_etuds_du_sem: gr_tit = "en" @@ -944,12 +870,12 @@ class ZAbsences( sem = sco_formsemestre.do_formsemestre_list( self, {"formsemestre_id": formsemestre_id} )[0] - - jourdebut = ddmmyyyy(datedebut, work_saturday=self.is_work_saturday()) - jourfin = ddmmyyyy(datefin, work_saturday=self.is_work_saturday()) + work_saturday = sco_abs.is_work_saturday(self) + jourdebut = ddmmyyyy(datedebut, work_saturday=work_saturday) + jourfin = ddmmyyyy(datefin, work_saturday=work_saturday) today = ddmmyyyy( time.strftime("%d/%m/%Y", time.localtime()), - work_saturday=self.is_work_saturday(), + work_saturday=work_saturday, ) today.next() if jourfin > today: # ne propose jamais les semaines dans le futur @@ -964,7 +890,7 @@ class ZAbsences( ) # calcule dates dates = [] # ddmmyyyy instances - d = ddmmyyyy(datedebut, work_saturday=self.is_work_saturday()) + d = ddmmyyyy(datedebut, work_saturday=work_saturday) while d <= jourfin: dates.append(d) d = d.next(7) # avance d'une semaine @@ -982,7 +908,7 @@ class ZAbsences( url_link_semaines += "&moduleimpl_id=" + moduleimpl_id # dates = [x.ISO() for x in dates] - dayname = self.day_names()[jourdebut.weekday] + dayname = sco_abs.day_names(self)[jourdebut.weekday] if groups_infos.tous_les_etuds_du_sem: gr_tit = "en" @@ -1119,7 +1045,7 @@ class ZAbsences( odates = [datetime.date(*[int(x) for x in d.split("-")]) for d in dates] # 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]) @@ -1844,7 +1770,7 @@ ou entrez une date pour visualiser les absents un jour donné : # 1-- ajout des absences (et justifs) datedebut = billet["abs_begin"].strftime("%d/%m/%Y") datefin = billet["abs_end"].strftime("%d/%m/%Y") - dates = self.DateRangeISO(datedebut, datefin) + dates = sco_abs.DateRangeISO(self, datedebut, datefin) # commence après-midi ? if dates and billet["abs_begin"].hour > 11: self._AddAbsence( diff --git a/ZEntreprises.py b/ZEntreprises.py index 53d287a0e..56f16eaac 100644 --- a/ZEntreprises.py +++ b/ZEntreprises.py @@ -43,7 +43,6 @@ from sco_permissions import ScoEntrepriseView, ScoEntrepriseChange # --------------- -from notesdb import * from notes_log import log from scolog import logdb from sco_utils import SCO_ENCODING @@ -53,169 +52,17 @@ import VERSION from gen_tables import GenTable from TrivialFormulator import TrivialFormulator, TF import scolars +import sco_entreprises -def _format_nom(nom): - "formatte nom (filtre en entree db) d'une entreprise" - if not nom: - return nom - nom = nom.decode(SCO_ENCODING) - return (nom[0].upper() + nom[1:]).encode(SCO_ENCODING) +def entreprise_header(context, REQUEST=None, page_title=""): + "common header for all Entreprises pages" + return context.sco_header(REQUEST, container=context, page_title=page_title) -class EntreprisesEditor(EditableTable): - def delete(self, cnx, oid): - "delete correspondants and contacts, then self" - # first, delete all correspondants and contacts - cursor = cnx.cursor(cursor_factory=ScoDocCursor) - cursor.execute( - "delete from entreprise_contact where entreprise_id=%(entreprise_id)s", - {"entreprise_id": oid}, - ) - cursor.execute( - "delete from entreprise_correspondant where entreprise_id=%(entreprise_id)s", - {"entreprise_id": oid}, - ) - cnx.commit() - EditableTable.delete(self, cnx, oid) - - def list( - self, - cnx, - args={}, - operator="and", - test="=", - sortkey=None, - sort_on_contact=False, - ZEntrepriseInstance=None, - limit="", - offset="", - ): - # list, then sort on date of last contact - R = EditableTable.list( - self, - cnx, - args=args, - operator=operator, - test=test, - sortkey=sortkey, - limit=limit, - offset=offset, - ) - if sort_on_contact: - for r in R: - c = ZEntrepriseInstance.do_entreprise_contact_list( - args={"entreprise_id": r["entreprise_id"]}, disable_formatting=True - ) - if c: - r["date"] = max([x["date"] or datetime.date.min for x in c]) - else: - r["date"] = datetime.date.min - # sort - R.sort(lambda r1, r2: cmp(r2["date"], r1["date"])) - for r in R: - r["date"] = DateISOtoDMY(r["date"]) - return R - - def list_by_etud( - self, cnx, args={}, sort_on_contact=False, disable_formatting=False - ): - "cherche rentreprise ayant eu contact avec etudiant" - cursor = cnx.cursor(cursor_factory=ScoDocCursor) - cursor.execute( - "select E.*, I.nom as etud_nom, I.prenom as etud_prenom, C.date from entreprises E, entreprise_contact C, identite I where C.entreprise_id = E.entreprise_id and C.etudid = I.etudid and I.nom ~* %(etud_nom)s ORDER BY E.nom", - args, - ) - _, res = [x[0] for x in cursor.description], cursor.dictfetchall() - R = [] - for r in res: - r["etud_prenom"] = r["etud_prenom"] or "" - d = {} - for key in r: - v = r[key] - # format value - if not disable_formatting and self.output_formators.has_key(key): - v = self.output_formators[key](v) - d[key] = v - R.append(d) - # sort - if sort_on_contact: - R.sort( - lambda r1, r2: cmp( - r2["date"] or datetime.date.min, r1["date"] or datetime.date.min - ) - ) - for r in R: - r["date"] = DateISOtoDMY(r["date"] or datetime.date.min) - return R - - -_entreprisesEditor = EntreprisesEditor( - "entreprises", - "entreprise_id", - ( - "entreprise_id", - "nom", - "adresse", - "ville", - "codepostal", - "pays", - "contact_origine", - "secteur", - "privee", - "localisation", - "qualite_relation", - "plus10salaries", - "note", - "date_creation", - ), - sortkey="nom", - input_formators={"nom": _format_nom}, -) - -# ----------- Correspondants -_entreprise_correspEditor = EditableTable( - "entreprise_correspondant", - "entreprise_corresp_id", - ( - "entreprise_corresp_id", - "entreprise_id", - "civilite", - "nom", - "prenom", - "fonction", - "phone1", - "phone2", - "mobile", - "fax", - "mail1", - "mail2", - "note", - ), - sortkey="nom", -) - - -# ----------- Contacts -_entreprise_contactEditor = EditableTable( - "entreprise_contact", - "entreprise_contact_id", - ( - "entreprise_contact_id", - "date", - "type_contact", - "entreprise_id", - "entreprise_corresp_id", - "etudid", - "description", - "enseignant", - ), - sortkey="date", - output_formators={"date": DateISOtoDMY}, - input_formators={"date": DateDMYtoISO}, -) - -# --------------- +def entreprise_footer(context, REQUEST): + "common entreprise footer" + return context.sco_footer(REQUEST) class ZEntreprises( @@ -251,42 +98,22 @@ class ZEntreprises( self.id = id self.title = title - security.declareProtected(ScoEntrepriseView, "entreprise_header") - - def entreprise_header(self, REQUEST=None, page_title=""): - "common header for all Entreprises pages" - authuser = REQUEST.AUTHENTICATED_USER - # _read_only is used to modify pages properties (links, buttons) - # Python methods (do_xxx in this class) are also protected individualy) - if authuser.has_permission(ScoEntrepriseChange, self): - REQUEST.set("_read_only", False) - else: - REQUEST.set("_read_only", True) - return self.sco_header(REQUEST, container=self, page_title=page_title) - - security.declareProtected(ScoEntrepriseView, "entreprise_footer") - - def entreprise_footer(self, REQUEST): - "common entreprise footer" - return self.sco_footer(REQUEST) - security.declareProtected(ScoEntrepriseView, "sidebar") def sidebar(self, REQUEST): "barre gauche (overide std sco sidebar)" # rewritten from legacy DTML code - context = self - params = {"ScoURL": context.ScoURL()} - + # XXX rare cas restant d'utilisation de l'acquisition Zope2: à revoir + params = {"ScoURL": self.ScoURL()} H = [ """ """) return "".join(H) @@ -352,12 +181,13 @@ class ZEntreprises( offset = int(offset or 0) if etud_nom: - entreprises = self.do_entreprise_list_by_etud( - args=REQUEST.form, sort_on_contact=True + entreprises = sco_entreprises.do_entreprise_list_by_etud( + self, args=REQUEST.form, sort_on_contact=True ) table_navigation = "" else: - entreprises = self.do_entreprise_list( + entreprises = sco_entreprises.do_entreprise_list( + self, args=REQUEST.form, test="~*", sort_on_contact=True, @@ -390,15 +220,15 @@ class ZEntreprises( # Ajout des liens sur la table: for e in entreprises: e["_nom_target"] = "entreprise_edit?entreprise_id=%(entreprise_id)s" % e - e["correspondants"] = self.do_entreprise_correspondant_list( - args={"entreprise_id": e["entreprise_id"]} + 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"] = self.do_entreprise_contact_list( - args={"entreprise_id": e["entreprise_id"]} + 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"] = ( @@ -430,12 +260,14 @@ class ZEntreprises( return tab.make_page(self, format=format, REQUEST=REQUEST) else: H = [ - self.entreprise_header(REQUEST=REQUEST, page_title="Suivi entreprises"), + entreprise_header( + self, REQUEST=REQUEST, page_title="Suivi entreprises" + ), """

Suivi relations entreprises

""", """
""", tab.html(), """
""", - self.entreprise_footer(REQUEST), + entreprise_footer(self, REQUEST), ] return "\n".join(H) @@ -443,17 +275,21 @@ class ZEntreprises( def entreprise_contact_list(self, entreprise_id=None, format="html", REQUEST=None): """Liste des contacts de l'entreprise""" - H = [self.entreprise_header(REQUEST=REQUEST, page_title="Suivi entreprises")] + H = [entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises")] if entreprise_id: - E = self.do_entreprise_list(args={"entreprise_id": entreprise_id})[0] - C = self.do_entreprise_contact_list(args={"entreprise_id": 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} + ) H.append( """

Listes des contacts avec l'entreprise %(nom)s

""" % E ) else: - C = self.do_entreprise_contact_list(args={}) + C = sco_entreprises.do_entreprise_contact_list(self, args={}) H.append( """

Listes des contacts

""" @@ -465,8 +301,8 @@ class ZEntreprises( REQUEST.URL1, c["entreprise_contact_id"], ) - c["entreprise"] = self.do_entreprise_list( - args={"entreprise_id": c["entreprise_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] @@ -502,7 +338,7 @@ class ZEntreprises( H.append(tab.html()) - if not REQUEST["_read_only"]: # portage DTML, à modifier + if REQUEST.AUTHENTICATED_USER.has_permission(ScoEntrepriseChange, self): if entreprise_id: H.append( """

nouveau "contact"

@@ -510,7 +346,7 @@ class ZEntreprises( % E ) - H.append(self.entreprise_footer(REQUEST)) + H.append(entreprise_footer(self, REQUEST)) return "\n".join(H) security.declareProtected(ScoEntrepriseView, "entreprise_correspondant_list") @@ -522,23 +358,28 @@ class ZEntreprises( REQUEST=None, ): """Liste des correspondants de l'entreprise""" - E = self.do_entreprise_list(args={"entreprise_id": entreprise_id})[0] + E = sco_entreprises.do_entreprise_list( + self, args={"entreprise_id": entreprise_id} + )[0] H = [ - self.entreprise_header(REQUEST=REQUEST, page_title="Suivi entreprises"), + entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), """

Listes des correspondants dans l'entreprise %(nom)s

""" % E, ] - correspondants = self.do_entreprise_correspondant_list( - args={"entreprise_id": entreprise_id} + 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" - % (REQUEST.URL1, c["entreprise_corresp_id"]), + c[ + "_nomprenom_target" + ] = "%s/entreprise_correspondant_edit?entreprise_corresp_id=%s" % ( + REQUEST.URL1, + c["entreprise_corresp_id"], ) + c["nom_entreprise"] = E["nom"] l = [] if c["phone1"]: @@ -559,11 +400,11 @@ class ZEntreprises( ] ) c["modifier"] = ( - 'modifier' + 'modifier' % c["entreprise_corresp_id"] ) c["supprimer"] = ( - 'supprimer' + 'supprimer' % c["entreprise_corresp_id"] ) tab = GenTable( @@ -604,34 +445,36 @@ class ZEntreprises( H.append(tab.html()) - if not REQUEST["_read_only"]: # portage DTML, à modifier + if REQUEST.AUTHENTICATED_USER.has_permission(ScoEntrepriseChange, self): H.append( """

Ajouter un correspondant dans l'entreprise %(nom)s

""" % E ) - H.append(self.entreprise_footer(REQUEST)) + 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 = self.do_entreprise_contact_list( - args={"entreprise_contact_id": entreprise_contact_id} + c = sco_entreprises.do_entreprise_contact_list( + self, args={"entreprise_contact_id": entreprise_contact_id} )[0] link_create_corr = ( 'créer un nouveau correspondant' % (REQUEST.URL1, c["entreprise_id"]) ) - E = self.do_entreprise_list(args={"entreprise_id": c["entreprise_id"]})[0] - correspondants = self.do_entreprise_correspondant_listnames( - args={"entreprise_id": 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 = [ - self.entreprise_header(REQUEST=REQUEST, page_title="Suivi entreprises"), + entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), """

Suivi entreprises

Contact avec entreprise %(nom)s

""" % E, @@ -708,12 +551,14 @@ class ZEntreprises( cancelbutton="Annuler", initvalues=c, submitlabel="Modifier les valeurs", - readonly=REQUEST["_read_only"], + readonly=not REQUEST.AUTHENTICATED_USER.has_permission( + ScoEntrepriseChange, self + ), ) if tf[0] == 0: H.append(tf[1]) - if not REQUEST["_read_only"]: # portage DTML, à modifier + if REQUEST.AUTHENTICATED_USER.has_permission(ScoEntrepriseChange, self): H.append( """

Supprimer ce contact

""" % entreprise_contact_id @@ -721,30 +566,31 @@ class ZEntreprises( elif tf[0] == -1: REQUEST.RESPONSE.redirect(REQUEST.URL1) else: - etudok = self.do_entreprise_check_etudiant(tf[2]["etudiant"]) + 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]}) - self.do_entreprise_contact_edit(tf[2]) + sco_entreprises.do_entreprise_contact_edit(self, tf[2]) REQUEST.RESPONSE.redirect( REQUEST.URL1 + "/entreprise_contact_list?entreprise_id=" + str(c["entreprise_id"]) ) - H.append(self.entreprise_footer(REQUEST)) + 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""" - # F -> c - c = self.do_entreprise_correspondant_list( - args={"entreprise_corresp_id": entreprise_corresp_id} + c = sco_entreprises.do_entreprise_correspondant_list( + self, args={"entreprise_corresp_id": entreprise_corresp_id} )[0] H = [ - self.entreprise_header(REQUEST=REQUEST, page_title="Suivi entreprises"), + entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), """

Édition contact entreprise

""", ] tf = TrivialFormulator( @@ -829,7 +675,9 @@ class ZEntreprises( cancelbutton="Annuler", initvalues=c, submitlabel="Modifier les valeurs", - readonly=REQUEST["_read_only"], + readonly=not REQUEST.AUTHENTICATED_USER.has_permission( + ScoEntrepriseChange, self + ), ) if tf[0] == 0: H.append(tf[1]) @@ -839,21 +687,23 @@ class ZEntreprises( % (REQUEST.URL1, c["entreprise_id"]) ) else: - self.do_entreprise_correspondant_edit(tf[2]) + sco_entreprises.do_entreprise_correspondant_edit(self, tf[2]) REQUEST.RESPONSE.redirect( "%s/entreprise_correspondant_list?entreprise_id=%s" % (REQUEST.URL1, c["entreprise_id"]) ) - H.append(self.entreprise_footer(REQUEST)) + 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 = self.do_entreprise_list(args={"entreprise_id": entreprise_id})[0] - correspondants = self.do_entreprise_correspondant_listnames( - args={"entreprise_id": entreprise_id} + 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", "")] @@ -863,7 +713,7 @@ class ZEntreprises( % (REQUEST.URL1, entreprise_id) ) H = [ - self.entreprise_header(REQUEST=REQUEST, page_title="Suivi entreprises"), + entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), """

Nouveau "contact" avec l'entreprise %(nom)s

""" % E, ] @@ -934,32 +784,36 @@ class ZEntreprises( ), cancelbutton="Annuler", submitlabel="Ajouter ce contact", - readonly=REQUEST["_read_only"], + readonly=not REQUEST.AUTHENTICATED_USER.has_permission( + ScoEntrepriseChange, self + ), ) if tf[0] == 0: H.append(tf[1]) elif tf[0] == -1: REQUEST.RESPONSE.redirect(REQUEST.URL1) else: - etudok = self.do_entreprise_check_etudiant(tf[2]["etudiant"]) + 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]}) - self.do_entreprise_contact_create(tf[2]) + sco_entreprises.do_entreprise_contact_create(self, tf[2]) REQUEST.RESPONSE.redirect(REQUEST.URL1) - H.append(self.entreprise_footer(REQUEST)) + 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 = self.do_entreprise_contact_list( - args={"entreprise_contact_id": entreprise_contact_id} + c = sco_entreprises.do_entreprise_contact_list( + self, args={"entreprise_contact_id": entreprise_contact_id} )[0] H = [ - self.entreprise_header(REQUEST=REQUEST, page_title="Suivi entreprises"), + entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), """

Suppression du contact

""", ] tf = TrivialFormulator( @@ -969,25 +823,31 @@ class ZEntreprises( initvalues=c, submitlabel="Confirmer la suppression", cancelbutton="Annuler", - readonly=REQUEST["_read_only"], + readonly=not REQUEST.AUTHENTICATED_USER.has_permission( + ScoEntrepriseChange, self + ), ) if tf[0] == 0: H.append(tf[1]) elif tf[0] == -1: REQUEST.RESPONSE.redirect(REQUEST.URL1) else: - self.do_entreprise_contact_delete(c["entreprise_contact_id"]) + sco_entreprises.do_entreprise_contact_delete( + self, c["entreprise_contact_id"] + ) REQUEST.RESPONSE.redirect(REQUEST.URL1) - H.append(self.entreprise_footer(REQUEST)) + 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 = self.do_entreprise_list(args={"entreprise_id": entreprise_id})[0] + E = sco_entreprises.do_entreprise_list( + self, args={"entreprise_id": entreprise_id} + )[0] H = [ - self.entreprise_header(REQUEST=REQUEST, page_title="Suivi entreprises"), + entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), """

Nouveau correspondant l'entreprise %(nom)s

""" % E, ] @@ -1070,27 +930,29 @@ class ZEntreprises( ), cancelbutton="Annuler", submitlabel="Ajouter ce correspondant", - readonly=REQUEST["_read_only"], + readonly=not REQUEST.AUTHENTICATED_USER.has_permission( + ScoEntrepriseChange, self + ), ) if tf[0] == 0: H.append(tf[1]) elif tf[0] == -1: REQUEST.RESPONSE.redirect(REQUEST.URL1) else: - self.do_entreprise_correspondant_create(tf[2]) + sco_entreprises.do_entreprise_correspondant_create(self, tf[2]) REQUEST.RESPONSE.redirect(REQUEST.URL1) - H.append(self.entreprise_footer(REQUEST)) + 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 = self.do_entreprise_correspondant_list( - args={"entreprise_corresp_id": entreprise_corresp_id} + c = sco_entreprises.do_entreprise_correspondant_list( + self, args={"entreprise_corresp_id": entreprise_corresp_id} )[0] H = [ - self.entreprise_header(REQUEST=REQUEST, page_title="Suivi entreprises"), + entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), """

Suppression du correspondant %(nom)s %(prenom)s

""" % c, ] tf = TrivialFormulator( @@ -1100,32 +962,38 @@ class ZEntreprises( initvalues=c, submitlabel="Confirmer la suppression", cancelbutton="Annuler", - readonly=REQUEST["_read_only"], + readonly=not REQUEST.AUTHENTICATED_USER.has_permission( + ScoEntrepriseChange, self + ), ) if tf[0] == 0: H.append(tf[1]) elif tf[0] == -1: REQUEST.RESPONSE.redirect(REQUEST.URL1) else: - self.do_entreprise_correspondant_delete(c["entreprise_corresp_id"]) + sco_entreprises.do_entreprise_correspondant_delete( + self, c["entreprise_corresp_id"] + ) REQUEST.RESPONSE.redirect(REQUEST.URL1) - H.append(self.entreprise_footer(REQUEST)) + 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 = self.do_entreprise_list(args={"entreprise_id": entreprise_id})[0] + E = sco_entreprises.do_entreprise_list( + self, args={"entreprise_id": entreprise_id} + )[0] H = [ - self.entreprise_header(REQUEST=REQUEST, page_title="Suivi entreprises"), + 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 = self.do_entreprise_correspondant_list( - args={"entreprise_id": entreprise_id} + Cl = sco_entreprises.do_entreprise_correspondant_list( + self, args={"entreprise_id": entreprise_id} ) if Cl: H.append( @@ -1135,7 +1003,9 @@ class ZEntreprises( H.append("""
  • %(nom)s %(prenom)s (%(fonction)s)
  • """ % c) H.append("""""") - Cts = self.do_entreprise_contact_list(args={"entreprise_id": entreprise_id}) + Cts = sco_entreprises.do_entreprise_contact_list( + self, args={"entreprise_id": entreprise_id} + ) if Cts: H.append( """

    Contacts avec l'entreprise qui seront supprimés:

    ") - 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) else: - self.do_entreprise_edit(tf[2]) + sco_entreprises.do_entreprise_edit(self, tf[2]) return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "?start=" + start) diff --git a/ZScolar.py b/ZScolar.py index c39d8bdc5..8d4307809 100644 --- a/ZScolar.py +++ b/ZScolar.py @@ -599,7 +599,7 @@ UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo ') FA.append('") diff --git a/sco_abs.py b/sco_abs.py index 8d97d949e..21538e677 100644 --- a/sco_abs.py +++ b/sco_abs.py @@ -43,6 +43,11 @@ import sco_formsemestre import sco_compute_moy +def is_work_saturday(context): + "Vrai si le samedi est travaillé" + return int(context.get_preference("work_saturday")) + + def MonthNbDays(month, year): "returns nb of days in month" if month > 7: @@ -173,6 +178,39 @@ class ddmmyyyy: # d = ddmmyyyy( '21/12/99' ) +def DateRangeISO(context, date_beg, date_end, workable=1): + """returns list of dates in [date_beg,date_end] + workable = 1 => keeps only workable days""" + if not date_beg: + raise ScoValueError("pas de date spécifiée !") + if not date_end: + date_end = date_beg + r = [] + work_saturday = is_work_saturday(context) + cur = ddmmyyyy(date_beg, work_saturday=work_saturday) + end = ddmmyyyy(date_end, work_saturday=work_saturday) + while cur <= end: + if (not workable) or cur.iswork(): + r.append(cur) + cur = cur.next() + + return map(lambda x: x.ISO(), r) + + +def day_names(context): + """Returns week day names. + If work_saturday property is set, include saturday + """ + if is_work_saturday(context): + return ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"] + else: + return ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi"] + + +def next_iso_day(context, date): + "return date after date" + d = ddmmyyyy(date, fmt="iso", work_saturday=is_work_saturday(context)) + return d.next().ISO() def YearTable( @@ -207,7 +245,7 @@ def YearTable( events, halfday, dayattributes, - context.is_work_saturday(), + is_work_saturday(context), pad_width=pad_width, ) ) diff --git a/sco_abs_views.py b/sco_abs_views.py index 9ede1d384..a76e225a6 100644 --- a/sco_abs_views.py +++ b/sco_abs_views.py @@ -28,12 +28,16 @@ """Pages HTML gestion absences (la plupart portées du DTML) """ +import datetime from stripogram import html2text, html2safehtml + from gen_tables import GenTable -from notesdb import * -from sco_utils import * +from notesdb import DateISOtoDMY +import sco_utils as scu +from sco_exceptions import ScoValueError +from sco_permissions import ScoAbsChange from notes_log import log import sco_groups import sco_find_etud @@ -58,7 +62,7 @@ def doSignaleAbsence( etudid = etud["etudid"] description_abs = description - dates = context.DateRangeISO(datedebut, datefin) + dates = sco_abs.DateRangeISO(context, datedebut, datefin) nbadded = 0 for jour in dates: if demijournee == "2": @@ -248,7 +252,7 @@ def doJustifAbsence( etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0] etudid = etud["etudid"] description_abs = description - dates = context.DateRangeISO(datedebut, datefin) + dates = sco_abs.DateRangeISO(context, datedebut, datefin) nbadded = 0 for jour in dates: if demijournee == "2": @@ -371,7 +375,7 @@ def doAnnuleAbsence( etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0] etudid = etud["etudid"] - dates = context.DateRangeISO(datedebut, datefin) + dates = sco_abs.DateRangeISO(context, datedebut, datefin) nbadded = 0 for jour in dates: if demijournee == "2": @@ -506,7 +510,7 @@ def doAnnuleJustif( """Annulation d'une justification""" etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0] etudid = etud["etudid"] - dates = context.DateRangeISO(datedebut0, datefin0) + dates = sco_abs.DateRangeISO(context, datedebut0, datefin0) nbadded = 0 for jour in dates: # Attention: supprime matin et après-midi @@ -571,7 +575,7 @@ def EtatAbsences(context, REQUEST=None): """ - % (AnneeScolaire(REQUEST), datetime.datetime.now().strftime("%d/%m/%Y")), + % (scu.AnneeScolaire(REQUEST), datetime.datetime.now().strftime("%d/%m/%Y")), context.sco_footer(REQUEST), ] return "\n".join(H) @@ -610,7 +614,7 @@ def CalAbs(context, REQUEST=None): # etud implied # crude portage from 1999 DTML etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0] etudid = etud["etudid"] - anneescolaire = int(AnneeScolaire(REQUEST)) + anneescolaire = int(scu.AnneeScolaire(REQUEST)) datedebut = str(anneescolaire) + "-08-31" datefin = str(anneescolaire + 1) + "-07-31" nbabs = context.CountAbs(etudid=etudid, debut=datedebut, fin=datefin) @@ -693,7 +697,7 @@ def ListeAbsEtud( En format 'text': texte avec liste d'absences (pour mails). """ absjust_only = int(absjust_only) # si vrai, table absjust seule (export xls ou pdf) - datedebut = "%s-08-31" % AnneeScolaire(REQUEST) + datedebut = "%s-08-31" % scu.AnneeScolaire(REQUEST) etud = context.getEtudInfo(etudid=etudid, filled=True)[0] @@ -714,7 +718,7 @@ def ListeAbsEtud( html_class="table_leftalign", table_id="tab_absnonjust", base_url=base_url_nj, - filename="abs_" + make_filename(etud["nomprenom"]), + filename="abs_" + scu.make_filename(etud["nomprenom"]), caption="Absences non justifiées de %(nomprenom)s" % etud, preferences=context.get_preferences(), ) @@ -725,7 +729,7 @@ def ListeAbsEtud( html_class="table_leftalign", table_id="tab_absjust", base_url=base_url_j, - filename="absjust_" + make_filename(etud["nomprenom"]), + filename="absjust_" + scu.make_filename(etud["nomprenom"]), caption="Absences justifiées de %(nomprenom)s" % etud, preferences=context.get_preferences(), ) @@ -830,7 +834,7 @@ def absences_index_html(context, REQUEST=None): % REQUEST.URL0, formChoixSemestreGroupe(context), "

    ", - context.CalSelectWeek(REQUEST=REQUEST), + cal_select_week(context, REQUEST=REQUEST), """

    Sélectionner le groupe d'étudiants, puis cliquez sur une semaine pour saisir les absences de toute cette semaine.

    """, @@ -843,3 +847,16 @@ saisir les absences de toute cette semaine.

    H.append(context.sco_footer(REQUEST)) return "\n".join(H) + + +def cal_select_week(context, year=None, REQUEST=None): + "display calendar allowing week selection" + if not year: + year = scu.AnneeScolaire(REQUEST) + sems = sco_formsemestre.do_formsemestre_list(context) + if not sems: + js = "" + else: + js = 'onmouseover="highlightweek(this);" onmouseout="deselectweeks();" onclick="wclick(this);"' + C = sco_abs.YearTable(context, int(year), dayattributes=js) + return C diff --git a/sco_entreprises.py b/sco_entreprises.py new file mode 100644 index 000000000..fdbef5e55 --- /dev/null +++ b/sco_entreprises.py @@ -0,0 +1,326 @@ +# -*- mode: python -*- +# -*- coding: utf-8 -*- + +############################################################################## +# +# Gestion scolarite IUT +# +# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Emmanuel Viennet emmanuel.viennet@viennet.net +# +############################################################################## + +"""Fonctions sur les entreprises +""" +# codes anciens déplacés de ZEntreprise +import datetime + +import sco_utils as scu +from notesdb import ScoDocCursor, EditableTable, DateISOtoDMY, DateDMYtoISO + + +def _format_nom(nom): + "formatte nom (filtre en entree db) d'une entreprise" + if not nom: + return nom + nom = nom.decode(scu.SCO_ENCODING) + return (nom[0].upper() + nom[1:]).encode(scu.SCO_ENCODING) + + +class EntreprisesEditor(EditableTable): + def delete(self, cnx, oid): + "delete correspondants and contacts, then self" + # first, delete all correspondants and contacts + cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor.execute( + "delete from entreprise_contact where entreprise_id=%(entreprise_id)s", + {"entreprise_id": oid}, + ) + cursor.execute( + "delete from entreprise_correspondant where entreprise_id=%(entreprise_id)s", + {"entreprise_id": oid}, + ) + cnx.commit() + EditableTable.delete(self, cnx, oid) + + def list( + self, + cnx, + args={}, + operator="and", + test="=", + sortkey=None, + sort_on_contact=False, + context=None, + limit="", + offset="", + ): + # list, then sort on date of last contact + R = EditableTable.list( + self, + cnx, + args=args, + operator=operator, + test=test, + sortkey=sortkey, + limit=limit, + offset=offset, + ) + if sort_on_contact: + for r in R: + c = do_entreprise_contact_list( + context, + args={"entreprise_id": r["entreprise_id"]}, + disable_formatting=True, + ) + if c: + r["date"] = max([x["date"] or datetime.date.min for x in c]) + else: + r["date"] = datetime.date.min + # sort + R.sort(lambda r1, r2: cmp(r2["date"], r1["date"])) + for r in R: + r["date"] = DateISOtoDMY(r["date"]) + return R + + def list_by_etud( + self, cnx, args={}, sort_on_contact=False, disable_formatting=False + ): + "cherche rentreprise ayant eu contact avec etudiant" + cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor.execute( + "select E.*, I.nom as etud_nom, I.prenom as etud_prenom, C.date from entreprises E, entreprise_contact C, identite I where C.entreprise_id = E.entreprise_id and C.etudid = I.etudid and I.nom ~* %(etud_nom)s ORDER BY E.nom", + args, + ) + _, res = [x[0] for x in cursor.description], cursor.dictfetchall() + R = [] + for r in res: + r["etud_prenom"] = r["etud_prenom"] or "" + d = {} + for key in r: + v = r[key] + # format value + if not disable_formatting and self.output_formators.has_key(key): + v = self.output_formators[key](v) + d[key] = v + R.append(d) + # sort + if sort_on_contact: + R.sort( + lambda r1, r2: cmp( + r2["date"] or datetime.date.min, r1["date"] or datetime.date.min + ) + ) + for r in R: + r["date"] = DateISOtoDMY(r["date"] or datetime.date.min) + return R + + +_entreprisesEditor = EntreprisesEditor( + "entreprises", + "entreprise_id", + ( + "entreprise_id", + "nom", + "adresse", + "ville", + "codepostal", + "pays", + "contact_origine", + "secteur", + "privee", + "localisation", + "qualite_relation", + "plus10salaries", + "note", + "date_creation", + ), + sortkey="nom", + input_formators={"nom": _format_nom}, +) + +# ----------- Correspondants +_entreprise_correspEditor = EditableTable( + "entreprise_correspondant", + "entreprise_corresp_id", + ( + "entreprise_corresp_id", + "entreprise_id", + "civilite", + "nom", + "prenom", + "fonction", + "phone1", + "phone2", + "mobile", + "fax", + "mail1", + "mail2", + "note", + ), + sortkey="nom", +) + + +# ----------- Contacts +_entreprise_contactEditor = EditableTable( + "entreprise_contact", + "entreprise_contact_id", + ( + "entreprise_contact_id", + "date", + "type_contact", + "entreprise_id", + "entreprise_corresp_id", + "etudid", + "description", + "enseignant", + ), + sortkey="date", + output_formators={"date": DateISOtoDMY}, + input_formators={"date": DateDMYtoISO}, +) + + +def do_entreprise_create(context, args): + "entreprise_create" + cnx = context.GetDBConnexion() + r = _entreprisesEditor.create(cnx, args) + return r + + +def do_entreprise_delete(context, oid): + "entreprise_delete" + cnx = context.GetDBConnexion() + _entreprisesEditor.delete(cnx, oid) + + +def do_entreprise_list(context, **kw): + "entreprise_list" + cnx = context.GetDBConnexion() + kw["context"] = context + return _entreprisesEditor.list(cnx, **kw) + + +def do_entreprise_list_by_etud(context, **kw): + "entreprise_list_by_etud" + cnx = context.GetDBConnexion() + return _entreprisesEditor.list_by_etud(cnx, **kw) + + +def do_entreprise_edit(context, *args, **kw): + "entreprise_edit" + cnx = context.GetDBConnexion() + _entreprisesEditor.edit(cnx, *args, **kw) + + +def do_entreprise_correspondant_create(context, args): + "entreprise_correspondant_create" + cnx = context.GetDBConnexion() + r = _entreprise_correspEditor.create(cnx, args) + return r + + +def do_entreprise_correspondant_delete(context, oid): + "entreprise_correspondant_delete" + cnx = context.GetDBConnexion() + _entreprise_correspEditor.delete(cnx, oid) + + +def do_entreprise_correspondant_list(context, **kw): + "entreprise_correspondant_list" + cnx = context.GetDBConnexion() + return _entreprise_correspEditor.list(cnx, **kw) + + +def do_entreprise_correspondant_edit(context, *args, **kw): + "entreprise_correspondant_edit" + cnx = context.GetDBConnexion() + _entreprise_correspEditor.edit(cnx, *args, **kw) + + +def do_entreprise_correspondant_listnames(context, args={}): + "-> liste des noms des correspondants (pour affichage menu)" + C = do_entreprise_correspondant_list(context, args=args) + return [(x["prenom"] + " " + x["nom"], str(x["entreprise_corresp_id"])) for x in C] + + +def do_entreprise_contact_delete(context, oid): + "entreprise_contact_delete" + cnx = context.GetDBConnexion() + _entreprise_contactEditor.delete(cnx, oid) + + +def do_entreprise_contact_list(context, **kw): + "entreprise_contact_list" + cnx = context.GetDBConnexion() + return _entreprise_contactEditor.list(cnx, **kw) + + +def do_entreprise_contact_edit(context, *args, **kw): + "entreprise_contact_edit" + cnx = context.GetDBConnexion() + _entreprise_contactEditor.edit(cnx, *args, **kw) + + +def do_entreprise_contact_create(context, args): + "entreprise_contact_create" + cnx = context.GetDBConnexion() + r = _entreprise_contactEditor.create(cnx, args) + return r + + +def do_entreprise_check_etudiant(context, 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 = context.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), + ) + elif len(r) > 1: + e = ['
      '] + for x in r: + e.append( + "
    • %s %s (code %s)
    • " + % (scu.strupper(x[1]), x[2] or "", x[0].strip()) + ) + e.append("
    ") + return ( + 0, + "Les étudiants suivants correspondent: préciser le nom complet ou le code\n" + + "\n".join(e), + ) + else: # une seule reponse ! + return 1, r[0][0].strip() \ No newline at end of file diff --git a/sco_groups_view.py b/sco_groups_view.py index 152ceb98e..fbc622205 100644 --- a/sco_groups_view.py +++ b/sco_groups_view.py @@ -30,8 +30,16 @@ """ # Re-ecriture en 2014 (re-organisation de l'interface, modernisation du code) +import datetime +import cgi +import urllib +import time +import collections +import operator -from sco_utils import * +import sco_utils as scu +from sco_permissions import ScoEtudInscrit, ScoEtudAddAnnotations, ScoAbsChange +from sco_exceptions import ScoValueError import html_sco_header from gen_tables import GenTable import scolars @@ -441,8 +449,6 @@ def groups_table( # "enter groups_table %s: %s" # % (groups_infos.members[0]["nom"], groups_infos.members[0].get("etape", "-")) # ) - authuser = REQUEST.AUTHENTICATED_USER - with_codes = int(with_codes) with_paiement = int(with_paiement) with_archives = int(with_archives) @@ -891,7 +897,7 @@ def form_choix_jour_saisie_hebdo( FA.append(""" - -

    -(attention, vérifier que les groupes sont compatibles, selon votre organisation) -

    - - -

    Créer un nouveau groupe: - - - - -

    -

    - - - - -""" - % ( - etudid, - formsemestre_id, - sem["nomgroupetd"], - sem["nomgroupeta"], - sem["nomgroupetp"], - REQUEST.URL1, - ) - ) - - return header + "\n".join(H) + self.sco_footer(REQUEST) - # --- Gestion des groupes: security.declareProtected(ScoView, "affectGroups") affectGroups = sco_groups_edit.affectGroups diff --git a/config/create_dept.sh b/config/create_dept.sh index 0079cc6a0..52775272f 100755 --- a/config/create_dept.sh +++ b/config/create_dept.sh @@ -9,6 +9,7 @@ # E. Viennet, Juin 2008 # +set -euo pipefail source config.sh source utils.sh diff --git a/config/delete_dept.sh b/config/delete_dept.sh index 3f2f05f69..d5e2bce2c 100755 --- a/config/delete_dept.sh +++ b/config/delete_dept.sh @@ -4,11 +4,11 @@ # ScoDoc: suppression d'un departement # # Ce script supprime la base de donnees ScoDoc d'un departement -# *** le departement doit au prealable avoir �t� supprime via l'interface web ! *** +# *** le departement doit au prealable avoir été supprime via l'interface web ! *** # # Ne fonctionne que pour les configurations "standards" (dbname=xxx) # -# Il doit �tre lanc� par l'utilisateur unix root dans le repertoire .../config +# Il doit être lancé par l'utilisateur unix root dans le repertoire .../config # ^^^^^^^^^^^^^^^^^^^^^ # E. Viennet, Sept 2008 # @@ -17,7 +17,7 @@ source config.sh source utils.sh -check_uid_root $0 +check_uid_root "$0" usage() { echo "$0 [-n DEPT]" echo "(default to interactive mode)" @@ -59,11 +59,16 @@ then scodocctl stop # suppression de la base postgres - db_name=$(cat "$cfg_pathname" | sed '/^dbname=*/!d; s///;q') - echo "suppression de la base postgres $db_name" - su -c "dropdb $db_name" "$POSTGRES_SUPERUSER" || terminate "ne peux supprimer base de donnees $db_name" + db_name=$(sed '/^dbname=*/!d; s///;q' < "$cfg_pathname") + if su -c "psql -lt" "$POSTGRES_SUPERUSER" | cut -d \| -f 1 | grep -wq SCORT + then + echo "Suppression de la base postgres $db_name ..." + su -c "dropdb $db_name" "$POSTGRES_SUPERUSER" || terminate "ne peux supprimer base de donnees $db_name" + else + echo "la base postgres $db_name n'existe pas." + fi # suppression du fichier de config - /bin/rm -f "$cfg_pathname" || terminate "ne peux supprimer $cfg_pathname" + /bin/rm -f "$cfg_pathname" || terminate "Ne peux supprimer $cfg_pathname" # relance ScoDoc if [ "$interactive" = 1 ] then @@ -76,6 +81,7 @@ then fi exit 0 else - echo 'Erreur: pas de configuration trouvee pour "'"$DEPT"'"' - exit 1 + echo 'Attention: pas de configuration trouvee pour "'"$DEPT"'"' + echo " => ne fait rien." + exit 0 fi diff --git a/htmlutils.py b/htmlutils.py index 70ff837c7..f75d9ccf1 100644 --- a/htmlutils.py +++ b/htmlutils.py @@ -28,6 +28,8 @@ """Various HTML generation functions """ +import listhistogram + def horizontal_bargraph(value, mark): """html drawing an horizontal bar and a mark @@ -42,9 +44,6 @@ def horizontal_bargraph(value, mark): return tmpl % {"value": int(value), "mark": int(mark)} -import listhistogram - - def histogram_notes(notes): "HTML code drawing histogram" if not notes: @@ -70,3 +69,56 @@ def histogram_notes(notes): ) D.append("") return "\n".join(D) + + +def make_menu(title, items, css_class="", base_url="", alone=False): + """HTML snippet to render a simple drop down menu. + items is a list of dicts: + { 'title' : + 'url' : + 'id' : + 'attr' : "" # optionnal html attributes + 'enabled' : # True by default + 'helpmsg' : + 'submenu' : [ list of sub-items ] + } + """ + + def gen_menu_items(items): + H.append("") + + H = [] + if alone: + H.append('
      ' % css_class) + H.append("""
    • %s""" % title) + gen_menu_items(items) + H.append("
    • ") + if alone: + H.append("
    ") + return "".join(H) diff --git a/notes_table.py b/notes_table.py index 82613e8a5..bdb303004 100644 --- a/notes_table.py +++ b/notes_table.py @@ -41,7 +41,8 @@ from sco_parcours_dut import formsemestre_get_etud_capitalisation from sco_parcours_dut import list_formsemestre_utilisateurs_uecap import sco_parcours_dut import sco_formsemestre -from sco_formsemestre_edit import formsemestre_uecoef_list, formsemestre_uecoef_create +from sco_formsemestre import formsemestre_uecoef_list, formsemestre_uecoef_create +import sco_moduleimpl import sco_evaluations import sco_compute_moy from sco_formulas import NoteVector @@ -85,7 +86,9 @@ def get_sem_ues_modimpls(context, formsemestre_id, modimpls=None): (utilisé quand on ne peut pas construire nt et faire nt.get_ues()) """ if modimpls is None: - modimpls = context.do_moduleimpl_list(formsemestre_id=formsemestre_id) + modimpls = sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=formsemestre_id + ) uedict = {} for modimpl in modimpls: mod = context.do_module_list(args={"module_id": modimpl["module_id"]})[0] diff --git a/sco_abs_views.py b/sco_abs_views.py index a76e225a6..aabab46f4 100644 --- a/sco_abs_views.py +++ b/sco_abs_views.py @@ -42,6 +42,7 @@ from notes_log import log import sco_groups import sco_find_etud import sco_formsemestre +import sco_moduleimpl import sco_photos import sco_abs @@ -86,7 +87,7 @@ def doSignaleAbsence( J = "NON " M = "" if moduleimpl_id and moduleimpl_id != "NULL": - mod = context.Notes.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] + mod = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0] formsemestre_id = mod["formsemestre_id"] nt = context.Notes._getNotesCache().get_NotesTable( context.Notes, formsemestre_id diff --git a/sco_bulletins.py b/sco_bulletins.py index 1a8fe6d6f..9d2a81397 100644 --- a/sco_bulletins.py +++ b/sco_bulletins.py @@ -28,13 +28,16 @@ """Génération des bulletins de notes """ -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 -import htmlutils, time +import time +import htmlutils from reportlab.lib.colors import Color from sco_utils import * @@ -1146,7 +1149,7 @@ def _formsemestre_bulletinetud_header_html( ] H.append("""
    """) - H.append(sco_formsemestre_status.makeMenu("Autres opérations", menuBul, alone=True)) + H.append(htmlutils.make_menu("Autres opérations", menuBul, alone=True)) H.append("""
    """) H.append( ' %s' diff --git a/sco_compute_moy.py b/sco_compute_moy.py index 108f764fb..368506fc5 100644 --- a/sco_compute_moy.py +++ b/sco_compute_moy.py @@ -29,14 +29,24 @@ """ import traceback +import pprint +from types import FloatType -from sco_utils import * -from notesdb import * +import sco_utils as scu +from sco_utils import ( + NOTES_ATTENTE, + NOTES_NEUTRALISE, + EVALUATION_NORMALE, + EVALUATION_RATTRAPAGE, +) +from sco_exceptions import ScoException +from notesdb import EditableTable, quote_html from notes_log import log, sendAlarm import sco_formsemestre +import sco_moduleimpl import sco_groups import sco_evaluations -from sco_formulas import * +import sco_formulas import sco_abs @@ -67,7 +77,9 @@ def formsemestre_expressions_use_abscounts(context, formsemestre_id): if expr and expr[0] != "#" and ab in expr: return True # 2- moyennes de modules - for mod in context.Notes.do_moduleimpl_list(formsemestre_id=formsemestre_id): + for mod in sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=formsemestre_id + ): if moduleimpl_has_expression(context, mod) and ab in mod["computation_expr"]: return True return False @@ -148,7 +160,7 @@ def compute_user_formula( try: formula = formula.replace("\n", "").replace("\r", "") # log('expression : %s\nvariables=%s\n' % (formula, variables)) # XXX debug - user_moy = eval_user_expression(context, formula, variables) + user_moy = sco_formulas.eval_user_expression(context, formula, variables) # log('user_moy=%s' % user_moy) if user_moy != "NA0" and user_moy != "NA": user_moy = float(user_moy) @@ -188,10 +200,10 @@ def do_moduleimpl_moyennes(context, nt, mod): """ diag_info = {} # message d'erreur formule moduleimpl_id = mod["moduleimpl_id"] - is_malus = mod["module"]["module_type"] == MODULE_MALUS + is_malus = mod["module"]["module_type"] == scu.MODULE_MALUS sem = sco_formsemestre.get_formsemestre(context, mod["formsemestre_id"]) - etudids = context.do_moduleimpl_listeetuds( - moduleimpl_id + etudids = sco_moduleimpl.do_moduleimpl_listeetuds( + context, moduleimpl_id ) # tous, y compris demissions # Inscrits au semestre (pour traiter les demissions): inssem_set = set( @@ -256,7 +268,7 @@ def do_moduleimpl_moyennes(context, nt, mod): ] # R = {} - formula = unescape_html(mod["computation_expr"]) + formula = scu.unescape_html(mod["computation_expr"]) formula_use_abs = "abs" in formula for etudid in insmod_set: # inscrits au semestre et au module @@ -353,12 +365,14 @@ def do_formsemestre_moyennes(context, nt, formsemestre_id): la liste des moduleimpls, la liste des evaluations valides, liste des moduleimpls avec notes en attente. """ - sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - inscr = context.do_formsemestre_inscription_list( - args={"formsemestre_id": formsemestre_id} + # sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) + # inscr = context.do_formsemestre_inscription_list( + # args={"formsemestre_id": formsemestre_id} + # ) + # etudids = [x["etudid"] for x in inscr] + modimpls = sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=formsemestre_id ) - etudids = [x["etudid"] for x in inscr] - modimpls = context.do_moduleimpl_list(formsemestre_id=formsemestre_id) # recupere les moyennes des etudiants de tous les modules D = {} valid_evals = [] diff --git a/sco_cost_formation.py b/sco_cost_formation.py index 2334740f7..226938671 100644 --- a/sco_cost_formation.py +++ b/sco_cost_formation.py @@ -37,6 +37,7 @@ from gen_tables import GenTable import sco_excel, sco_pdf from sco_pdf import SU import sco_formsemestre +import sco_moduleimpl import sco_formsemestre_status @@ -60,7 +61,9 @@ def formsemestre_table_estim_cost( """ sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) sco_formsemestre_status.fill_formsemestre(context, sem, REQUEST=REQUEST) - Mlist = context.do_moduleimpl_withmodule_list(formsemestre_id=formsemestre_id) + Mlist = sco_moduleimpl.do_moduleimpl_withmodule_list( + context, formsemestre_id=formsemestre_id + ) T = [] for M in Mlist: Mod = M["module"] diff --git a/sco_evaluations.py b/sco_evaluations.py index e877b62c0..5e5b17e4f 100644 --- a/sco_evaluations.py +++ b/sco_evaluations.py @@ -41,9 +41,11 @@ from gen_tables import GenTable from TrivialFormulator import TrivialFormulator import sco_news import sco_formsemestre +import sco_moduleimpl import sco_groups import sco_abs import sco_evaluations +import sco_saisie_notes # -------------------------------------------------------------------- # @@ -101,7 +103,7 @@ def do_evaluation_delete(context, REQUEST, evaluation_id): context._evaluationEditor.delete(cnx, evaluation_id) # inval cache pour ce semestre - M = context.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0] context._inval_cache(formsemestre_id=M["formsemestre_id"]) # > eval delete # news mod = context.do_module_list(args={"module_id": M["module_id"]})[0] @@ -165,7 +167,7 @@ def do_evaluation_etat( last_modif = None # ---- Liste des groupes complets et incomplets E = context.do_evaluation_list(args={"evaluation_id": evaluation_id})[0] - M = context.do_moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0] + M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0] Mod = context.do_module_list(args={"module_id": M["module_id"]})[0] is_malus = Mod["module_type"] == scu.MODULE_MALUS # True si module de malus formsemestre_id = M["formsemestre_id"] @@ -182,7 +184,9 @@ def do_evaluation_etat( # (pour avoir l'etat et le groupe) et aussi les inscriptions # au module (pour gerer les modules optionnels correctement) insem = context.do_formsemestre_inscription_listinscrits(formsemestre_id) - insmod = context.do_moduleimpl_inscription_list(moduleimpl_id=E["moduleimpl_id"]) + insmod = sco_moduleimpl.do_moduleimpl_inscription_list( + context, moduleimpl_id=E["moduleimpl_id"] + ) insmodset = set([x["etudid"] for x in insmod]) # retire de insem ceux qui ne sont pas inscrits au module ins = [i for i in insem if i["etudid"] in insmodset] @@ -451,7 +455,9 @@ def formsemestre_evaluations_cal(context, formsemestre_id, REQUEST=None): if not e["jour"]: continue day = e["jour"].strftime("%Y-%m-%d") - mod = context.do_moduleimpl_withmodule_list(moduleimpl_id=e["moduleimpl_id"])[0] + mod = sco_moduleimpl.do_moduleimpl_withmodule_list( + context, moduleimpl_id=e["moduleimpl_id"] + )[0] txt = mod["module"]["code"] or mod["module"]["abbrev"] or "eval" if e["heure_debut"]: debut = e["heure_debut"].strftime("%Hh%M") @@ -524,10 +530,10 @@ def evaluation_date_first_completion(context, evaluation_id): # (pour avoir l'etat et le groupe) et aussi les inscriptions # au module (pour gerer les modules optionnels correctement) # E = context.do_evaluation_list(args={"evaluation_id": evaluation_id})[0] - # M = context.do_moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0] + # M = sco_moduleimpl.do_moduleimpl_list(context,moduleimpl_id=E["moduleimpl_id"])[0] # formsemestre_id = M["formsemestre_id"] # insem = context.do_formsemestre_inscription_listinscrits(formsemestre_id) - # insmod = context.do_moduleimpl_inscription_list(moduleimpl_id=E["moduleimpl_id"]) + # insmod = sco_moduleimpl.do_moduleimpl_inscription_list(context,moduleimpl_id=E["moduleimpl_id"]) # insmodset = set([x["etudid"] for x in insmod]) # retire de insem ceux qui ne sont pas inscrits au module # ins = [i for i in insem if i["etudid"] in insmodset] @@ -566,7 +572,9 @@ def formsemestre_evaluations_delai_correction( evals = nt.get_sem_evaluation_etat_list() T = [] for e in evals: - M = context.do_moduleimpl_list(moduleimpl_id=e["moduleimpl_id"])[0] + M = sco_moduleimpl.do_moduleimpl_list( + context, moduleimpl_id=e["moduleimpl_id"] + )[0] Mod = context.do_module_list(args={"module_id": M["module_id"]})[0] if (e["evaluation_type"] != scu.EVALUATION_NORMALE) or ( Mod["module_type"] == scu.MODULE_MALUS @@ -732,14 +740,14 @@ def evaluation_describe(context, evaluation_id="", edit_in_place=True, REQUEST=N """ E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] moduleimpl_id = E["moduleimpl_id"] - M = context.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0] Mod = context.do_module_list(args={"module_id": M["module_id"]})[0] formsemestre_id = M["formsemestre_id"] u = context.Users.user_info(M["responsable_id"]) resp = u["prenomnom"] nomcomplet = u["nomcomplet"] - can_edit = context.can_edit_notes( - REQUEST.AUTHENTICATED_USER, moduleimpl_id, allow_ens=False + can_edit = sco_saisie_notes.can_edit_notes( + context, REQUEST.AUTHENTICATED_USER, moduleimpl_id, allow_ens=False ) link = ( @@ -810,7 +818,9 @@ def evaluation_create_form( the_eval = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] moduleimpl_id = the_eval["moduleimpl_id"] # - M = context.do_moduleimpl_withmodule_list(moduleimpl_id=moduleimpl_id)[0] + M = sco_moduleimpl.do_moduleimpl_withmodule_list( + context, moduleimpl_id=moduleimpl_id + )[0] is_malus = M["module"]["module_type"] == scu.MODULE_MALUS # True si module de malus formsemestre_id = M["formsemestre_id"] min_note_max = scu.NOTES_PRECISION # le plus petit bareme possible diff --git a/sco_formsemestre.py b/sco_formsemestre.py index 55c88ecec..6ad764e1a 100644 --- a/sco_formsemestre.py +++ b/sco_formsemestre.py @@ -241,6 +241,53 @@ def write_formsemestre_responsables(context, sem): return _write_formsemestre_aux(context, sem, "responsables", "responsable_id") +# ---------------------- Coefs des UE + +_formsemestre_uecoef_editor = EditableTable( + "notes_formsemestre_uecoef", + "formsemestre_uecoef_id", + ("formsemestre_uecoef_id", "formsemestre_id", "ue_id", "coefficient"), +) + +formsemestre_uecoef_create = _formsemestre_uecoef_editor.create +formsemestre_uecoef_edit = _formsemestre_uecoef_editor.edit +formsemestre_uecoef_list = _formsemestre_uecoef_editor.list +formsemestre_uecoef_delete = _formsemestre_uecoef_editor.delete + + +def do_formsemestre_uecoef_edit_or_create(context, cnx, formsemestre_id, ue_id, coef): + "modify or create the coef" + coefs = formsemestre_uecoef_list( + cnx, args={"formsemestre_id": formsemestre_id, "ue_id": ue_id} + ) + if coefs: + formsemestre_uecoef_edit( + cnx, + args={ + "formsemestre_uecoef_id": coefs[0]["formsemestre_uecoef_id"], + "coefficient": coef, + }, + ) + else: + formsemestre_uecoef_create( + cnx, + args={ + "formsemestre_id": formsemestre_id, + "ue_id": ue_id, + "coefficient": coef, + }, + ) + + +def do_formsemestre_uecoef_delete(context, cnx, formsemestre_id, ue_id): + "delete coef for this (ue,sem)" + coefs = formsemestre_uecoef_list( + cnx, args={"formsemestre_id": formsemestre_id, "ue_id": ue_id} + ) + if coefs: + formsemestre_uecoef_delete(cnx, coefs[0]["formsemestre_uecoef_id"]) + + def read_formsemestre_etapes(context, formsemestre_id): """recupere liste des codes etapes associés à ce semestre :returns: liste d'instance de ApoEtapeVDI diff --git a/sco_formsemestre_custommenu.py b/sco_formsemestre_custommenu.py index 661856bff..5365aa5c0 100644 --- a/sco_formsemestre_custommenu.py +++ b/sco_formsemestre_custommenu.py @@ -74,7 +74,7 @@ def formsemestre_custommenu_html(context, formsemestre_id, base_url=""): + formsemestre_id, } ) - return sco_formsemestre_status.makeMenu("Liens", menu) + return sco_formsemestre_status.htmlutils.make_menu("Liens", menu) def formsemestre_custommenu_edit(context, formsemestre_id, REQUEST=None): diff --git a/sco_formsemestre_edit.py b/sco_formsemestre_edit.py index b35b36495..7850202ea 100644 --- a/sco_formsemestre_edit.py +++ b/sco_formsemestre_edit.py @@ -41,6 +41,7 @@ import sco_codes_parcours import sco_compute_moy import sco_modalites import sco_formsemestre +import sco_moduleimpl from sco_formsemestre import ApoEtapeVDI @@ -155,7 +156,9 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): # if REQUEST.form.get('tf-submitted',False) and not REQUEST.form.has_key('inscrire_etudslist'): # REQUEST.form['inscrire_etudslist'] = [] # add associated modules to tf-checked - ams = context.do_moduleimpl_list(formsemestre_id=formsemestre_id) + ams = sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=formsemestre_id + ) sem_module_ids = set([x["module_id"] for x in ams]) initvalues["tf-checked"] = [x["module_id"] for x in ams] for x in ams: @@ -706,7 +709,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): "formsemestre_id": formsemestre_id, "responsable_id": tf[2][module_id], } - mid = context.do_moduleimpl_create(modargs) + mid = sco_moduleimpl.do_moduleimpl_create(context, modargs) return REQUEST.RESPONSE.redirect( "formsemestre_status?formsemestre_id=%s&head_message=Nouveau%%20semestre%%20créé" % formsemestre_id @@ -720,7 +723,9 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): # nouveaux modules checkedmods = tf[2]["tf-checked"] sco_formsemestre.do_formsemestre_edit(context, tf[2]) - ams = context.do_moduleimpl_list(formsemestre_id=formsemestre_id) + ams = sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=formsemestre_id + ) existingmods = [x["module_id"] for x in ams] mods_tocreate = [x for x in checkedmods if not x in existingmods] # modules a existants a modifier @@ -735,7 +740,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): "formsemestre_id": formsemestre_id, "responsable_id": tf[2][module_id], } - moduleimpl_id = context.do_moduleimpl_create(modargs) + moduleimpl_id = sco_moduleimpl.do_moduleimpl_create(context, modargs) mod = context.do_module_list({"module_id": module_id})[0] msg += ["création de %s (%s)" % (mod["code"], mod["titre"])] # INSCRIPTIONS DES ETUDIANTS @@ -771,8 +776,8 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): ) msg += diag for module_id in mods_toedit: - moduleimpl_id = context.do_moduleimpl_list( - formsemestre_id=formsemestre_id, module_id=module_id + moduleimpl_id = sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=formsemestre_id, module_id=module_id )[0]["moduleimpl_id"] modargs = { "moduleimpl_id": moduleimpl_id, @@ -780,7 +785,9 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): "formsemestre_id": formsemestre_id, "responsable_id": tf[2][module_id], } - context.do_moduleimpl_edit(modargs, formsemestre_id=formsemestre_id) + sco_moduleimpl.do_moduleimpl_edit( + context, modargs, formsemestre_id=formsemestre_id + ) mod = context.do_module_list({"module_id": module_id})[0] if msg: @@ -814,8 +821,8 @@ def formsemestre_delete_moduleimpls(context, formsemestre_id, module_ids_to_del) msg = [] for module_id in module_ids_to_del: # get id - moduleimpl_id = context.do_moduleimpl_list( - formsemestre_id=formsemestre_id, module_id=module_id + moduleimpl_id = sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=formsemestre_id, module_id=module_id )[0]["moduleimpl_id"] mod = context.do_module_list({"module_id": module_id})[0] # Evaluations dans ce module ? @@ -828,7 +835,9 @@ def formsemestre_delete_moduleimpls(context, formsemestre_id, module_ids_to_del) ok = False else: msg += ["suppression de %s (%s)" % (mod["code"], mod["titre"])] - context.do_moduleimpl_delete(moduleimpl_id, formsemestre_id=formsemestre_id) + sco_moduleimpl.do_moduleimpl_delete( + context, moduleimpl_id, formsemestre_id=formsemestre_id + ) return ok, msg @@ -984,17 +993,21 @@ def do_formsemestre_clone( formsemestre_id = context.do_formsemestre_create(args, REQUEST) log("created formsemestre %s" % formsemestre_id) # 2- create moduleimpls - mods_orig = context.do_moduleimpl_list(formsemestre_id=orig_formsemestre_id) + mods_orig = sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=orig_formsemestre_id + ) for mod_orig in mods_orig: args = mod_orig.copy() args["formsemestre_id"] = formsemestre_id - mid = context.do_moduleimpl_create(args) + mid = sco_moduleimpl.do_moduleimpl_create(context, args) # copy notes_modules_enseignants - ens = context.do_ens_list(args={"moduleimpl_id": mod_orig["moduleimpl_id"]}) + ens = sco_moduleimpl.do_ens_list( + context, args={"moduleimpl_id": mod_orig["moduleimpl_id"]} + ) for e in ens: args = e.copy() args["moduleimpl_id"] = mid - context.do_ens_create(args) + sco_moduleimpl.do_ens_create(context, args) # optionally, copy evaluations if clone_evaluations: evals = context.do_evaluation_list( @@ -1007,11 +1020,13 @@ def do_formsemestre_clone( evaluation_id = context.do_evaluation_create(REQUEST=REQUEST, **args) # 3- copy uecoefs - objs = formsemestre_uecoef_list(cnx, args={"formsemestre_id": orig_formsemestre_id}) + objs = sco_formsemestre.formsemestre_uecoef_list( + cnx, args={"formsemestre_id": orig_formsemestre_id} + ) for obj in objs: args = obj.copy() args["formsemestre_id"] = formsemestre_id - c = formsemestre_uecoef_create(cnx, args) + c = sco_formsemestre.formsemestre_uecoef_create(cnx, args) # NB: don't copy notes_formsemestre_custommenu (usually specific) @@ -1177,7 +1192,9 @@ def _reassociate_moduleimpls( et met à jour les décisions de jury (validations d'UE). """ # re-associate moduleimpls to new modules: - modimpls = context.do_moduleimpl_list(formsemestre_id=formsemestre_id) + modimpls = sco_moduleimpl.do_moduleimpl_list( + context, formsemestre_id=formsemestre_id + ) for mod in modimpls: mod["module_id"] = modules_old2new[mod["module_id"]] context.do_moduleimpl_edit(mod, formsemestre_id=formsemestre_id, cnx=cnx) @@ -1314,8 +1331,8 @@ def do_formsemestre_delete(context, formsemestre_id, REQUEST): ) context.get_evaluations_cache().inval_cache(key=e["evaluation_id"]) - context.do_moduleimpl_delete( - mod["moduleimpl_id"], formsemestre_id=formsemestre_id + sco_moduleimpl.do_moduleimpl_delete( + context, mod["moduleimpl_id"], formsemestre_id=formsemestre_id ) # --- Desinscription des etudiants cursor = cnx.cursor(cursor_factory=ScoDocCursor) @@ -1465,20 +1482,6 @@ def formsemestre_change_publication_bul( ) -# ---------------------- Coefs des UE - -_formsemestre_uecoef_editor = EditableTable( - "notes_formsemestre_uecoef", - "formsemestre_uecoef_id", - ("formsemestre_uecoef_id", "formsemestre_id", "ue_id", "coefficient"), -) - -formsemestre_uecoef_create = _formsemestre_uecoef_editor.create -formsemestre_uecoef_edit = _formsemestre_uecoef_editor.edit -formsemestre_uecoef_list = _formsemestre_uecoef_editor.list -formsemestre_uecoef_delete = _formsemestre_uecoef_editor.delete - - def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST=None): """Changement manuel des coefficients des UE capitalisées.""" context = context.Notes # si appele d'en haut, eg par exception ScoValueError @@ -1527,7 +1530,7 @@ def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST= initvalues = {"formsemestre_id": formsemestre_id} form = [("formsemestre_id", {"input_type": "hidden"})] for ue in ues: - coefs = formsemestre_uecoef_list( + coefs = sco_formsemestre.formsemestre_uecoef_list( cnx, args={"formsemestre_id": formsemestre_id, "ue_id": ue["ue_id"]} ) if coefs: @@ -1564,7 +1567,7 @@ def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST= msg = [] for ue in ues: val = tf[2]["ue_" + ue["ue_id"]] - coefs = formsemestre_uecoef_list( + coefs = sco_formsemestre.formsemestre_uecoef_list( cnx, args={"formsemestre_id": formsemestre_id, "ue_id": ue["ue_id"]} ) if val == "" or val == "auto": @@ -1594,11 +1597,13 @@ def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST= # apply modifications for ue in ue_modified: - do_formsemestre_uecoef_edit_or_create( + sco_formsemestre.do_formsemestre_uecoef_edit_or_create( context, cnx, formsemestre_id, ue["ue_id"], ue["coef"] ) for ue in ue_deleted: - do_formsemestre_uecoef_delete(context, cnx, formsemestre_id, ue["ue_id"]) + sco_formsemestre.do_formsemestre_uecoef_delete( + context, cnx, formsemestre_id, ue["ue_id"] + ) if ue_modified or ue_deleted: z = ["""

    Modification effectuées

    """] @@ -1630,39 +1635,6 @@ def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST= ) -def do_formsemestre_uecoef_edit_or_create(context, cnx, formsemestre_id, ue_id, coef): - "modify or create the coef" - coefs = formsemestre_uecoef_list( - cnx, args={"formsemestre_id": formsemestre_id, "ue_id": ue_id} - ) - if coefs: - formsemestre_uecoef_edit( - cnx, - args={ - "formsemestre_uecoef_id": coefs[0]["formsemestre_uecoef_id"], - "coefficient": coef, - }, - ) - else: - formsemestre_uecoef_create( - cnx, - args={ - "formsemestre_id": formsemestre_id, - "ue_id": ue_id, - "coefficient": coef, - }, - ) - - -def do_formsemestre_uecoef_delete(context, cnx, formsemestre_id, ue_id): - "delete coef for this (ue,sem)" - coefs = formsemestre_uecoef_list( - cnx, args={"formsemestre_id": formsemestre_id, "ue_id": ue_id} - ) - if coefs: - formsemestre_uecoef_delete(cnx, coefs[0]["formsemestre_uecoef_id"]) - - # ----- identification externe des sessions (pour SOJA et autres logiciels) def get_formsemestre_session_id(context, sem, F, parcours): """Identifiant de session pour ce semestre diff --git a/sco_formsemestre_exterieurs.py b/sco_formsemestre_exterieurs.py index e90e48054..1240d5e1d 100644 --- a/sco_formsemestre_exterieurs.py +++ b/sco_formsemestre_exterieurs.py @@ -436,7 +436,7 @@ def _list_ue_with_coef_and_validations(context, sem, etudid): ue_list = context.do_ue_list({"formation_id": sem["formation_id"]}) for ue in ue_list: # add coefficient - uecoef = sco_formsemestre_edit.formsemestre_uecoef_list( + uecoef = sco_formsemestre.formsemestre_uecoef_list( cnx, args={"formsemestre_id": formsemestre_id, "ue_id": ue["ue_id"]} ) if uecoef: diff --git a/sco_formsemestre_inscriptions.py b/sco_formsemestre_inscriptions.py index 602ad670c..44f2d137b 100644 --- a/sco_formsemestre_inscriptions.py +++ b/sco_formsemestre_inscriptions.py @@ -37,6 +37,7 @@ from TrivialFormulator import TrivialFormulator, TF # from notes_table import * import sco_find_etud import sco_formsemestre +import sco_moduleimpl import sco_groups @@ -75,10 +76,13 @@ def do_formsemestre_inscription_with_modules( gdone[group_id] = 1 # inscription a tous les modules de ce semestre - modimpls = context.do_moduleimpl_withmodule_list(formsemestre_id=formsemestre_id) + modimpls = sco_moduleimpl.do_moduleimpl_withmodule_list( + context, formsemestre_id=formsemestre_id + ) for mod in modimpls: if mod["ue"]["type"] != UE_SPORT: - context.do_moduleimpl_inscription_create( + sco_moduleimpl.do_moduleimpl_inscription_create( + context, {"moduleimpl_id": mod["moduleimpl_id"], "etudid": etudid}, REQUEST=REQUEST, formsemestre_id=formsemestre_id, @@ -278,8 +282,10 @@ def formsemestre_inscription_option(context, etudid, formsemestre_id, REQUEST=No ] # Cherche les moduleimpls et les inscriptions - mods = context.do_moduleimpl_withmodule_list(formsemestre_id=formsemestre_id) - inscr = context.do_moduleimpl_inscription_list(etudid=etudid) + mods = sco_moduleimpl.do_moduleimpl_withmodule_list( + context, formsemestre_id=formsemestre_id + ) + inscr = sco_moduleimpl.do_moduleimpl_inscription_list(context, etudid=etudid) # Formulaire modimpls_by_ue_ids = DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_id ] modimpls_by_ue_names = DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_name ] @@ -502,13 +508,14 @@ def do_moduleimpl_incription_options( # inscriptions for moduleimpl_id in a_inscrire: # verifie que ce module existe bien - mods = context.do_moduleimpl_list(moduleimpl_id=moduleimpl_id) + mods = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id) if len(mods) != 1: raise ScoValueError( "inscription: invalid moduleimpl_id: %s" % moduleimpl_id ) mod = mods[0] - context.do_moduleimpl_inscription_create( + sco_moduleimpl.do_moduleimpl_inscription_create( + context, {"moduleimpl_id": moduleimpl_id, "etudid": etudid}, REQUEST=REQUEST, formsemestre_id=mod["formsemestre_id"], @@ -516,14 +523,14 @@ def do_moduleimpl_incription_options( # desinscriptions for moduleimpl_id in a_desinscrire: # verifie que ce module existe bien - mods = context.do_moduleimpl_list(moduleimpl_id=moduleimpl_id) + mods = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id) if len(mods) != 1: raise ScoValueError( "desinscription: invalid moduleimpl_id: %s" % moduleimpl_id ) mod = mods[0] - inscr = context.do_moduleimpl_inscription_list( - moduleimpl_id=moduleimpl_id, etudid=etudid + inscr = sco_moduleimpl.do_moduleimpl_inscription_list( + context, moduleimpl_id=moduleimpl_id, etudid=etudid ) if not inscr: raise ScoValueError( @@ -531,8 +538,8 @@ def do_moduleimpl_incription_options( % (etudid, moduleimpl_id) ) oid = inscr[0]["moduleimpl_inscription_id"] - context.do_moduleimpl_inscription_delete( - oid, formsemestre_id=mod["formsemestre_id"] + sco_moduleimpl.do_moduleimpl_inscription_delete( + context, oid, formsemestre_id=mod["formsemestre_id"] ) if REQUEST: diff --git a/sco_formsemestre_status.py b/sco_formsemestre_status.py index b3132e6a1..e71e4624c 100644 --- a/sco_formsemestre_status.py +++ b/sco_formsemestre_status.py @@ -31,9 +31,18 @@ # Rewritten from ancient DTML code from mx.DateTime import DateTime as mxDateTime -from notesdb import * from notes_log import log -from sco_utils import * +import sco_utils as scu +from sco_permissions import ( + ScoImplement, + ScoChangeFormation, + ScoEtudInscrit, + ScoView, + ScoEtudChangeAdr, +) +from sco_exceptions import ScoValueError +import VERSION +import htmlutils from sco_formsemestre_custommenu import formsemestre_custommenu_html from gen_tables import GenTable import sco_archives @@ -41,64 +50,12 @@ import sco_groups import sco_evaluations import sco_formsemestre import sco_formsemestre_edit +import sco_moduleimpl import sco_compute_moy import sco_codes_parcours import sco_bulletins -def makeMenu(title, items, css_class="", base_url="", alone=False): - """HTML snippet to render a simple drop down menu. - items is a list of dicts: - { 'title' : - 'url' : - 'id' : - 'attr' : "" # optionnal html attributes - 'enabled' : # True by default - 'helpmsg' : - 'submenu' : [ list of sub-items ] - } - """ - - def gen_menu_items(items): - H.append("") - - H = [] - if alone: - H.append('
      ' % css_class) - H.append("""
    • %s""" % title) - gen_menu_items(items) - H.append("
    • ") - if alone: - H.append("
    ") - return "".join(H) - - # H = [ """