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/ZNotes.py b/ZNotes.py index c565b24f7..e42082c52 100644 --- a/ZNotes.py +++ b/ZNotes.py @@ -52,6 +52,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 @@ -839,7 +840,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 !

    """, @@ -917,7 +918,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") @@ -1207,158 +1208,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, @@ -1453,8 +1308,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 @@ -1467,7 +1322,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, @@ -1535,7 +1390,8 @@ 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"], ) @@ -1572,7 +1428,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, @@ -1616,7 +1472,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"], @@ -1636,11 +1493,13 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl 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) + list_insc = sco_moduleimpl.do_moduleimpl_listeetuds(self, moduleimpl_id) T = [] for etudid in list_insc: @@ -1779,7 +1638,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: @@ -1855,7 +1716,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, sem = sco_moduleimpl.can_change_ens(self, REQUEST, moduleimpl_id) # search ens_id ok = False for ens in M["ens"]: @@ -1864,59 +1725,11 @@ 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( "notes_formsemestre_inscription", @@ -2132,8 +1945,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( @@ -2164,123 +1977,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): @@ -2397,7 +2093,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 ( @@ -2473,7 +2169,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 @@ -2516,7 +2212,7 @@ 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) @@ -2548,7 +2244,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) @@ -2671,7 +2367,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( @@ -2694,7 +2390,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, ...) @@ -2770,42 +2466,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): @@ -3088,21 +2748,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" @@ -3514,7 +3159,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: @@ -3588,7 +3235,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( diff --git a/ZScolar.py b/ZScolar.py index ef2857e83..07c783a10 100644 --- a/ZScolar.py +++ b/ZScolar.py @@ -277,8 +277,8 @@ UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo ') FA.append('") @@ -654,13 +654,13 @@ UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo ") else: H.append('

    Aucun groupe dans cette partition') - if self.Notes.can_change_groups(REQUEST, formsemestre_id): + if sco_groups.can_change_groups(self, REQUEST, formsemestre_id): H.append( ' (créer)' % partition["partition_id"] ) H.append("

    ") - if self.Notes.can_change_groups(REQUEST, formsemestre_id): + if sco_groups.can_change_groups(self, REQUEST, formsemestre_id): H.append( '

    Ajouter une partition

    ' % formsemestre_id @@ -1161,88 +1161,6 @@ UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo Changement de groupe de %(nomprenom)s (semestre %(semtitre)s)

    ' - % etud - ] - header = self.sco_header( - REQUEST, page_title="Changement de groupe de %(nomprenom)s" % etud - ) - # Liste des groupes existants - raise NotImplementedError # XXX utiliser form_group_choice ou supprimer completement ? - # - H.append("""

    """) - - H.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 40f7ad615..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)" @@ -60,10 +60,15 @@ then # suppression de la base postgres db_name=$(sed '/^dbname=*/!d; s///;q' < "$cfg_pathname") - echo "suppression de la base postgres $db_name" - su -c "dropdb $db_name" "$POSTGRES_SUPERUSER" || terminate "ne peux supprimer base de donnees $db_name" + 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.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..aabab46f4 100644 --- a/sco_abs_views.py +++ b/sco_abs_views.py @@ -28,16 +28,21 @@ """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 import sco_formsemestre +import sco_moduleimpl import sco_photos import sco_abs @@ -58,7 +63,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": @@ -82,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 @@ -248,7 +253,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 +376,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 +511,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 +576,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 +615,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 +698,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 +719,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 +730,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 +835,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 +848,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_bulletins.py b/sco_bulletins.py index eb5bc6f4a..7a06625d2 100644 --- a/sco_bulletins.py +++ b/sco_bulletins.py @@ -34,11 +34,12 @@ from email.mime.text import MIMEText from email.mime.base import MIMEBase from email.header import Header -import htmlutils, time +import time from reportlab.lib.colors import Color from sco_utils import * from notes_table import * +import htmlutils import sco_formsemestre import sco_groups import sco_pvjury @@ -1146,7 +1147,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_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_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 = [ """