added tarifs_import with xlrd
This commit is contained in:
BIN
.temp_TARIF AXA 2021-converti.xlsx
Normal file
BIN
.temp_TARIF AXA 2021-converti.xlsx
Normal file
Binary file not shown.
@@ -8,19 +8,39 @@ Author-email:
|
|||||||
License: UNKNOWN
|
License: UNKNOWN
|
||||||
Description: # README #
|
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
|
||||||
|
|
||||||
|
|
||||||
|
[Learn Markdown](https://bitbucket.org/tutorials/markdowndemo)
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ CHANGES.txt
|
|||||||
MANIFEST.in
|
MANIFEST.in
|
||||||
README.md
|
README.md
|
||||||
development.ini
|
development.ini
|
||||||
|
diff.txt
|
||||||
production.ini
|
production.ini
|
||||||
pytest.ini
|
pytest.ini
|
||||||
setup.py
|
setup.py
|
||||||
@@ -21,12 +22,16 @@ mondumas.egg-info/top_level.txt
|
|||||||
mondumas/models/__init__.py
|
mondumas/models/__init__.py
|
||||||
mondumas/models/agenda.py
|
mondumas/models/agenda.py
|
||||||
mondumas/models/default.py
|
mondumas/models/default.py
|
||||||
|
mondumas/models/devis.py
|
||||||
mondumas/models/dossier.py
|
mondumas/models/dossier.py
|
||||||
mondumas/models/parametres.py
|
mondumas/models/parametres.py
|
||||||
|
mondumas/models/utils.py
|
||||||
mondumas/scripts/__init__.py
|
mondumas/scripts/__init__.py
|
||||||
mondumas/views/__init__.py
|
mondumas/views/__init__.py
|
||||||
mondumas/views/agenda.py
|
mondumas/views/agenda.py
|
||||||
mondumas/views/default.py
|
mondumas/views/default.py
|
||||||
|
mondumas/views/devis.py
|
||||||
mondumas/views/dossier.py
|
mondumas/views/dossier.py
|
||||||
mondumas/views/notfound.py
|
mondumas/views/notfound.py
|
||||||
mondumas/views/parametres.py
|
mondumas/views/parametres.py
|
||||||
|
mondumas/views/utils.py
|
||||||
@@ -9,10 +9,11 @@ transaction
|
|||||||
zope.sqlalchemy
|
zope.sqlalchemy
|
||||||
waitress
|
waitress
|
||||||
mysqlclient
|
mysqlclient
|
||||||
|
docutils
|
||||||
pdfkit
|
pdfkit
|
||||||
python-dateutil
|
python-dateutil
|
||||||
docutils
|
|
||||||
user-agents
|
user-agents
|
||||||
|
xlrd
|
||||||
|
|
||||||
[testing]
|
[testing]
|
||||||
WebTest>=1.3.1
|
WebTest>=1.3.1
|
||||||
|
|||||||
@@ -224,3 +224,24 @@ def update_societe(request, code, new_values):
|
|||||||
new_values['societe'] = code
|
new_values['societe'] = code
|
||||||
query = "UPDATE p_societe SET %s WHERE societe = :societe;" % s
|
query = "UPDATE p_societe SET %s WHERE societe = :societe;" % s
|
||||||
execute_query(request, query, new_values)
|
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})
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ def includeme(config):
|
|||||||
config.add_route('text_edit', '/text_edit/{text_id}')
|
config.add_route('text_edit', '/text_edit/{text_id}')
|
||||||
config.add_route('text_list', '/text_list')
|
config.add_route('text_list', '/text_list')
|
||||||
config.add_route('text_view', '/text_view/{text_id}')
|
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('user_edit', '/user_edit/{cd_uti}')
|
||||||
config.add_route('users', '/users')
|
config.add_route('users', '/users')
|
||||||
config.add_route('users_ua', '/users_ua')
|
config.add_route('users_ua', '/users_ua')
|
||||||
|
|||||||
@@ -12,12 +12,12 @@
|
|||||||
<h4>ARTICLES</h4>
|
<h4>ARTICLES</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-3">
|
||||||
<a href="${request.application_url}/cabinets"><span class="glyphicon glyphicon-list logo-primary"></span></a>
|
<a href="${request.application_url}/tarifs"><span class="glyphicon glyphicon-list-alt logo-primary"></span></a>
|
||||||
<h4>CABINETS EXP.</h4>
|
<h4>TARIFS</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-3">
|
||||||
<a href="${request.application_url}/text_list"><span class="glyphicon glyphicon-list logo-primary"></span></a>
|
<a href="${request.application_url}/cabinets"><span class="glyphicon glyphicon-list logo-primary"></span></a>
|
||||||
<h4>TEXTES EMAIL</h4>
|
<h4>CABINETS EXP.</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
@@ -30,6 +30,10 @@
|
|||||||
<a href="${request.application_url}/rdf_causes"><span class="glyphicon glyphicon-list logo-primary"></span></a>
|
<a href="${request.application_url}/rdf_causes"><span class="glyphicon glyphicon-list logo-primary"></span></a>
|
||||||
<h4>RDF : CAUSES</h4>
|
<h4>RDF : CAUSES</h4>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<a href="${request.application_url}/text_list"><span class="glyphicon glyphicon-list logo-primary"></span></a>
|
||||||
|
<h4>TEXTES EMAIL</h4>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
<div class="row text-center">
|
<div class="row text-center">
|
||||||
|
|||||||
166
mondumas/templates/parametres/tarif_edit.pt
Normal file
166
mondumas/templates/parametres/tarif_edit.pt
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
<metal:block use-macro="main_template">
|
||||||
|
<div metal:fill-slot="content">
|
||||||
|
|
||||||
|
<div tal:condition="message" tal:content="message" class="alert alert-danger" />
|
||||||
|
<br />
|
||||||
|
<form id="user_edit-form" class="form-horizontal" action="${url}" method="post" tal:condition="item"
|
||||||
|
data-fv-framework="bootstrap"
|
||||||
|
data-fv-icon-valid="glyphicon glyphicon-ok"
|
||||||
|
data-fv-icon-invalid="glyphicon glyphicon-remove"
|
||||||
|
data-fv-icon-validating="glyphicon glyphicon-refresh">
|
||||||
|
|
||||||
|
<div id="tarif" class="tab-pane fade in active">
|
||||||
|
<br />
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-xs-2" for="REF">Référence</label>
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<input class="form-control" type="text" id="REF" name="REF" value="${item.REF}"
|
||||||
|
placeholder="10 caractères maximum"
|
||||||
|
data-fv-notempty="true"
|
||||||
|
data-fv-notempty-message="La référence est obligatoire"
|
||||||
|
data-fv-stringlength="true"
|
||||||
|
data-fv-stringlength-max="10"
|
||||||
|
data-fv-stringlength-message="10 caractères maximum" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-xs-2">Famille</label>
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<select class="form-control" id="FAM" name="FAM">
|
||||||
|
<tal:block tal:repeat="famille familles">
|
||||||
|
<option value="${famille}" tal:attributes="selected famille[0]==item.FAM and 'selected' or None">${famille}</option>
|
||||||
|
</tal:block>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-xs-2" for="LIBART">Libellé</label>
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<input class="form-control" type="text" id="LIBART" name="LIBART" value="${item.LIBART}"
|
||||||
|
placeholder="45 caractères maximum"
|
||||||
|
data-fv-notempty="true"
|
||||||
|
data-fv-notempty-message="Le libellé est obligatoire"
|
||||||
|
data-fv-stringlength="true"
|
||||||
|
data-fv-stringlength-max="45"
|
||||||
|
data-fv-stringlength-message="45 caractères maximum" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-xs-2" for="LIBCOMPL1">Libellé compl. 1</label>
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<input class="form-control" type="text" id="LIBCOMPL1" name="LIBCOMPL1" value="${item.LIBCOMPL1}"
|
||||||
|
placeholder="45 caractères maximum"
|
||||||
|
data-fv-stringlength="true"
|
||||||
|
data-fv-stringlength-max="45"
|
||||||
|
data-fv-stringlength-message="45 caractères maximum" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-xs-2" for="LIBCOMPL2">Libellé compl. 2</label>
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<input class="form-control" type="text" id="LIBCOMPL2" name="LIBCOMPL2" value="${item.LIBCOMPL2}"
|
||||||
|
placeholder="45 caractères maximum"
|
||||||
|
data-fv-stringlength="true"
|
||||||
|
data-fv-stringlength-max="45"
|
||||||
|
data-fv-stringlength-message="45 caractères maximum" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-xs-2" for="LIBCOMPL3">Libellé compl. 3</label>
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<input class="form-control" type="text" id="LIBCOMPL3" name="LIBCOMPL3" value="${item.LIBCOMPL3}"
|
||||||
|
placeholder="45 caractères maximum"
|
||||||
|
data-fv-stringlength="true"
|
||||||
|
data-fv-stringlength-max="45"
|
||||||
|
data-fv-stringlength-message="45 caractères maximum" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-xs-2" for="LIBCOMPL4">Libellé compl. 4</label>
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<input class="form-control" type="text" id="LIBCOMPL4" name="LIBCOMPL4" value="${item.LIBCOMPL4}"
|
||||||
|
placeholder="45 caractères maximum"
|
||||||
|
data-fv-stringlength="true"
|
||||||
|
data-fv-stringlength-max="45"
|
||||||
|
data-fv-stringlength-message="45 caractères maximum" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-xs-2 control-label">Prix HT 1</label>
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-addon"><i class="glyphicon glyphicon-euro"></i></span>
|
||||||
|
<input class="form-control" type="text" id="PRIXHT1" name="PRIXHT1" value="${item.PRIXHT1}"
|
||||||
|
data-fv-numeric="true"
|
||||||
|
data-fv-numeric-message="Le montant est invalide" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-xs-2 control-label">Prix HT 2</label>
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-addon"><i class="glyphicon glyphicon-euro"></i></span>
|
||||||
|
<input class="form-control" type="text" id="PRIXHT2" name="PRIXHT2" value="${item.PRIXHT2}"
|
||||||
|
data-fv-numeric="true"
|
||||||
|
data-fv-numeric-message="Le montant est invalide" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-xs-2" for="ref_cli1">Réf. client 1</label>
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<input class="form-control" type="text" id="ref_cli1" name="ref_cli1" value="${item.ref_cli1}"
|
||||||
|
placeholder="20 caractères maximum"
|
||||||
|
data-fv-stringlength="true"
|
||||||
|
data-fv-stringlength-max="20"
|
||||||
|
data-fv-stringlength-message="20 caractères maximum" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-xs-2" for="ref_cli2">Réf. client 2</label>
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<input class="form-control" type="text" id="ref_cli2" name="ref_cli2" value="${item.ref_cli2}"
|
||||||
|
placeholder="20 caractères maximum"
|
||||||
|
data-fv-stringlength="true"
|
||||||
|
data-fv-stringlength-max="20"
|
||||||
|
data-fv-stringlength-message="20 caractères maximum" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-xs-2" for="access">Dernière modif.</label>
|
||||||
|
<div class="col-xs-7">
|
||||||
|
<p class="form-control-static" tal:condition="item.REF != '0'">${item.modif_le.strftime('%d/%m/%Y - %H:%M')}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-xs-offset-2 col-xs-10">
|
||||||
|
<div class="form-group">
|
||||||
|
<a class="btn btn-default" href="${request.application_url}/articles">
|
||||||
|
<span class="glyphicon glyphicon-chevron-left"></span> Annuler</a>
|
||||||
|
<button class="btn btn-primary" type="submit" name="form.submitted">
|
||||||
|
<span class="glyphicon glyphicon-ok"></span> Enregistrer</button>
|
||||||
|
<button class="btn btn-warning" type="submit" name="form.deleted"
|
||||||
|
tal:condition="item.REF != '0'">
|
||||||
|
<span class="glyphicon glyphicon-remove"></span> Supprimer</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#user_edit-form').formValidation();
|
||||||
|
$('form input').on('keypress', function(e) {
|
||||||
|
return e.which !== 13;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</metal:block>
|
||||||
72
mondumas/templates/parametres/tarifs.pt
Normal file
72
mondumas/templates/parametres/tarifs.pt
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<metal:block use-macro="main_template">
|
||||||
|
<div metal:fill-slot="content">
|
||||||
|
|
||||||
|
<form method="POST" id="frm" class="form-horizontal">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-md-1">Famille : </label>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<select class="form-control" id="famille" name="famille" onChange="$('#frm').submit()">
|
||||||
|
<tal:block tal:repeat="item familles">
|
||||||
|
<option value="${item}" tal:attributes="selected famille==item and 'selected' or None">${item}</option>
|
||||||
|
</tal:block>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<p>
|
||||||
|
<a href="${request.application_url}/parametres" class="btn btn-default" role="button">
|
||||||
|
<span class="glyphicon glyphicon-chevron-left"></span> Retour</a>
|
||||||
|
<a href="${request.application_url}/article_edit/0" class="btn btn-success" role="button">
|
||||||
|
<span class="glyphicon glyphicon-plus"></span> Nouvel tarif</a>
|
||||||
|
<a href="${request.application_url}/tarifs_import" class="btn btn-primary" role="button">
|
||||||
|
<span class="glyphicon glyphicon-import"></span> Import tarifs</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table id="articles_list" class="table table-condensed table-striped table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Référence</th>
|
||||||
|
<th>Libellé</th>
|
||||||
|
<th>Libellé 2</th>
|
||||||
|
<th class="text-right">Prix HT 1</th>
|
||||||
|
<th class="text-right">Prix HT 2</th>
|
||||||
|
<th>Réf. client 1</th>
|
||||||
|
<th>Réf. client 2</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var dataSet = ${dt_data};
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
$.fn.dataTable.moment('DD-MM-YYYY HH:mm');
|
||||||
|
$('#articles_list').DataTable({
|
||||||
|
data: dataSet,
|
||||||
|
pageLength: 100,
|
||||||
|
bLengthChange: false,
|
||||||
|
searching: false,
|
||||||
|
language: {
|
||||||
|
url: 'https://cdn.datatables.net/plug-ins/1.10.16/i18n/French.json'
|
||||||
|
},
|
||||||
|
columnDefs: [
|
||||||
|
{ className: "text-right", "targets": [3,4] },
|
||||||
|
{ targets: 0,
|
||||||
|
render: function (data, type, full, meta) {
|
||||||
|
// ajouter un link vers le formulaire
|
||||||
|
return '<a href="/article_edit/' + data + '">' + data + '</a>';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</div><!-- content -->
|
||||||
|
</metal:block>
|
||||||
|
|
||||||
|
|
||||||
45
mondumas/templates/parametres/tarifs_import.pt
Normal file
45
mondumas/templates/parametres/tarifs_import.pt
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<metal:block use-macro="main_template">
|
||||||
|
<div metal:fill-slot="content">
|
||||||
|
|
||||||
|
<div class="alert alert-danger" tal:condition="message" tal:content="message" />
|
||||||
|
<br />
|
||||||
|
<form id="upload_doc-form" action="${url}" method="post" accept-charset="utf-8" enctype="multipart/form-data"
|
||||||
|
data-fv-framework="bootstrap"
|
||||||
|
data-fv-icon-valid="glyphicon glyphicon-ok"
|
||||||
|
data-fv-icon-invalid="glyphicon glyphicon-remove"
|
||||||
|
data-fv-icon-validating="glyphicon glyphicon-refresh">
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label">Groupe :</label>
|
||||||
|
<select class="form-control" id="groupe" name="groupe">
|
||||||
|
<tal:block tal:repeat="item groupes">
|
||||||
|
<option value="${item}" tal:attributes="selected groupe==item and 'selected' or None"> ${item}</option>
|
||||||
|
</tal:block>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label" for="uploadfile">Veuillez séléctionner un fichier :</label>
|
||||||
|
<input id="uploadfile" name="filename" type="file" accept=".xls,.xlsx" value="" required />
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div class="form-group">
|
||||||
|
<a class="btn btn-default" href="/">
|
||||||
|
<span class="glyphicon glyphicon-arrow-left"></span> Retour</a>
|
||||||
|
<button id="uploadButton" class="btn btn-primary" type="submit" name="form.submitted">
|
||||||
|
<i class="glyphicon glyphicon-refresh"></i> Importer</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$('#uploadButton').on('click', function(){
|
||||||
|
$('i.gly-spin').removeClass('gly-spin');
|
||||||
|
$('i').addClass('gly-spin');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
</metal:block>
|
||||||
@@ -848,7 +848,7 @@ def mailbox_connect(request, societe):
|
|||||||
mbx_pwd = 'sasdumas'
|
mbx_pwd = 'sasdumas'
|
||||||
else:
|
else:
|
||||||
request.session.flash("Cette société est inconnue ou non traitée : %s" % societe, 'danger')
|
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')
|
conn = imaplib.IMAP4_SSL('imap.entreprise-dumas.com')
|
||||||
try:
|
try:
|
||||||
@@ -856,7 +856,7 @@ def mailbox_connect(request, societe):
|
|||||||
conn.login(mbx_name, mbx_pwd)
|
conn.login(mbx_name, mbx_pwd)
|
||||||
except imaplib.IMAP4.error:
|
except imaplib.IMAP4.error:
|
||||||
request.session.flash("ERREUR connexion au compte %s" % mbx_name, 'danger')
|
request.session.flash("ERREUR connexion au compte %s" % mbx_name, 'danger')
|
||||||
return HTTPFound(location=request.route_url('home'))
|
return None
|
||||||
|
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ from pyramid_mailer.message import Message, Attachment
|
|||||||
from datetime import *
|
from datetime import *
|
||||||
from dateutil.relativedelta import *
|
from dateutil.relativedelta import *
|
||||||
from docutils.core import publish_parts
|
from docutils.core import publish_parts
|
||||||
import hashlib
|
|
||||||
|
|
||||||
from sqlalchemy.exc import DBAPIError
|
from sqlalchemy.exc import DBAPIError
|
||||||
from ..security import groupfinder
|
from ..security import groupfinder
|
||||||
@@ -26,6 +25,7 @@ from ..models.parametres import *
|
|||||||
from ..models.default import *
|
from ..models.default import *
|
||||||
from ..models.utils import *
|
from ..models.utils import *
|
||||||
from ..views.default import *
|
from ..views.default import *
|
||||||
|
from ..views.dossier import *
|
||||||
|
|
||||||
@view_config(route_name='parametres', renderer='../templates/parametres/parametres.pt', permission='manage')
|
@view_config(route_name='parametres', renderer='../templates/parametres/parametres.pt', permission='manage')
|
||||||
def parametres(request):
|
def parametres(request):
|
||||||
@@ -801,3 +801,167 @@ def societe_edit(request):
|
|||||||
'code': code,
|
'code': code,
|
||||||
'code_postal': code_postal,
|
'code_postal': code_postal,
|
||||||
'message': message,
|
'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,
|
||||||
|
}
|
||||||
|
|||||||
3
setup.py
3
setup.py
@@ -20,10 +20,11 @@ requires = [
|
|||||||
'zope.sqlalchemy',
|
'zope.sqlalchemy',
|
||||||
'waitress',
|
'waitress',
|
||||||
'mysqlclient',
|
'mysqlclient',
|
||||||
|
'docutils',
|
||||||
'pdfkit',
|
'pdfkit',
|
||||||
'python-dateutil',
|
'python-dateutil',
|
||||||
'docutils',
|
|
||||||
'user-agents',
|
'user-agents',
|
||||||
|
'xlrd',
|
||||||
]
|
]
|
||||||
|
|
||||||
tests_require = [
|
tests_require = [
|
||||||
|
|||||||
Reference in New Issue
Block a user