# -*- coding: utf8 -*- from pyramid.response import Response from pyramid.renderers import render, get_renderer from pyramid.view import ( view_config, forbidden_view_config, ) from pyramid.security import ( remember, forget, ) from pyramid.httpexceptions import ( HTTPFound, HTTPNotFound, HTTPForbidden, ) from pyramid_mailer import get_mailer from pyramid_mailer.message import Message, Attachment from datetime import * from sqlalchemy.exc import DBAPIError from ..security import groupfinder from PIL import Image import os import io import shutil import pdfkit import imaplib import base64 import email from pdfminer3.layout import LAParams, LTTextBox, LTTextLine from pdfminer3.pdfpage import PDFPage from pdfminer3.pdfparser import PDFParser from pdfminer3.pdfdocument import PDFDocument from pdfminer3.pdfdevice import PDFDevice from pdfminer3.pdfinterp import PDFResourceManager, PDFPageInterpreter from pdfminer3.converter import PDFPageAggregator from ..views.default import * from ..models.default import * from ..models.dossier import * @view_config(route_name='dossier_lookup', renderer='../templates/dossier/dossier_lookup.pt', permission='view') @view_config(route_name='dossier_select', renderer='../templates/dossier/dossier_lookup.pt', permission='view') def dossier_lookup(request): if 'dossier_select' in request.current_route_path() : # récupérer les paramètres de l'appel de la view datePlan = request.matchdict['date'] # sélectionner dossier -> goto planning goto_url = '/dossier_selected/agenda/%s/' % datePlan url = request.route_url('dossier_select', date=datePlan) else: # recherche dossier -> goto fiche dossier goto_url = '/dossier_selected/dossier_view/%s/' % date.today().strftime('%Y-%m-%d') url = request.route_url('dossier_lookup') logged_in = request.authenticated_userid.upper() message = '' societes = ['PE','ME','PL','PO','CD'] member = get_member_by_id(request, logged_in) societe_defaut = member.societe societe = societe_defaut access_defaut = member.access liste=[] name = '' cb_tous = "non" if 'form.submitted' in request.params: name = request.params['name'] societe = request.params['societe'] if access_defaut > 0: societe = request.params['societe'] else: societe = societe_defaut # lire les chantiers chantiers = get_chantiers_byName(request, societe, name) if len(chantiers) == 0: message = "Chantier non trouvé : %s" % name # construire la liste for item in chantiers: d = ('%s-%s' % (societe, item.numero),item.date.strftime('%d-%m-%Y'), item.nomcli, item.chantier, to_euro(item.montant), item.nosin, item.status) liste.append(d) if len(name) == 0 : order_option = 'desc' else: order_option = 'asc' return { 'page_title': "Rechercher un chantier", 'url': url, 'goto_url': goto_url, 'message': message, 'dt_data': json.dumps(liste), 'societes': societes, 'societe': societe, 'name': name, 'order_option': order_option, } @view_config(route_name='dossier_view', renderer='../templates/dossier/dossier_view.pt', permission='view') def dossier_view(request): nodossier = request.matchdict['nodossier'] societe = nodossier[0:2] logged_in = request.authenticated_userid.upper() url = request.route_url("dossier_view", nodossier=nodossier) dossier = get_dossier_by_no(request, nodossier) if dossier is None: request.session.flash(u"Le dossier no %s est introuvable" % (nodossier), 'danger') return HTTPFound(location=request.route_url("dossier_lookup")) # lire tous le suivi du dossier details = get_dossier_rdv_by_no(request, nodossier, '0') # lire toutes les dossiers du chantiers documents = get_documents_byChantier(request, nodossier) # lire toutes les dossiers similaires similaires = get_similaires_byChantier(request, dossier.societe, dossier.C_NOM, dossier.C_ADR, dossier.C_CP, dossier.C_VILLE) # lire tous les documents attachés docs_attaches = get_docs_attaches(request, nodossier, 0, '') if nodossier.startswith('PL'): # lire rapport de rdf rapports = get_rapport_by_no(request, nodossier, '') else: rapports = [] # select background color according to society bg_color = "bg-%s" % societe return { 'page_title': u"Dossier : %s" % (nodossier), 'nodossier': nodossier, 'dossier': dossier, 'details': details, 'rapports': rapports, 'documents': documents, 'similaires': similaires, 'docs_attaches': docs_attaches, 'docs_url': request.static_url(request.registry.settings['mondumas.devfac_url']), 'bg_color': bg_color, } @view_config(route_name='devis_view', renderer='../templates/dossier/devis_view.pt', permission='view') def devis_view(request): nodossier = request.matchdict['nodossier'] societe = nodossier[0:2] url = request.route_url("devis_view", nodossier=nodossier) type_doc = nodossier[3:5] if type_doc == 'DE': page_title = u"Devis no : %s" % (nodossier) elif type_doc == 'FA': page_title = u"Facture no : %s" % (nodossier) else: page_title = u"Proforma no : %s" % (nodossier) dossier = get_devis_by_no(request, nodossier) if dossier is None: request.session.flash(u"Le document no %s est introuvable" % (nodossier), 'danger') return HTTPFound(location=request.route_url("dossier_lookup")) # lire tous les lignes du devis details = get_devis_lig_by_no(request, nodossier) # select background color according to society bg_color = "bg-%s" % societe return { 'page_title': page_title, 'nodossier': nodossier, 'dossier': dossier, 'details': details, 'bg_color': bg_color, } @view_config(route_name='dossier_selected', permission='view') def dossier_selected(request): # récupérer les paramètres de l'appel de la view goto = request.matchdict['goto'] datePlan = request.matchdict['date'] nodossier = request.matchdict['nodossier'] # fiche dossier dossier = get_dossier_by_no(request, nodossier) # memorize nodossier et nom dossier request.session['mem_nodossier'] = nodossier request.session['mem_nomdossier'] = '%s %s' % (dossier.C_QUALITE, dossier.C_NOM) if goto == 'dossier_view': return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier)) else: return HTTPFound(location=request.route_url('agenda', date=datePlan)) @view_config(route_name='suivi_edit', renderer='../templates/dossier/suivi_edit.pt', permission='view') def suivi_edit(request): logged_in = request.authenticated_userid.upper() nodossier = request.matchdict['nodossier'] nolig = request.matchdict['nolig'] url = request.route_url("suivi_edit", nodossier=nodossier, nolig=nolig) message = '' if nolig == '0': # nouveau suivi = {} suivi['COMMENT'] = '' suivi['USERMAJ'] = logged_in suivi['DATEMAJ'] = datetime.now() page_title= 'Nouveau suivi' else: # lire le suivi suivi = get_dossier_rdv_by_no(request, nodossier, nolig) if not suivi: request.session.flash(u"Suivi non trouvé : %s" % nodossier, 'warning') return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier)) page_title= u"Modification du suivi %s" % (nolig) if 'form.submitted' in request.params: new_values = {} for param, db_value in suivi.items(): if param in request.params and request.params[param] != db_value: new_values[param] = request.params[param] if new_values: new_values['USERMAJ'] = logged_in new_values['DATE'] = date.today() update_suivi(request, nodossier, nolig, new_values) request.session.flash(u"Le suivi a été mis à jour avec succès.", 'success') return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier)) if 'form.deleted' in request.params: delete_rdv(request, nodossier, nolig) request.session.flash(u"Le suivi a été supprimé avec succès.", 'success') return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier)) return { 'page_title': page_title, 'logged_in': logged_in, 'url': url, 'nodossier': nodossier, 'nolig': nolig, 'suivi': suivi, 'message': message, } @view_config(route_name='dossier_edit', renderer='../templates/dossier/dossier_edit.pt', permission='view') def dossier_edit(request): logged_in = request.authenticated_userid nodossier = request.matchdict['nodossier'] url = request.route_url('dossier_edit', nodossier=nodossier) dossier = get_dossier_by_no(request, nodossier) if not dossier: request.session.flash(u"Le dossier no %s est introuvable" % (nodossier), 'danger') return HTTPFound(location=request.route_url('dossier_lookup')) if 'form.submitted' in request.params: new_values = {} for param, db_value in dossier.items(): if param in request.params and request.params[param] != db_value: new_values[param] = request.params[param] if new_values: update_dossier(request, nodossier, new_values) request.session.flash(u"Le dossier a été mis à jour avec succès.", 'success') return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier)) return { 'page_title': u"Modifier le dossier : %s" % nodossier, 'url': url, 'dossier': dossier, 'nodossier': nodossier, } @view_config(route_name='upload_doc', renderer='../templates/dossier/upload_doc.pt', permission='view') def upload_doc(request): logged_in = request.authenticated_userid.upper() nodossier = request.matchdict['nodossier'] societe = nodossier[0:2] nochantier = nodossier[3:] url = request.route_url("upload_doc", nodossier=nodossier) message = "" dossier = get_dossier_by_no(request, nodossier) if dossier is None: request.session.flash(u"Le dossier no %s est introuvable" % (nodossier), 'danger') return HTTPFound(location=request.route_url("dossier_lookup")) # lire tous les documents attachés docs_attaches = get_docs_attaches(request, nodossier, 0, '') if 'form.submitted' in request.params: # récupère le fichier lui-même input_file = request.POST['filename'].file # récupère son nom input_name = request.POST['filename'].filename # récupère son extension input_ext = input_name.split('.')[-1] # controler l'extension ext_allowed = ['jpeg','jpg','png','pdf'] if input_ext.lower() not in ext_allowed : request.session.flash("Le format de ce fichier n'est pas valide. Téléchargement impossible.", 'warning') else: # récupère le nom du fichier et ajouter le no de dossier filename = '%s-DD%s-%s' % (societe, nochantier, request.POST['filename'].filename) # créer le répertoire du chantier s'il n'existe pas encore path = '%s/%s/%s' % (request.registry.settings['mondumas.devfac_dir'],societe,nochantier) os.makedirs(path, exist_ok=True) file_path = os.path.join(path, filename) # We first write to a temporary file to prevent incomplete files temp_file_path = file_path + '~' # Finally write the data to a temporary file input_file.seek(0) with open(temp_file_path, 'wb') as output_file: shutil.copyfileobj(input_file, output_file) # controler la taille du fichier < 4 Mo filesize = round(os.path.getsize(temp_file_path) / 1024) if filesize > 4096 : os.remove(temp_file_path) request.session.flash("La taille de ce fichier dépasse la limite autorisée. Téléchargement impossible.", 'warning') else: # Now that we know the file has been fully saved to disk move it into place. try: os.rename(temp_file_path, file_path) except OSError: os.remove(temp_file_path) request.session.flash('%s : Ce fichier existe déjà dans le rapport.' % input_name, 'danger') else: insert_dossier_attaches(request, nodossier, 0, filename, '%s Ko' % str(filesize), logged_in) request.session.flash('%s : Ce fichier est téléchargé avec succès.' % input_name, 'success') # lire tous les documents attachés docs_attaches = get_docs_attaches(request, nodossier, 0, '') return { 'page_title': u"Télécharger un document", 'url': url, 'nodossier': nodossier, 'dossier': dossier, 'docs_attaches': docs_attaches, 'docs_url': request.static_url(request.registry.settings['mondumas.devfac_url']), } @view_config(route_name='upload_img', renderer='../templates/dossier/upload_img.pt', permission='view') def upload_img(request): def photos_size(photos): # calculer la taille totale des photos sum_size = 0 for photo in photos : # récupère la taille sans ' Ko' sum_size += int(photo.taillefichier[:-3]) return '%s Mo' % round(sum_size / 1024, 1) logged_in = request.authenticated_userid.upper() norapport = request.matchdict['norapport'] url = request.route_url("upload_img", norapport=norapport) message = "" rapport = get_rapport_by_no_id(request, norapport) if rapport is None: request.session.flash(u"Le rapport no %s est introuvable" % (norapport), 'danger') return HTTPFound(location=request.route_url("rdf_list")) societe = rapport.societe nochantier = rapport.nochantier # lire tous les photos attachées photos = get_photos(request, nochantier, norapport) if 'form.submitted' in request.params: # récupère le fichier lui-même input_file = request.POST['filename'].file # récupère son nom input_name = request.POST['filename'].filename # récupère son extension input_ext = input_name.split('.')[-1] # controler l'extension ext_allowed = ['jpeg','jpg','png'] if input_ext.lower() not in ext_allowed : request.session.flash("Le format de ce fichier n'est pas valide. Téléchargement impossible.", 'warning') else: # récupère le nom du fichier et ajouter le no de rapport filename = '%s-RDF%s-%s' % (societe, norapport, input_name) # créer le répertoire du chantier s'il n'existe pas encore path = '%s/%s/%s/%s' % (request.registry.settings['mondumas.devfac_dir'], societe, nochantier, norapport) os.makedirs(path, exist_ok=True) file_path = os.path.join('%s/%s' % (path, filename)) # We first write to a temporary file to prevent incomplete files temp_file_path = file_path + '~' # Finally write the data to a temporary file input_file.seek(0) with open(temp_file_path, 'wb') as output_file: shutil.copyfileobj(input_file, output_file) # controler la taille du fichier < 4 Mo filesize = round(os.path.getsize(temp_file_path) / 1024) if filesize > 4096 : os.remove(temp_file_path) request.session.flash("La taille de ce fichier dépasse la limite autorisée. Téléchargement impossible.", 'warning') else: try: # using the Python Image Library (PIL) to resize an image resize_photos(temp_file_path, file_path) filesize = round(os.path.getsize(file_path) / 1024) # Now that we know the file has been fully saved to disk move it into place. os.remove(temp_file_path) except OSError: os.remove(temp_file_path) request.session.flash('%s : Ce fichier existe déjà dans le rapport.' % input_name, 'danger') else: insert_dossier_attaches(request, 'PL-%s' % nochantier, norapport, filename, '%s Ko' % str(filesize), logged_in) request.session.flash('%s : Ce fichier est téléchargé avec succès.' % input_name, 'success') # lire tous les photos attachées photos = get_photos(request, nochantier, norapport) return { 'page_title': u"Gérer les photos", 'url': url, 'nochantier': nochantier, 'norapport': norapport, 'rapport': rapport, 'photos': photos, 'total_size' : photos_size(photos), 'docs_url': request.static_url(request.registry.settings['mondumas.devfac_url']), } @view_config(route_name='rdf_edit', renderer='../templates/dossier/rdf_edit.pt', permission='view') def rdf_edit(request): logged_in = request.authenticated_userid.upper() nodossier = request.matchdict['nodossier'] date_inter = request.matchdict['date_inter'] if date_inter == 'new': date_inter = date.today().strftime('%Y-%m-%d') rapport = get_rapport_by_no(request, nodossier, date_inter) if not rapport: # creer un nouveau rapport insert_rapport(request, nodossier, logged_in) # lire le rapport rapport = get_rapport_by_no(request, nodossier, date_inter) url = request.route_url('rdf_edit', nodossier=nodossier, date_inter=date_inter) caracteristiques = ["Maison individuelle", "Immeuble collectif", "Copropriété", "Commerce", "Bureaux"] equipements = get_rdf_causes(request, 'C01') reseaux_int = get_rdf_causes(request, 'C02') reseaux_ext = get_rdf_causes(request, 'C03') reseaux_local = get_rdf_causes(request, 'C04') elements_clos = get_rdf_causes(request, 'C05') elements_couvert = get_rdf_causes(request, 'C06') voisins = get_rdf_causes(request, 'C07') tierce_personnes = get_rdf_causes(request, 'C08') if 'form.submitted' in request.params: if 'signature_svg' in request.params: if len(request.params['signature_svg']) > 7000: request.session.flash(u"La signature est trop grande !", 'danger') return HTTPFound(location=url) new_values = {} for param, db_value in rapport.items(): if param in request.params and request.params[param] != db_value: new_values[param] = request.params[param] # case à cocher ? if 'sonde_capa' in request.params: new_values['sonde_capa'] = 1 else: new_values['sonde_capa'] = 0 if 'sonde_cond' in request.params: new_values['sonde_cond'] = 1 else: new_values['sonde_cond'] = 0 if 'test_mano' in request.params: new_values['test_mano'] = 1 else: new_values['test_mano'] = 0 if 'test_gaz' in request.params: new_values['test_gaz'] = 1 else: new_values['test_gaz'] = 0 if 'visu_camera' in request.params: new_values['visu_camera'] = 1 else: new_values['visu_camera'] = 0 if 'visu_endoscope' in request.params: new_values['visu_endoscope'] = 1 else: new_values['visu_endoscope'] = 0 if 'visu_tele' in request.params: new_values['visu_tele'] = 1 else: new_values['visu_tele'] = 0 if 'rech_magnetique' in request.params: new_values['rech_magnetique'] = 1 else: new_values['rech_magnetique'] = 0 if 'rech_accoustique' in request.params: new_values['rech_accoustique'] = 1 else: new_values['rech_accoustique'] = 0 if 'test_accoustique' in request.params: new_values['test_accoustique'] = 1 else: new_values['test_accoustique'] = 0 if 'test_mise_en_eau' in request.params: new_values['test_mise_en_eau'] = 1 else: new_values['test_mise_en_eau'] = 0 if 'test_fumigenes' in request.params: new_values['test_fumigenes'] = 1 else: new_values['test_fumigenes'] = 0 if new_values: update_rapport(request, nodossier, date_inter, new_values) request.session.flash(u"Le dossier a été mis à jour avec succès.", 'success') return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier)) return { 'page_title': "Rapport de RDF : %s du %s" % (nodossier, rapport.date_inter.strftime('%d-%m-%Y')), 'url': url, 'logged_in': logged_in, 'rapport': rapport, 'nodossier': nodossier, 'caracteristiques': caracteristiques, 'equipements': equipements, 'reseaux_int': reseaux_int, 'reseaux_ext': reseaux_ext, 'reseaux_local': reseaux_local, 'elements_clos': elements_clos, 'elements_couvert': elements_couvert, 'voisins':voisins, 'tierce_personnes': tierce_personnes, } @view_config(route_name='rdf_list', renderer='../templates/dossier/rdf_list.pt', permission='view') def rdf_list(request): # lire les rapports de RDF items = get_rapport_rdf(request) # construire la liste liste=[] for item in items: if item.date_relu : date_relu = item.date_relu.strftime('%d-%m-%Y') else: date_relu = '' if item.date_rapport : date_rapport = item.date_rapport.strftime('%d-%m-%Y') else: date_rapport = '' d = (item.no_id, item.date_inter.strftime('%d-%m-%Y'), date_relu, date_rapport, '%s - %s %s' % (item.nochantier, item.C_QUALITE, item.C_NOM), item.NOMCLI, item.NOSIN, item.auteur_code) liste.append(d) return { 'page_title': u'Liste des rapports de RDF', 'dt_data': json.dumps(liste), } @view_config(route_name='rdf_view', renderer='../templates/dossier/rdf_view.pt', permission='view') def rdf_view(request): logged_in = request.authenticated_userid.upper() norapport = request.matchdict['no_id'] url = request.route_url('rdf_view', no_id=norapport) # lire le rapport rapport = get_rapport_by_no_id(request, norapport) nodossier = 'PL-' + str(rapport.nochantier) if rapport.date_relu: date_relu = rapport.date_relu.strftime('%d-%m-%Y') else: date_relu = '' if rapport.date_rapport: date_rapport = rapport.date_rapport.strftime('%d-%m-%Y') else: date_rapport = '' # lire tous les photos attachées photos = get_photos(request, rapport.nochantier, norapport) if 'form.generate' in request.params: options = { 'page-size': 'A4', 'margin-top': '0.65in', 'margin-right': '0.75in', 'margin-bottom': '0.65in', 'margin-left': '0.75in', } # créer le répertoire du rapport s'il n'existe pas encore path = '%s/%s/%s/%s' % (request.registry.settings['mondumas.devfac_dir'], 'PL', rapport.nochantier, norapport) os.makedirs(path, exist_ok=True) # générer le rapport en PDF filename = "PL-DD%s-rapport_RDF_no_%s.pdf" % (str(rapport.nochantier), norapport) dest = "mondumas/static/DEVFAC/DOCS_ATTACHES/PL/%s/%s" % (str(rapport.nochantier), filename) # developpement ou production if request.registry.settings["mail.host"] == "smtp.orange.fr": origin = 'https://gestion.entreprise-dumas.com/rdf_rapport/%s' % norapport pdfkit.from_url(origin, dest, options=options) else: origin = request.route_url('rdf_rapport', no_id=norapport) config = pdfkit.configuration(wkhtmltopdf="C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe") pdfkit.from_url(origin, dest, configuration=config, options=options) insert_dossier_attaches(request, nodossier, 0, filename, '160 Ko', logged_in) # si generation pdf, maj de la date du rapport new_values = {} new_values['date_rapport'] = date.today() update_rapport(request, nodossier, rapport.date_inter.strftime('%Y-%m-%d'), new_values) request.session.flash(u"Le rapport a été génré avec succès.", 'success') return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier)) if 'form.validate' in request.params: validate_rapport(request, norapport) request.session.flash(u"Le rapporta été validé avec succès.", 'success') if 'form.delete' in request.params: delete_rapport(request, norapport) request.session.flash(u"Le rapport a été supprimé avec succès.", 'success') return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier)) return { 'page_title': "Rapport no %s du %s" % (norapport, rapport.date_inter.strftime('%d-%m-%Y')), 'url': url, 'pt_name': 'rdf_view', 'logged_in': logged_in, 'rapport': rapport, 'nodossier': nodossier, 'nochantier': rapport.nochantier, 'norapport': norapport, 'date_rapport': date_rapport, 'date_relu': date_relu, 'photos': photos, 'docs_url': request.static_url(request.registry.settings['mondumas.devfac_url']), } @view_config(route_name='rdf_rapport', renderer='../templates/dossier/rdf_view.pt') def rdf_rapport(request): norapport = request.matchdict['no_id'] # lire le rapport rapport = get_rapport_by_no_id(request, norapport) nodossier = 'PL-' + str(rapport.nochantier) if rapport.date_rapport: date_rapport = rapport.date_rapport.strftime('%d-%m-%Y') else: date_rapport = '' if rapport.date_relu: date_relu = rapport.date_relu.strftime('%d-%m-%Y') else: date_relu = '' # lire tous les photos attachées photos = get_photos(request, rapport.nochantier, norapport) return { 'page_title': '', 'url': '', 'pt_name': 'rdf_rapport', 'rapport': rapport, 'nodossier': nodossier, 'nochantier': rapport.nochantier, 'norapport': norapport, 'date_rapport': date_rapport, 'date_relu': date_relu, 'photos': photos, 'docs_url': request.static_url(request.registry.settings['mondumas.devfac_url']), } @view_config(route_name='rdf_imgdel', permission='view') def rdf_imgdel(request): logged_in = request.authenticated_userid.upper() nochantier = request.matchdict['nochantier'] norapport = request.matchdict['norapport'] nomfic = request.matchdict['nomfic'] # supprimer le fichier file_path = '%s/PL/%s/%s/%s' % (request.registry.settings['mondumas.devfac_dir'], nochantier, norapport, nomfic) if os.path.exists(file_path): os.remove(file_path) delete_photos(request, nochantier, norapport, nomfic) request.session.flash(u"La photo %s a été supprimé avec succès" % (nomfic), 'success') return HTTPFound(location=request.route_url("upload_img", norapport=norapport)) @view_config(route_name='rdf_bill', renderer='../templates/dossier/rdf_bill.pt', permission='view') def rdf_bill(request): logged_in = request.authenticated_userid.upper() norapport = request.matchdict['no_id'] url = request.route_url('rdf_bill', no_id=norapport) # lire le rapport rapport = get_rapport_by_no_id(request, norapport) nodossier = 'PL-' + str(rapport.nochantier) if not rapport.date_rapport: request.session.flash(u"Le rapport n'a été encore généré. Facturation impossible", 'danger') return HTTPFound(location=request.route_url('rdf_view', no_id=norapport)) # lire tous les articles RDF articles = get_articles_by_fam(request, 'RDF') article = 'RDF1' if 'form.submitted' in request.params: # lire article à facturer article = request.params['article'] insert_facture_rdf(request, 'PL', rapport.nochantier, logged_in, article, rapport.date_rapport.strftime('%d-%m-%Y')) request.session.flash("Le rapport a été généré avec succès.", 'success') return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier)) return { 'page_title': "Générer une facture pour le rapport du %s" % (rapport.date_inter.strftime('%d-%m-%Y')), 'url': url, 'pt_name': 'rdf_view', 'logged_in': logged_in, 'rapport': rapport, 'nodossier': nodossier, 'nochantier': rapport.nochantier, 'norapport': norapport, 'articles': articles, 'article' : article, } @view_config(route_name='demandes', renderer='../templates/dossier/demandes.pt', permission='view') def demandes(request): logged_in = request.authenticated_userid.upper() url = request.route_url('demandes') # lire les demandes d'interventions arrivées par email mbx_name = 'peinture-dumas@entreprise-dumas.com' mbx_pwd = 'sasdumas' conn = imaplib.IMAP4_SSL('imap.entreprise-dumas.com') try: # se connecter à la mailbox 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')) # lire le INBOX rv, data = conn.select('INBOX', readonly =True) liste=[] # lire demandes de la MAIF mbx_search = 'FROM gestionsinistre@maif.fr SUBJECT "Missionnement r"' if 'form.submitted' in request.params: demandes_generer(request, conn, mbx_name, mbx_search, liste, logged_in) demandes_afficher(conn, mbx_name, mbx_search, liste) # lire demandes de DOMUS # mbx_search = 'FROM service.sinistres@domus-services.fr SUBJECT "Ordre de mission DOMUS - Dossier"' # demandes_afficher(conn, mbx_name, mbx_search, liste) conn.logout() return { 'page_title': 'Liste des demandes pour la PEINTURE', 'url': url, 'dt_data': json.dumps(liste), } def demandes_afficher(conn, mbx_name, search_criteria, liste): # créer la liste des entêtes des messages à afficher rv, data = conn.search(None, search_criteria) if rv != 'OK': request.session.flash("ERREUR de lecture de la boîte de réception", 'danger') return HTTPFound(location=request.route_url('home')) mail_ids = data[0] for num in mail_ids.split(): rv, msg_data = conn.fetch(num, '(RFC822)') if rv != 'OK': request.session.flash("ERREUR de lecture du message %s" % num, 'danger') return HTTPFound(location=request.route_url('home')) msg = email.message_from_bytes(msg_data[0][1]) hdr = email.header.make_header(email.header.decode_header(msg['Subject'])) email_subject = str(hdr) email_from = email.utils.parseaddr(msg['from'])[1] # Now convert to local date-time date_tuple = email.utils.parsedate_tz(msg['Date']) if date_tuple: email_date = datetime.fromtimestamp(email.utils.mktime_tz(date_tuple)) else: email_date = datetime.now() d = (str(int(num)), email_date.strftime('%d-%m-%Y %H:%M:%S'), email_from, mbx_name.replace('entreprise-dumas.com', ''), email_subject) liste.append(d) return liste def demandes_generer(request, conn, mbx_name, mbx_search, liste, logged_in): def download_pdf_to_tmp(email_message): # downloading attachments for part in email_message.walk(): # this part comes from the snipped I don't understand yet... if part.get_content_maintype() == 'multipart': continue if part.get('Content-Disposition') is None: continue fileName = part.get_filename() if bool(fileName): # copier le fichier PDF dans le dossier /tmp temp_file_path = os.path.join('/tmp/', fileName) if not os.path.isfile(temp_file_path) : fp = open(temp_file_path, 'wb') fp.write(part.get_payload(decode=True)) fp.close() return temp_file_path def convert_pdf_to_txt(path): resource_manager = PDFResourceManager() laparams = LAParams() converter = PDFPageAggregator(resource_manager, laparams=laparams) page_interpreter = PDFPageInterpreter(resource_manager, converter) extracted_text = "" with open(path, 'rb') as fh: for page in PDFPage.get_pages(fh, caching=True, check_extractable=True): page_interpreter.process_page(page) # The converter renders the layout from interpreter layout = converter.get_result() # Out of the many LT objects within layout, we are interested in LTTextBox and LTTextLine for lt_obj in layout: if isinstance(lt_obj, LTTextBox) or isinstance(lt_obj, LTTextLine): extracted_text += lt_obj.get_text() # close open handles converter.close() fh.close() # ecrire le texte dans un fichier extracted_file = '/tmp/log_file.txt' with open(extracted_file, "w") as my_log: my_log.write(extracted_text) my_log.close() return extracted_text, extracted_file def generer_dossier(request, mbx_name, mbx_search, extracted_file, temp_file_path, logged_in): # parcourir les lignes pour retrouver les infos utiles with open(extracted_file) as fp: cnt = 1 line = fp.readline() c_obs = '' tx_trav = '' while line: if line.find('Nos références') == 0: line = fp.readline() line = fp.readline() no_sinistre = line[:-1] if line.find('Bénéficiaire des travaux :') == 0: elt = line.split(' : ') c_nom = elt[1][:-1] line = fp.readline() line = fp.readline() line = fp.readline() c_adr = line[:-1] line = fp.readline() c_adr2 = line[:-1] line = fp.readline() c_adr3 = line[:-1] # début 3ème ligne adr est un code postal ? if to_int(c_adr3[0:5]) > 0 : # oui, mémoriser le code postal et la ville c_cp = c_adr3[0:5] c_ville = c_adr3[6:] else: # non, le code postal et la ville se trouvent dans la 2è ligne c_cp = c_adr2[0:5] c_ville = c_adr2[6:] c_adr2 = '' if line.find('N° de téléphone :') == 0: # les 10 derniers caratères c_tel1 = line[-11:-1] if 'une franchise de ' in line: i1 = line.find('franchise de ') i2 = line.find(' € ') c_obs = line[i1:i2+2] if ' pour un montant de ' in line: i1 = line.find('pour un montant de ') tx_trav = line[i1:-2].replace(',', '.') # lire ligne suivante line = fp.readline() cnt += 1 fp.close() # créer un dem_devis et récupèrer son no_id nochantier = insert_dossier(request, mbx_name, mbx_search, logged_in, c_nom, c_adr, c_adr2, c_cp, c_ville, c_tel1, no_sinistre, c_obs, tx_trav) societe = mbx_name[0:2].upper() nodossier = "%s-%s" % (societe, nochantier) # récupère le nom du fichier et ajouter le no de dossier filename = os.path.basename(temp_file_path) filename = '%s-DD%s-%s' % (societe, nochantier, filename) # créer le répertoire du chantier s'il n'existe pas encore path = '%s/%s/%s' % (request.registry.settings['mondumas.devfac_dir'],societe,nochantier) os.makedirs(path, exist_ok=True) file_path = os.path.join(path, filename) # Now that we know the file has been fully saved to disk move it into place. shutil.move(temp_file_path, file_path) # get filz size filesize = round(os.stat(file_path).st_size / 1000) insert_dossier_attaches(request, nodossier, 0, filename, '%s Ko' % str(filesize), logged_in) return # rechercher les emails de demandes dans le INBOX rv, data = conn.search(None, mbx_search) if rv != 'OK': request.session.flash("ERREUR de lecture de la boîte de réception", 'danger') return HTTPFound(location=request.route_url('home')) mail_ids = data[0] for num in mail_ids.split(): rv, msg_data = conn.fetch(num, '(RFC822)') if rv != 'OK': request.session.flash("ERREUR de lecture du message %s" % num, 'danger') return HTTPFound(location=request.route_url('home')) raw_email = msg_data[0][1] # converts byte literal to string removing b'' raw_email_string = raw_email.decode('utf-8') email_message = email.message_from_string(raw_email_string) email_subject = email_message['subject'] # demande annulée ? if email_subject.find('Annulation ') < 0: # downloading attachment temp_file_path = download_pdf_to_tmp(email_message) # convertir le fichier pdf en texte texte, extracted_file = convert_pdf_to_txt(temp_file_path) # mission annulée if 'Objet : ANNULATION MISSION' in texte: # supprime le pdf os.remove(temp_file_path) else: # genere le dossier d'après le mail generer_dossier(request, mbx_name, mbx_search, extracted_file, temp_file_path, logged_in) return def resize_photos(image_file, new_image_file): # using the Python Image Library (PIL) to resize an image img_org = Image.open(image_file) # get the size of the original image width_org, height_org = img_org.size # set the resizing factor so the aspect ratio can be retained # factor > 1.0 increases size # factor < 1.0 decreases size factor = 0.75 width = int(width_org * factor) height = int(height_org * factor) # best down-sizing filter img_anti = img_org.resize((width, height), Image.ANTIALIAS) # split image filename into name and extension name, ext = os.path.splitext(image_file) # create a new file name for saving the result img_anti.save(new_image_file) return