diff --git a/intranet/conf/intranet.cfg b/intranet/conf/intranet.cfg index cb6b6df3..90ce464a 100644 --- a/intranet/conf/intranet.cfg +++ b/intranet/conf/intranet.cfg @@ -11,11 +11,6 @@ crans.modules.dir = "/usr/scripts/intranet/modules/" # Now we can work on our filter as with the standard filters templatesEngine.on = True -[/digicode] -crans.droits="Imprimeur" -[/gestionFactures] -crans.droits="Imprimeur" - [/impression] crans.activate = True crans.activate.errorMsg = u"Plus d'encre ! Le fournisseur s'est trompé dans la commande." diff --git a/intranet/modules/digicode/main.py b/intranet/modules/digicode/main.py new file mode 100755 index 00000000..52f03dee --- /dev/null +++ b/intranet/modules/digicode/main.py @@ -0,0 +1,81 @@ +#! /usr/bin/env python +import cherrypy, tempfile, shutil, os +import crans.impression +import crans.impression.digicode +import crans.cp +from ClassesIntranet.ModuleBase import ModuleBase + + +class main(ModuleBase): + _droits = ["Imprimeur"] + def category(self): + return "Imprimeur" + def title(self): + return "Digicode" + + ########################## + # affichage + ########################## + # + # methode qui affiche la template + # + def index(self, submit = None, fileList = None, newFile = None ): + return {'template':'digicode', + 'values':{}, + 'stylesheets':['digicode.css'], + 'scripts':['digicode.js', 'popup.js'], + } + index.exposed = True + + + ########################## + # AJAX + ########################## + # + # methode qui renvoie la liste des codes + # + def codeList(self): + try: + listeBrute = crans.impression.digicode.list_code() + liste_formatee = [] + for aCode in listeBrute: + age = aCode[1] + age_jours = (age/3600)/24 + age_heures = (age/3600) - age_jours*24 + age_minutes = (age/60) - (age/3600)*60 + if age_jours > 0: + age_string = "%sj %sh %smin" % (str(age_jours), str(age_heures), str( age_minutes )) + elif age_heures > 0: + age_string = "%sh %smin" % (str(age_heures), str( age_minutes )) + else: + age_string = "%smin" % (str( age_minutes )) + liste_formatee.append({'code':aCode[0], 'age':age_string, 'desc':aCode[2]}) + return {'codes': liste_formatee} + except Exception, e: + crans.cp.log('erreur lors de la creation de la liste de codes :' + str(e), 'DIGICODE', 1) + return {'erreur':str(e)} + codeList.exposed= True + + # + # methode qui cree un code + # + def createCode(self, code=None, adherent=''): + try: + if adherent == '': + adherent = cherrypy.session['uid'] + if code: + try: + int(code) + if code.__len__() != 6: + raise + except: + return {'formatErreur':1} + code = crans.impression.digicode.save_code(code, adherent) + else: + code = crans.impression.digicode.gen_code(adherent) + crans.cp.log("code cree : %s" % code, 'DIGICODE') + return {'code': code, "age" : "new", "desc":adherent} + except Exception, e: + crans.cp.log("erreur lors de la creation de code : " + str(e), 'DIGICODE', 1) + return {'erreur':str(e)} + createCode.exposed= True diff --git a/intranet/modules/digicode/static/digicode.css b/intranet/modules/digicode/static/digicode.css new file mode 100644 index 00000000..921f9165 --- /dev/null +++ b/intranet/modules/digicode/static/digicode.css @@ -0,0 +1,85 @@ +/************************************************************* + .. + .... ............ ........ + . ....... . .... .. + . ... .. .. .. .. ..... . .. + .. .. ....@@@. .. . ........ . + .. . .. ..@.@@..@@. .@@@@@@@ @@@@@@. .... + .@@@@. .@@@@. .@@@@..@@.@@..@@@..@@@..@@@@.... .... + @@@@... .@@@.. @@ @@ .@..@@..@@...@@@. .@@@@@. .. + .@@@.. . @@@. @@.@@..@@.@@..@@@ @@ .@@@@@@.. ..... + ...@@@.... @@@ .@@.......... ........ ..... .. + . ..@@@@.. . .@@@@. .. ....... . ............. + . .. .... .. .. . ... .... +. . .... ............. .. ... +.. .. ... ........ ... ... + ................................ + +============================================================== +digicode.css - Intranet Style + + STYLE PAGE DU DIGICODE + + +Copyright (c) 2006 by www.crans.org + +**************************************************************/ +#codesTable { +width:60%; +border:thin black solid; +float:left; +} + + +#codesTable thead { +color:gray; +} + +#codesTable .code { +border-right:thin gray solid; +width:70%; +} + +#codesTable tbody .age { +text-align:right; +} + +#codesTable td, +#codesTable th { +margin:0; +padding:2px 5px; +} + +#codesTable tbody td { +border-top:thin gray solid; +} + +#codesTable thead th { +border-top:none; +} + + +div#addCodeBox { +float: right; +border:thin black solid; +padding:10px; +margin:0 5%; +width:25%; +} + +div#addCodeBox h1 { +font-size:1.1em; +margin:2px 10px 20px 10px; +text-align:center; +} + +div#addCodeBox form { +} +div#addCodeBox form input, +div#addCodeBox form button { +margin:3px; +} + +form input.textinput { +border: thin gray solid; +} diff --git a/intranet/modules/digicode/static/digicode.js b/intranet/modules/digicode/static/digicode.js new file mode 100644 index 00000000..5fca191e --- /dev/null +++ b/intranet/modules/digicode/static/digicode.js @@ -0,0 +1,170 @@ +/* ************************************************************ + * Digicode + ************************************************************ + * Digicode.init : initialisation de la page + * Digicode.makeCode : creation de codes + * Digicode.codelist : liste des codes + * Digicode.AJAX : ajax + */ +Digicode = {}; + +/***************************** + Digicode.init + *****************************/ +Digicode.init = function() +{ + // afficher le tableau codelist + appendChildNodes("globalDiv", Digicode.codelist.create()); + // recuperer la liste des codes + this.codelist.load(); + // afficher le formulaire de creation de code + appendChildNodes("globalDiv", DIV({"id":"addCodeBox"})); + Digicode.makeCode.displayForm(); +} + +/***************************** + Digicode.makeCode + *****************************/ +Digicode.makeCode = {} + +Digicode.makeCode.displayForm = function() +{ + var myForm = FORM({'id':'createCodeForm', 'name':'createCodeForm','onsubmit':"Digicode.makeCode.createCode(document.createCodeForm.newCodeLogin.value, document.createCodeForm.newCode.value); return false;", 'style':'display: none;'}, + LABEL({'for':'newCodeLogin'}, "Login adhérent :"), + INPUT({"name":"newCodeLogin", "size":"10", "maxlength":"20", "class":"textinput"}), + BR(), + LABEL({'for':'newCode'}, "Code :"), + INPUT({"name":"newCode", "size":"6", "maxlength":"6", "class":"textinput"}), + BUTTON({"type":"submit","onclick":"Digicode.makeCode.createCode(document.createCodeForm.newCodeLogin.value, document.createCodeForm.newCode.value)", "style":"float:right;"},"Créer code"), + BUTTON({"type":"button","onclick":"Digicode.makeCode.createCode(document.createCodeForm.newCodeLogin.value)", "style":"float:right;"},"Code aléatoire") + ); + replaceChildNodes("addCodeBox", H1({},"Nouveau code"), myForm ); + appear(myForm); + +} + +Digicode.makeCode.restoreForm = function() +{ + try + { + removeElement("newCodeDisplay"); + removeElement("loading"); + } catch (error){} + appear("createCodeForm"); + +} + +Digicode.makeCode.disableForm = function() +{ + try + { + var form = getElement("createCodeForm"); + var elts = form.elements; + for (i=0 ; i < elts.length ; i++) + elts[i].disabled = true; + } + catch (error){} +} + +Digicode.makeCode.createCode = function(login, code) +{ + var image = createDOM("IMG",{'style':'margin-right:2px;float:right;','src':'/static/images/indicator.gif'}); + appendChildNodes("addCodeBox", DIV({'id':"loading",'style':'display:none;max-height:1em;float:left;'},image,"Loading")); + this.disableForm(); + //removeElement("createCodeForm"); + appear("loading"); + if (code) + Digicode.AJAX.call("createCode?code="+code + "&adherent=" + login, this.handleNewCode); + else + Digicode.AJAX.call("createCode?adherent=" + login, this.handleNewCode); + +} +Digicode.makeCode.handleNewCode = function(res) +{ + if (res.code) + { + replaceChildNodes("addCodeBox", + H1({}, "Code créé"), + DIV({'id':"newCodeDisplay", + 'style':'display:none;font-size:2em;maring:1em;font-weight:bold;text-align:center;', + 'onclick':"Digicode.makeCode.displayForm();"},res.code)); + appear("newCodeDisplay"); + //removeElement("loading"); + Digicode.codelist.addCode(res); + } else if (res.erreur) { + logError("Erreur distante : " + res.erreur); + alert("Erreur sur le serveur, le code est peut-être déjà pris.") + Digicode.makeCode.displayForm(); + } else if (res.formatErreur) { + alert("Ceci n'est pas un code valide"); + Digicode.makeCode.displayForm(); + } + +} +/***************************** + Digicode.codelist + *****************************/ +Digicode.codelist = {}; + +Digicode.codelist.create = function () +{ + var thead = createDOM("thead", {}, + createDOM("th", {'class':'code'}, "Code" ), + createDOM("th", {'class':'age'}, "Age") + ); + var tbody = createDOM("tbody", {"id":"codeList"}); + return TABLE({"id":"codesTable", "cellspacing":"0"}, thead, tbody) +} + + + +Digicode.codelist.load = function() +{ + Digicode.AJAX.call("codeList", Digicode.codelist.displayCodes); +} + +Digicode.codelist.displayCodes = function(result) +{ + if (result.codes) + replaceChildNodes('codeList',map(Digicode.codelist.newCodeTrNodeFromDict,result.codes)); + else if (result.erreur) + logError("Erreur distante : " + result.erreur); +} + +Digicode.codelist.newCodeTrNodeFromDict = function (aDict, style) +{ + if (style) { + var aRow = createDOM("TR", {'id':'code'+aDict.code,"style":style}); + } else + var aRow = createDOM("TR", {'id':'code'+aDict.code}); + appendChildNodes(aRow, createDOM("TD", {'class':'code'}, aDict.code, SPAN({'style':'color:gray;margin-left:2em;'}, aDict.desc ) ) ); + appendChildNodes(aRow, createDOM("TD", {'class':'age'}, aDict.age) ); + return aRow; +} + +Digicode.codelist.addCode = function (aDict) +{ + var newLine = this.newCodeTrNodeFromDict(aDict); + appendChildNodes("codeList", newLine); + pulsate(newLine); +} + + +/***************************** + Digicode.AJAX + *****************************/ +Digicode.AJAX = {} + +Digicode.AJAX.call = function(page, callBack) { + logDebug("calling AJAX : " + page); + var e = loadJSONDoc(page); + e.addCallback(callBack); + e.addErrback(this.errorHandler); +} + +Digicode.AJAX.errorHandler = function(d) { + //Digicode.AJAX..modifPrix("Erreur", false); + logError("AJAX Error: " + d); +} + +setInterval(Digicode.codelist.load, 30000); diff --git a/intranet/modules/digicode/static/icon.png b/intranet/modules/digicode/static/icon.png new file mode 100644 index 00000000..fe3729c6 Binary files /dev/null and b/intranet/modules/digicode/static/icon.png differ diff --git a/intranet/modules/digicode/templates/digicode.tmpl b/intranet/modules/digicode/templates/digicode.tmpl new file mode 100644 index 00000000..33cce42f --- /dev/null +++ b/intranet/modules/digicode/templates/digicode.tmpl @@ -0,0 +1,14 @@ +#import crans.impression + +
+

Gestion des codes pour le local impression

+
+ + diff --git a/intranet/modules/factures/main.py b/intranet/modules/factures/main.py new file mode 100755 index 00000000..2a8e0048 --- /dev/null +++ b/intranet/modules/factures/main.py @@ -0,0 +1,100 @@ +#! /usr/bin/env python +# -*- coding: iso-8859-15 -*- +# ##################################################################################################### # +# Factures +# ##################################################################################################### # +# Description: +# Affiche la liste des factures et l'historique de débits/crédits de l'adhérent. +# Informations: +# +# Pages: +# index:liste des factures +# historique: historique des débits/crédits +# +# ##################################################################################################### # +import cherrypy, sys, os, datetime +from ClassesIntranet.ModuleBase import ModuleBase + + +class main(ModuleBase): + def title(self): + return "Factures" + def icon(self): + return "icon.png" + + + def index(self, message = '', error = ''): + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'])['adherent'][0] + t = {} + t['message'] = message + t['error'] = error + + ############## liste des factures ############## + listeFactures = [] + for f in adh.factures(): + facture = {} + facture['no'] = f.numero() + facture['intitule'] = f.articles()[0]['designation'] + facture['details'] = [ + { + 'intitule':art['designation'], + 'quantite':art['nombre'], + 'prixUnitaire':art['pu'], + 'prixTotal':art['pu']*art['nombre'], + } for art in f.articles()] + facture['montant'] = f.total() + facture['paypal'] = f.urlPaypal(useSandbox = cherrypy.config.get("paypal.useSandbox", False), + businessMail = cherrypy.config.get("paypal.businessAdress", "paypal@crans.org"), + return_page = "https://intranet.crans.org/monCompte/paypalReturn", + cancel_return_page = "https://intranet.crans.org/monCompte/paypalCancel", + ) + + facture['payee'] = f.recuPaiement() + listeFactures.append(facture) + t['listeFactures'] = listeFactures + + return { + 'template' :'factures', + 'values' :t, + 'stylesheets' :['cransFactures.css'], + 'scripts' :[], + } + index.exposed = True + + def historique(self): + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'])['adherent'][0] + + lst = [ x for x in adh.historique() if x.split(u' : ',1)[1].startswith(u'credit') or x.split(u' : ',1)[1].startswith(u'debit') ] + histLst = [] + for anItem in lst: + aLine = {} + aLine["date"] = anItem.split(u",")[0] + aLine["type"] = anItem.split(u' : ',2)[1].split(u' ')[0] + aLine["montant"] = anItem.split(u' : ',2)[1].split(u' ')[1] + try: + aLine["intitule"] = anItem.split(u'[')[1].split(u']')[0] + except Exception: + aLine["intitule"] = "" + histLst.append(aLine) + + return { + 'template' :'factures-historique', + 'values' :{'liste':lst, 'historic_items':histLst}, + 'stylesheets' :['cransFactures.css'], + 'scripts' :[], + } + historique.exposed = True + + def delFacture(self, no): + try: + # trrouver la factures + fact = cherrypy.session['LDAP'].search('fid=' + no, 'w')['facture'][0] + #verifier qu'elle appartient bien a l'adherent + if not fact.proprietaire().mail() == cherrypy.session['uid']: + raise Exception, "Impossible de supprimer cette facture" + # la supprimer + fact.delete() + except Exception, e: + cherrypy.log(str(e), "FACTURES", 1) + return self.index() + delFacture.exposed = True diff --git a/intranet/modules/factures/static/cransFactures.css b/intranet/modules/factures/static/cransFactures.css new file mode 100644 index 00000000..cc230642 --- /dev/null +++ b/intranet/modules/factures/static/cransFactures.css @@ -0,0 +1,205 @@ +/******************************************** + * +********************************************/ +#globalDiv { + //padding-left:20%; + position: relative; +} + +ul#actionMenu { + list-style-type:none; + width:18%; + padding:0; + float:left; +} + +h1 { + font-size:1.4em; + margin:2px; +} +td, tr { + margin:0; +} + +#factureListDiv { + padding:5px; + background:#fad163; + float:left; + width:75%; +} + +#factureListDiv table#listeFactures { + padding:0; + width:100%; +} + +.factureRow { + margin:2px; + position:relative; +} + +.help_text { + background:#fff7D7; + font-weight:normal; + padding:10px 20px; + +} + +.factureRow .factureSummary { + background:#fff7D7; + height:30px; + font-weight:bold; + padding:10px 20px; +} + +.factureRow .factureSummary span.intitule { + float:left; +} + +.factureRow .factureSummary span.montant { + float:right; + text-align:right; +} + +.tdNoFactures { + text-align:center; + font-size:1.2em; + background-color:#fff7D7; + color:#666; + margin:0; + padding:5px; +} + +.facturePayee { +} +.factureNonPayee .factureSummary { + color:red; +} + + +.actions { + display:block; + float:right; + font-size:0.9em; + font-weight:normal; +} +.actions a { + margin:2px 10px; +} + +/******************************************** + * +********************************************/ + +table.factureDetails { + background: #fff7D7 url(fondFacturesDetails.png) repeat-x top; + padding:1%; + width:96%; + margin:0 1% 10px 1%; +} + +.tdTotalDetail, +.tdTotalDetailIntitule { + border-top:thin black solid; +} + +.tdTotalDetailIntitule { + text-align:right; + font-weight:bold; +} + +table.factureDetails th { + border-bottom:thin black solid; +} +table.factureDetails th, +table.factureDetails td { + border-right:thin black solid; + margin:0; + padding:5px 20px; +} + +/******************************************** + * +********************************************/ +.note { + display:block; + font-size:small; + margin:3px; + font-weight:normal; +} +.note { + color:#666 +} + +.linkToggle { + display:block; + float:left; + height:15px; + width:15px; + background:transparent url(fl.png) top left; + margin-right:1px; +} + +/******************************************** + * +********************************************/ + +table#historique_sous { + width:100%; +} + +table#historique_sous td { + background:#fff7D7; + padding:5px; + text-align:center; + border-top:2px #fad163 solid; +} + +table#historique_sous th { + background:#fff7D7; + padding:5px; + text-decoration:underline; +} + +/******************************************** + * +********************************************/ + +form.search { + display:block; + border: thin black solid; + padding:.2em 1em; + float:left; + //position:absolute; + width:18%; + //top:0; + //left:0; + margin:0 1%; +} + +form.search input { + max-width:95%; + margin:.3em; + float:left; + border: thin gray solid; +} + +form.search label { + padding-top:7px; + display:block; + width:4em; + float:left; + clear:left; +font-weight:bold; +} + +form.search h3 { + margin:.2em 0; +} + +form.search input.button { + margin:.5em; + text-align:center; + clear:left; +} + diff --git a/intranet/modules/factures/static/fl.png b/intranet/modules/factures/static/fl.png new file mode 100644 index 00000000..2c72f9ea Binary files /dev/null and b/intranet/modules/factures/static/fl.png differ diff --git a/intranet/modules/factures/static/fondFacturesDetails.png b/intranet/modules/factures/static/fondFacturesDetails.png new file mode 100644 index 00000000..b747a69c Binary files /dev/null and b/intranet/modules/factures/static/fondFacturesDetails.png differ diff --git a/intranet/modules/factures/static/icon.png b/intranet/modules/factures/static/icon.png new file mode 100644 index 00000000..136dec31 Binary files /dev/null and b/intranet/modules/factures/static/icon.png differ diff --git a/intranet/modules/factures/templates/factures-historique.tmpl b/intranet/modules/factures/templates/factures-historique.tmpl new file mode 100644 index 00000000..065725d9 --- /dev/null +++ b/intranet/modules/factures/templates/factures-historique.tmpl @@ -0,0 +1,45 @@ +
+ +
+ + + +
+

Historique

+
+ + + + + + + + #for anItem in $historic_items + + + + #if $anItem.type=="debit" + + #else + + #end if + #if $anItem.type=="credit" + + #else + + #end if + + #end for + #if $historic_items == [] + + #end if +
DateIntituléDébitCrédit
$anItem.date$anItem.intitule$anItem.montant $anItem.montant 
+ AUCUNE TRANSACTION ENREGISTRÉE +
+
+ +
+
diff --git a/intranet/modules/factures/templates/factures.tmpl b/intranet/modules/factures/templates/factures.tmpl new file mode 100644 index 00000000..7551fcc8 --- /dev/null +++ b/intranet/modules/factures/templates/factures.tmpl @@ -0,0 +1,107 @@ +
+ +#if $message != '' + +#end if + +#if $error != '' + +#end if + + + + +
+ + +
+

Mes factures PayPal

+ + #for f in $listeFactures + #if $f.payee +
+ #else +
+ #end if +
+ + #if $f.details.__len__() > 1 + + #end if + $f.intitule + #if not $f.payee + (non payée) + #end if + + + + $f.montant € + + Crée le - + #if not $f.payee + + Annuler + Payer avec PayPal + + #else + Payée + #end if + +
+ #if $f.details.__len__() > 1 + +
+ #end if + #end for + + #if $listeFactures == [] +
+ AUCUNE TRANSACTION PAYPAL ENREGISTRÉE +
+ #end if +
+ +
diff --git a/intranet/modules/gestionFactures/main.py b/intranet/modules/gestionFactures/main.py new file mode 100755 index 00000000..b558dce4 --- /dev/null +++ b/intranet/modules/gestionFactures/main.py @@ -0,0 +1,140 @@ +#! /usr/bin/env python +# -*- coding: iso-8859-15 -*- +# ##################################################################################################### # +# Factures (gestion) +# ##################################################################################################### # +# Description: +# Permet de chercher dans les facture, d'en créditer et d'en supprimer +# Informations: +# +# Pages: +# index:afiche le formulaire et les factures +# +# ##################################################################################################### # +import cherrypy, sys, os, datetime +import crans.cp +from ClassesIntranet.ModuleBase import ModuleBase + +class main(ModuleBase): + _droits = ["Imprimeur"] + def title(self): + return "Gestion factures" + def category(self): + return "Imprimeur" + + def index(self, message = '', erreur = ''): + if cherrypy.session.has_key('gestion_factures-current_search'): + del cherrypy.session['gestion_factures-current_search'] + return self.displayTemplate() + index.exposed = True + + def search(self, fid=None, uid=None, aid=None): + cherrypy.session['gestion_factures-current_search'] = { + "fid":fid, + "uid":uid, + "aid":aid, + } + return self.displayTemplate() + search.exposed = True + + + + def displayTemplate(self, message = '', erreur = ''): + t = {} + t['message'] = message + t['error'] = erreur + if cherrypy.session.has_key('gestion_factures-current_search'): + fid = cherrypy.session['gestion_factures-current_search']['fid'] + uid = cherrypy.session['gestion_factures-current_search']['uid'] + aid = cherrypy.session['gestion_factures-current_search']['aid'] + t['listeFactures'] = self.buildInvoiceList( + fid = fid, + uid = uid, + aid = aid, + ) + + else: + fid = "" + uid = "" + aid = "" + t["form"] = [] + t["form"]+= [{'name':'fid', 'label':'fid', 'value':fid}] + t["form"]+= [{'name':'uid', 'label':'login', 'value':uid}] + t["form"]+= [{'name':'aid', 'label':'aid', 'value':aid}] + + return { + 'template' :'factures-gestion', + 'values' :t, + 'stylesheets' :['cransFactures.css'], + } + + + + + def buildInvoiceList(self, fid=None, uid=None, aid=None): + ############## liste des factures ############## + if fid: + search_string = "fid=%s" % str(fid) + liste_factures_ldap = cherrypy.session['LDAP'].search(search_string)['facture'] + elif uid: + search_string = "uid=%s" % str(uid) + try: + liste_factures_ldap = cherrypy.session['LDAP'].search(search_string)['adherent'][0].factures() + except: + liste_factures_ldap = [] + elif aid: + search_string = "aid=%s" % str(aid) + try: + liste_factures_ldap = cherrypy.session['LDAP'].search(search_string)['adherent'][0].factures() + except: + liste_factures_ldap = [] + else: + return [] + liste_factures_affichees = [] + for f in liste_factures_ldap: + try: + facture = {} + facture['no'] = f.numero() + facture['adherent'] = f.proprietaire().mail() + facture['montant'] = f.total() + facture['payee'] = f.recuPaiement() + facture['intitule'] = f.articles()[0]['designation'] + facture['details'] = [ + { + 'intitule':art['designation'], + 'quantite':art['nombre'], + 'prixUnitaire':art['pu'], + 'prixTotal':art['pu']*art['nombre'], + } for art in f.articles()] + liste_factures_affichees.append(facture) + except: + crans.cp.log("Facture non affichable : fid=%s" % str(f.numero()), "GESTION FACTURES", 1) + + return liste_factures_affichees + + def delFacture(self, fid): + try: + # trrouver la factures + fact = cherrypy.session['LDAP'].search('fid=' + fid, 'w')['facture'][0] + # la supprimer + fact.delete() + except Exception, e: + crans.cp.log(unicode(e), "GESTION FACTURES", 1) + return self.index(erreur=u"Probleme lors de la suppression") + crans.cp.log(u"Facture supprimee [fid=%s]" % fid, "GESTION FACTURES") + return self.displayTemplate(message=u"Facture suprimée") + delFacture.exposed = True + + def crediteFacture(self, fid): + try: + # trrouver la factures + fact = cherrypy.session['LDAP'].search('fid=' + fid, 'w')['facture'][0] + # la supprimer + fact.recuPaiement(cherrypy.session['uid']) + fact.save() + except Exception, e: + crans.cp.log("pb crédit", "GESTION FACTURES", 1) + return self.index(erreur=u"Problème lors du crédit") + crans.cp.log("Facture creditee [fid=%s]" % fid, "GESTION FACTURES") + return self.displayTemplate(message=u"Facture créditée") + crediteFacture.exposed = True diff --git a/intranet/modules/gestionFactures/static/cransFactures.css b/intranet/modules/gestionFactures/static/cransFactures.css new file mode 100644 index 00000000..cc230642 --- /dev/null +++ b/intranet/modules/gestionFactures/static/cransFactures.css @@ -0,0 +1,205 @@ +/******************************************** + * +********************************************/ +#globalDiv { + //padding-left:20%; + position: relative; +} + +ul#actionMenu { + list-style-type:none; + width:18%; + padding:0; + float:left; +} + +h1 { + font-size:1.4em; + margin:2px; +} +td, tr { + margin:0; +} + +#factureListDiv { + padding:5px; + background:#fad163; + float:left; + width:75%; +} + +#factureListDiv table#listeFactures { + padding:0; + width:100%; +} + +.factureRow { + margin:2px; + position:relative; +} + +.help_text { + background:#fff7D7; + font-weight:normal; + padding:10px 20px; + +} + +.factureRow .factureSummary { + background:#fff7D7; + height:30px; + font-weight:bold; + padding:10px 20px; +} + +.factureRow .factureSummary span.intitule { + float:left; +} + +.factureRow .factureSummary span.montant { + float:right; + text-align:right; +} + +.tdNoFactures { + text-align:center; + font-size:1.2em; + background-color:#fff7D7; + color:#666; + margin:0; + padding:5px; +} + +.facturePayee { +} +.factureNonPayee .factureSummary { + color:red; +} + + +.actions { + display:block; + float:right; + font-size:0.9em; + font-weight:normal; +} +.actions a { + margin:2px 10px; +} + +/******************************************** + * +********************************************/ + +table.factureDetails { + background: #fff7D7 url(fondFacturesDetails.png) repeat-x top; + padding:1%; + width:96%; + margin:0 1% 10px 1%; +} + +.tdTotalDetail, +.tdTotalDetailIntitule { + border-top:thin black solid; +} + +.tdTotalDetailIntitule { + text-align:right; + font-weight:bold; +} + +table.factureDetails th { + border-bottom:thin black solid; +} +table.factureDetails th, +table.factureDetails td { + border-right:thin black solid; + margin:0; + padding:5px 20px; +} + +/******************************************** + * +********************************************/ +.note { + display:block; + font-size:small; + margin:3px; + font-weight:normal; +} +.note { + color:#666 +} + +.linkToggle { + display:block; + float:left; + height:15px; + width:15px; + background:transparent url(fl.png) top left; + margin-right:1px; +} + +/******************************************** + * +********************************************/ + +table#historique_sous { + width:100%; +} + +table#historique_sous td { + background:#fff7D7; + padding:5px; + text-align:center; + border-top:2px #fad163 solid; +} + +table#historique_sous th { + background:#fff7D7; + padding:5px; + text-decoration:underline; +} + +/******************************************** + * +********************************************/ + +form.search { + display:block; + border: thin black solid; + padding:.2em 1em; + float:left; + //position:absolute; + width:18%; + //top:0; + //left:0; + margin:0 1%; +} + +form.search input { + max-width:95%; + margin:.3em; + float:left; + border: thin gray solid; +} + +form.search label { + padding-top:7px; + display:block; + width:4em; + float:left; + clear:left; +font-weight:bold; +} + +form.search h3 { + margin:.2em 0; +} + +form.search input.button { + margin:.5em; + text-align:center; + clear:left; +} + diff --git a/intranet/modules/gestionFactures/static/fl.png b/intranet/modules/gestionFactures/static/fl.png new file mode 100644 index 00000000..2c72f9ea Binary files /dev/null and b/intranet/modules/gestionFactures/static/fl.png differ diff --git a/intranet/modules/gestionFactures/static/fondFacturesDetails.png b/intranet/modules/gestionFactures/static/fondFacturesDetails.png new file mode 100644 index 00000000..b747a69c Binary files /dev/null and b/intranet/modules/gestionFactures/static/fondFacturesDetails.png differ diff --git a/intranet/modules/gestionFactures/static/icon.png b/intranet/modules/gestionFactures/static/icon.png new file mode 100644 index 00000000..efe29dd9 Binary files /dev/null and b/intranet/modules/gestionFactures/static/icon.png differ diff --git a/intranet/modules/gestionFactures/templates/factures-historique.tmpl b/intranet/modules/gestionFactures/templates/factures-historique.tmpl new file mode 100644 index 00000000..065725d9 --- /dev/null +++ b/intranet/modules/gestionFactures/templates/factures-historique.tmpl @@ -0,0 +1,45 @@ +
+ +
+ + + +
+

Historique

+
+ + + + + + + + #for anItem in $historic_items + + + + #if $anItem.type=="debit" + + #else + + #end if + #if $anItem.type=="credit" + + #else + + #end if + + #end for + #if $historic_items == [] + + #end if +
DateIntituléDébitCrédit
$anItem.date$anItem.intitule$anItem.montant $anItem.montant 
+ AUCUNE TRANSACTION ENREGISTRÉE +
+
+ +
+
diff --git a/intranet/modules/gestionFactures/templates/factures.tmpl b/intranet/modules/gestionFactures/templates/factures.tmpl new file mode 100644 index 00000000..7551fcc8 --- /dev/null +++ b/intranet/modules/gestionFactures/templates/factures.tmpl @@ -0,0 +1,107 @@ +
+ +#if $message != '' + +#end if + +#if $error != '' + +#end if + + + + +
+ + +
+

Mes factures PayPal

+ + #for f in $listeFactures + #if $f.payee +
+ #else +
+ #end if +
+ + #if $f.details.__len__() > 1 + + #end if + $f.intitule + #if not $f.payee + (non payée) + #end if + + + + $f.montant € + + Crée le - + #if not $f.payee + + Annuler + Payer avec PayPal + + #else + Payée + #end if + +
+ #if $f.details.__len__() > 1 + +
+ #end if + #end for + + #if $listeFactures == [] +
+ AUCUNE TRANSACTION PAYPAL ENREGISTRÉE +
+ #end if +
+ +
diff --git a/intranet/modules/impression/main.py b/intranet/modules/impression/main.py new file mode 100755 index 00000000..deb384b0 --- /dev/null +++ b/intranet/modules/impression/main.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python +# -*- coding: iso-8859-15 -*- +# ############################################################# +# .. +# .... ............ ........ +# . ....... . .... .. +# . ... .. .. .. .. ..... . .. +# .. .. ....@@@. .. . ........ . +# .. . .. ..@.@@..@@. .@@@@@@@ @@@@@@. .... +# .@@@@. .@@@@. .@@@@..@@.@@..@@@..@@@..@@@@.... .... +# @@@@... .@@@.. @@ @@ .@..@@..@@...@@@. .@@@@@. .. +# .@@@.. . @@@. @@.@@..@@.@@..@@@ @@ .@@@@@@.. ..... +# ...@@@.... @@@ .@@.......... ........ ..... .. +# . ..@@@@.. . .@@@@. .. ....... . ............. +# . .. .... .. .. . ... .... +# . . .... ............. .. ... +# .. .. ... ........ ... ... +# ................................ +# +# ############################################################# +# +# interface d'impression +# +# Copyright (c) 2006 by www.crans.org +# ############################################################# + +import cherrypy, tempfile, shutil, os +import crans.impression +import crans.impression.digicode +import crans.impression.etat_imprimante +import crans.cp +FILE_UPLOAD_BASE_FOLDER = cherrypy.config.get('fileUpload.folder', "/var/impression/fichiers/") + +class FileError(Exception): + pass +from ClassesIntranet.ModuleBase import ModuleBase + +class main(ModuleBase): + def category(self): + return "Services" + def title(self): + return "Impression" + def icon(self): + return "icon.png" + + + ########################## + # affichage + ########################## + # + # template principale + # + def index(self, submit = None, fileList = None, newFile = None ): + data = {} + # on efface un eventuel objet impression existant + cherrypy.session['impression'] = None + if submit == "Envoyer": + try: + self.savePDF(newFile) + data['fileName'] = newFile.filename + except FileError, e: + data['openError'] = e.args[0] + elif submit == "Choisir": + if (fileList): + data['fileName'] = fileList + else: + data['openError'] = "Choisissez un fichier" + + data['fileList'] = self.getUploadedFileListFor(cherrypy.session['uid']) + try: + crans.impression.etat_imprimante.etat() + except Exception, e: + data['Erreur_imprimante'] = str(e).replace("\"", "\\\"") + data['errorMsg'] = u"Imprimante injoignable" + if not cherrypy.config.get('crans.activate', True): + data['Erreur_imprimante'] = "Config impression" + data['errorMsg'] = cherrypy.config.get('crans.activate.errorMsg', u"Imprimante HS") + return {'template':'impression', + 'values':data, + 'stylesheets':['impression.css'], + 'scripts':['impression.js', 'popup.js'], + } + index.exposed = True + + ########################## + # devis + ########################## + # + # methode qui affiche la template du devis + # + + def devis(self): + return { + 'template':'impression-devis', + 'values': + { + 'devis':cherrypy.session['impression'].devisDetaille(), + 'total':cherrypy.session['impression'].prix(), + 'nomFichier':cherrypy.session['impression'].fileName(), + }, + 'standalone':True, + } + devis.exposed=True + + + ########################## + # AJAX + ########################## + # + # methode qui renvoie la liste des codes de l'adherent + # + def codeList(self): + try: + listeBrute = crans.impression.digicode.list_code() + # liste de la forme : + # [(code, age, description),...] + listeBrute = [item[0] for item in listeBrute if item[2] == cherrypy.session['uid']] + return {'codes': listeBrute} + except Exception, e: + crans.cp.log('erreur lors de la creation de la liste de codes :' + str(e), 'IMPRESSION', 1) + return {'erreur':str(e)} + codeList.exposed= True + + # + # methode qui indique quel fichier utiliser + # + def useFile(self, fileName): + try: + filepath = os.path.join(os.path.join(FILE_UPLOAD_BASE_FOLDER, cherrypy.session['uid']+"/"), fileName) + cherrypy.session['impression'] = crans.impression.impression(filepath, cherrypy.session['uid']) + return {'nbPages': cherrypy.session['impression'].pages()} + except crans.impression.FichierInvalide, e: + crans.cp.log("useFile : %s (%s)" % (str(e), e.file()), 'IMPRESSION', 1) + return {'erreur':str(e) } + except Exception, e: + crans.cp.log("useFile : %s" % str(e), 'IMPRESSION', 1) + return {'erreur':str(e) } + useFile.exposed= True + + + # + # methode pour changer les parametres + # + def changeSettings(self, copies=None, couleurs=None, recto_verso=None, agrafes=None, papier=None): + try: + nouvPrix = cherrypy.session['impression'].changeSettings(papier=papier, couleurs=couleurs, agraphes=agrafes, recto_verso=recto_verso, copies=int(copies)) + except Exception, e: + crans.cp.log("changeSettings : %s" % str(e), 'IMPRESSION', 1) + return {"erreur":str(e)} + return {'nouvPrix':nouvPrix} + changeSettings.exposed = True + + + # + # methode pour lancer l'impression + # + def lancerImpression(self): + try: + cherrypy.session['impression'].imprime() + except crans.impression.SoldeInsuffisant: + return {"SoldeInsuffisant":1} + except Exception, e: + crans.cp.log("lancerImpression : %s" % str(e), 'IMPRESSION', 1) + return {"erreur":str(e)} + crans.cp.log("impression", 'IMPRESSION') + return {'code':str(crans.impression.digicode.gen_code(cherrypy.session['uid'])) + "#"} + lancerImpression.exposed = True + + # + # methode pour recuperer l'etat de l'imprimante + # + def etatImprimante(self): + if not cherrypy.config.get('crans.activate', True): + return {"printer_state" : u"Système down"} + try: + return {"printer_state" : u"\\n".join(crans.impression.etat_imprimante.etat())} + except Exception, e: + return {"printer_state" : 'Imprimante hors ligne'} + etatImprimante.exposed = True + + # + # methode pour le solde + # + def AJAXGetSolde(self): + try: + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'])['adherent'][0] + return {"solde" : adh.solde() } + except Exception, e: + return {"erreur" : str(e)} + AJAXGetSolde.exposed = True + + + + + ########################## + # privees + ########################## + # + # methode pour obtenir la liste des fichiers uploadés + # + def getUploadedFileListFor(self, adh): + file_folder = os.path.join(FILE_UPLOAD_BASE_FOLDER, cherrypy.session['uid']+"/") + if not os.path.isdir(file_folder): + return [] + return os.listdir(file_folder) + + + # + # methode pour enregistrer un fichier + # + def savePDF(self, aFile): + + _, tempFileName = tempfile.mkstemp() + f = open(tempFileName, 'w+b') + size=0 + while True: + data = aFile.file.read(1024 * 8) # Read blocks of 8KB at a time + if not data: + break + f.write(data) + size += len(data) + f.close() + if size == 0: + raise FileError("Fichier vide") + + file_folder = os.path.join(FILE_UPLOAD_BASE_FOLDER, cherrypy.session['uid']+"/") + if not os.path.isdir(file_folder): + os.makedirs(file_folder) + newFilePath = os.path.join(file_folder, aFile.filename) + shutil.move(tempFileName, newFilePath) + crans.cp.log("New file uploaded at : %s" % newFilePath, "IMPRESSION") + return newFilePath + + + + + diff --git a/intranet/modules/impression/static/WindowTitleLogo.png b/intranet/modules/impression/static/WindowTitleLogo.png new file mode 100644 index 00000000..d704d48e Binary files /dev/null and b/intranet/modules/impression/static/WindowTitleLogo.png differ diff --git a/intranet/modules/impression/static/dialog-printer.png b/intranet/modules/impression/static/dialog-printer.png new file mode 100644 index 00000000..e812c880 Binary files /dev/null and b/intranet/modules/impression/static/dialog-printer.png differ diff --git a/intranet/modules/impression/static/dialog-solde.png b/intranet/modules/impression/static/dialog-solde.png new file mode 100644 index 00000000..a6cd9dd8 Binary files /dev/null and b/intranet/modules/impression/static/dialog-solde.png differ diff --git a/intranet/modules/impression/static/dialog-warning.png b/intranet/modules/impression/static/dialog-warning.png new file mode 100644 index 00000000..632f99a3 Binary files /dev/null and b/intranet/modules/impression/static/dialog-warning.png differ diff --git a/intranet/modules/impression/static/icon.png b/intranet/modules/impression/static/icon.png new file mode 100644 index 00000000..efe62510 Binary files /dev/null and b/intranet/modules/impression/static/icon.png differ diff --git a/intranet/modules/impression/static/impression.css b/intranet/modules/impression/static/impression.css new file mode 100644 index 00000000..09f330ea --- /dev/null +++ b/intranet/modules/impression/static/impression.css @@ -0,0 +1,162 @@ +/* ****************************************** * + * + * ****************************************** */ +#globalDiv { + padding-left:200px; + position: relative; +} + +ul#actionMenu { + list-style-type:none; + position:absolute; + width:150px; + top:0; + left:0; + margin:20px; + padding:0; +} +ul#actionMenu li { + clear:both; +} +/* ****************************************** * + * + * ****************************************** */ +#fileName { + display: block; + width:150px; + text-align:center; + padding:50px 5px 5px 5px; + background: url(../images/pdf-icon.png) center top no-repeat; + margin:0 0 10px 0; + overflow:auto; +} + +#actionMenu li { + margin: .8em 0; +} + +#actionEtatImprimante { + padding:0.4em; + border: thin black solid; +} + +/* ******************************************* * + * + * ******************************************* */ +form#form_impression { + margin: 0px; + font-size: 100%; + min-width:600px; +} +form#form_impression #preview { + border:1px black solid; + width:150px; + height:150px; + padding:10px; + background-color:#C0C0C0; +} + +form#form_impression #rightColumn { + margin:10px 10px 10px 240px; +} + +form#form_impression #leftColumn { + float:left; + width:170px; + margin:10px; + padding:0; +} +div#prix_placeholder { + margin:6px 0; + width:170px; + min-height:16px; + padding:0; + color:gray; +} +div#prix_placeholder img { + margin-right:2px; + float:right; +} +form#form_impression fieldset fieldset { + margin:10px; +} +form#form_impression>fieldset { + position:relative; + padding:20px; +} + +.clear { + clear:both; +} + +form#form_impression .bouttons { + text-align:right; +} +form#form_impression label.labelInput { + display:block; + width:4em; + margin-right:4px; + float:left; + text-align:right; +} + +/* ****************************************** * + * + * ****************************************** */ +#popupFichiers { + background:#AE0F3E; + z-index:500; + float:left; + position:fixed; + min-width:450px; + top:110px; + left:20%; + right:20%; + padding:0; +} +#popupFichiers #insideDiv { + background:white; + margin:2px 5px; +} +#popupFichiers #insideDiv form { + margin:2px 5px; +} +#popupFichiers h1 { + font-size:1em; + margin:0; + text-align:center; + color:white; +} +#popupFichiers h1:before { + content:url("../images/WindowTitleLogo.png"); + margin-right:5px; +} + +#popupFichiers h2 { + font-size:1.1em; + border-bottom:thin black solid; +} +#popupFichiers select, +#popupFichiers input.file { + width:100%; +} + +.button { + float:right; +} + +/* ****************************************** * + * + * ****************************************** */ +div#printingPopupContent { + background: white url("../images/printer.png") left center no-repeat;; + padding:10px 10px 10px 115px; + min-height:100px; +} + +#printingPopupContent a, +#printingPopupContent span { + display:block; + font-weight: bold; + margin:5px 0; +} diff --git a/intranet/modules/impression/static/impression.js b/intranet/modules/impression/static/impression.js new file mode 100644 index 00000000..298ab375 --- /dev/null +++ b/intranet/modules/impression/static/impression.js @@ -0,0 +1,404 @@ +/* ************************************************************ + * Impression + ************************************************************ + * Impression.settings : panneau de configuration + * Impression.popup : popup + * Impression.AJAX : ajax + */ +Impression = {}; + +/***************************** + Impression.settings + *****************************/ + +Impression.settings = {}; + + // +//// images : images used for previewing +// +Impression.settings.images = [ + "portrait_couleurs_agraphediagonale.png", + "portrait_couleurs_pasdagraphes.png", + "portrait_couleurs_uneagraphe.png", + "portrait_couleurs_Deuxagraphes.png", + "portrait_couleurs_troisAgraphes.png", + "portrait_couleurs_stitching.png", + "portrait_nb_agraphediagonale.png", + "portrait_nb_pasdagraphes.png", + "portrait_nb_uneagraphe.png", + "portrait_nb_Deuxagraphes.png", + "portrait_nb_troisAgraphes.png", + "portrait_nb_stitching.png", + "portrait_transparent_couleurs.png", + "portrait_transparent_nb.png", + ]; + +Impression.settings.preloadImage = function(imageName) { + var image = new Image(); + image.src = "/static/images/"+imageName; +} + +Impression.settings.preloadAllImages = function() { + log("Preloading images..."); + map(this.preloadImage,this.images); +} + + // +//// init : parse every field and display preview +// +Impression.settings.init = function () { + log("Init settings..."); + this.theform = document.form_impression; + this.disableForm(false); +} + // +//// reset : reset form and then re-init settings +// +Impression.settings.reset = function () { + log("Reset form"); + this.theform.reset(); + this.init(); + Impression.settings.update(); +} + +Impression.settings.disableForm = function(bool) +{ + log("Set Disable Form : " + bool); + var fields = this.theform.elements; + for( var i=0; i< fields.length; i++) + { + this.setDisableField( fields[i], bool ); + } +} + + // +//// getValue : parse a field and store value in fielld.name +// +Impression.settings.getValue = function(field) +{ + if (field.value) + { + this[field.name] = field.value; + log( field.name + " is now " + this[field.name]); + } + else + { + logError("Can't get fieldValue"); + } +} + // +//// getCopies : parse copies field +// +Impression.settings.getCopies = function(field) { + if ( (!field.value) || (parseInt(field.value)!=field.value-0) || (parseInt(field.value) < 1) ) + { + this.copies = 1; + logError("Can't get copies"); + } + else + { + this.copies = parseInt(field.value); + } + log("copies is now " + this.copies); +} + + // +//// setValue : set field value +// +Impression.settings.setValue = function(afield, avalue) { + afield.value = avalue; + this.getValue(afield); +} + + // +//// setDisableField : set field disabled on/off +// +Impression.settings.setDisableField = function( afield, isdisabled ) { + afield.disabled = isdisabled ; +} + + // +//// disableField : set field disabled on +// +Impression.settings.disableField = function(afield) { + this.setDisableField(afield, true); +} + + // +//// fieldChanges : when a field is changed +// +Impression.settings.update = function () { + var orientation = "portrait"; + if (this.theform.type_impression_couleur.checked) + this.getValue(this.theform.type_impression_couleur); + else + this.getValue(this.theform.type_impression_nb); + + if (this.theform.disposition_recto.checked) + this.getValue(this.theform.disposition_recto); + else + this.getValue(this.theform.disposition_recto_verso); + this.getValue(this.theform.papier); + this.getCopies(this.theform.nb_copies); + this.getValue(this.theform.agrafes); + // Contraintes + if ( + ( this.papier != "A4" ) || + ( (this.disposition == "recto") && (this.nb_pages>50) ) || + ( (this.disposition == "rectoverso") && (this.nb_pages>100) ) ) + { + this.setValue(this.theform.agrafes, "pasdagraphes"); + this.disableField(this.theform.agrafes); + this.getValue(this.theform.agrafes); + } else { + this.setDisableField(this.theform.agrafes, false); + } + if (this.papier == "A4tr") + { + this.theform.disposition_recto.checked = true; + this.disableField(this.theform.disposition_recto); + this.disableField(this.theform.disposition_recto_verso); + this.getValue(this.theform.disposition_recto); + } + else + { + this.setDisableField(this.theform.disposition_recto, false); + this.setDisableField(this.theform.disposition_recto_verso, false); + } + + this.updatePreview(); + Impression.AJAX.recalcPrix(); + +} + + // +//// updatePreview : update preview with new value +// +Impression.settings.updatePreview = function() +{ + var image_name = ""; + if (this.papier == "A4tr") + image_name = "portrait_transparent_" + this.type_impression + ".png"; + else + image_name = "portrait_" + this.type_impression + '_' + this.agrafes + ".png"; + var image = createDOM("IMG",{'src':'/static/images/'+image_name}); + log("Updating preview (new image : " + image_name + ")"); + replaceChildNodes("preview",image) +} + + +/***************************** + Impression.popup + *****************************/ +Impression.popup = {}; + +Impression.popup.popupImpression = function(code) { + Popup.hide(); + Popup.create({}, "Impression en cours...", + DIV( + {"id":"printingPopupContent", "style":"background-image:url(/static/images/dialog-printer.png)"}, + SPAN("code: "+code), + A({"href":"https://wiki.crans.org/VieCrans/ImpressionReseau", "class":"aide", "target":"_blank"}, "Comment récupérer mon impression ? "), + A({"href":"index", "class":"aide", "style":"text-align:right;"}, "Nouvelle impression") + ) + + ); +Popup.display(); +} + +Impression.popup.popupError = function(erreur) { + Popup.hide(); + Popup.create({}, "Erreur", + DIV({"id":"printingPopupContent", "style":"background-image:url(/static/images/dialog-warning.png)"}, + SPAN(erreur), + A({"href":"mailto:nounous@crans.org", "class":"crans_help aide"}, "Envoyer un rapport aux nounous"), + Popup.closeLink({"class":"aide", "style":"text-align:right;"}, "Fermer"))); + Popup.display(); +} + +Impression.popup.popupSolde = function(code) { + Popup.hide(); + Popup.create({}, "Solde insuffisant", + DIV( + {"id":"printingPopupContent", "style":"background-image:url(/static/images/dialog-solde.png)"}, + SPAN("pas assez de sous"), + A({"href":"https://wiki.crans.org/CransPratique/SoldeImpression", "class":"aide", "target":"_blank"}, "Comment recharger mon compte ? "), + Popup.closeLink({"class":"aide", "style":"text-align:right;"}, "Fermer"))); + Popup.display(); +} + +Impression.popup.popupCodes = function(codeList) { + Popup.hide(); + Popup.create({}, "Codes de mes impressions", + DIV( + {"id":"printingPopupContent", "style":"background-image:url(/static/images/dialog-printer.png)"}, + SPAN("Mes codes"), + //UL({"size":"4", "style":"width:6em;; height:4em;padding:0;margin:0;list-style-type:none;overflow:auto;"}, map(function (code) {return LI({}, code);}, codeList)), + SELECT({"size":"4", "style":"width:100%;"}, map(function (code) {return LI({}, code);}, codeList)), + Popup.closeLink({"class":"aide", "style":"text-align:right;"}, "Fermer"))); + Popup.display(); +} + + + +/***************************** + Impression.mesCodes + *****************************/ +Impression.mesCodes = {}; +Impression.mesCodes.getCodes = function () +{ + Impression.AJAX.call('codeList', this.displayCodes ); +} + +Impression.mesCodes.displayCodes = function (result) { + if (result.codes) + Impression.popup.popupCodes(result.codes); + else if (result.erreur) + logError('erreur distante (codeLlist) : ' + result.erreur); + else + logError('erreur bizarre (codeLlist) : '); +} + +/***************************** + Impression.AJAX + *****************************/ +Impression.AJAX = {}; + + +Impression.AJAX.modifPrix = function( text, wheel ) +{ + if (wheel) + { + var image = createDOM("IMG",{'src':'/static/images/indicator.gif'}); + } + else + { + var image = new DIV({}); + } + var item = new DIV({'onclick':'Impression.AJAX.recalcPrix();'}, image, text); + replaceChildNodes("prix_placeholder",item); +} + +Impression.AJAX.modifNbPages = function( nbpages ) +{ + Impression.settings.nb_pages = nbpages; + replaceChildNodes("fileNbPages",nbpages); +} + +Impression.AJAX.call = function(page, callBack) { + logDebug("calling AJAX : " + page); + var e = loadJSONDoc(page); + e.addCallback(callBack); + e.addErrback(this.errorHandler); +} + +Impression.AJAX.errorHandler = function(d) { + logError("AJAX Error: " + d); + //Impression.AJAX.modifPrix("Erreur...", false); +} + + +Impression.AJAX.usefile = function(filename) { + var item = new DIV({}, "Calculs en cours..."); + this.modifPrix("Analyse du fichier...", true); + this.call('useFile?fileName=' + filename,this.analysefini ); +} + +Impression.AJAX.analysefini = function(AJAXResp) +{ + logDebug('AJAX terminated (usefile)'); + if (AJAXResp.erreur) { + Impression.AJAX.modifPrix(AJAXResp.erreur, false); + Impression.popup.popupError(AJAXResp.erreur); + Impression.settings.disableForm(true); + logWarning('Erreur distante : ' + AJAXResp.erreur); + } else { + Impression.AJAX.modifPrix("Analyse terminée", true); + Impression.settings.update(); + Impression.AJAX.modifNbPages(AJAXResp.nbPages); + } +} + +Impression.AJAX.recalcPrix = function() +{ + settings = Impression.settings; + var url = "changeSettings?copies=" + settings.copies + +"&couleurs="+ settings.type_impression + +"&papier="+ settings.papier + +"&recto_verso="+ settings.disposition + +"&agrafes="+ settings.agrafes; + this.modifPrix("Calcul en cours", true); + this.call(url, this.changePrix); +} + +Impression.AJAX.changePrix = function(AJAXResp) +{ + logDebug('AJAX terminated (recalcPrix)'); + if (AJAXResp.erreur) { + Impression.AJAX.modifPrix(AJAXResp.erreur, false); + Impression.popup.popupError(AJAXResp.erreur); + Impression.settings.disableForm(true); + logWarning('Erreur distante : ' + AJAXResp.erreur); + } else { + Impression.AJAX.modifPrix("Coût : " + AJAXResp.nouvPrix + "€", false); + } +} + +Impression.AJAX.lancerImpression = function(AJAXResp) +{ + var url = "lancerImpression"; + Impression.settings.disableForm(true); + this.call(url, this.finImpression); +} + +Impression.AJAX.finImpression = function(AJAXResp) +{ + logDebug('AJAX terminated (lancerImpression)'); + if (AJAXResp.erreur) { + Impression.popup.popupError(AJAXResp.erreur); + logWarning('Erreur distante : ' + AJAXResp.erreur); + } else if (AJAXResp.SoldeInsuffisant) { + Impression.popup.popupSolde(); + Impression.settings.disableForm(false); + Impression.settings.update(); + } else { + Impression.popup.popupImpression(AJAXResp.code); + } + Impression.AJAX.updateSolde(); + +} + +Impression.AJAX.getPrinterState = function() +{ + var url = "etatImprimante"; + Impression.AJAX.call(url, Impression.AJAX.displayPrinterState); +} + +Impression.AJAX.displayPrinterState = function(AJAXResp) +{ + logDebug('AJAX terminated (getPrinterState)'); + if (AJAXResp.erreur) { + logWarning('Erreur distante (etatImprimante) : ' + AJAXResp.erreur); + } else { + replaceChildNodes("etatImprimanteIci", AJAXResp.printer_state) + } +} + +Impression.AJAX.updateSolde = function() +{ + var url = "AJAXGetSolde"; + Impression.AJAX.call(url, Impression.AJAX.displaySolde); +} + +Impression.AJAX.displaySolde = function(AJAXResp) +{ + logDebug('AJAX terminated (updateSolde)'); + if (AJAXResp.erreur) { + logWarning('Erreur distante (etatImprimante) : ' + AJAXResp.erreur); + } else { + replaceChildNodes("soldePlaceHolder", AJAXResp.solde ) + } +} + +setInterval(Impression.AJAX.getPrinterState, 30000); +setInterval(Impression.AJAX.updateSolde, 60000); diff --git a/intranet/modules/impression/static/indicator.gif b/intranet/modules/impression/static/indicator.gif new file mode 100644 index 00000000..085ccaec Binary files /dev/null and b/intranet/modules/impression/static/indicator.gif differ diff --git a/intranet/modules/impression/static/paysage_b&w_non.png b/intranet/modules/impression/static/paysage_b&w_non.png new file mode 100644 index 00000000..441ac6d2 Binary files /dev/null and b/intranet/modules/impression/static/paysage_b&w_non.png differ diff --git a/intranet/modules/impression/static/paysage_couleur_non.png b/intranet/modules/impression/static/paysage_couleur_non.png new file mode 100644 index 00000000..d3b440d7 Binary files /dev/null and b/intranet/modules/impression/static/paysage_couleur_non.png differ diff --git a/intranet/modules/impression/static/pdf-icon.png b/intranet/modules/impression/static/pdf-icon.png new file mode 100644 index 00000000..552079fd Binary files /dev/null and b/intranet/modules/impression/static/pdf-icon.png differ diff --git a/intranet/modules/impression/static/portrait_couleur_diagonale.psd b/intranet/modules/impression/static/portrait_couleur_diagonale.psd new file mode 100644 index 00000000..55c6280c Binary files /dev/null and b/intranet/modules/impression/static/portrait_couleur_diagonale.psd differ diff --git a/intranet/modules/impression/static/portrait_couleurs_Deuxagraphes.png b/intranet/modules/impression/static/portrait_couleurs_Deuxagraphes.png new file mode 100644 index 00000000..f431ce39 Binary files /dev/null and b/intranet/modules/impression/static/portrait_couleurs_Deuxagraphes.png differ diff --git a/intranet/modules/impression/static/portrait_couleurs_agraphediagonale.png b/intranet/modules/impression/static/portrait_couleurs_agraphediagonale.png new file mode 100644 index 00000000..25d82c81 Binary files /dev/null and b/intranet/modules/impression/static/portrait_couleurs_agraphediagonale.png differ diff --git a/intranet/modules/impression/static/portrait_couleurs_pasdagraphes.png b/intranet/modules/impression/static/portrait_couleurs_pasdagraphes.png new file mode 100644 index 00000000..68f469cc Binary files /dev/null and b/intranet/modules/impression/static/portrait_couleurs_pasdagraphes.png differ diff --git a/intranet/modules/impression/static/portrait_couleurs_stitching.png b/intranet/modules/impression/static/portrait_couleurs_stitching.png new file mode 100644 index 00000000..62c2df16 Binary files /dev/null and b/intranet/modules/impression/static/portrait_couleurs_stitching.png differ diff --git a/intranet/modules/impression/static/portrait_couleurs_troisAgraphes.png b/intranet/modules/impression/static/portrait_couleurs_troisAgraphes.png new file mode 100644 index 00000000..bd7d91f0 Binary files /dev/null and b/intranet/modules/impression/static/portrait_couleurs_troisAgraphes.png differ diff --git a/intranet/modules/impression/static/portrait_couleurs_uneagraphe.png b/intranet/modules/impression/static/portrait_couleurs_uneagraphe.png new file mode 100644 index 00000000..cd7df8dc Binary files /dev/null and b/intranet/modules/impression/static/portrait_couleurs_uneagraphe.png differ diff --git a/intranet/modules/impression/static/portrait_nb_Deuxagraphes.png b/intranet/modules/impression/static/portrait_nb_Deuxagraphes.png new file mode 100644 index 00000000..77308966 Binary files /dev/null and b/intranet/modules/impression/static/portrait_nb_Deuxagraphes.png differ diff --git a/intranet/modules/impression/static/portrait_nb_agraphediagonale.png b/intranet/modules/impression/static/portrait_nb_agraphediagonale.png new file mode 100644 index 00000000..d76ce6fa Binary files /dev/null and b/intranet/modules/impression/static/portrait_nb_agraphediagonale.png differ diff --git a/intranet/modules/impression/static/portrait_nb_pasdagraphes.png b/intranet/modules/impression/static/portrait_nb_pasdagraphes.png new file mode 100644 index 00000000..d58be940 Binary files /dev/null and b/intranet/modules/impression/static/portrait_nb_pasdagraphes.png differ diff --git a/intranet/modules/impression/static/portrait_nb_stitching.png b/intranet/modules/impression/static/portrait_nb_stitching.png new file mode 100644 index 00000000..ed5ee87b Binary files /dev/null and b/intranet/modules/impression/static/portrait_nb_stitching.png differ diff --git a/intranet/modules/impression/static/portrait_nb_troisAgraphes.png b/intranet/modules/impression/static/portrait_nb_troisAgraphes.png new file mode 100644 index 00000000..cb3b5b35 Binary files /dev/null and b/intranet/modules/impression/static/portrait_nb_troisAgraphes.png differ diff --git a/intranet/modules/impression/static/portrait_nb_uneagraphe.png b/intranet/modules/impression/static/portrait_nb_uneagraphe.png new file mode 100644 index 00000000..84191d66 Binary files /dev/null and b/intranet/modules/impression/static/portrait_nb_uneagraphe.png differ diff --git a/intranet/modules/impression/static/portrait_transparent.png b/intranet/modules/impression/static/portrait_transparent.png new file mode 100644 index 00000000..b34b64cc Binary files /dev/null and b/intranet/modules/impression/static/portrait_transparent.png differ diff --git a/intranet/modules/impression/static/portrait_transparent_couleurs.png b/intranet/modules/impression/static/portrait_transparent_couleurs.png new file mode 100644 index 00000000..b55adf05 Binary files /dev/null and b/intranet/modules/impression/static/portrait_transparent_couleurs.png differ diff --git a/intranet/modules/impression/static/portrait_transparent_nb.png b/intranet/modules/impression/static/portrait_transparent_nb.png new file mode 100644 index 00000000..e891650f Binary files /dev/null and b/intranet/modules/impression/static/portrait_transparent_nb.png differ diff --git a/intranet/modules/impression/templates/impression-devis.tmpl b/intranet/modules/impression/templates/impression-devis.tmpl new file mode 100644 index 00000000..06c2eb10 --- /dev/null +++ b/intranet/modules/impression/templates/impression-devis.tmpl @@ -0,0 +1,67 @@ + + + + + Cr@ns Intranet + + + +
+

Devis pour impression

+ Fichier : $nomFichier +
+ + + + + + + + + #for anItem in $devis + + + + + + + + #end for + + + +
DescriptionPrix unitaireQuantitétotal
$anItem[0]$anItem[1] €$anItem[2] + #echo str($anItem[1] * $anItem[2]) + ' €' +
+ Total + $total €
+
+
+ + diff --git a/intranet/modules/impression/templates/impression.tmpl b/intranet/modules/impression/templates/impression.tmpl new file mode 100644 index 00000000..1f5b7e00 --- /dev/null +++ b/intranet/modules/impression/templates/impression.tmpl @@ -0,0 +1,170 @@ +#import crans.impression + +#if $getVar('errorMsg',False) + +#end if + +
+
+
Options d'impression +
+
+
+
+ +
+
Type d'impression + + +
+ +
Copies et papier + + + +
+ + +
+ + + +
+ +
Disposition + + +
+
+ +
+ + + +
+
+
+ + +
    + #if $getVar('fileName',False) +
  • $fileName
  • +
  • pages:
  • +
    + #end if +
  • Nouvelle impression
  • +
  • Mes codes
  • +
  • + Solde: + - € +
  • + +
  • + État imprimante:
    + - +
  • + +
+ +#if not $getVar('Erreur_imprimante',False) + #if not $getVar('fileName',False) +
+

Impression - Choix fichier

+
+ #if $getVar('openError',False) +
$openError
+ #end if +

Il semblerait que l'interface d'impression ne soit +pas compatible avec internet explorer. Nous espérons pouvoir +régler ce problème au plus vite. Nous vous conseillons en attendant +d'utiliser Firefox. Les +nounous

+
+

Mes fichiers

+
+ +
+
+ +
+

Envoyer un fichier

+
+ + +
+
+
+
+
+ + #end if +
+ + #if $getVar('fileName',False) + + #else + + #end if +#else + ## desactivation de l'interface si l'imprimant a un probleme + +#end if diff --git a/intranet/modules/infos/main.py b/intranet/modules/infos/main.py new file mode 100644 index 00000000..797773c1 --- /dev/null +++ b/intranet/modules/infos/main.py @@ -0,0 +1,16 @@ +from ClassesIntranet.ModuleBase import ModuleBase + + +class main(ModuleBase): + def category(self): + return u"Services" + def title(self): + return u"Informations utiles" + + def index(self): + return { + 'template':'info-diverses', + 'values':{}, + 'stylesheets':['infos.css'], + } + index.exposed = True diff --git a/intranet/modules/infos/static/icon.png b/intranet/modules/infos/static/icon.png new file mode 100644 index 00000000..df73c4d5 Binary files /dev/null and b/intranet/modules/infos/static/icon.png differ diff --git a/intranet/modules/infos/static/infos.css b/intranet/modules/infos/static/infos.css new file mode 100644 index 00000000..c2f0b785 --- /dev/null +++ b/intranet/modules/infos/static/infos.css @@ -0,0 +1,75 @@ +/************************************************************* + .. + .... ............ ........ + . ....... . .... .. + . ... .. .. .. .. ..... . .. + .. .. ....@@@. .. . ........ . + .. . .. ..@.@@..@@. .@@@@@@@ @@@@@@. .... + .@@@@. .@@@@. .@@@@..@@.@@..@@@..@@@..@@@@.... .... + @@@@... .@@@.. @@ @@ .@..@@..@@...@@@. .@@@@@. .. + .@@@.. . @@@. @@.@@..@@.@@..@@@ @@ .@@@@@@.. ..... + ...@@@.... @@@ .@@.......... ........ ..... .. + . ..@@@@.. . .@@@@. .. ....... . ............. + . .. .... .. .. . ... .... +. . .... ............. .. ... +.. .. ... ........ ... ... + ................................ + +============================================================== +mainInterface.css - Intranet Style + + Mise en page de l'accueil + + +Copyright (c) 2006 by www.crans.org + +**************************************************************/ + +div.framed_gray { + border:5px solid #e2e2e2; /* #acc0ff */ + background-color:#f2f2f2; + padding:10px; +} + +div.framed_gray fieldset { + border-width:2px; + border-style:solid none none none; + border-color:#a2a2a2; + padding:10px; + margin:10px 10px; + font-weight:bold; +} + +div.framed_gray fieldset legend { + color:#a2a2a2; +} + +div.framed_gray fieldset ul { + list-style-type:none; + margin:0; + padding:0; +} + +div.framed_gray fieldset ul li { + float:left; + height:70px; + width:100px; + margin:5px; + display:block; + text-align:center; +} + +div.framed_gray fieldset ul li span { + margin-bottom:0; + display:block; +} +div.framed_gray fieldset ul a { + color:black; + text-decoration:none; +} + +div.framed_gray fieldset ul li img { + margin:2px auto; + width:32px; + height:32px; +} diff --git a/intranet/modules/infos/templates/info-diverses.tmpl b/intranet/modules/infos/templates/info-diverses.tmpl new file mode 100644 index 00000000..82e8ee53 --- /dev/null +++ b/intranet/modules/infos/templates/info-diverses.tmpl @@ -0,0 +1,17 @@ +
+

Mots de passe Cr@ns

+

Pour les news

+
+
Utilisateur :
+
Vivelapa
+
Mot de passe :
+
ranoia!
+
+

Pour le wiki

+
+
Utilisateur :
+
ViveLe
+
Mot de passe :
+
Wiki!
+
+
diff --git a/intranet/modules/mesMachines/main.py b/intranet/modules/mesMachines/main.py new file mode 100755 index 00000000..a98f8b9b --- /dev/null +++ b/intranet/modules/mesMachines/main.py @@ -0,0 +1,249 @@ +#! /usr/bin/env python +# -*- coding: iso-8859-15 -*- +# ##################################################################################################### # +# Machines +# ##################################################################################################### # +# Description: +# Affiche la liste des machies, les infons sur une machine et permet des modifications +# Informations: +# +# Pages: +# index:liste des machines + le reste (AJAX) +# +# ##################################################################################################### # +import cherrypy, sys, os, datetime +from time import strftime, localtime, time +# libraries crans +sys.path.append('/usr/scripts/gestion/') +import crans.cp +if (cherrypy.config.configMap["global"]["server.environment"] == "development"): + from ldap_crans_test import * +# print("mesmachines : unsing test ldap : env=" + cherrypy.config.configMap["global"]["server.environment"]) +else: + from ldap_crans import * +# print("mesmachines : unsing prod ldap : env=" + cherrypy.config.configMap["global"]["server.environment"]) + +from ClassesIntranet.ModuleBase import ModuleBase + +class main(ModuleBase): + def title(self): + return "Mes Machines" + def icon(self): + return "machines_icon_fixe.png" + + def AJAXListeMachines(self): + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'])['adherent'][0] + machines = [] + for une_machine in adh.machines(): + machineInfos = {} + # nom, mac, mid, ip + machineInfos['nom'] = une_machine.nom() + machineInfos['nomCourt'] = une_machine.nom().split('.',1)[0] + machineInfos['mid'] = une_machine.id() + # type + if une_machine.objectClass == 'machineFixe': + machineInfos['type'] = 'fixe' + #machineInfos['type'] = 'Machine fixe' + else: + machineInfos['type'] = 'wifi' + #machineInfos['type'] = 'Machine wifi' + # clef ipsec + machines.append(machineInfos) + + return {"machines":machines} + AJAXListeMachines.exposed = True + + def AJAXMachineInfo(self, mid): + try: + machine = cherrypy.session['LDAP'].search('mid=' + mid)['machine'][0] + if machine.proprietaire().mail() != cherrypy.session['uid']: + raise Exception + # zamok -> pour tester l'affichage des ports, des alias + #machine = cherrypy.session['LDAP'].search('mid=896')['machine'][0] + machineInfos = {} + # nom, mac, mid, ip + machineInfos['nom'] = machine.nom() + machineInfos['nomCourt'] = machine.nom().split('.',1)[0] + machineInfos['mac'] = machine.mac() + machineInfos['mid'] = machine.id() + machineInfos['ip'] = machine.ip() + # type + if machine.objectClass == 'machineFixe': + machineInfos['type'] = 'fixe' + else: + machineInfos['type'] = 'wifi' + # clef ipsec + try: + machineInfos['ipsec'] = machine.ipsec() + except: + machineInfos['ipsec'] = '' + # alias + machineInfos['alias'] = machine.alias() + # blacklists + machineInfos['blacklist'] = [] + for blacklist_type in machine.blacklist_all()[0].keys(): + for (begin, end) in machine.blacklist_all()[0][blacklist_type]: + blacklist = {} + blacklist['begin'] = strftime('%d/%m/%Y %H:%M', localtime(int(begin))) + blacklist['end'] = strftime('%d/%m/%Y %H:%M', localtime(int(end))) + blacklist['type'] = blacklist_type + blacklist['actif'] = 1 + machineInfos['blacklist'].append(blacklist) + for blacklist_type in machine.blacklist_all()[1].keys(): + for (begin, end) in machine.blacklist_all()[1][blacklist_type]: + blacklist = {} + blacklist['begin'] = strftime('%d/%m/%Y %H:%M', localtime(int(begin))) + blacklist['end'] = strftime('%d/%m/%Y %H:%M', localtime(int(end))) + blacklist['type'] = blacklist_type + blacklist['actif'] = 0 + machineInfos['blacklist'].append(blacklist) + # ports + machineInfos['ports'] = [] + if machine.portTCPin() != []: + machineInfos['ports'].append( + { + 'titre':'Ports TCP ouvert ext->machine', + 'ports':machine.portTCPin() + } + ) + if machine.portTCPout() != []: + machineInfos['ports'].append( + { + 'titre':'Ports TCP ouvert machine->ext', + 'ports':machine.portTCPout() + } + ) + if machine.portUDPin() != []: + machineInfos['ports'].append( + { + 'titre':'Ports UDP ouvert ext->machine', + 'ports':machine.portUDPin() + } + ) + if machine.portUDPout() != []: + machineInfos['ports'].append( + { + 'titre':'Ports TCP ouvert machine->ext', + 'ports':machine.portUDPout() + } + ) + + return machineInfos + except Exception, e: + return {"erreur":str(e)} + AJAXMachineInfo.exposed = True + + ########################## + # affichage + ########################## + # + # methode qui affiche la template + # + def index(self): + return { + 'template' :'machines', + 'values' :{}, + 'stylesheets' :['machines.css'], + 'scripts':['machines.js'], + } + index.exposed = True + + + ########################################################################### + # methodes pour changer + # des valeurs + ########################################################################### + # + + ########################## + # machine:nom + ########################## + def AJAXChangerNom(self, mid, nouveauNom): + try: + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'])['adherent'][0] + mach = cherrypy.session['LDAP'].search('mid=' + mid, 'w')['machine'][0] + # tester si c'est bien la machine de l'adherent + if mach.proprietaire().compte() != cherrypy.session['uid']: + del adh, mach + raise Exception(u"L'uid de l'adherent ne correspond mas au proprietaire de la machine.") + anciennom = mach.nom() + nouveauNom = mach.nom(nouveauNom) + mach.save() + del mach + except ValueError, e: + raise e + #return {'error':str(e)} + crans.cp.log("Changer nom machine : %s->%s" % (anciennom, nouveauNom), "MESMACHINES") + return {'message':u"Modification réussie", 'mid':mid} + AJAXChangerNom.exposed = True + + ########################## + # machine:mac + ########################## + def AJAXchangerMAC(self, mid, nouvelleMAC): + try: + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'])['adherent'][0] + mach = cherrypy.session['LDAP'].search('mid=' + mid, 'w')['machine'][0] + # tester si c'est bien la machine de l'adherent + if mach.proprietaire().compte() != cherrypy.session['uid']: + del adh, mach + raise Exception(u"L'uid de l'adherent ne correspond mas au proprietaire de la machine.") + anciennemac = mach.mac() + nommachine = mach.nom() + mach.mac(nouvelleMAC) + mach.save() + del mach + except ValueError, e: + return {'error':e.args[0]} + crans.cp.log("Change mac machine %s : %s->%s" % (nommachine, anciennemac, nouvelleMAC), "MESMACHINES") + return {'message':u"Modification réussie", 'mid':mid} + AJAXchangerMAC.exposed = True + + + + ########################## + # machine:suppression + ########################## + def AJAXSupprimerMachine(self, mid): + try: + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'])['adherent'][0] + mach = cherrypy.session['LDAP'].search('mid=' + mid, 'w')['machine'][0] + # tester si c'est bien la machine de l'adherent + if mach.proprietaire().compte() != cherrypy.session['uid']: + del adh, mach + raise Exception(u"L'uid de l'adherent ne correspond mas au proprietaire de la machine.") + mach.delete() + except ValueError, e: + return {'error':e.args[0]} + crans.cp.log("Machine supprimee", "MACHINES") + return {'message':u"Machine supprimée"} + AJAXSupprimerMachine.exposed = True + + ########################## + # machine:creation + ########################## + def AJAXCreerMachine(self, nomNouvelleMachine, MACNouvelleMachine, typeNouvelleMachine): + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'])['adherent'][0] + if typeNouvelleMachine=='fixe' and adh.droits() == [] and adh.machines_fixes() != []: + return {'error':'Vous avez deja une machine fixe. Vous ne pouvez ajouter que des machines WiFi.'} + try: + if typeNouvelleMachine=='wifi': + m = MachineWifi(adh) + elif typeNouvelleMachine=='fixe': + m = MachineFixe(adh) + else: + raise Exception, "type de machine inconnu : %s " % typeNouvelleMachine + m.nom(nomNouvelleMachine) + m.mac(MACNouvelleMachine) + m.ip("") + message = m.save() + del m + except ValueError, e: + del m + return {'error':e.args[0].replace("\n","\\n")} + crans.cp.log("Nouvelle machine %s" % nomNouvelleMachine, "MACHINES") + return {'message':u"Machine enregistrée avec succès"} + AJAXCreerMachine.exposed = True + + + diff --git a/intranet/modules/mesMachines/static/machines.css b/intranet/modules/mesMachines/static/machines.css new file mode 100644 index 00000000..b25aba27 --- /dev/null +++ b/intranet/modules/mesMachines/static/machines.css @@ -0,0 +1,160 @@ +/************************************************************* + .. + .... ............ ........ + . ....... . .... .. + . ... .. .. .. .. ..... . .. + .. .. ....@@@. .. . ........ . + .. . .. ..@.@@..@@. .@@@@@@@ @@@@@@. .... + .@@@@. .@@@@. .@@@@..@@.@@..@@@..@@@..@@@@.... .... + @@@@... .@@@.. @@ @@ .@..@@..@@...@@@. .@@@@@. .. + .@@@.. . @@@. @@.@@..@@.@@..@@@ @@ .@@@@@@.. ..... + ...@@@.... @@@ .@@.......... ........ ..... .. + . ..@@@@.. . .@@@@. .. ....... . ............. + . .. .... .. .. . ... .... +. . .... ............. .. ... +.. .. ... ........ ... ... + ................................ + +============================================================== +macines.css - Intranet Style + +Copyright (c) 2006 by www.crans.org + +**************************************************************/ +#globalDiv { + padding-left : 20%; + margin:0; + position:relative; +} +h2 { + margin: 0 5px .5em 5px;padding:5px; +} + +div.alias { + color:gray; + margin:0; + padding:0 0 0 60px; + display:block; + font-weight:normal; + font-size:0.6em; + +} + +table.blacklist_table, +table.ports_table { + border-top: thin black solid; + border-left: thin black solid; +} + +table.blacklist_table td, +table.blacklist_table th, +table.ports_table td, +table.ports_table th { + border-right: thin black solid; + border-bottom: thin black solid; + padding: 3px; +} + +.actif { + color:red; +} +.inactif { +} + + +#gestion_machines_main_frame { + padding:5px; +} + +dl.basicInfos dt { + float:left; + font-weight:bold; + clear:left; +} + +dl.basicInfos dd { + float:left; + margin:0 1em; +} + +ul#listeMachines { + list-style-type:none; + margin:0; + padding:0; +} + +ul#listeMachines li { + float:left; + height:70px; + width:100px; + margin:5px; + display:block; + text-align:center; +} + +ul#listeMachines li span { + margin-bottom:0; + display:block; +} + +ul#listeMachines li a { +display:block; + color:black; + text-decoration:none; +} + +ul#listeMachines li a:hover { + background:#bbbbff; +} + +ul#listeMachines li a:active { + background:#8888ff; +} + +ul#listeMachines li img { + margin:2px auto; + width:32px; + height:32px; +} + +#menu_actions { + background:#eeeeff; + padding:.3em; + width:18%; + float:left; + position:absolute; + top:1em; + left:0; + border: thin black solid; +} + +#menu_actions ul { + list-style-type:none; + padding:0; + margin:.5em; +} +#menu_actions ul li a { + text-decoration:none; +} +#menu_actions ul li a:hover { + text-decoration:underline; +} + +#menu_actions h1 { + font-size:1em; + margin:0; + text-align:center; + border-bottom: thin black solid; +} + +// on change la couleur des messages +.message { + background-color:#000080; + color:white; +} + +label { + width:175px; + display:block; + float:left; +} diff --git a/intranet/modules/mesMachines/static/machines.js b/intranet/modules/mesMachines/static/machines.js new file mode 100644 index 00000000..023002bb --- /dev/null +++ b/intranet/modules/mesMachines/static/machines.js @@ -0,0 +1,348 @@ +/* ************************************************************ + * Machines + ************************************************************ + * Machines.init : initialisation de la page + * Machines.listeMachines : liste des machines + * Machines.infoPane : information sur une machine + * Machines.actions : modifications, ajout... + * Machines.AJAX : ajax + */ +Machines = {}; + +/***************************** + Machines.init + *****************************/ +Machines.init = function() +{ + // afficher le tableau codelist + appendChildNodes("globalDiv", Machines.createFrames()); + appendChildNodes("globalDiv", Machines.actions.makeMenu()); + // recuperer la liste des codes + this.listeMachines.load(); +} + +Machines.createFrames = function() +{ + var main = DIV({"id":"gestion_machines_main_frame"}); + var inside = DIV({"id":"__insideDivId", "style":"background:white;margin:5px;padding:5px;"},main); + var outside = DIV({"id":"__outsideDivId","style":"background:#000080;z-index:500;padding:0;"}, inside ); + roundElement(outside); + roundElement(inside); + log("Creation du cadre"); + return outside +} + +/***************************** + Machines.listeMachines + *****************************/ +Machines.listeMachines = {}; + + +Machines.listeMachines.load = function() +{ + Machines.AJAX.call("AJAXListeMachines", Machines.listeMachines.display); + log("Chargement liste..."); + Machines.currentMachine = ''; +} + +Machines.listeMachines.display = function(result) +{ + Crans.loading.display(false); + log("display liste"); + + replaceChildNodes( "gestion_machines_main_frame", + H2({}, "Mes machines"), + UL({"id":"listeMachines"}), + DIV( {"style":"clear:both;"} ) + ); + if (result.machines) { + replaceChildNodes('listeMachines',map(Machines.listeMachines.newMachineNodeFromDict ,result.machines)); + Machines.actions.updateMenu(Machines.actions.actionForMachineList); + Machines.currentMid = ''; + } + else if (result.erreur) + logError("Erreur distante : " + result.erreur); + else + logError("Probleme bizarre..."); +} + +Machines.listeMachines.newMachineNodeFromDict = function (aDict, style) +{ + var nom = aDict.nomCourt; + var mid = aDict.mid; + var image = "machines_icon_" + aDict.type + ".png"; + //log("create an item : " + nom); + if (style) { + var anIcon = LI({'id':'machine_' + mid,"style":style}); + } else + var anIcon = LI( {'id':'machine_' + mid} ); + appendChildNodes(anIcon, A({"href":"#", "onclick":"Machines.infoPane.loadInfo('"+mid+"');return false;"}, IMG({"src":"/static/images/" + image}), SPAN({},nom) ) ); + return anIcon; +} + +/***************************** + Machines.infoPane + *****************************/ +Machines.infoPane = {}; + +Machines.infoPane.loadInfo = function(mid) +{ + if (!mid) + if (!Machines.currentMachine) { + logError("Machines.infoPane.loadInfo : pas de mid, pas de machine courrante..."); + return + } else + mid = Machines.currentMachine.mid; + + log("load info : " + mid); + Machines.AJAX.call("AJAXMachineInfo?mid=" + mid, Machines.infoPane.display); + try { + pulsate('machine_' + mid); + } catch (error) {} +} + +Machines.infoPane.display = function(result) +{ + Crans.loading.display(false); + if (result.nom) { + log("displaying info : " + result.mid); + // building pane + var machinePane = DIV({"id":"machine_pane"}); + + // lien pour retourner a la liste des machines + var back_link = A({"href":"#", "onclick":"Machines.listeMachines.load(); return false;"},"Retour"); + appendChildNodes( machinePane, back_link ); + + // titre (nom de machine + alias) + var title = H2({}, IMG({"src":"/static/images/machines_icon_" + result.type + ".png"}), " ", result.nom); + var alias = DIV({"class":"alias"}, + map(function(a_name) { return SPAN({}, a_name + " ")}, result.alias)); + appendChildNodes( title, alias ); + appendChildNodes( machinePane, title ); + + // infos de base (type, mac, ip, ipsec...) + var basicInfos = createDOM("DL", {"class":"basicInfos"}); + appendChildNodes(basicInfos, createDOM("DT", "type:" ), createDOM("DD",{},"Machine " + result.type ) ); + appendChildNodes(basicInfos, createDOM("DT", "mac: " ), createDOM("DD",{},result.mac ) ); + appendChildNodes(basicInfos, createDOM("DT", "ip: " ), createDOM("DD",{},result.ip ) ); + if (result.ipsec) + appendChildNodes(basicInfos, createDOM("DT", "Clef ipSec:" ), createDOM("DD",{},result.ipsec ) ); + appendChildNodes( machinePane, basicInfos ); + appendChildNodes( machinePane, DIV( {"style":"clear:both;"} ) ); + + + // blacklist + if (result.blacklist) + if (result.blacklist.length) { + var subtitle = H3({}, "Blacklist"); + appendChildNodes( machinePane, subtitle ); + var blacklist_table = TABLE({"class":"blacklist_table", "cellspacing":"0"}, + THEAD({}, + TH({}, "Cause"), + TH({}, "Debut"), + TH({}, "Fin") + ) + ); + map(function(a_blacklist_dict) { + var style = "inactif"; + if (a_blacklist_dict.actif) + style = "actif"; + var line = TR({"class":style}, + TD({}, a_blacklist_dict.type), + TD({}, a_blacklist_dict.begin), + TD({}, a_blacklist_dict.end) + ); + appendChildNodes(blacklist_table, line); + }, result.blacklist ); + appendChildNodes( machinePane, blacklist_table ); + } + // liste des ports ouverts + if (result.ports) + if (result.ports.length) { + var subtitle = H3({}, "Ports ouverts"); + appendChildNodes( machinePane, subtitle ); + var port_table = TABLE({"class":"ports_table", "cellspacing":"0"}); + map(function(a_port_dict) { + var line = TR({}, + TH({}, a_port_dict.titre), + map(function(a_port) {return TD({}, a_port);}, a_port_dict.ports) + ); + appendChildNodes(port_table, line); + }, result.ports ); + appendChildNodes( machinePane, port_table ); + } + + // attaching pane to document + replaceChildNodes( "gestion_machines_main_frame", machinePane); + // updationg actions + Machines.currentMachine = result; + Machines.actions.updateMenu(Machines.actions.actionsForInfoPane); + } else if (result.erreur) { + logError("Erreur distante : " + result.erreur); + } else + logError("Probleme bizarr..."); + +} + +/***************************** + Machines.actions + *****************************/ +Machines.actions = {} + +Machines.actions.disponibles = +{ + 'Ajouter machine fixe':'Machines.actions.formulaire.nouvelleMachine(\'fixe\');', + 'Ajouter machine wifi':'Machines.actions.formulaire.nouvelleMachine(\'wifi\');', + 'Modifier Mac':'Machines.actions.formulaire.modifierMac(Machines.currentMid);', + 'Renommer':'Machines.actions.formulaire.renommer(Machines.currentMid);', + 'Supprimer':'Machines.actions.formulaire.supprimer(Machines.currentMid);', + 'Demander l\'ouverture d\'un port':'Machines.actions.formulaire.ouverturePort(Machines.currentMid);' +} +Machines.actions.actionForMachineList = ['Ajouter machine fixe', 'Ajouter machine wifi']; +Machines.actions.actionsForInfoPane = ['Modifier Mac', 'Renommer', 'Supprimer']; + +Machines.actions.makeMenu = function(actionListe) +{ + log("building action menu"); + var liste = UL({"id":"liste_actions"}); + //this.updateMenu(actionListe, liste) + return DIV( {"id":"menu_actions"}, + H1( {}, "ACTIONS"), + liste + ); +} + +Machines.actions.updateMenu = function(actionListe, liste_actionsNode) +{ + if (!liste_actionsNode) + liste_actionsNode = "liste_actions"; + replaceChildNodes(liste_actionsNode); + map( + function(actionName) { + appendChildNodes(liste_actionsNode, LI({}, Machines.actions.makeActionLink(actionName))); + } + , actionListe); +} + +Machines.actions.makeActionLink = function(actionName) +{ + if (this.disponibles[actionName]) + { + return A({"href":"#", "onclick":this.disponibles[actionName] + "return false;"}, actionName); + } else + logError("action inconnue " + actionName); + return A({}, "???"); +} + + + +Machines.actions.callback = function(result) { + Crans.loading.display(false); + if (result.message){ + log(result.message); + Crans.messages.setMessage(result.message); + if (result.mid) + Machines.infoPane.loadInfo(result.mid); + else + Machines.listeMachines.load(); + } + if (result.error){ + alert(result.error); + logError("AJAX error"); + } +} + +// actions : affichage des formulaires +Machines.actions.formulaire = {} +Machines.actions.formulaire.modifierMac = function() +{ + if (!Machines.currentMachine) + logError("pas de machine courrante"); + else { + var c = ''; + while ( c == '') + c = prompt("Adresse MAC de la machine :",Machines.currentMachine.mac); + if (c == null) + return false; + // AJAX stuff + Machines.AJAX.call('AJAXchangerMAC?nouvelleMAC=' + c + '&mid=' + Machines.currentMachine.mid, + Machines.actions.callback); + } + return false; +} +Machines.actions.formulaire.renommer = function() { + if (!Machines.currentMachine) + logError("pas de machine courrante"); + else { + var c = ''; + while ( c == '') + c = prompt("Nom de la machine :",Machines.currentMachine.nomCourt); + if (c == null) + return false; + // AJAX stuff + Machines.AJAX.call('AJAXChangerNom?nouveauNom=' + c + '&mid=' + Machines.currentMachine.mid, + Machines.actions.callback); + } + return false; +} +Machines.actions.formulaire.supprimer = function() { + if (!Machines.currentMachine) + logError("pas de machine courrante"); + else { + if (confirm("Supprimer la machine " + Machines.currentMachine.nomCourt +" ?")) { + // AJAX stuff + Machines.AJAX.call('AJAXSupprimerMachine?mid=' + Machines.currentMachine.mid, + Machines.actions.callback); + } + } + return false; +} + +Machines.actions.formulaire.nouvelleMachine = function(type) { + replaceChildNodes( "gestion_machines_main_frame", + A({"href":"#", "onclick":"Machines.listeMachines.load(); return false;"},"Retour"), + H2({}, "Nouvelle machine"), + FORM({"style":"clear:both;", 'onsubmit':'Machines.actions.creerMachine(this.typeField.value, this.nom.value, this.mac.value);return false;'}, + createDOM('label', {'for':'add_machine_nom'}, "Nom de la machine : "), + INPUT({"name":"nom"}), + BR(), + createDOM('label', {'for':'add_machine_mac'}, "Adresse MAC : "), + INPUT({"name":"mac"}), + BR(), + createDOM('label', {'for':'add_machine_type'}, "Type de machine : "), + SPAN({'id':'add_machine_type'}, type), + INPUT({"name":"typeField", 'type':'hidden', 'value':type}), + BR(), + BUTTON({"class":"liens", 'type':'submit'}, 'Ajouter') + ) + ); + return false; +} + +Machines.actions.creerMachine = function(type, nom, mac) { + Machines.AJAX.call('AJAXCreerMachine?nomNouvelleMachine=' + nom + + '&MACNouvelleMachine=' + mac + + '&typeNouvelleMachine=' + type, + Machines.actions.callback); +} + +/***************************** + Machines.AJAX + *****************************/ +Machines.AJAX = {} + +Machines.AJAX.call = function(page, callBack) { + logDebug("calling AJAX : " + page); + var e = loadJSONDoc(page); + e.addCallback(callBack); + e.addErrback(this.errorHandler); + Crans.loading.display(true); + +} + +Machines.AJAX.errorHandler = function(d) { + //Machines.AJAX..modifPrix("Erreur", false); + logError("AJAX Error: " + d); + Crans.loading.display(false); +} + diff --git a/intranet/modules/mesMachines/static/machines_icon_fixe.png b/intranet/modules/mesMachines/static/machines_icon_fixe.png new file mode 100644 index 00000000..11ffbb71 Binary files /dev/null and b/intranet/modules/mesMachines/static/machines_icon_fixe.png differ diff --git a/intranet/modules/mesMachines/static/machines_icon_wifi.png b/intranet/modules/mesMachines/static/machines_icon_wifi.png new file mode 100644 index 00000000..caca9a1d Binary files /dev/null and b/intranet/modules/mesMachines/static/machines_icon_wifi.png differ diff --git a/intranet/modules/monCompte/main.py b/intranet/modules/monCompte/main.py new file mode 100755 index 00000000..6e487a82 --- /dev/null +++ b/intranet/modules/monCompte/main.py @@ -0,0 +1,359 @@ +#! /usr/bin/env python +# -*- coding: iso-8859-15 -*- +# ##################################################################################################### # +# MonCompte +# ##################################################################################################### # +# Description: +# +# Informations: +# +# Pages: +# +# +# ##################################################################################################### # + +import cherrypy, sys, os, datetime +# libraries crans +import crans.cp as _crans_cp +sys.path.append('/usr/scripts/gestion/') +from config_mail import MailConfig + +if (cherrypy.config.configMap["global"]["server.environment"] == "development"): + from ldap_crans_test import * +# print("monCompte : unsing test ldap : env=" + cherrypy.config.configMap["global"]["server.environment"]) +else: + from ldap_crans import * +# print("monCompte : unsing prod ldap : env=" + cherrypy.config.configMap["global"]["server.environment"]) + +from ClassesIntranet.ModuleBase import ModuleBase + +class main(ModuleBase): + def title(self): + return "Mon Compte" + + def getCurrentAdministrativeYear(self): + ''' + premiere partie de l''annee scolaire en cours + ex : le 5 juin 2006 retourne 2005 + ''' + now = datetime.datetime.now() + currentYear = int(now.strftime("%Y")) + currentMonth = int(now.strftime("%m")) + if currentMonth > 8: + administrativeYear = currentYear + else: + administrativeYear = currentYear - 1 + return administrativeYear + + ########################## + # affichage + ########################## + # + # methode qui affiche la template avec toutes les infos de + # l'adherent + les formulaires + # + def index(self, message = '', error = '', currentTab = 'mainTab'): + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'])['adherent'][0] + t = {} + t['message'] = message + t['error'] = error + + + ############## info adherent ############## + adherent = {} + # nom, prenom, chambre, tel, solde, droits, mail + adherent['prenom'] = adh.prenom() + adherent['nom'] = adh.nom() + adherent['chambre'] = adh.chbre() + if adherent['chambre'] == "EXT": + adr = adh.adresse() + adherent['adresse'] = {} + adherent['adresse']['ligne1'] = adr[0] + adherent['adresse']['ligne2'] = adr[1] + adherent['adresse']['cp'] = adr[2] + adherent['adresse']['ville'] = adr[3] + adherent['telephone'] = adh.tel + adherent['solde'] = adh.solde + adherent['droits'] = u", ".join(adh.droits()) + adherent['mail'] = adh.email() + # cotisation + administrativeYear = self.getCurrentAdministrativeYear() + if administrativeYear in adh.paiement(): + adherent['cotisationOK'] = 'OK' + else: + adherent['cotisationOK'] = None + # carte etudiant + if administrativeYear in adh.carteEtudiant(): + adherent['carteOK'] = 'OK' + else: + adherent['carteOK'] = None + # annee scolaire (ex 2001-2002) + adherent['anneeScolaire'] = str(administrativeYear) + '-' + str(administrativeYear + 1) + t['adherent'] = adherent + + ############## info mail ############## + mailInfos = {} + try: + mailConfig = MailConfig(cherrypy.session['uid']) + mailInfos['forwarding_address'] = mailConfig['forward'] + mailInfos['spam'] = {} + mailInfos['spam']['no'] = mailConfig['spam'] == 'accepte' + mailInfos['spam']['mark'] = mailConfig['spam'] == 'marque' + mailInfos['spam']['drop'] = mailConfig['spam'] == 'supprime' + except Exception, e: + t['mailError'] = u"Erreur:fichiers de configuration mail personnels" + + mailInfos['alias'] = adh.alias() + mailInfos['contourneGreylist'] = adh.contourneGreylist() + mailInfos['rewriteMailHeaders'] = adh.rewriteMailHeaders() + t['mailInfos'] = mailInfos + + + + return { + 'template' :'monCompte', + 'values' :t, + 'stylesheets' :['monCompte.css'], + 'scripts':['crans_domtab.js','moncompte.js','passwordGenerator.js'], + } + index.exposed = True + + + + ########################## + # paypal + ########################## + # + # methode qui affiche successivement les + # templates du popup pour recharger son compte impression + # via paypal + # + def rechargerCompteImpression(self, etape = '1', combien = None): + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'])['adherent'][0] + if (etape == "1"): # Introduction + return { + 'template' :'MonCompteRechargePaypal1', + 'standalone' :True, + 'values' :{}, + } + elif (etape == "2"): # choix montant + return { + 'template' :'MonCompteRechargePaypal2', + 'standalone' :True, + 'values' :{}, + } + elif (etape == "3"): # confirmer facture + # creer objet facture + f = Facture(adh) + # /!\ verifier que combien est un nombre + # et qu'il n'y a pas plus de 2 chiffres après le point... + # (ce serait bien aussi si on pouvait mettre une virgue a la place du point) + try: + # remplacage des virgules + combien = combien.replace(u',', u'.') + # convertissage + combien = float(combien) + # arrondissage-tronquage : + combien = float(int(combien*100)/100.0) + # nombre positif + if combien < 0: + raise ValueError + except Exception: + return { + 'template' :'MonCompteRechargePaypal2', + 'standalone' :True, + 'values' :{'error':"Le montant doit être un nombre positif !", 'combien':combien}, + } + f.ajoute({'nombre': 1, 'code': 'SOLDE', 'designation': 'Credit du compte impression (intranet)', 'pu': combien}) + cherrypy.session['freshFacture'] = f + pageData = {} + pageData['details'] = [ + { + 'intitule':art['designation'], + 'quantite':art['nombre'], + 'prixUnitaire':art['pu'], + 'prixTotal':art['pu']*art['nombre'], + } for art in f.articles()] + pageData['total'] = f.total() + return { + 'template' :'MonCompteRechargePaypal3', + 'standalone' :True, + 'values' :pageData, + } + elif (etape == "4"):# payer maintenant ? + # sauver objet facture + f = cherrypy.session['freshFacture'] + f.save() + return { + 'template' :'MonCompteRechargePaypal4', + 'standalone' :True, + 'values' :{'lienPaypal' : f.urlPaypal(useSandbox = cherrypy.config.get("paypal.useSandbox", False), + businessMail = cherrypy.config.get("paypal.businessAdress", "paypal@crans.org"), + return_page = "https://intranet.crans.org/monCompte/paypalReturn", + cancel_return_page = "https://intranet.crans.org/monCompte/paypalCancel", + )}, + } + rechargerCompteImpression.exposed = True + + def paypalReturn(self, **kw): + _crans_cp.log("retour de paypal avec les infos : %s" % " ".join( [ "[%s: %s]" % (str(a), str(kw[a])) for a in kw] ) ) + return { + 'template' :'MonComptePaypalReturn', + 'standalone' :True, + 'values' :{}, + } + paypalReturn.exposed = True + + def paypalCancel(self, **kw): + _crans_cp.log("annulation de paypal avec les infos : %s" % " ".join( [ "[%s: %s]" % (str(a), str(kw[a])) for a in kw] ) ) + return { + 'template' :'MonComptePaypalCancel', + 'standalone' :True, + 'values' :{}, + } + paypalCancel.exposed = True + + + + ########################################################################### + # methodes pour changer + # des valeurs + ########################################################################### + # + # En fait, les methodes recoivent les valeurs d'un formulaire + # (ou equivalent de javascript), font la modification puis + # appellent la methode principale d'affichage + # en lui passant eventuellement un message a afficher + # (pour indiquer la reussite ou non de l'operation) + # + + ########################## + # Adherent:nom + ########################## + def changeNomAdherent(self, nouveauNom): + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'], 'w')['adherent'][0] + try: + ancienNom = adh.nom() + adh.nom(nouveauNom) + adh.save() + except ValueError, e: + return self.index(error=e.args[0]) + del adh + _crans_cp.log("Change nom : %s -> %s" % (ancienNom, nouveauNom), "MONCOMPTE") + return self.index(message=u'Modification réussie') + changeNomAdherent.exposed = True + + ########################## + # Adherent:password + ########################## + def changePasswordAdherent(self, ancienPassword, nouveauPassword1, nouveauPassword2): + if ancienPassword=='': + msg = 'Erreur, mot de passe incorrect' + return self.index(error=msg) + if nouveauPassword1=='': + msg = 'Erreur, le nouveau mot de passe ne doit pas ètre vide.' + return self.index(error=msg) + if nouveauPassword1!=nouveauPassword2: + msg = 'Erreur, la confirmation ne correspond pas au nouveau mot de passe.' + return self.index(error=msg) + + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'],'w')['adherent'][0] + if adh.checkPassword(ancienPassword): + adh.changePasswd(nouveauPassword1) + adh.save() + msg = u'Changement effectué' + else: + msg = 'Erreur, mot de passe incorrect' + return self.index(error=msg) + del adh + _crans_cp.log("Change password", "MONCOMPTE") + return self.index(message=msg) + changePasswordAdherent.exposed = True + + + ########################## + # Adherent:prenom + ########################## + def changePrenomAdherent(self, nouveauPrenom): + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'], 'w')['adherent'][0] + try: + ancienPrenom = adh.prenom() + adh.prenom(nouveauPrenom) + adh.save() + except ValueError, e: + return self.index(error=e.args[0]) + del adh + _crans_cp.log("Change prenom : %s -> %s" % (ancienPrenom, nouveauPrenom), "MONCOMPTE") + return self.index(message=u'Modification réussie') + changePrenomAdherent.exposed = True + + ########################## + # Adherent:tel + ########################## + def changeTelAdherent(self, nouveauTel): + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'], 'w')['adherent'][0] + try: + ancienTel = adh.tel() + adh.tel(nouveauTel) + adh.save() + except ValueError, e: + return self.index(error=e.args[0]) + del adh + _crans_cp.log("Change tel : %s -> %s" % (ancienTel, nouveauTel), "MONCOMPTE") + return self.index(message=u'Modification réussie') + changeTelAdherent.exposed = True + + ########################## + # mail:alias:creation + ########################## + def newAlias(self, alias): + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'],'w')['adherent'][0] + if adh.alias().__len__() >= 3 and adh.droits() == []: + return self.index(error=u"Vous avez plus de 2 alias. Demander a un cableur pour en rajouter.") + try: + adh.alias(alias) + adh.save() + del adh + except ValueError, e: + return self.index(error=e.args[0]) + except RuntimeError: + return self.index(error=u"Vous possèdez déjà  cet alias") + except EnvironmentError: + return self.index(error=u"Vous possèdez déjà  cet alias") + _crans_cp.log("Nouvel alias : %s" % alias, "MONCOMPTE") + return self.index(message=u'Alias enregistré') + newAlias.exposed = True + + + ########################## + # mail:sauver + ########################## + def saveMailPrefs(self, forwarding_address=None, spanTreatment=None, contourneGreylist=False, rewriteMailHeaders=False): + if spanTreatment == 'no': + spanTreatment = 'accepte' + if spanTreatment == 'mark': + spanTreatment = 'marque' + if spanTreatment == 'drop': + spanTreatment = 'supprime' + + if contourneGreylist == 'oui': + contourneGreylist = True + if rewriteMailHeaders == 'oui': + rewriteMailHeaders = True + + try: + adh = cherrypy.session['LDAP'].search('uid=' + cherrypy.session['uid'],'w')['adherent'][0] + if forwarding_address!=None: + MailConfig(cherrypy.session['uid'], forward=forwarding_address, spam=spanTreatment) + adh.contourneGreylist(contourneGreylist) + adh.rewriteMailHeaders(rewriteMailHeaders) + adh.save() + del adh + except ValueError, e: + return self.index(error=e.args[0]) + except Exception, e: + return self.index(error=u"Une erreur est survenue lors de lenregistrement. Vérifiez que l'adresse mail fournie est correcte.") + _crans_cp.log("Change mail prefs", "MONCOMPTE ACTION") + return self.index(message=u'Vos préférences ont été enregistrées') + saveMailPrefs.exposed = True + diff --git a/intranet/modules/monCompte/static/crans_domtab.js b/intranet/modules/monCompte/static/crans_domtab.js new file mode 100644 index 00000000..ce6a1fce --- /dev/null +++ b/intranet/modules/monCompte/static/crans_domtab.js @@ -0,0 +1,259 @@ +/* + DOMtab Version 3.1415927 + Updated March the First 2006 + written by Christian Heilmann + check blog for updates: http://www.wait-till-i.com + free to use, not free to resell +*/ + +domtab={ + tabClass:'domtab', // class to trigger tabbing + listClass:'domtabs', // class of the menus + activeClass:'active', // class of current link + contentElements:'div', // elements to loop through + backToLinks:/#top/, // pattern to check "back to top" links + printID:'domtabprintview', // id of the print all link + showAllLinkText:'show all content', // text for the print all link + prevNextIndicator:'doprevnext', // class to trigger prev and next links + prevNextClass:'prevnext', // class of the prev and next list + prevLabel:'previous', // HTML content of the prev link + nextLabel:'next', // HTML content of the next link + prevClass:'prev', // class for the prev link + nextClass:'next', // class for the next link + init:function(){ + var temp; + if(!document.getElementById || !document.createTextNode){return;} + var tempelm=document.getElementsByTagName('div'); + for(var i=0;i'); +document.write('div.domtab>div{display:none;}<'); +document.write('/s'+'tyle>'); diff --git a/intranet/modules/monCompte/static/icon.png b/intranet/modules/monCompte/static/icon.png new file mode 100644 index 00000000..f2551b9f Binary files /dev/null and b/intranet/modules/monCompte/static/icon.png differ diff --git a/intranet/modules/monCompte/static/monCompte.css b/intranet/modules/monCompte/static/monCompte.css new file mode 100644 index 00000000..28d9ba70 --- /dev/null +++ b/intranet/modules/monCompte/static/monCompte.css @@ -0,0 +1,368 @@ +/******************************************** + * +********************************************/ +#globalDiv { + padding-left:100px; +} + +/* style du titre au dessus des onglet et des titres pour les pages PayPal */ +div.domtab>h1, +h2 { + font-size:1.4em; + margin:2px; +} + + +/******************************************** + * +********************************************/ +/* conteneur de l'ensemble */ +div.domtab{ + padding:3px; + width:100%; + background:#fad163; + clear:left; +} + +/* onglets */ +ul.domtabs{ + float:left; + width:100%; + margin:0; + padding:0; + list-style-type:none; + +} +ul.domtabs li{ + float:left; +} +ul.domtabs a:link, +ul.domtabs a:visited, +ul.domtabs a:active, +ul.domtabs a:hover{ + font-weight:bold; + display:block; + padding:0.4em; + text-align:center; + background:#fad163; +} + +ul.domtabs li.active a:link, +ul.domtabs li.active a:visited, +ul.domtabs li.active a:active, +ul.domtabs li.active a:hover{ + background:#fff7D7; + color:#000; + text-decoration:none; +} + +/* les pages */ +div.domtab>div { + padding:0; + clear:both; + border:5px solid #fff7D7; +} +/* ancre des pages */ +.mark { + height:0; + clear:both; + display:none; +} + +/******************************************** + * +********************************************/ +.tabbed_page { + padding:0; + margin:0; +} + +ul.tabbed_page { + list-style-type:none; +} + +dl.tabbed_page>dt, +dl.tabbed_page>dd, +ul.tabbed_page>li { + background:#fff7D7; + padding:10px; + margin:0 0 2px 0; + font-weight:bold; +} +dl.tabbed_page>dt.last, +dl.tabbed_page>dd.last, +ul.tabbed_page>li.last { + margin:0 0 0 0; +} + +dl.tabbed_page>dt { + width:40%; + display:block; + height:100%; + float:left; + clear:left; +} + +dl.tabbed_page>dd { + padding-left:45%; +} + +span.actions { + display:block; + float:right; + font-size:0.9em; + font-weight:normal; +} +.tabbed_page span.actions a { + margin:2px 10px; +} + + +.tabbed_page dl, +.tabbed_page dl dt, +.tabbed_page dl dd { + margin:0; + padding:0; +} + +.tabbed_page dl dt { + float:left; + margin-right:5px; +} + +.tabbed_page dl dd, +.tabbed_page p { + font-weight:normal; + margin:3px; +} + + +span.valide { + color:green; + font-weight:bold; +} + +span.invalide { + color:red; + font-weight:bold; +} + +.clear { + clear:both; +} + +ul.tabbed_page li.centrer { + padding:10px; + margin-left:0; + text-align:center; +} + + +/******************************************** + * +********************************************/ + +.textInputNote { + display:block; + padding-left:0; + font-size:0.8em; + font-weight:normal; +} + +dd .textInputNote { + padding-left:0; +} +li .textInputNote { + padding-left:175px; +} + +label.textInputLabel{ + width:175px; + display:block; + float:left; +} + +label.checkBoxLabel{ + float:none; + padding-left:175px; +} + +/******************************************** + * +********************************************/ +dl#machineList, +dl#machineList>dt { + margin:0; + padding:0; +} +#machineList>dt { + + font-size:1.2em; + font-weight:bold; + margin:5px 5px 5px 5px; + height:30px; + padding:10px 20px; + background:#fff7D7; +} +#machineList>dd { + margin:0 0 2px 0; +} +.linkToggle { + display:block; + float:left; + height:15px; + width:15px; + background:transparent url(../images/fl.png) top left; + margin-right:1px; +} +/******************************************** + * +********************************************/ +.machineDetails { + background: #fff7D7;/*/ url(../images/fondFacturesDetails.png) repeat-x top;*/ + padding:0; + /*width:96%;*/ + display:none; + margin:0; +} + +dl.machineInfos dt, dl.machineInfos dd { + float:left; + margin-top:0; + padding:.1em; + display:block; + width:20%; +} + +dl.machineInfos dt { + text-align:right; + width:20%; + +} +/******************************************** + * +********************************************/ +ul.listeAlias { + list-style-type:none; + margin:0; + padding:0; +} +ul.listeAlias li span { + color:#666; +} + + +/******************************************** + * +********************************************/ +#loadings { + background:#cc0000; + position:fixed; + top:1px; + right:1px; + z-index:1000; + display:none; + padding:2px 3px; + color:white; +} + +.messageText { + padding:2px 10px; + display:block; +} +#messagePlaceHolder { + height:0; + overflow:visible; + position:relative; + top:-4em; +} + +.message { + padding:0; + background:#fad163; + width:300px; + text-align:center; + margin : 1px auto 10px auto; +} +.errorMessage { + display:block; + background:white; + border:2px #cc0000 solid; + padding:5px; + text-align:center; + min-width:230px; + max-width:430px; + font-weight:bold; + margin : 1px auto 10px auto; +} + +/******************************************** + * +********************************************/ +div#popupInnerBody { + border:5px solid #fad163; + background: #fff7D7; + margin:5px; + padding:5px; +} + +div#popupInnerBody .liens { + list-style-type:none; + float:right; + height:1em; + background: #fff7D7; + border-color:#fad163; + border-style: none solid solid solid; + border-width:3px; + margin:0; + padding:2px; +} + +div#popupInnerBody .liens a { + display:block; + height:1em; + float : left; + margin:0 5px; +} + +a { color:blue; } + +/******************************************** + * +********************************************/ + +table.factureDetails { + padding:1%; + width:96%; + margin:0 1% 10px 1%; +} + + +.tdTotalDetail, +.tdTotalDetailIntitule { + border-top:thin black solid; +} + +.tdTotalDetailIntitule { + text-align:right; + font-weight:bold; +} + +table.factureDetails th { + border-bottom:thin black solid; +} +table.factureDetails th, +table.factureDetails td { + border-right:thin black solid; + margin:0; + padding:5px 20px; +} + + + +/******************************************** + * divers +********************************************/ +.empty { + color:gray; +} diff --git a/intranet/modules/monCompte/static/moncompte.js b/intranet/modules/monCompte/static/moncompte.js new file mode 100644 index 00000000..3abaac7e --- /dev/null +++ b/intranet/modules/monCompte/static/moncompte.js @@ -0,0 +1,41 @@ +function askForName(oldName) { + var c = ''; + while ( c == '') + c = prompt("Votre nom :",oldName); + if (c == null) + return false; + else + window.location.href= 'changeNomAdherent?nouveauNom=' + c; +} + + +function askForSurname(oldSurname) { + var c = ''; + while ( c == '') + c = prompt("Votre prénom :",oldSurname); + if (c == null) + return false; + else + window.location.href= 'changePrenomAdherent?nouveauPrenom=' + c; +} + +function askForTel(oldTel) { + var c = ''; + while ( c == '') + c = prompt("Votre numéro de téléphone :",oldTel); + if (c == null) + return false; + else + window.location.href= 'changeTelAdherent?nouveauTel=' + c; +} + + +function newAlias() { + var c = ''; + while ( c == '') + c = prompt("Nouvel alias :"); + if (c == null) + return false; + else + window.location.href= 'newAlias?alias=' + c + "#mailTab"; +} diff --git a/intranet/modules/monCompte/static/passwordGenerator.js b/intranet/modules/monCompte/static/passwordGenerator.js new file mode 100644 index 00000000..18b6cf90 --- /dev/null +++ b/intranet/modules/monCompte/static/passwordGenerator.js @@ -0,0 +1,66 @@ +/************************************************************************ + Password generator + ************************************************************************/ + +function GeneratePassword() { + + if (parseInt(navigator.appVersion) <= 3) { + alert("Sorry this only works in 4.0 browsers"); + return false; + } + + var length=8; + var sPassword = ""; + length = 10;//document.aForm.charLen.options[document.aForm.charLen.selectedIndex].value; + + var noPunction = false;//(document.aForm.punc.checked); + var randomLength = true;//(document.aForm.rLen.checked); + + if (randomLength) { + length = Math.random(); + + length = parseInt(length * 100); + length = (length % 7) + 6 + } + + + for (i=0; i < length; i++) { + + numI = getRandomNum(); + if (noPunction) { while (checkPunc(numI)) { numI = getRandomNum(); } } + + sPassword = sPassword + String.fromCharCode(numI); + } + + //document.aForm.passField.value = sPassword + c = prompt('Mot de passe généré : ', sPassword) + if (c!= null) { + document.changePasswordForm.nouveauPassword1.value = c + document.changePasswordForm.nouveauPassword2.value = c + } + return false; +} + +function getRandomNum() { + + // between 0 - 1 + var rndNum = Math.random() + + // rndNum from 0 - 1000 + rndNum = parseInt(rndNum * 1000); + + // rndNum from 33 - 127 + rndNum = (rndNum % 94) + 33; + + return rndNum; +} + +function checkPunc(num) { + + if ((num >=33) && (num <=47)) { return true; } + if ((num >=58) && (num <=64)) { return true; } + if ((num >=91) && (num <=96)) { return true; } + if ((num >=123) && (num <=126)) { return true; } + + return false; +} diff --git a/intranet/modules/monCompte/templates/MonComptePaypalCancel.tmpl b/intranet/modules/monCompte/templates/MonComptePaypalCancel.tmpl new file mode 100644 index 00000000..7bef45d6 --- /dev/null +++ b/intranet/modules/monCompte/templates/MonComptePaypalCancel.tmpl @@ -0,0 +1,22 @@ +#import cherrypy +#set bugMail = cherrypy.config.get("mail.bugreport", "nounous@crans.org") + + +#include "inc-paypal-head.tmpl" + + +
+

Paiement annulé

+

Ton compte impressions sera crédité dés que la facture sera réglée.

+

Tu peux régler la facture plus tard en allant dans Mes Factures

+

En cas de problème, envoie un mail à $bugMail

+
+ Retour +
+
+ + + +
+ + diff --git a/intranet/modules/monCompte/templates/MonComptePaypalReturn.tmpl b/intranet/modules/monCompte/templates/MonComptePaypalReturn.tmpl new file mode 100644 index 00000000..e96cd6c3 --- /dev/null +++ b/intranet/modules/monCompte/templates/MonComptePaypalReturn.tmpl @@ -0,0 +1,21 @@ +#import cherrypy +#set bugMail = cherrypy.config.get("mail.bugreport", "nounous@crans.org") + + +#include "inc-paypal-head.tmpl" + + +
+

Paiement terminé

+

Ton compte impressions sera crédité dans quelques minutes.

+

N'hésite pas à nous envoyer tes remarques et/ou suggestions à $bugMail

+
+ Retour +
+
+ + + +
+ + diff --git a/intranet/modules/monCompte/templates/MonCompteRechargePaypal1.tmpl b/intranet/modules/monCompte/templates/MonCompteRechargePaypal1.tmpl new file mode 100644 index 00000000..f8e76575 --- /dev/null +++ b/intranet/modules/monCompte/templates/MonCompteRechargePaypal1.tmpl @@ -0,0 +1,20 @@ + + +#include "inc-paypal-head.tmpl" + + +
+

Recharger son compte impression

+

Le cr@ns te permet de recharger ton compte pour les impressions via PayPal ou en allant voir un câbleur.

+

La méthode PayPal est plus rapide mais PayPal facture des frais de transaction.

+
+ Annuler + Continuer avec Paypal +
+
+ + + + + + \ No newline at end of file diff --git a/intranet/modules/monCompte/templates/MonCompteRechargePaypal2.tmpl b/intranet/modules/monCompte/templates/MonCompteRechargePaypal2.tmpl new file mode 100644 index 00000000..e8a4e9ff --- /dev/null +++ b/intranet/modules/monCompte/templates/MonCompteRechargePaypal2.tmpl @@ -0,0 +1,33 @@ + + +#include "inc-paypal-head.tmpl" + + +
+

Étape 1 : Choisir le montant

+#if $getVar('error',False) +
$error
+#end if +
+ + +

+
+ Annuler + + +
+ + +
+
+ + diff --git a/intranet/modules/monCompte/templates/MonCompteRechargePaypal3.tmpl b/intranet/modules/monCompte/templates/MonCompteRechargePaypal3.tmpl new file mode 100644 index 00000000..3ce6045b --- /dev/null +++ b/intranet/modules/monCompte/templates/MonCompteRechargePaypal3.tmpl @@ -0,0 +1,35 @@ + + +#include "inc-paypal-head.tmpl" + +
+

Étape 2 : Confirmer la facture

+ + + + + + + + #for unDetail in $details + + + + + + + #end for + + + +
DescriptionPrix unitaireQuantitétotal
$unDetail.intitule$unDetail.prixUnitaire €$unDetail.quantite$unDetail.prixTotal €
+ Total + $total €
+
+ Précédent + Annuler + Confirmer +
+
+ + \ No newline at end of file diff --git a/intranet/modules/monCompte/templates/MonCompteRechargePaypal4.tmpl b/intranet/modules/monCompte/templates/MonCompteRechargePaypal4.tmpl new file mode 100644 index 00000000..c9c52d59 --- /dev/null +++ b/intranet/modules/monCompte/templates/MonCompteRechargePaypal4.tmpl @@ -0,0 +1,15 @@ + + +#include "inc-paypal-head.tmpl" + +
+

Étape 3 : Fin

+

Ton compte impressions sera crédité dés que la facture sera réglée.

+

Tu peux régler la facture plus tard en allant dans Mes Factures

+
+ Payer plus tard + Payer tout de suite +
+
+ + \ No newline at end of file diff --git a/intranet/modules/monCompte/templates/inc-paypal-head.tmpl b/intranet/modules/monCompte/templates/inc-paypal-head.tmpl new file mode 100644 index 00000000..907ec0c7 --- /dev/null +++ b/intranet/modules/monCompte/templates/inc-paypal-head.tmpl @@ -0,0 +1,11 @@ + + + Cr@nsIntranet + + + + + + + + diff --git a/intranet/modules/monCompte/templates/monCompte.tmpl b/intranet/modules/monCompte/templates/monCompte.tmpl new file mode 100644 index 00000000..2ce3fbe9 --- /dev/null +++ b/intranet/modules/monCompte/templates/monCompte.tmpl @@ -0,0 +1,211 @@ +#if $message != '' + +#end if + +#if $error != '' + +#end if + +
+
+

Paramètres de mon compte

+ + +
+

+
+
Nom :
+
$adherent.nom + modifier +
+
+
Prénom :
+
$adherent.prenom + modifier +
+
+ #if $getVar('adherent.adresse', False) +
Adresse :
+
+ $adherent.adresse.ligne1
+ #if $adherent.adresse.ligne2 != u' ' + $adherent.adresse.ligne2
+ #end if + $adherent.adresse.cp $adherent.adresse.ville +
+ #else +
Chambre :
+
$adherent.chambre
+ #end if +
Solde :
+
+ $adherent.solde € + modifier +
+
+
Téléphone :
+
$adherent.telephone + modifier +
+
+ #if $adherent.droits +
Droits :
+
+ $adherent.droits +
+ #end if +
État administratif pour l'année $adherent.anneeScolaire :
+
+
+
Cotisation :
+
+ #if $adherent.cotisationOK + OK + #else + Non payée + #end if +
+
Carte d'étudiant :
+
+ #if $adherent.carteOK + OK + #else + pas de carte d'étudiant + #end if +
+
+
+
Changer mon mot de passe
+
+
+
+ +
+ +
+ Générer un nouveau mot de passe
+ +
+ +
+
+
+
+
+ +
+

+
+
+
Alias:
+
+ #if $mailInfos.alias==[] + Vous n'avez pas d'alias + #else +
    + #for $an_alias in $mailInfos.alias +
  • $an_alias@crans.org
  • + #end for +
+ #end if +
+ + Nouvel alias + +
+
+
Greylisting:
+
+ #if $mailInfos.contourneGreylist==True + + #else + + #end if + Plus d'infos
+
+
+ Entêtes: +
+
+ #if $mailInfos.rewriteMailHeaders==True + + #else + + #end if +
+
+#if $getVar('mailError', False) +
    +
  • + $mailError +
  • +
+#else +
+
Transfert:
+
+ +

Laisser vide pour désactiver le transfert


+ +
+
Tri des spams:
+
+
+
+
+
+
+#end if +
    +
  • + + +
  • +
+
+
+
+
diff --git a/intranet/modules/quota/main.py b/intranet/modules/quota/main.py new file mode 100755 index 00000000..958308c3 --- /dev/null +++ b/intranet/modules/quota/main.py @@ -0,0 +1,107 @@ +#! /usr/bin/env python +import cherrypy, tempfile, shutil, os +import crans.utils.quota +import crans.cp +from ClassesIntranet.ModuleBase import ModuleBase + + +class main(ModuleBase): + def category(self): + return "Personnel" + def title(self): + return "Quotas" + def icon(self): + quotas = self._get_quota() + for a_quota in quotas: + if a_quota['quota'] < a_quota['usage']: + return "icon_alert.png" + return "icon.png" + + + def _get_quota(self): + #return quotas = crans.utils.quota.getUserQuota(cherrypy.session['uid']) + return [{'%': 33.9, 'quota': 390.62, 'label': u'Dossier personnel', 'limite': 585.94, 'filesystem': '/home', 'usage': 420.32}, {'%': 0.1, 'quota': 100.00, 'label': u'Boite de r\xe9ception', 'limite': 150.00, 'filesystem': '/var/mail', 'usage': 0.06}] + + + ########################## + # affichage + ########################## + # + # methode qui affiche la template + # + def index(self ): + values = {} + try: + quotas = self._get_quota() + returned_quotas = [] + for a_quota in quotas: + # calculate text equivalent + quota = a_quota['quota'] + usage = a_quota['usage'] + limite = a_quota['limite'] + text_equiv = "[" + text_equiv+= "#" * min( 10, int( 10 * usage / quota ) ) + text_equiv+= "." * max(0, int( 10 * ( quota - usage ) / quota ) ) + if limite > quota: + text_equiv+= "|" + limite_diff = limite - quota + diff_proportion = 10 * limite_diff / quota + depassement = max(0, usage - quota) + text_equiv+= "#" * min(0, int(diff_proportion* ( depassement / limite_diff ) ) ) + text_equiv+= "." * max(0, int(diff_proportion*( limite_diff - depassement ) / limite_diff ) ) + text_equiv+= "]" + a_returned_quota = { + "label":a_quota['label'], + "usage":a_quota['usage'], + "quota":a_quota['quota'], + "limite":a_quota['limite'], + "percents":a_quota['%'], + "%":a_quota['%'], + "text_equiv":text_equiv, + "svg_url":"barreSVG?filesystem=%s" % a_quota['filesystem'], + } + returned_quotas.append(a_returned_quota) + values = {'quotas': returned_quotas, 'e': "eeede"} + except Exception, e: + crans.cp.log('error getting quota for user %s : %s' % (cherrypy.session['uid'], str(e)), 'QUOTA', 1) + values = {'erreur':str(e), 'e': "eee"} + return {'template':'quota', + 'values': values, + 'stylesheets':['quota.css'], + 'scripts':['quota.js', 'popup.js'], + } + index.exposed = True + + def index_html(self ): + result = self.index() + result['template'] = 'quota_html' + return result + index_html.exposed = True + + + ########################## + # SVG + ########################## + # + # methode qui renvoie une barre en svg + # + def barreSVG(self, filesystem = ""): + try: + values = {'erreur':"Not found"} + quotas = self._get_quota() + for a_quota in quotas: + if a_quota['filesystem'] == filesystem: + values = { + "usage":a_quota['usage'], + "quota":a_quota['quota'], + "limite":a_quota['limite'], + "percents":a_quota['%'], + } + except Exception, e: + values = {'erreur':str(e) } + cherrypy.response.headers['Content-Type']="image/svg+xml" + return {'template':'barre.svg', + 'values': values, + 'standalone':True, + } + barreSVG.exposed= True diff --git a/intranet/modules/quota/static/icon.png b/intranet/modules/quota/static/icon.png new file mode 100644 index 00000000..7621d2fa Binary files /dev/null and b/intranet/modules/quota/static/icon.png differ diff --git a/intranet/modules/quota/static/icon_alert.png b/intranet/modules/quota/static/icon_alert.png new file mode 100644 index 00000000..52b477f9 Binary files /dev/null and b/intranet/modules/quota/static/icon_alert.png differ diff --git a/intranet/modules/quota/static/icon_digicode.png b/intranet/modules/quota/static/icon_digicode.png new file mode 100644 index 00000000..fe3729c6 Binary files /dev/null and b/intranet/modules/quota/static/icon_digicode.png differ diff --git a/intranet/modules/quota/templates/barre.svg.tmpl b/intranet/modules/quota/templates/barre.svg.tmpl new file mode 100644 index 00000000..f190b393 --- /dev/null +++ b/intranet/modules/quota/templates/barre.svg.tmpl @@ -0,0 +1,40 @@ + + + + +#if $getVar('usage', False) + +#set total = $limite +#set quota = $quota +#set usage = $usage +#set usage_percent = int( 100 * $usage/$limite ) +#set quota_percent = int( 100 * $quota/$limite ) + + + + + + + + + + + + +0Mo +$int(quota) Mo +$int(total) Mo + + + + + +$percents% + + +#else + +$getVar('erreur', 'BROKEN') + +#end if + diff --git a/intranet/modules/quota/templates/quota.tmpl b/intranet/modules/quota/templates/quota.tmpl new file mode 100644 index 00000000..07d8c2c6 --- /dev/null +++ b/intranet/modules/quota/templates/quota.tmpl @@ -0,0 +1,13 @@ +
+ +#for un_truc in $quotas +

$un_truc.label

+ + +#end for + +
Si les graphiques ne s'affichent pas, essayez la version html
+ +
\ No newline at end of file diff --git a/intranet/modules/quota/templates/quota_html.tmpl b/intranet/modules/quota/templates/quota_html.tmpl new file mode 100644 index 00000000..9cf178a7 --- /dev/null +++ b/intranet/modules/quota/templates/quota_html.tmpl @@ -0,0 +1,22 @@ +
+ + +#for un_truc in $quotas +

$un_truc.label

+ #set total = $un_truc.limite + #set usage = int( 100 * $un_truc.usage/$un_truc.limite ) + #set quota = int( 100 * $un_truc.quota/$un_truc.limite ) +
+
+ + $un_truc.text_equiv + +
+
+
$un_truc['%'] % + +#end for + +
version svg
+ +
\ No newline at end of file