# -*- coding: utf8 -*- from pyramid.view import ( view_config, ) from pyramid.httpexceptions import ( HTTPFound, ) from datetime import * from PIL import Image import os import io import shutil import pdfkit 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 = '' member = get_member_by_id(request, logged_in) societe_defaut = member.societe societe = societe_defaut liste=[] name = '' if 'form.submitted' in request.params: name = request.params['name'] societe = request.params['societe'] # 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.libelle, item.usermaj) 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), '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) # lire son niveau d'accès member = get_member_by_id(request, logged_in) access = member.access 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 devis et factures du chantier 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, 'CLT', '') # lire tous les documents techniques docs_techniques = get_docs_attaches(request, nodossier, 0, 'FRN', '') 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 status = get_status_by_id(request, '') motifs = get_motifs(request) # lire les notes du dossier dem_notes = get_dem_notes(request, nodossier, '0') if 'form.close' in request.params: status = request.params["status"] motif = request.params["motif"] code, libelle = status.split(' | ') code = int(code) if code >= 10: comment = 'Le dossier est ' + libelle + ' : ' + motif insert_suivi(request, nodossier, comment) update_dossier_cloture(request, nodossier, code, logged_in) request.session.flash(u"Le dossier a été cloturé avec succès.", 'success') return HTTPFound(url) return { 'page_title': "Dossier : %s" % (nodossier), 'url': url, 'logged_in': logged_in, 'nodossier': nodossier, 'dossier': dossier, 'details': details, 'rapports': rapports, 'documents': documents, 'similaires': similaires, 'docs_attaches': docs_attaches, 'docs_techniques': docs_techniques, 'docs_url': request.static_url(request.registry.settings['mondumas.devfac_url']), 'bg_color': bg_color, 'access': access, 'status': status, 'motifs': motifs, 'motif': '', 'dem_notes': dem_notes, } @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) 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) # lire son niveau d'accès member = get_member_by_id(request, logged_in) access = member.access message = '' if nolig == '0': # nouveau suivi = {} suivi['attached_text'] = '' 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= "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, 'access': access, } @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) message = '' 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')) code_postal = '%s - %s' % (dossier.C_CP, dossier.C_VILLE) # lire table expert experts = get_experts(request, dossier.CABINET, 0) 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] # controle saisie code postal code_postal = request.params['code_postal'] cp = code_postal.split(' - ') if len(cp) < 2: message = 'Code postal invalide. Veuillez sélectionner un parmi la liste.' else: new_values['c_cp'] = cp[0] new_values['c_ville'] = cp[1] new_values['USERMAJ'] = logged_in.upper() # ascenseur coché ? if 'ascenseur' in request.params: new_values['c_ascenseur'] = 1 else: new_values['c_ascenseur'] = 0 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': "Modifier le dossier : %s" % nodossier, 'url': url, 'message': message, 'dossier': dossier, 'nodossier': nodossier, 'experts': experts, 'code_postal': code_postal, } @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'] origine = request.matchdict['origine'] if origine == 'CLT': page_title = "Télécharger un document PDF" else: page_title = "Télécharger un document technique" societe = nodossier[0:2] nochantier = nodossier[3:] url = request.route_url("upload_doc", nodossier=nodossier, origine=origine) 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, origine, '') if 'form.submitted' in request.params: # récupère le(s) fichier(s) download dans le dossier /tmp fileslist = request.POST.getall('files') for f in fileslist: # récupère le fichier download dans le dossier /tmp input_file = f.file input_name = f.filename ext_allowed = ['pdf',] temp_file = downloadFile2Temp(input_file, input_name, ext_allowed) if temp_file[:8] == 'ERREUR: ': request.session.flash(temp_file, 'danger') return HTTPFound(location=url) # fabriquer le nom du document filename = '%s-DD%s-%s' % (societe, nochantier, input_name) tempFile2Dossier(request, societe, nochantier, '0', origine, temp_file, filename, 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, origine, '') return { 'page_title': page_title, '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): """ Paramètres d'appel : - gestion images d'un dossier : norapport = numero du dossier origine = 'CLT' si images du dossier 'FRN' si images techniques - gestion images d'un rapport RDF : norapport = numéro du rapport de RDF origine = '1' ou '2', numéro du de la section du rapport """ origine = request.matchdict['origine'] # Gérer les photos d'un dossier ? if len(origine) > 1: norapport = '0' # oui, lire le dossier nodossier = request.matchdict['norapport'] rapport = get_dossier_by_no(request, nodossier) if rapport is None: request.session.flash(u"Le dossier no %s est introuvable" % (norapport), 'danger') return HTTPFound(location=request.route_url("rdf_list")) societe = rapport.societe nochantier = rapport.NO_ID url = request.route_url("upload_img", norapport=nodossier, origine=origine) url_retour = request.route_url('dossier_view', nodossier=nodossier) + '#tab_attaches' titre = "Gérer les photos du dossier %s" % (nodossier) else: norapport = request.matchdict['norapport'] 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 = 'PL' nochantier = rapport.nochantier nodossier = '%s-%s' % (societe, nochantier) url = request.route_url("upload_img", norapport=norapport, origine=origine) url_retour = request.route_url('rdf_view', no_id=norapport) titre = "Gérer les photos du rapport %s-%s/%s" % (societe, norapport, origine) logged_in = request.authenticated_userid.upper() message = "" if 'form.submitted' in request.params: # récupère le(s) fichier(s) download dans le dossier /tmp fileslist = request.POST.getall('files') for f in fileslist: input_file = f.file input_name = f.filename ext_allowed = ['jpeg','jpg','png'] temp_file = downloadFile2Temp(input_file, input_name, ext_allowed) if temp_file[:8] == 'ERREUR: ': request.session.flash(temp_file, 'danger') return HTTPFound(location=url) # fabriquer le nom du rapport filename = '%s-DD%s-%s-%s' % (societe, nochantier, norapport, input_name) tempFile2Dossier(request, societe, nochantier, norapport, origine, temp_file, filename, 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, nodossier, int(norapport), origine) return { 'page_title': titre, 'url': url, 'url_retour': url_retour, 'nodossier': nodossier, 'nochantier': nochantier, 'norapport': norapport, 'origine': origine, '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') # liste des users avec agenda users = get_users_agenda(request, '') # lire code accès du user access = get_userAccess(request, logged_in) 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] if 'date_inter' in request.params: ddate = datetime.strptime(request.params['date_inter'], '%d-%m-%Y') new_values['date_inter'] = ddate.strftime("%Y-%m-%d") # 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) + '#tab_rdf') 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, 'users': users, 'access': access, } @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': 'Liste des rapports de RDF', 'dt_data': json.dumps(liste), } @view_config(route_name='rdf_client', renderer='../templates/dossier/rdf_client.pt', permission='view') def rdf_client(request): logged_in = request.authenticated_userid.upper() norapport = request.matchdict['no_id'] message = '' # lire code accès du user access = get_userAccess(request, logged_in) if access == 0: request.session.flash("Vous n'avez pas les droits nécessaires pour changer de client.", 'danger') return HTTPFound(location=request.route_url('rdf_view', no_id=norapport)) url = request.route_url('rdf_client', no_id=norapport) # lire le rapport rapport = get_rapport_by_no_id(request, norapport) nodossier = 'PL-' + str(rapport.nochantier) if 'form.submitted' in request.params: nomClient = request.params['name'].split(' | ') if len(nomClient) == 2: update_rapport_client(request, norapport, nomClient[0], nomClient[1]) request.session.flash("Le client du rapporta été modifié avec succès.", 'success') return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier) + '#tab_rdf') else: message = "Veuillez saisir un nom de client ou Annuler" return { 'page_title': "Changer le client du RDF n° %s" % norapport, 'url': url, 'message': message, 'access': access, 'norapport': norapport, 'rapport': rapport, } @view_config(route_name='rdf_nochantier', renderer='../templates/dossier/rdf_nochantier.pt', permission='view') def rdf_nochantier(request): logged_in = request.authenticated_userid.upper() norapport = request.matchdict['no_id'] message = '' # lire code accès du user access = get_userAccess(request, logged_in) if access == 0: request.session.flash("Vous n'avez pas les droits nécessaires pour changer de client.", 'danger') return HTTPFound(location=request.route_url('rdf_view', no_id=norapport)) url = request.route_url('rdf_nochantier', no_id=norapport) # lire le rapport rapport = get_rapport_by_no_id(request, norapport) nodossier = 'PL-' + str(rapport.nochantier) if 'form.submitted' in request.params: new_nochantier = request.params['new_nochantier'] if len(new_nochantier) == 6: retour = update_rapport_nochantier(request, norapport, new_nochantier) if retour == "OK": request.session.flash("Le numéro du dossier été modifié avec succès.", 'success') return HTTPFound(location=request.route_url('rdf_view', no_id=norapport)) else: message = "Le numéro du dossier n'existe pas : %s" % new_nochantier else: message = "Un numero de dossier doit avoir 6 chiffres" return { 'page_title': "Changer le no du dossier du rapport n° %s" % norapport, 'url': url, 'message': message, 'access': access, 'norapport': norapport, 'rapport': rapport, } @view_config(route_name='rdf_view', renderer='../templates/dossier/rdf_view.pt', permission='view') def rdf_view(request): logged_in = request.authenticated_userid.upper() # lire code accès du user access = get_userAccess(request, logged_in) 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 = '' if rapport.date_facture: date_facture = rapport.date_facture.strftime('%d-%m-%Y') else: date_facture = '' # lire tous les photos attachées photos1 = get_photos(request, nodossier, norapport, '1') photos2 = get_photos(request, nodossier, norapport, '2') if 'form.generate' in request.params: footer_url = request.static_url('mondumas:static/img/footer_PL.html') # import pdb;pdb.set_trace() options = { 'page-size': 'A4', 'margin-top': '1cm', 'margin-right': '1cm', 'margin-bottom': '2cm', 'margin-left': '1.5cm', 'footer-font-size':'7', 'footer-right': '[page] / [topage]', } # 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) # supprimer le fichier s'il existe déjà if os.path.exists(dest): os.remove(dest) # developpement ou production if request.registry.settings["mondumas.admin_email"].find('@entreprise-dumas.com') > 0: 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, 'CLT', 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énéré avec succès.", 'success') return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier) + '#tab_rdf') if 'form.validate' in request.params: update_rapport_validate(request, norapport) request.session.flash(u"Le rapporta été validé avec succès.", 'success') return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier) + '#tab_rdf') if 'form.delete' in request.params: # le rapport a-t-il des photos ? if len(photos1) > 0 or len(photos2) > 0: request.session.flash(u"Veuillez supprimer les photos avant de supprimer Le rapport.", 'warning') return HTTPFound(location=url) 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) + '#tab_rdf') return { 'page_title': "Rapport no %s du %s" % (norapport, rapport.date_inter.strftime('%d-%m-%Y')), 'url': url, 'pt_name': 'rdf_view', 'access': access, 'rapport': rapport, 'nodossier': nodossier, 'nochantier': rapport.nochantier, 'norapport': norapport, 'date_rapport': date_rapport, 'date_relu': date_relu, 'date_facture': date_facture, 'photos1': photos1, 'photos2': photos2, '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'] logged_in = request.authenticated_userid if logged_in: # lire code accès du user access = get_userAccess(request, logged_in) else: # user anonyme access = 0 # 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 photos1 = get_photos(request, nodossier, norapport, '1') photos2 = get_photos(request, nodossier, norapport, '2') 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, 'photos1': photos1, 'photos2': photos2, 'docs_url': request.static_url(request.registry.settings['mondumas.devfac_url']), 'access': access, } @view_config(route_name='delete_img', permission='view') def delete_img(request): logged_in = request.authenticated_userid.upper() nodossier = request.matchdict['nodossier'] societe = nodossier[0:2] nochantier = nodossier[3:] norapport = request.matchdict['norapport'] origine = request.matchdict['origine'] nomfic = request.matchdict['nomfic'] # origine de l'image ? if len(origine) > 1: url_retour = location=request.route_url("upload_img", norapport=nodossier, origine=origine) else: url_retour = location=request.route_url("upload_img", norapport=norapport, origine=origine) delete_photos(request, nodossier, norapport, origine, nomfic) request.session.flash(u"La photo %s a été supprimée avec succès" % (nomfic), 'success') return HTTPFound(url_retour) @view_config(route_name='rotate_img', permission='view') def rotate_img(request): nodossier = request.matchdict['nodossier'] societe = nodossier[0:2] nochantier = nodossier[3:] norapport = request.matchdict['norapport'] origine = request.matchdict['origine'] nomfic = request.matchdict['nomfic'] angle = int(request.matchdict['angle']) # afin de refresh l'image, il faut lui donner un nouveau nom n = nomfic.split('.') new_nomfic = n[0] + 'r.' + n[1] # origine de l'image ? if len(origine) > 1: url_retour = location=request.route_url("upload_img", norapport=nodossier, origine=origine) image_file = '%s/%s/%s/%s' % (request.registry.settings['mondumas.devfac_dir'], societe, nochantier, nomfic) new_file = '%s/%s/%s/%s' % (request.registry.settings['mondumas.devfac_dir'], societe, nochantier, new_nomfic) else: url_retour = location=request.route_url("upload_img", norapport=norapport, origine=origine) image_file = '%s/%s/%s/%s/%s' % (request.registry.settings['mondumas.devfac_dir'], societe, nochantier, norapport, nomfic) new_file = '%s/%s/%s/%s/%s' % (request.registry.settings['mondumas.devfac_dir'], societe, nochantier, norapport, new_nomfic) # using the Python Image Library (PIL) to rotate an image img_in = Image.open(image_file) img_out = img_in.rotate(angle, expand=True) # create a new file name for saving the result img_out.save(new_file) # rename dans la BD rename_photos(request, nodossier, norapport, origine, nomfic, new_nomfic) return HTTPFound(url_retour) @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_rdf(request) article = 'RDF1' if 'form.submitted' in request.params: # lire article à facturer article = request.params['article'] insert_facture_rdf(request, 'PL', rapport.nochantier, rapport.CD_CLI, rapport.NOMCLI, logged_in, article, rapport.date_inter.strftime('%d-%m-%Y')) # marquer le rapport comme facturé update_rapport_facture(request, norapport) request.session.flash("Le rapport a été généré avec succès.", 'success') return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier) + '#tab_rdf') 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): def demandes_lister(societe, search_criteria): # créer la liste des entêtes des messages à afficher liste = [] # connecter au serveur de mail conn = mailbox_connect(request, societe) if conn == None: return liste # select INBOX rv, data = conn.select('INBOX', readonly =True) for criteria in search_criteria: rv, data = conn.search(None, 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 email_UID in mail_ids.split(): rv, msg_data = conn.fetch(email_UID, '(RFC822)') if rv != 'OK': request.session.flash("ERREUR de lecture du message %s" % email_UID, '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 = { "email_societe": societe, "email_date": email_date, "email_from": email_from.split('@')[1], 'email_subject':email_subject, "email_uid": email_UID } liste.append(d) # deconnexion du serveur conn.close() conn.logout() return liste # ------- main ------- logged_in = request.authenticated_userid.upper() url = request.route_url('demandes') message = '' societes = ['PE','ME','PL','PO'] # critères de recherche des demandes d'interventions de la MAIF # search_criteria = ['FROM service.sinistres@domus-services.fr SUBJECT "Ordre de mission DOMUS - Dossier" UNDELETED'] " search_criteria = ['FROM gestionsinistre@maif.fr SUBJECT "Intervention entreprise partenaire"', 'FROM service.sinistres@domus-services.fr SUBJECT "Ordre de mission DOMUS" UNDELETED'] emails=[] # lister les demandes par societe for societe in societes: emails = emails + demandes_lister(societe, search_criteria) dossiers_traites = get_dossiers_importes(request) return { 'page_title': "Liste des emails de demandes d'intervention", 'url': url, 'emails': emails, 'dossiers_traites': dossiers_traites, } @view_config(route_name='demandes_dl', permission='view') def demandes_dl(request): """ Lire le message et récupérer le PDF Analyser le PDF et génère le dossier """ def generer_mission(request, societe, mbx_search, extracted_file, temp_file_path): if 'maif.fr' in mbx_search: # extraire les infos de la demmande MAIF dem_info = get_pdf_infos_maif(extracted_file) if societe == 'PE': cd_cli = 2813 elif societe == 'ME': cd_cli = 589 elif societe == 'PO': cd_cli = 31 else: # VERSANIT cd_cli = 1743 elif 'domus-services.fr' in mbx_search: # extraire les infos de la demmande DOMUS dem_info = get_pdf_infos_domus(extracted_file) # toutes les demandes sont pour la société PE cd_cli = 8991 # extraction OK ? oui, créer une dem_devis et récupèrer son no_id traite = 0 if dem_info['c_nom'] != '': # oui, rechercher la dem_devis concerné par le no de sinistre nosin = dem_info['no_sinistre'] dem_devis = get_dossier_by_sinistre(request,societe, nosin) if dem_devis: # dem_devis existe, ajouter le PDF dans ce dossier nochantier = dem_devis.NO_ID nodossier = "%s-%s" % (societe, nochantier) # insérer une ligne de suivi ANNULATION insert_suivi(request, nodossier, '!!MISSION CONFIRMEE ou MODIFIEE PAR la MAIF') # log de nuit print('--> MODIFIER DOSSIER sinistre %s <--' % nodossier) else: # dem_devis n'existe pas, creer nouveau dossier nochantier = insert_dossier(request, societe, cd_cli, dem_info['c_nom'], dem_info['c_adr'], dem_info['c_adr2'], \ dem_info['c_cp'], dem_info['c_ville'], dem_info['c_telp'], dem_info['c_email'], nosin, '', dem_info['c_obs'], dem_info['tx_trav']) nodossier = "%s-%s" % (societe, nochantier) # log de nuit print('--> CREER DOSSIER sinistre %s <--' % nodossier) # 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) tempFile2Dossier(request, societe, nochantier, '0', 'CLT', temp_file_path, filename, 'EMAIL') traite = 1 return traite def generer_annul_maif(request, societe, extracted_file, temp_file_path): # extraire les infos de la demmande MAIF dem_info = get_pdf_infos_maif(extracted_file) # extraction OK ? oui, rechercher la dem_devis concerné traite = 0 if dem_info['c_nom'] != '': # oui, rechercher la dem_devis concerné par le no de sinistre nosin = dem_info['no_sinistre'] dem_devis = get_dossier_by_sinistre(request,societe, nosin) if dem_devis: nodossier = "%s-%s" % (societe, dem_devis.NO_ID) # récupère le nom du fichier et ajouter le no de dossier filename = '%s-DD%s-%s' % (societe, dem_devis.NO_ID, 'ANNULATION.pdf') tempFile2Dossier(request, societe, dem_devis.NO_ID, '0', 'CLT', temp_file_path, filename, 'EMAIL') # insérer une ligne de suivi ANNULATION insert_suivi(request, nodossier, '!!MISSION ANNULEE PAR la MAIF') # log de nuit print('--> ANNULATION DOSSIER sinistre %s <--' % nodossier) traite = 1 return traite def generer_annul_domus(request, societe, nosin, temp_file_path): traite = 0 # oui, rechercher la dem_devis concerné par le no de sinistre dem_devis = get_dossier_by_sinistre(request,societe, nosin) if dem_devis: nodossier = "%s-%s" % (societe, dem_devis.NO_ID) # récupère le nom du fichier et ajouter le no de dossier filename = '%s-DD%s-%s' % (societe, dem_devis.NO_ID, 'ANNULATION.pdf') tempFile2Dossier(request, societe, dem_devis.NO_ID, '0', 'CLT', temp_file_path, filename, 'EMAIL') #import pdb;pdb.set_trace() # insérer une ligne de suivi ANNULATION insert_suivi(request, nodossier, '!!MISSION ANNULEE PAR DOMUS') traite = 1 return traite # ------- main ------- societe = request.matchdict['societe'] email_from = request.matchdict['email_from'] email_uid = request.matchdict['email_uid'] logged_in = request.authenticated_userid.upper() message = '' if logged_in == 'TST': request.session.flash("Cette fonction est désactivée dans cette version de test", 'warning') return HTTPFound(request.route_url('demandes')) if 'maif' in email_from: search_criteria = 'FROM gestionsinistre@maif.fr SUBJECT "Intervention entreprise partenaire" UNDELETED' else: search_criteria = 'FROM ne-pas-repondre@domus-services.fr SUBJECT "Ordre de mission DOMUS" UNDELETED' # connecter au serveur de mail conn = mailbox_connect(request, societe) # select INBOX rv, data = conn.select('INBOX') conn.expunge() # rechercher les emails de demandes dans le INBOX 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('demandes')) # lire le message avec UID rv, msg_data = conn.fetch(email_uid, '(RFC822)') if rv != 'OK': request.session.flash("ERREUR de lecture du message %S-%s" % (email_from, email_uid), 'danger') return HTTPFound(location=request.route_url('demandes')) email_message = email.message_from_bytes(msg_data[0][1]) # get the message's body body = '' for part in email_message.walk(): ctype = part.get_content_type() cdispo = str(part.get('Content-Disposition')) # skip any text/plain (txt) attachments if ctype == 'text/html' and 'attachment' not in cdispo: body = part.get_payload(decode=True) # decode break # downloading attachment temp_file_path = download_pdf_to_tmp(email_message) if temp_file_path != '': # si attachement existe, convertir le fichier pdf en texte texte, extracted_file = pdf_convert_to_txt(temp_file_path) # mission annulée ? if 'Objet : ANNULATION MISSION' in texte : # genere ANNULATION mission MAIF n = generer_annul_maif(request, societe, extracted_file, temp_file_path) if n > 0: # déplacer le message dans la poubelle # import pdb;pdb.set_trace() conn.store(email_uid, '+FLAGS', '\\Deleted') elif 'ANNULATION ORDRE DE MISSION' in texte: # genere ANNULATION mission DOMUS nosin = texte.split('\n')[3] # 4ème ligne de texte n = generer_annul_domus(request, societe, nosin, temp_file_path) if n > 0: # déplacer le message dans la poubelle # import pdb;pdb.set_trace() conn.store(email_uid, '+FLAGS', '\\Deleted') else: #import pdb;pdb.set_trace() # genere le dossier d'après le mail n = generer_mission(request, societe, email_from, extracted_file, temp_file_path) if n > 0: # déplacer le message dans la poubelle # import pdb;pdb.set_trace() conn.store(email_uid, '+FLAGS', '\\Deleted') conn.expunge() conn.close() # deconnexion du serveur conn.logout() request.session.flash("La mission no %s de %s a été importée avec succès" % (email_uid, email_from), 'success') return HTTPFound(request.route_url('demandes')) def downloadFile2Temp(input_file, input_name, ext_allowed): # récupère son extension input_extension = input_name.split('.')[-1] # extensions autorisées ? if input_extension.lower() not in ext_allowed : return "ERREUR: Le format du fichier n'est pas valide. Téléchargement impossible." # Finally write the data to a temporary file temp_file_path = os.path.join('/tmp/', input_name) # supprimer le fichier s'il existe déjà if os.path.exists(temp_file_path): os.remove(temp_file_path) 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) return "ERREUR: La taille du fichier dépasse la limite autorisée. Téléchargement impossible." if input_extension in ['jpeg','jpg','png']: # using the Python Image Library (PIL) to resize an image resize_photos(temp_file_path) return temp_file_path def tempFile2Dossier(request, societe, nochantier, norapport, origine, temp_file, filename, logged_in): # créer le répertoire du chantier if norapport == '0': path = '%s/%s/%s' % (request.registry.settings['mondumas.devfac_dir'], societe, nochantier) else: path = '%s/%s/%s/%s' % (request.registry.settings['mondumas.devfac_dir'], societe, nochantier, norapport) os.makedirs(path, exist_ok=True) filepath = os.path.join('%s/%s' % (path, filename)) # supprimer le fichier s'il existe déjà if os.path.exists(filepath): os.remove(filepath) # Finally move the temporary file to folder shutil.move(temp_file, filepath) filesize = round(os.path.getsize(filepath) / 1024) insert_dossier_attaches(request, '%s-%s' % (societe, nochantier), norapport, origine, filename, '%s Ko' % str(filesize), logged_in) def download_pdf_to_tmp(email_message): # import pdb;pdb.set_trace() temp_file_path = '' # 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 pdf_convert_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", encoding="utf-8") as my_log: my_log.write(extracted_text) my_log.close() return extracted_text, extracted_file def get_pdf_infos_maif(extracted_file): # à partir du fichier texte du pdf # parcourir les lignes pour retrouver les infos utiles with open(extracted_file, encoding="utf-8") as fp: cnt = 1 line = fp.readline() # première ligne doit contenir "MAIF" ou "FILIA-MAIF" if line[:-1] not in ['MAIF', 'FILIA-MAIF']: return {'c_nom': ''} c_obs = '' tx_trav = '' c_telp = '' c_email = '' while line: if line.find('Nos références') == 0: line = fp.readline() line = fp.readline() # ne prendre que les 11 premiers car. du no sinistre MAIF no_sinistre = line[:11] if line.find('Bénéficiaire des travaux :') == 0: elt = line[:-1].split(' :') if len(elt) == 1: # le nom du chantier est sur la ligne suivante line = fp.readline() c_nom = line[:-1] c_nom = c_nom[:40] # ne prendre que 40 carac else: # le nom du chantier est sur la même ligne c_nom = elt[1].strip()[:40] 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 ' téléphone : ' in line: # les 10 derniers caratères # import pdb;pdb.set_trace() c_telp = line[-11:-1] if 'E-mail : ' in line: # séparer l'émail # import pdb;pdb.set_trace() elt = line[:-1].split(' : ') if len(elt) == 2: c_email = elt[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 montsant de ') tx_trav = line[i1:-2].replace(',', '.') # lire ligne suivante line = fp.readline() cnt += 1 fp.close() return {'c_nom': c_nom, 'c_adr': c_adr, 'c_adr2': c_adr2, 'c_cp': c_cp, 'c_ville': c_ville, 'c_telp': c_telp, 'c_obs': c_obs, 'c_email': c_email, 'tx_trav': tx_trav, 'no_sinistre': no_sinistre, } def get_pdf_infos_domus(extracted_file): # à partir du fichier texte du pdf de DOMUS # parcourir les lignes pour retrouver les infos utiles with open(extracted_file, encoding="utf-8") as fp: cnt = 1 line = fp.readline() # première ligne doit être : if line[:-1] != 'ORDRE DE MISSION': fp.close() return {'c_nom': ''} c_obs = '' tx_trav = '' c_telp = '' c_email = '' while line: if line.find('SINISTRE N°') == 0: line = fp.readline() line = fp.readline() no_sinistre = line[:-1] if line.find('Adresse du sinistre :') == 0: line = fp.readline() c_nom = line[:-1] line = fp.readline() c_adr = line[:-1] line = fp.readline() c_adr2 = line[:-1] # début 2ème ligne adr est un code postal ? if to_int(c_adr2) > 0 : # oui, mémoriser le code postal et la ville c_cp = c_adr2 line = fp.readline() c_ville = line[:-1] c_adr2 = '' else: # non, le code postal et la ville se trouvent dans la 3è ligne line = fp.readline() c_cp = line[:-1] c_ville = line[:-1] line = fp.readline() if 'Gsm : ' in line: # les 10 derniers caratères c_telp = line[-11:-1] # lire ligne suivante line = fp.readline() cnt += 1 fp.close() return {'c_nom': c_nom, 'c_adr': c_adr, 'c_adr2': c_adr2, 'c_cp': c_cp[:5], 'c_ville': c_ville, 'c_telp': c_telp, 'c_email': c_email, 'c_obs': c_obs, 'tx_trav': tx_trav, 'no_sinistre': no_sinistre, } def get_pdf_infos_axa(extracted_file): # à partir du fichier texte du pdf de AXA # parcourir les lignes pour retrouver les infos utiles with open(extracted_file, encoding="utf-8") as fp: cnt = 1 line = fp.readline() # première ligne doit être : #if line[:-1] != 'Assurance et Banque': # fp.close() # return {'c_nom': ''} c_nom = '' c_telp = '' c_email = '' while line: # déterminer la société if '@entreprise-dumas.com' in line : if 'peinture' in line : societe = 'PE' elif 'menuiserie' in line : societe = 'ME' else: societe = '' if line[:-1] == 'Contrat': # import pdb;pdb.set_trace() line = fp.readline() no_police = line[:-1] if line[:-1] == 'RØfØrence sinistre': # import pdb;pdb.set_trace() line = fp.readline() no_sinistre = line[:-1] if line[:-1] == 'Notre assurØ': # import pdb;pdb.set_trace() line = fp.readline() c_nom = line[:-1] 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 'portable ' in line: # import pdb;pdb.set_trace() # les 10 derniers caratères c_telp = line[-11:-1] line = fp.readline() # séparer l'émail # import pdb;pdb.set_trace() elt = line[:-1].split(': ') if len(elt) == 2: c_email = elt[1] # lire ligne suivante line = fp.readline() cnt += 1 fp.close() # import pdb;pdb.set_trace() return {'c_nom': c_nom, 'c_adr': c_adr, 'c_adr2': c_adr2, 'c_cp': c_cp[:5], 'c_ville': c_ville, 'c_telp': c_telp, 'c_email': c_email, 'no_police': no_police, 'no_sinistre': no_sinistre, 'societe': societe, 'assureur': 'AXA' } def get_pdf_infos_sinapps_AXA(extracted_file): # à partir du fichier texte du pdf de SINAPPS # parcourir les lignes pour retrouver les infos utiles with open(extracted_file, encoding="utf-8") as fp: line = fp.readline() # première ligne doit être : if line[:-1] != 'Mission': fp.close() return {'c_nom': ''} else: line = fp.readline() if 'AVANSSUR' in line: assureur = 'AVANSSUR' else: assureur = 'AXA' c_nom = '' c_telp = '' c_email = '' while line: # déterminer la société if 'Prestataire' in line : line = fp.readline() line = fp.readline() line = fp.readline() line = fp.readline() # import pdb;pdb.set_trace() if line[:-1] == 'DUMAS' : societe = 'PE' elif line[:-1] == 'MENUISERIE DUMAS' : societe = 'ME' else : societe = '' if line[:-1] == 'Numéro du contrat': line = fp.readline() no_police = line[:-1].lstrip("0") if 'Référence sinistre : ' in line: # import pdb;pdb.set_trace() no_sinistre = line[:-1].split(':')[1] no_sinistre = no_sinistre.strip().lstrip("0") if line[:-1] == 'Assuré/client': # import pdb;pdb.set_trace() line = fp.readline() c_nom = line[:-1].strip() line = fp.readline() c_email = line[:-1].strip() line = fp.readline() # tél = les 10 derniers caratères c_telp = line[-12:-1].strip() line = fp.readline() c_adr = line[:-1].strip() line = fp.readline() c_adr2 = line[:-1].strip() 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:].strip() 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 = '' # lire ligne suivante line = fp.readline() fp.close() # import pdb;pdb.set_trace() return {'c_nom': c_nom, 'c_adr': c_adr, 'c_adr2': c_adr2, 'c_cp': c_cp, 'c_ville': c_ville, 'c_telp': c_telp, 'c_email': c_email, 'no_police': no_police, 'no_sinistre': no_sinistre, 'societe': societe, 'assureur': assureur, } def get_pdf_infos_sinapps_MAIF(extracted_file): # à partir du fichier texte du pdf de SINAPPS # parcourir les lignes pour retrouver les infos utiles with open(extracted_file, encoding="utf-8") as fp: line = fp.readline() # première ligne doit être : if line[:-1] != 'Mission': fp.close() return {'c_nom': ''} c_nom = '' c_telp = '' c_email = '' no_police = '' while line: # déterminer la société if 'Prestataire' in line : # import pdb;pdb.set_trace() line = fp.readline() if 'VER SANIT' in line : societe = 'PL' else: line = fp.readline() line = fp.readline() line = fp.readline() if 'DUMAS' in line : societe = 'PE' elif 'MENUISERIE DUMAS' in line : societe = 'ME' elif 'VER SANIT' in line : societe = 'PL' else: societe = '' if 'Référence sinistre : ' in line: # import pdb;pdb.set_trace() no_sinistre = line[:-1].split(':')[1] no_sinistre = no_sinistre.strip().lstrip("0") if line[:-1] == 'Assuré/client': # import pdb;pdb.set_trace() line = fp.readline() c_nom = line[:-1].strip() line = fp.readline() c_email = line[:-1].strip() line = fp.readline() # tél = les 10 derniers caratères c_telp = line[-12:-1].strip() line = fp.readline() c_adr = line[:-1].strip() line = fp.readline() c_adr2 = line[:-1].strip() 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:].strip() 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 = '' # lire ligne suivante line = fp.readline() fp.close() # import pdb;pdb.set_trace() return {'c_nom': c_nom, 'c_adr': c_adr, 'c_adr2': c_adr2, 'c_cp': c_cp[:5], 'c_ville': c_ville, 'c_telp': c_telp, 'c_email': c_email, 'no_police': no_police, 'no_sinistre': no_sinistre, 'societe': societe, 'assureur': 'MAIF' } def resize_photos(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 max width width = 1366 height = int(height_org / width_org * width) # 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(image_file) return 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) @view_config(route_name='upload_om', renderer='../templates/dossier/upload_om.pt', permission='view') def upload_om(request): """ UPLOAD d'un ordre de mission en PDF """ def generer_mission(request, dem_info, temp_file_path): # import pdb;pdb.set_trace() societe = dem_info['societe'] if societe == '': return "Descriptif de travaux non prevu par le programme. Prévenir M. CAO." if dem_info['assureur'] == 'AXA': if societe == 'PE': cd_cli = 9150 else : # menuiserie cd_cli = 5858 elif dem_info['assureur'] == 'AVANSSUR': if societe == 'PE': cd_cli = 10149 else : # menuiserie cd_cli = 1929 else: # assureur = MAIF if societe == 'PE': cd_cli = 2813 elif societe == 'ME': # menuiserie cd_cli = 589 else: cd_cli = 1743 # extraction OK ? oui, créer une dem_devis et récupèrer son no_id message = '' if dem_info['c_nom'] != '': # oui, rechercher la dem_devis concerné par le no de sinistre nosin = dem_info['no_sinistre'] dem_devis = get_dossier_by_sinistre(request,societe, nosin) if dem_devis: # dem_devis existe, ajouter le PDF dans ce dossier nochantier = dem_devis.NO_ID nodossier = "%s-%s" % (societe, nochantier) # insérer une ligne de suivi ANNULATION insert_suivi(request, nodossier, '!!MISSION CONFIRMEE ou MODIFIEE PAR la MAIF') # log de nuit print('--> MODIFIER DOSSIER sinistre %s <--' % nodossier) else: # dem_devis n'existe pas, creer nouveau dossier nochantier = insert_dossier(request, societe, cd_cli, dem_info['c_nom'], dem_info['c_adr'], dem_info['c_adr2'], dem_info['c_cp'], \ dem_info['c_ville'], dem_info['c_telp'], dem_info['c_email'], dem_info['no_sinistre'], dem_info['no_police'], '', '') nodossier = "%s-%s" % (societe, nochantier) # log de nuit print('--> CREER DOSSIER sinistre %s <--' % nodossier) # 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) tempFile2Dossier(request, societe, nochantier, '0', 'CLT', temp_file_path, filename, 'EMAIL') return message logged_in = request.authenticated_userid.upper() url = request.route_url("upload_om") message = '' html_text = '' if 'form.submitted' in request.params or 'form.previewed' in request.params: # récupère le fichier download dans le dossier /tmp input_file = request.POST['filename'].file input_name = request.POST['filename'].filename ext_allowed = ['pdf'] temp_file = downloadFile2Temp(input_file, input_name, ext_allowed) if temp_file[:8] == 'ERREUR: ': request.session.flash(temp_file, 'danger') return HTTPFound(location=url) # convertir le fichier pdf en texte extracted_text, extracted_file = pdf_convert_to_txt(temp_file) # prévisualiser le pdf if 'form.previewed' in request.params: # convert text to html html_text = "

" + extracted_text.replace("\n", "
") + "

" html_text = html_text.replace("Ø", "é") # importer le pdf if 'form.submitted' in request.params: # import pdb;pdb.set_trace() # Déterminer l'origine du PDF if 'Votre conseiller AXA' in extracted_text and 'bon de commande pour les travaux' in extracted_text: # PDF = ordre de mission AXA ? # extraire les infos de la demmande AXA dem_info = get_pdf_infos_axa(extracted_file) elif 'Envoyé par MAIF le ' in extracted_text : # PDF envoyé par sur SINAPPS # extraire les infos de la mission dem_info = get_pdf_infos_sinapps_MAIF(extracted_file) elif 'Envoyé par AXA FRANCE IRD le' in extracted_text or 'Envoyé par AVANSSUR - DIRECT ASSURANCE le' in extracted_text: # PDF envoyé par AXA ou AVANSSUR sur SINAPPS # extraire les infos de la mission dem_info = get_pdf_infos_sinapps_AXA(extracted_file) else: message = "ERREUR : Ce document n'est pas une demande de prestations AXA ou MAIF." # genere le dossier d'après le fichier PDF if message == '': message = generer_mission(request, dem_info, temp_file) if message : request.session.flash(message, 'danger') else: request.session.flash("Le fichier PDF de %s a été importé dans la societe %s avec succès." % (dem_info['assureur'], dem_info['societe']), 'success') return HTTPFound(location=request.route_url('dossier_lookup')) return { 'page_title': 'Importer un ordre de mission AXA ou MAIF', 'url': url, 'message': message, 'html_text': html_text, } @view_config(route_name='dem_devis', renderer='../templates/dossier/dem_devis.pt', permission='view') def dem_devis(request): logged_in = request.authenticated_userid.upper() goto_url = '/dossier_selected/dossier_view/%s/' % date.today().strftime('%Y-%m-%d') url = request.route_url('dem_devis') member = get_member_by_id(request, logged_in) societe_defaut = member.societe societe = societe_defaut access_defaut = member.access liste=[] if 'form.submitted' in request.params: societe = request.params['societe'] dossiers_traites = get_dossiers_traites(request, societe) for item in dossiers_traites: d = ('%s-%s' % (societe, item.numero),item.date.strftime('%d-%m-%Y'), item.nomcli, item.chantier, to_euro(item.montant), item.nosin, item.libelle, item.usermaj) liste.append(d) order_option = 'desc' return { 'page_title': 'Dossiers avec statut: "A TRAITER"', 'url': url, 'goto_url': goto_url, 'dt_data': json.dumps(liste), 'societe': societe, 'order_option': order_option, } @view_config(route_name='note_edit', renderer='../templates/dossier/note_edit.pt', permission='view') def note_edit(request): logged_in = request.authenticated_userid.upper() nodossier = request.matchdict['nodossier'] noligne = request.matchdict['noligne'] url = request.route_url('note_edit', nodossier=nodossier, noligne=noligne) message = "" if noligne == '0': page_title = nodossier + ' : Nouvelle note' note = {} note['notes'] = '' note['usermaj'] = logged_in note['modif_le'] = date.today() else: note = get_dem_notes(request, nodossier, noligne) page_title = nodossier + " : " + note.libelle if 'form.submitted' in request.params: notes = request.params["notes"] update_dem_note(request, nodossier, noligne, notes, logged_in) request.session.flash("La note a été modifiée avec succès.", 'success') return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier) + '#tab_attaches') if 'form.deleted' in request.params: delete_dem_note(request, nodossier, noligne) request.session.flash("'%s' a été supprimée avec succès." % note.libelle, 'success') return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier) + '#tab_attaches') return { 'page_title': page_title, 'url': url, 'message': message, 'nodossier': nodossier, 'note': note, } @view_config(route_name='dessin_edit', renderer='../templates/dossier/dessin_edit.pt', permission='view') def dessin_edit(request): logged_in = request.authenticated_userid.upper() nodossier = request.matchdict['nodossier'] noligne = request.matchdict['noligne'] url = request.route_url('dessin_edit', nodossier=nodossier, noligne=noligne) societe = nodossier[0:2] nochantier = nodossier[3:] message = "" if noligne == '0': page_title = nodossier + ' : Nouveau dessin' else: page_title = nodossier + " : " if 'form.submitted' in request.params: # get the base64-encoded-canvas image img_data = request.params["image"] img_data = img_data.replace('data:image/png;base64', '') img_data = img_data.replace(' ', '+') # convertir image de string en bytes img_bytes = img_data.encode('utf-8') decoded_image = base64.decodebytes(img_bytes) # lire le nombre de dessins déjà créés nb_dessins = get_nb_dessins(request, nodossier) # fabriquer le nom du dessin filename = '%s-DD%s-%s' % (societe, nochantier, 'DESSIN No ' + str(nb_dessins + 1) + ".png") path = '%s/%s/%s' % (request.registry.settings['mondumas.devfac_dir'], societe, nochantier) # créer le répertoire du chantier os.makedirs(path, exist_ok=True) filepath = os.path.join('%s/%s' % (path, filename)) # ecrire l'image dans un fichier PNG f = open(filepath, "wb") f.write(decoded_image) f.close filesize = round(os.path.getsize(filepath) / 1024) insert_dossier_attaches(request, '%s-%s' % (societe, nochantier), 0, 'FRN', filename, '%s Ko' % str(filesize), logged_in) request.session.flash('%s est enregistré dans les DOC. TECHNIQUES.' % filename, 'success') return HTTPFound(location=request.route_url('dossier_view', nodossier=nodossier) + '#tab_attaches') return { 'page_title': page_title, 'url': url, 'message': message, 'nodossier': nodossier, } @view_config(route_name='dern_suivis', renderer='../templates/dossier/dern_suivis.pt', permission='view') def dern_suivis(request): # lire les derniers suivis créés par les attachés de clientèle items = get_derniers_suivis(request) return { 'page_title': 'Derniers suivis créés', 'items': items, }