diff --git a/.temp_TARIF AXA 2021-converti.xlsx b/.temp_TARIF AXA 2021-converti.xlsx new file mode 100644 index 0000000..12de3ba Binary files /dev/null and b/.temp_TARIF AXA 2021-converti.xlsx differ diff --git a/mondumas.egg-info/PKG-INFO b/mondumas.egg-info/PKG-INFO index 442dec3..d373b8e 100644 --- a/mondumas.egg-info/PKG-INFO +++ b/mondumas.egg-info/PKG-INFO @@ -8,19 +8,39 @@ Author-email: License: UNKNOWN Description: # README # + Cette application web permet aux collaborateurs de l'entreprise Dumas : - Application web permettant aux personnels de l'entreprise Dumas d'accéder aux dossiers des clients + - de consulter et de gérer les dossiers des clients depuis leur tablette + - de créer un rapport de fuite et le faire signer par le client + + Elle est développée avec les composants open source suivants : + + ## Backend + + - [Python](https://www.python.org/downloads/) 3.7 + - [Pyramid web framework](https://trypyramid.com/) 1.10 + - [MySQL server](https://mysql.com/) 5.7 sur Windows Server 2008 R2 Standard + - [Apache web server](https://apache.org/) 2.4 sur Debian GNU/Linux 9 (stretch) + + ## Frontend + + - [Bootstrap framework](https://getbootstrap.com/) for CSS 3.3.7 + - [Jquery](https://jquery.com/download/) for JavaScript 3.2.1 + - Chameleon templates + - [FormValidation](https://formvalidation.io/) form validator 0.7.0 + + ## Jquery Plugins + + - [DataTables](https://datatables.net/) 1.10.20 + - [Fullcalendar](https://fullcalendar.io/) 3.9.0 + - [fullcalendar Scheduler](https://fullcalendar.io/) 1.9.4 + - [Jquery-ui et jquery-ui-themes](https://jqueryui.com/) 1.12.1 + - [jSignature](https://willowsystems.github.io/jSignature) + - [less.js](http://lesscss.org/) 3.11.1 + - [moment.js](https://momentjs.com/) with-locales.min.js - - Développé avec : - - Pyramid Framework - - MySQL - - Chameleon - - * [Exemple d'une comptabilité simple] (http://perso.numericable.fr/assoc1901/droit/comptabilite1.htm) - - * [Learn Markdown](https://bitbucket.org/tutorials/markdowndemo) + [Learn Markdown](https://bitbucket.org/tutorials/markdowndemo) diff --git a/mondumas.egg-info/SOURCES.txt b/mondumas.egg-info/SOURCES.txt index c757d95..0434673 100644 --- a/mondumas.egg-info/SOURCES.txt +++ b/mondumas.egg-info/SOURCES.txt @@ -2,6 +2,7 @@ CHANGES.txt MANIFEST.in README.md development.ini +diff.txt production.ini pytest.ini setup.py @@ -21,12 +22,16 @@ mondumas.egg-info/top_level.txt mondumas/models/__init__.py mondumas/models/agenda.py mondumas/models/default.py +mondumas/models/devis.py mondumas/models/dossier.py mondumas/models/parametres.py +mondumas/models/utils.py mondumas/scripts/__init__.py mondumas/views/__init__.py mondumas/views/agenda.py mondumas/views/default.py +mondumas/views/devis.py mondumas/views/dossier.py mondumas/views/notfound.py -mondumas/views/parametres.py \ No newline at end of file +mondumas/views/parametres.py +mondumas/views/utils.py \ No newline at end of file diff --git a/mondumas.egg-info/requires.txt b/mondumas.egg-info/requires.txt index dffee05..43d4a38 100644 --- a/mondumas.egg-info/requires.txt +++ b/mondumas.egg-info/requires.txt @@ -9,10 +9,11 @@ transaction zope.sqlalchemy waitress mysqlclient +docutils pdfkit python-dateutil -docutils user-agents +xlrd [testing] WebTest>=1.3.1 diff --git a/mondumas/models/parametres.py b/mondumas/models/parametres.py index 0cae193..95bfcec 100644 --- a/mondumas/models/parametres.py +++ b/mondumas/models/parametres.py @@ -224,3 +224,24 @@ def update_societe(request, code, new_values): new_values['societe'] = code query = "UPDATE p_societe SET %s WHERE societe = :societe;" % s execute_query(request, query, new_values) + +def update_tarif(request, ref, new_values): + # formater les champs + s = '' + for param in new_values.keys(): + if s: + s += ",%s=:%s" % (param, param) + else: + s = "%s=:%s" % (param, param) + + if ref == '0': + query = "INSERT INTO tarifs SET %s" % s + else: + new_values['ref'] = ref + query = "UPDATE tarifs SET %s WHERE ref = :ref;" % s + execute_query(request, query, new_values) + +def delete_tarifs(request, ref): + query = "DELETE FROM tarifs WHERE ref = :ref ;" + execute_query(request, query, {'ref': ref}) + diff --git a/mondumas/routes.py b/mondumas/routes.py index f2bd940..0902a5c 100644 --- a/mondumas/routes.py +++ b/mondumas/routes.py @@ -68,6 +68,9 @@ def includeme(config): config.add_route('text_edit', '/text_edit/{text_id}') config.add_route('text_list', '/text_list') config.add_route('text_view', '/text_view/{text_id}') + config.add_route('tarif_edit', '/tarif_edit/{ref}') + config.add_route('tarifs', '/tarifs') + config.add_route('tarifs_import', '/tarifs_import') config.add_route('user_edit', '/user_edit/{cd_uti}') config.add_route('users', '/users') config.add_route('users_ua', '/users_ua') diff --git a/mondumas/templates/parametres/parametres.pt b/mondumas/templates/parametres/parametres.pt index 0634f08..c26895d 100644 --- a/mondumas/templates/parametres/parametres.pt +++ b/mondumas/templates/parametres/parametres.pt @@ -12,12 +12,12 @@

ARTICLES

- -

CABINETS EXP.

+ +

TARIFS

- -

TEXTES EMAIL

+ +

CABINETS EXP.


@@ -30,6 +30,10 @@

RDF : CAUSES

+
+ +

TEXTES EMAIL

+

diff --git a/mondumas/templates/parametres/tarif_edit.pt b/mondumas/templates/parametres/tarif_edit.pt new file mode 100644 index 0000000..2fac368 --- /dev/null +++ b/mondumas/templates/parametres/tarif_edit.pt @@ -0,0 +1,166 @@ + +
+ +
+
+
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+ + +
+
+
+
+ +
+
+ + +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+

${item.modif_le.strftime('%d/%m/%Y - %H:%M')}

+
+
+
+ +
+
+
+ + Annuler + + +
+
+
+ + +
+
+ + + +
+ diff --git a/mondumas/templates/parametres/tarifs.pt b/mondumas/templates/parametres/tarifs.pt new file mode 100644 index 0000000..038b77c --- /dev/null +++ b/mondumas/templates/parametres/tarifs.pt @@ -0,0 +1,72 @@ + +
+ +
+
+ +
+ +
+
+
+

+ + Retour + + Nouvel tarif + + Import tarifs +

+ + + + + + + + + + + + + +
RéférenceLibelléLibellé 2Prix HT 1Prix HT 2Réf. client 1Réf. client 2
+ +
+
+ + + +
+
+ + diff --git a/mondumas/templates/parametres/tarifs_import.pt b/mondumas/templates/parametres/tarifs_import.pt new file mode 100644 index 0000000..54e056e --- /dev/null +++ b/mondumas/templates/parametres/tarifs_import.pt @@ -0,0 +1,45 @@ + +
+ +
+
+
+ +
+ + +
+ +
+ + +
+
+
+ + Retour + +
+
+ +
+
+
+ + +
+ diff --git a/mondumas/views/dossier.py b/mondumas/views/dossier.py index 7f03956..f9a5239 100644 --- a/mondumas/views/dossier.py +++ b/mondumas/views/dossier.py @@ -848,7 +848,7 @@ def mailbox_connect(request, societe): mbx_pwd = 'sasdumas' else: request.session.flash("Cette société est inconnue ou non traitée : %s" % societe, 'danger') - return HTTPFound(location=request.route_url('home')) + return None conn = imaplib.IMAP4_SSL('imap.entreprise-dumas.com') try: @@ -856,7 +856,7 @@ def mailbox_connect(request, societe): conn.login(mbx_name, mbx_pwd) except imaplib.IMAP4.error: request.session.flash("ERREUR connexion au compte %s" % mbx_name, 'danger') - return HTTPFound(location=request.route_url('home')) + return None return conn diff --git a/mondumas/views/parametres.py b/mondumas/views/parametres.py index d9e1b5f..d83c8a9 100644 --- a/mondumas/views/parametres.py +++ b/mondumas/views/parametres.py @@ -15,7 +15,6 @@ from pyramid_mailer.message import Message, Attachment from datetime import * from dateutil.relativedelta import * from docutils.core import publish_parts -import hashlib from sqlalchemy.exc import DBAPIError from ..security import groupfinder @@ -26,6 +25,7 @@ from ..models.parametres import * from ..models.default import * from ..models.utils import * from ..views.default import * +from ..views.dossier import * @view_config(route_name='parametres', renderer='../templates/parametres/parametres.pt', permission='manage') def parametres(request): @@ -801,3 +801,167 @@ def societe_edit(request): 'code_postal': code_postal, 'message': message, } + +@view_config(route_name='tarifs', renderer='../templates/parametres/tarifs.pt', permission='manage') +def tarifs(request): + + familles = ["Article", "Texte"] + famille = 'ARticle' + + # si table a changé + if 'famille' in request.params: + famille = request.params["famille"] + + # lire les articles + items = get_articles_byFam(request, famille[0]) + + # construire la liste + liste=[] + for item in items: + d = (item.REF, item.LIBART, item.LIBCOMPL1, to_euro(item.PRIXHT1), to_euro(item.PRIXHT2), item.ref_cli1, item.ref_cli2) + liste.append(d) + + return { + 'page_title': 'Liste des articles', + 'dt_data': json.dumps(liste), + 'familles': familles, + 'famille': famille, + } + +@view_config(route_name='tarif_edit', renderer='../templates/parametres/tarif_edit.pt', permission='manage') +def tarif_edit(request): + ref = request.matchdict['ref'] + url = request.route_url('article_edit', ref=ref) + logged_in = request.authenticated_userid + message = '' + + familles = ["Article", "Texte"] + + if ref == '0': + # nouveau + item = {} + item['REF'] = '0' + item['FAM'] = 'A' + item['LIBART'] = '' + item['PRIXHT1'] = 0 + item['PRIXHT2'] = 0 + item['ref_cli1'] = '' + item['ref_cli2'] = '' + item['LIBCOMPL1'] = '' + item['LIBCOMPL2'] = '' + item['LIBCOMPL3'] = '' + item['LIBCOMPL4'] = '' + page_title= 'Nouvel article' + else: + # lire l'article + item = get_article(request, 'REF', ref) + if not item: + request.session.flash("article non trouvé : %s" % ref, 'warning') + return HTTPFound(location=request.route_url('articles')) + page_title= "article : %s - %s" %(item.REF, item.LIBART) + + if 'form.submitted' in request.params: + new_ref = request.params["REF"] + if new_ref == '0': + message = "Veuillez saisir un code article valide." + else: + new_values = {} + for param, db_value in item.items(): + if param in request.params and request.params[param] != db_value: + new_values[param] = request.params[param] + + if new_values: + update_article(request, ref, new_values) + request.session.flash("Le article a été mis à jour avec succès.", 'success') + return HTTPFound(location=request.route_url('articles')) + + if 'form.deleted' in request.params: + delete_article(request, ref) + request.session.flash("Le article a été supprimé avec succès.", 'success') + return HTTPFound(location=request.route_url('articles')) + + return { + 'page_title': page_title, + 'url': url, + 'message': message, + 'item': item, + 'familles': familles, + } + +@view_config(route_name='tarifs_import', renderer='../templates/parametres/tarifs_import.pt', permission='view') +def tarifs_import(request): + """ + UPLOAD d'un tarif en fichier EXCEL + + """ + import xlrd + + logged_in = request.authenticated_userid.upper() + + url = request.route_url("tarifs_import") + message = '' + + groupes = ['AXA','MAIF'] + groupe = 'AXA' + + + if 'form.submitted' in request.params: + groupe = request.params["groupe"] + + # récupère le fichier download dans le dossier /tmp + input_file = request.POST['filename'].file + input_name = request.POST['filename'].filename + ext_allowed = ['xls', 'xlsx'] + temp_file = downloadFile2Temp(input_file, input_name, ext_allowed) + if temp_file[:8] == 'ERREUR: ': + request.session.flash(temp_file, 'danger') + return HTTPFound(location=url) + + # readxl returns a pylightxl database that holds all worksheets and its data + book = xlrd.open_workbook(temp_file) + + # lire la 1ère feuille et contôler que c'est fichier AXA + sh = book.sheet_by_index(0) + ctl_cellA1 = sh.cell_value(rowx=0, colx=0) + if ctl_cellA1 != 'PEN_2_MISEEN': + request.session.flash(temp_file + " -> Ce fichier ne semble pas être un tarif AXA", 'danger') + return HTTPFound(location=url) + + # import pdb;pdb.set_trace() + for nsheet in range(book.nsheets): + # pour chaque feuille dans le tableau XLS + sh = book.sheet_by_index(nsheet) + for rx in range(sh.nrows): + ref = sh.cell_value(rx, 0).strip() + # ligne ayant un ref de tarifs ? + if len(ref) >= 12 and len(ref) < 15 and ref[3]=='_': + new_values = {} + new_values['groupe'] = groupe + new_values['ref'] = ref + new_values['famille'] = ref[0:3] + libelle = sh.cell_value(rx, 1) + new_values['libelle'] = libelle.replace(' F+P M²', '').replace(' F+P U', '') + new_values['prixht'] = sh.cell_value(rx, 5) + # col Unité renseigné ? + if len(sh.cell_value(rx, 3)) > 0: + unite = sh.cell_value(rx, 3) + else: + if sh.cell_value(rx, 1).find(' M2'): + unite = 'M²' + else: + unite = 'U' + new_values['unite'] = unite + + update_tarif(request, '0', new_values) + + request.session.flash("Le fichier PDF a été importé avec succès.", 'success') + return HTTPFound(location=url) + + return { + 'page_title': 'Importer un fichier Tarifs en Excel', + 'url': url, + 'message': message, + 'groupes': groupes, + 'groupe': groupe, + } + diff --git a/setup.py b/setup.py index 604eee6..1d164fb 100644 --- a/setup.py +++ b/setup.py @@ -20,10 +20,11 @@ requires = [ 'zope.sqlalchemy', 'waitress', 'mysqlclient', + 'docutils', 'pdfkit', 'python-dateutil', - 'docutils', 'user-agents', + 'xlrd', ] tests_require = [