""" Ce fichier permet de gerer la relance des factures des client """ import ast import smtplib from email import encoders from email.mime.base import MIMEBase from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText import dateutil import pymongo import xlsxwriter from flask import send_file from pandas.io.formats.style import jinja2 from pymongo import MongoClient import json from bson import ObjectId import re from datetime import datetime, timezone, date from xhtml2pdf import pisa import prj_common as mycommon import secrets import inspect import sys, os import csv import pandas as pd from pymongo import ReturnDocument import GlobalVariable as MYSY_GV from math import isnan import GlobalVariable as MYSY_GV from datetime import timedelta from datetime import timedelta import Dashbord_queries.formation_tbd_qries as formation_tbd_qries from dateutil.relativedelta import relativedelta """ Creation d'une relance client """ def Create_Relance_Client_Facture_Given_Client_PDF(diction): try: diction = mycommon.strip_dictionary(diction) """ Verification des input acceptés """ field_list = ['token', 'client_id' ] incom_keys = diction.keys() for val in incom_keys: if val not in field_list and val.startswith('my_') is False: mycommon.myprint(str( inspect.stack()[0][3]) + " Le champ '" + val + "' n'est pas autorisé ") return False, " Les informations fournies sont incorrectes", """ Verification des champs obligatoires """ field_list_obligatoire = ['token', 'client_id' ] for val in field_list_obligatoire: if val not in diction: mycommon.myprint( str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans la liste des arguments ") return False, " Les informations fournies sont incorrectes", local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction) if (local_status is not True): return local_status, my_partner """ Verifier la validité du client """ is_clien_valide = MYSY_GV.dbname['partner_client'].count_documents({'_id':ObjectId(str(diction['client_id'])), 'partner_owner_recid':str(my_partner['recid']), 'valide':'1', 'locked':'0'}) if( is_clien_valide != 1): mycommon.myprint( str(inspect.stack()[0][ 3]) + " L'identifiant du client est invalide ") return False, " L'identifiant du client est invalide " """ Recuperer le modèle de document """ local_diction = {} local_diction['ref_interne'] = "RELANCE_FACTURE_CLIENT_LEVEL_1" local_diction['type_doc'] = "pdf" local_diction['partner_owner_recid'] = str(my_partner['recid']) courrier_data_status, courrier_data_retval = mycommon.Get_Courrier_Template_Include_Default_Data(local_diction) if (courrier_data_status is False): return courrier_data_status, courrier_data_retval if ("contenu_doc" not in courrier_data_retval.keys() or str(courrier_data_retval['contenu_doc']) == ""): mycommon.myprint( str(inspect.stack()[0][ 3]) + " Le modèle de courrier 'RELANCE_FACTURE_CLIENT_LEVEL_1' n'est pas correctement configuré ") return False, " Le modèle de courrier 'RELANCE_FACTURE_CLIENT_LEVEL_1' n'est pas correctement configuré " """ Recuperation du dictionnaire des info """ tab_client = [] tab_client.append(ObjectId(str(diction['client_id']))) new_diction = {} new_diction['token'] = diction['token'] new_diction['list_stagiaire_id'] = [] new_diction['list_session_id'] = [] new_diction['list_class_id'] = [] new_diction['list_client_id'] = tab_client new_diction['list_apprenant_id'] = [] local_status, local_retval = mycommon.Get_Dictionnary_data_For_Template(new_diction) if (local_status is False): return local_status, local_retval convention_dictionnary_data = local_retval """ Algo : 1 - recuperer toutes les facture du client arrivée a échangé et non payées 2 - Parcours les factures pour : - recuperer le total du reste à payer - le plus haut degré de relance 3 - Faire le courrier 4 - Mettre à jour chaque facutre pour mettre à jour la date de relance et le niveau de relance - tab_relance = [ {date_relance:'xxx', relance_id:'xxx'} ] 5 - Ajouter l'action dans l'historique du client """ todays_date = str(date.today().strftime("%d/%m/%Y")) todays_date_ISO_Date = datetime.strptime(str(todays_date).strip(), '%d/%m/%Y') find_qry = { 'mysy_invoice_reste_to_paye_num': { '$gt': 0}, 'mysy_invoice_du_date': {'$lt': todays_date_ISO_Date}, 'order_header_client_id': str(diction['client_id']), 'invoice_litige': {'$ne':'1'}, } query_invoice_echance_depace = [ {"$addFields": { "partner_invoice_header_Id": {"$toString": "$_id"}, "mysy_total_header_toutes_taxes": {"$convert": { 'input': "$total_header_toutes_taxes", 'to': "double", 'onError': {'error': 0}, 'onNull': {'isnull': 0} } }, "mysy_invoice_du_date": { '$dateFromString': { "dateString": { "$substr": [ {"$ifNull": ["$invoice_date_echeance", ""]}, 0, 10 ] }, "format": "%d/%m/%Y", "onError": "null", "onNull": "null" } }, "mysy_invoice_date": { "$dateFromString": { "dateString": { "$substr": [ {"$ifNull": ["$invoice_date", ""]}, 0, 10 ] }, "format": "%d/%m/%Y", "onError": 'null', "onNull": 'null' } }, "mysy_invoice_reste_to_paye_num": { "$convert": { "input": { "$replaceAll": { "input": { "$replaceAll": { "input": { "$ifNull": ["$reste_to_paye", "0"] }, "find": " ", "replacement": "" } }, "find": ",", "replacement": "." } }, "to": "double", "onError": 0, "onNull": 0 } } }, }, {'$match': find_qry}, { "$sort": { "mysy_invoice_reste_to_paye_num": 1 } }, { "$project": { "_id": 1, "invoice_header_ref_interne": 1, "invoice_header_type": 1, "invoice_date": 1, "invoice_date_echeance": 1, "order_header_client_id": 1, "order_header_email_client": 1, "partner_owner_recid": 1, "total_header_toutes_taxes": 1, "invoice_paiement_status": 1, "reste_to_paye": 1, "mysy_invoice_reste_to_paye_num": 1, 'tab_relance':1, } } ] print(" ### query_invoice_echance_depace = ", query_invoice_echance_depace) RetObject = [] val_tmp = 0 total_reste_to_paye = 0 max_relance_done = 0 tab_invoice_a_relancer = [] mytoday22 = datetime.today().strftime("%d/%m/%Y") for retval in MYSY_GV.dbname['partner_invoice_header'].aggregate(query_invoice_echance_depace): user = retval user['id'] = str(val_tmp) node_tab_relance = {} node_tab_relance['invoice_id'] = str(retval['_id']) node_tab_relance['invoice_header_ref_interne'] = retval['invoice_header_ref_interne'] node_tab_relance['total_header_toutes_taxes'] = str(round(float(retval['total_header_toutes_taxes']), 2)) node_tab_relance['reste_to_paye'] = str(round(float(retval['reste_to_paye']), 2)) node_tab_relance['invoice_date_echeance'] = retval['invoice_date_echeance'] node_tab_relance['invoice_date'] = retval['invoice_date'] retard = ( datetime.strptime( str(mytoday22),'%d/%m/%Y') - datetime.strptime(str(retval['invoice_date_echeance'])[0:10], '%d/%m/%Y')).days node_tab_relance['paiement_retard'] = str(retard) tab_invoice_a_relancer.append(node_tab_relance) total_reste_to_paye = total_reste_to_paye + float(retval['mysy_invoice_reste_to_paye_num']) """ Recuperer le niveau de relance à faire """ if( "tab_relance" in retval.keys()): if( len(retval['tab_relance']) > max_relance_done ): max_relance_done = len(retval['tab_relance']) val_tmp = val_tmp + 1 RetObject.append(mycommon.JSONEncoder().encode(user)) total_reste_to_paye = f"{float(total_reste_to_paye):,.2f}" total_reste_to_paye = total_reste_to_paye.replace(",", " ").replace(".", ",") print(" TOTAL DU = ", total_reste_to_paye) print(" Niveau relance = ", max_relance_done) new_relance_level = 0 if( max_relance_done < 3 ): new_relance_level = max_relance_done + 1 else: new_relance_level = 3 convention_dictionnary_data['tab_invoice_a_relancer'] = tab_invoice_a_relancer convention_dictionnary_data['total_reste_to_paye'] = str(total_reste_to_paye) convention_dictionnary_data['new_relance_level'] = str(new_relance_level) company_data = { "params": convention_dictionnary_data, } #print(" ###company_data = ", company_data) # read css file css_file = "./css_document/elyos_css.css" from xhtml2pdf.default import DEFAULT_CSS if css_file is not None: with open(css_file) as f: DEFAULT_CSS += f.read() contenu_doc_Template = jinja2.Template(str(courrier_data_retval['contenu_doc'])) sourceHtml = contenu_doc_Template.render(params=company_data['params']) ts = datetime.now().timestamp() ts = str(ts).replace(".", "").replace(",", "")[-5:] orig_file_name = "Relance_Fact_Client_" + str(my_partner['recid'])[0:2] + "_" + str(ts) + ".pdf" outputFilename = str(MYSY_GV.TEMPORARY_DIRECTORY) + "/" + str(orig_file_name) # open output file for writing (truncated binary) resultFile = open(outputFilename, "w+b") # convert HTML to PDF pisaStatus = pisa.CreatePDF( src=sourceHtml, # the HTML to convert dest=resultFile, default_css=DEFAULT_CSS) # file handle to receive result # close output file resultFile.close() """ Mettre à jour la relance des factures """ todays_date_heure = datetime.now().strftime("%d/%m/%Y %H:%M") for fact in tab_invoice_a_relancer: new_data = {} new_data['date_relance'] = str(todays_date_heure) new_data['relance_id'] = "xxx" create = MYSY_GV.dbname['partner_invoice_header'].update_one({ '_id': ObjectId(str(fact['invoice_id'])), 'partner_owner_recid': str(my_partner['recid']), }, { '$push': { "tab_relance": { '$each': [new_data] } } }, ) """ Inserter la relantion dans la collection : 'relance_client_invoice' """ new_relance_data = {} new_relance_data['clien_id'] = diction['client_id'] new_relance_data['tab_invoice'] = tab_invoice_a_relancer new_relance_data['relance_date'] = str(datetime.now().strftime("%d/%m/%Y %H:%M")) new_relance_data['relance_level'] = str(new_relance_level) new_relance_data['relance_by'] = str(my_partner['_id']) new_relance_data['total_reste_to_paye'] = str(total_reste_to_paye) new_relance_data['partner_owner_recid'] = str(my_partner['recid']) new_relance_data['update_date'] = str(datetime.now()) new_relance_data['update_by'] = str(my_partner['_id']) new_relance_data['valide'] = "1" new_relance_data['locked'] = "0" MYSY_GV.dbname['relance_client_invoice'].insert_one(new_relance_data) """ # Ajout de l'evenement sur la fiche client """ now = str(datetime.now().strftime("%d/%m/%Y %H:%M:%S")) history_event_dict = {} history_event_dict['token'] = diction['token'] history_event_dict['related_collection'] = "partnair_account" history_event_dict['related_collection_recid'] = str(diction['client_id']) history_event_dict['action_date'] = str(now) history_event_dict['action_description'] = "Relance facture client " local_status, local_retval = mycommon.Collection_Historique.Add_Historique_Event(history_event_dict) if (local_status is False): mycommon.myprint( " WARNING : Impossible de logguer l'historique pour l'évènement : " + str(history_event_dict)) # print(" ### outputFilename = "+str(outputFilename)) if os.path.exists(outputFilename): # print(" ### ok os.path.exists(outputFilename) "+str(outputFilename)) return True, send_file(outputFilename, as_attachment=True) # return True on success and False on errors print(pisaStatus.err, type(pisaStatus.err)) return True, " le fichier generé " except Exception as e: exc_type, exc_obj, exc_tb = sys.exc_info() mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno)) return False, " Impossible de faire la relance client " def Create_Relance_Client_Facture_Given_Client_Email(tab_files, Folder, diction): try: diction = mycommon.strip_dictionary(diction) """ Verification des input acceptés """ field_list = ['token', 'client_id' ] incom_keys = diction.keys() for val in incom_keys: if val not in field_list and val.startswith('my_') is False: mycommon.myprint(str( inspect.stack()[0][3]) + " Le champ '" + val + "' n'est pas autorisé ") return False, " Les informations fournies sont incorrectes", """ Verification des champs obligatoires """ field_list_obligatoire = ['token', 'client_id'] for val in field_list_obligatoire: if val not in diction: mycommon.myprint( str(inspect.stack()[0][ 3]) + " - La valeur '" + val + "' n'est pas presente dans la liste des arguments ") return False, " Les informations fournies sont incorrectes", local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction) if (local_status is not True): return local_status, my_partner """ Verifier la validité du client """ is_clien_valide = MYSY_GV.dbname['partner_client'].count_documents({'_id': ObjectId(str(diction['client_id'])), 'partner_owner_recid': str( my_partner['recid']), 'valide': '1', 'locked': '0'}) if (is_clien_valide != 1): mycommon.myprint( str(inspect.stack()[0][ 3]) + " L'identifiant du client est invalide ") return False, " L'identifiant du client est invalide " """ Recuperer le modèle de document """ local_diction = {} local_diction['ref_interne'] = "RELANCE_FACTURE_CLIENT_LEVEL_1" local_diction['type_doc'] = "email" local_diction['partner_owner_recid'] = str(my_partner['recid']) courrier_data_status, courrier_data_retval = mycommon.Get_Courrier_Template_Include_Default_Data(local_diction) if (courrier_data_status is False): return courrier_data_status, courrier_data_retval if ("contenu_doc" not in courrier_data_retval.keys() or str(courrier_data_retval['contenu_doc']) == ""): mycommon.myprint( str(inspect.stack()[0][ 3]) + " Le modèle de courrier 'RELANCE_FACTURE_CLIENT_LEVEL_1' n'est pas correctement configuré ") return False, " Le modèle de courrier 'RELANCE_FACTURE_CLIENT_LEVEL_1' n'est pas correctement configuré " #print(" IIIIIIIIIIIIIIIIIII courrier_data_retval[_id] = ", str(courrier_data_retval['_id'])) """ Recuperation du dictionnaire des info """ tab_client = [] tab_client.append(ObjectId(str(diction['client_id']))) new_diction = {} new_diction['token'] = diction['token'] new_diction['list_stagiaire_id'] = [] new_diction['list_session_id'] = [] new_diction['list_class_id'] = [] new_diction['list_client_id'] = tab_client new_diction['list_apprenant_id'] = [] local_status, local_retval = mycommon.Get_Dictionnary_data_For_Template(new_diction) if (local_status is False): return local_status, local_retval convention_dictionnary_data = local_retval """ Algo : 1 - recuperer toutes les facture du client arrivée a échangé et non payées 2 - Parcours les factures pour : - recuperer le total du reste à payer - le plus haut degré de relance 3 - Faire le courrier 4 - Mettre à jour chaque facutre pour mettre à jour la date de relance et le niveau de relance - tab_relance = [ {date_relance:'xxx', relance_id:'xxx'} ] 5 - Ajouter l'action dans l'historique du client """ todays_date = str(date.today().strftime("%d/%m/%Y")) todays_date_ISO_Date = datetime.strptime(str(todays_date).strip(), '%d/%m/%Y') find_qry = { 'mysy_invoice_reste_to_paye_num': {'$gt': 0}, 'mysy_invoice_du_date': {'$lt': todays_date_ISO_Date}, 'order_header_client_id': str(diction['client_id']), 'invoice_litige': {'$ne': '1'}, } query_invoice_echance_depace = [ {"$addFields": { "partner_invoice_header_Id": {"$toString": "$_id"}, "mysy_total_header_toutes_taxes": {"$convert": { 'input': "$total_header_toutes_taxes", 'to': "double", 'onError': {'error': 0}, 'onNull': {'isnull': 0} } }, "mysy_invoice_du_date": { '$dateFromString': { "dateString": { "$substr": [ {"$ifNull": ["$invoice_date_echeance", ""]}, 0, 10 ] }, "format": "%d/%m/%Y", "onError": "null", "onNull": "null" } }, "mysy_invoice_date": { "$dateFromString": { "dateString": { "$substr": [ {"$ifNull": ["$invoice_date", ""]}, 0, 10 ] }, "format": "%d/%m/%Y", "onError": 'null', "onNull": 'null' } }, "mysy_invoice_reste_to_paye_num": { "$convert": { "input": { "$replaceAll": { "input": { "$replaceAll": { "input": { "$ifNull": ["$reste_to_paye", "0"] }, "find": " ", "replacement": "" } }, "find": ",", "replacement": "." } }, "to": "double", "onError": 0, "onNull": 0 } } }, }, {'$match': find_qry}, { "$sort": { "mysy_invoice_reste_to_paye_num": 1 } }, { "$project": { "_id": 1, "invoice_header_ref_interne": 1, "invoice_header_type": 1, "invoice_date": 1, "invoice_date_echeance": 1, "order_header_client_id": 1, "order_header_email_client": 1, "partner_owner_recid": 1, "total_header_toutes_taxes": 1, "invoice_paiement_status": 1, "reste_to_paye": 1, "mysy_invoice_reste_to_paye_num": 1, 'tab_relance': 1, } } ] print(" ### query_invoice_echance_depace = ", query_invoice_echance_depace) RetObject = [] val_tmp = 0 total_reste_to_paye = 0 max_relance_done = 0 tab_invoice_a_relancer = [] mytoday22 = datetime.today().strftime("%d/%m/%Y") for retval in MYSY_GV.dbname['partner_invoice_header'].aggregate(query_invoice_echance_depace): user = retval user['id'] = str(val_tmp) node_tab_relance = {} node_tab_relance['invoice_id'] = str(retval['_id']) node_tab_relance['invoice_header_ref_interne'] = retval['invoice_header_ref_interne'] node_tab_relance['total_header_toutes_taxes'] = str(round(float(retval['total_header_toutes_taxes']), 2)) node_tab_relance['reste_to_paye'] = str(round(float(retval['reste_to_paye']), 2)) node_tab_relance['invoice_date_echeance'] = retval['invoice_date_echeance'] node_tab_relance['invoice_date'] = retval['invoice_date'] retard = (datetime.strptime(str(mytoday22), '%d/%m/%Y') - datetime.strptime( str(retval['invoice_date_echeance'])[0:10], '%d/%m/%Y')).days node_tab_relance['paiement_retard'] = str(retard) tab_invoice_a_relancer.append(node_tab_relance) total_reste_to_paye = total_reste_to_paye + float(retval['mysy_invoice_reste_to_paye_num']) """ Recuperer le niveau de relance à faire """ if ("tab_relance" in retval.keys()): if (len(retval['tab_relance']) > max_relance_done): max_relance_done = len(retval['tab_relance']) val_tmp = val_tmp + 1 RetObject.append(mycommon.JSONEncoder().encode(user)) total_reste_to_paye = f"{float(total_reste_to_paye):,.2f}" total_reste_to_paye = total_reste_to_paye.replace(",", " ").replace(".", ",") print(" TOTAL DU = ", total_reste_to_paye) print(" Niveau relance = ", max_relance_done) new_relance_level = 0 if (max_relance_done < 3): new_relance_level = max_relance_done + 1 else: new_relance_level = 3 convention_dictionnary_data['tab_invoice_a_relancer'] = tab_invoice_a_relancer convention_dictionnary_data['total_reste_to_paye'] = str(total_reste_to_paye) convention_dictionnary_data['new_relance_level'] = str(new_relance_level) company_data = { "params": convention_dictionnary_data, } ############################### # Traitement de l'eventuel fichier joint tab_files_to_attache_to_mail = [] tab_list_file_for_queu_mail_and_internal_mail = [] for saved_file in tab_files: file_to_attache_to_mail = MIMEBase('application', "octet-stream") file_to_attache_to_mail.set_payload(open(saved_file, "rb").read()) encoders.encode_base64(file_to_attache_to_mail) file_to_attache_to_mail.add_header('Content-Disposition', 'attachment; filename="{0}"'.format(os.path.basename(saved_file))) new_node = {"attached_file": file_to_attache_to_mail} tab_files_to_attache_to_mail.append(new_node) tab_list_file_for_queu_mail_and_internal_mail.append(saved_file) orig_file_name = None outputFilename = None # Verifier s'il s'agit d'un document à envoyer avec une version de pièce jointe. if ("joint_pdf" in courrier_data_retval.keys() and str(courrier_data_retval['joint_pdf']) == "1"): # Il s'agit bien d'un envoie avec 'contenu_doc' en pièce jointe PDF """ 1 - Creation du PDF """ contenu_doc_Template = jinja2.Template(str(courrier_data_retval['contenu_doc'])) sourceHtml = contenu_doc_Template.render(params=company_data["params"]) ts = datetime.now().timestamp() ts = str(ts).replace(".", "").replace(",", "")[-5:] orig_file_name = "Relance_Fact_Client_" + str(my_partner['recid'])[0:2] + "_" + str(ts) + ".pdf" outputFilename = str(MYSY_GV.TEMPORARY_DIRECTORY) + "/" + str(orig_file_name) # open output file for writing (truncated binary) resultFile = open(outputFilename, "w+b") # convert HTML to PDF pisaStatus = pisa.CreatePDF( src=sourceHtml, # the HTML to convert dest=resultFile) # file handle to receive result # close output file resultFile.close() # Attachement du fichier joint file_to_attache_to_mail = MIMEBase('application', "octet-stream") file_to_attache_to_mail.set_payload(open(outputFilename, "rb").read()) encoders.encode_base64(file_to_attache_to_mail) file_to_attache_to_mail.add_header('Content-Disposition', 'attachment; filename="{0}"'.format(os.path.basename(outputFilename))) new_node = {"attached_file": file_to_attache_to_mail} tab_files_to_attache_to_mail.append(new_node) ## Creation du mail au format email corps_mail_Template = jinja2.Template(str(courrier_data_retval['corps_mail'])) sourceHtml = corps_mail_Template.render(params=company_data["params"]) html_mime = MIMEText(sourceHtml, 'html') # Creation de l'email à enoyer msg = MIMEMultipart("alternative") # Attacher l'eventuelle pièces jointes for myfile in tab_files_to_attache_to_mail: msg.attach(myfile['attached_file']) else: # Il s'agit d'une simple email ## Creation du mail au format email contenu_doc_Template = jinja2.Template(str(courrier_data_retval['contenu_doc'])) sourceHtml = contenu_doc_Template.render(params=company_data["params"]) html_mime = MIMEText(sourceHtml, 'html') # Creation de l'email à enoyer msg = MIMEMultipart("alternative") # Traitement du sujet du mail sujet_mail_Template = jinja2.Template(str(courrier_data_retval['sujet'])) sujetHtml = sujet_mail_Template.render(params=company_data["params"]) # Recuperation des donnes smpt local_stpm_status, partner_SMTP_COUNT_smtpsrv, partner_own_smtp_value, partner_SMTP_COUNT_password, partner_SMTP_COUNT_user, partner_SMTP_COUNT_From_User, partner_SMTP_COUNT_port = mycommon.Get_Partner_SMTP_Param( my_partner['recid']) if (local_stpm_status is False): return local_stpm_status, partner_SMTP_COUNT_smtpsrv msg.attach(html_mime) if (str(partner_own_smtp_value) == "1"): msg['From'] = partner_SMTP_COUNT_From_User else: msg['From'] = str(partner_SMTP_COUNT_From_User) msg['Bcc'] = 'contact@mysy-training.com' msg['Subject'] = sujetHtml # msg['to'] = "billardman01@hotmail.com" """ Important : L'email est envoyé - au client principale, - au mail du invoiced - en copie le responsable du compte chez OF """ tab_email_contact_client_destinataire = [] client_data = MYSY_GV.dbname['partner_client'].find_one({'_id': ObjectId(str(diction['client_id'])), 'partner_owner_recid': str( my_partner['recid']), 'valide': '1', 'locked': '0'}, {'email':1, 'invoice_email':1, 'responsable_compte_id':1}) if( client_data and "email" in client_data.keys()): tab_email_contact_client_destinataire.append(client_data['email']) if (client_data and "invoice_email" in client_data.keys()): tab_email_contact_client_destinataire.append(client_data['invoice_email']) responsable_compte_email = "" if (client_data and "responsable_compte_id" in client_data.keys()): responsable_compte_data = MYSY_GV.dbname['ressource_humaine'].find_one({'_id': ObjectId(str(client_data['responsable_compte_id'])), 'partner_recid': str( my_partner['recid']), 'valide': '1', 'locked': '0'}, {'email':1, 'nom':1, 'prenom':1}) if( responsable_compte_data and 'email' in responsable_compte_data.keys()): responsable_compte_email = responsable_compte_data['email'] toaddrs = ",".join(tab_email_contact_client_destinataire) msg['to'] = str(toaddrs) msg['cc'] = str(responsable_compte_email) smtpserver = smtplib.SMTP(partner_SMTP_COUNT_smtpsrv, partner_SMTP_COUNT_port) smtpserver.ehlo() smtpserver.starttls() smtpserver.login(partner_SMTP_COUNT_user, partner_SMTP_COUNT_password) val = smtpserver.send_message(msg) smtpserver.close() print(" Email envoyé icii" + str(val)) ################################ """ Mettre à jour la relance des factures """ todays_date_heure = datetime.now().strftime("%d/%m/%Y %H:%M") for fact in tab_invoice_a_relancer: new_data = {} new_data['date_relance'] = str(todays_date_heure) new_data['relance_id'] = "xxx" create = MYSY_GV.dbname['partner_invoice_header'].update_one({ '_id': ObjectId(str(fact['invoice_id'])), 'partner_owner_recid': str(my_partner['recid']), }, { '$push': { "tab_relance": { '$each': [new_data] } } }, ) """ Inserter la relantion dans la collection : 'relance_client_invoice' """ new_relance_data = {} new_relance_data['clien_id'] = diction['client_id'] new_relance_data['tab_invoice'] = tab_invoice_a_relancer new_relance_data['relance_date'] = str(datetime.now().strftime("%d/%m/%Y %H:%M")) new_relance_data['relance_level'] = str(new_relance_level) new_relance_data['relance_by'] = str(my_partner['_id']) new_relance_data['total_reste_to_paye'] = str(total_reste_to_paye) new_relance_data['partner_owner_recid'] = str(my_partner['recid']) new_relance_data['update_date'] = str(datetime.now()) new_relance_data['update_by'] = str(my_partner['_id']) new_relance_data['valide'] = "1" new_relance_data['locked'] = "0" MYSY_GV.dbname['relance_client_invoice'].insert_one(new_relance_data) """ # Ajout de l'evenement sur la fiche client """ now = str(datetime.now().strftime("%d/%m/%Y %H:%M:%S")) history_event_dict = {} history_event_dict['token'] = diction['token'] history_event_dict['related_collection'] = "partnair_account" history_event_dict['related_collection_recid'] = str(diction['client_id']) history_event_dict['action_date'] = str(now) history_event_dict['action_description'] = "Relance facture client " local_status, local_retval = mycommon.Collection_Historique.Add_Historique_Event(history_event_dict) if (local_status is False): mycommon.myprint( " WARNING : Impossible de logguer l'historique pour l'évènement : " + str(history_event_dict)) return True, " La relance client a été correctement envoyée par email " except Exception as e: exc_type, exc_obj, exc_tb = sys.exc_info() mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno)) return False, " Impossible d'envoyer la relance client par email" """ Recuperer la liste des relances avec un filter """ def Get_List_Relance_with_filter(diction): try: diction = mycommon.strip_dictionary(diction) """ Verification des input acceptés """ field_list = ['token', 'client_id', 'invoice_id', 'invoice_ref', 'client_info'] incom_keys = diction.keys() for val in incom_keys: if val not in field_list and val.startswith('my_') is False: mycommon.myprint(str( inspect.stack()[0][3]) + " Le champ '" + val + "' n'est pas autorisé") return False, " Les informations fournies sont incorrectes" """ Verification des champs obligatoires """ field_list_obligatoire = ['token',] for val in field_list_obligatoire: if val not in diction: mycommon.myprint( str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans la liste des arguments ") return False, " Les informations fournies sont incorrectes" """ Verification de l'identité et autorisation de l'entité qui appelle cette API """ token = "" if ("token" in diction.keys()): if diction['token']: token = diction['token'] local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction) if (local_status is not True): return local_status, my_partner """ Filtre général sur le client (raison_sociale, nom, email, telephone """ filt_gle_client = {} tab_client_id = [] if ("client_info" in diction.keys() and diction['client_info']): local_myquery_gle = { "partner_owner_recid": str(my_partner['recid']), "valide": "1", "locked": "0", "$or": [ {'raison_sociale': {'$regex': mycommon.regex_replace_cartere(str(diction['client_info'])), "$options": "i"}}, {'nom': {'$regex': mycommon.regex_replace_cartere(str(diction['client_info'])), "$options": "i"}}, {'email': {'$regex': mycommon.regex_replace_cartere(str(diction['client_info'])), "$options": "i"}}, {'telephone': {'$regex': mycommon.regex_replace_cartere(str(diction['client_info'])), "$options": "i"}}, ] } for tmp in MYSY_GV.dbname['partner_client'].find(local_myquery_gle): tab_client_id.append(str(tmp['_id'])) if ("client_id" in diction.keys() and diction['client_id']): if (diction['client_id'] not in tab_client_id): tab_client_id.append(str(diction['client_id'])) filt_gle_client = {'client_id': {'$in': tab_client_id}} filter_invoice_id = {} if ("invoice_id" in diction.keys() and diction['invoice_id']): filter_invoice_id = {'tab_invoice.invoice_id': str(diction['invoice_id'])} filter_invoice_ref = {} if ("invoice_ref" in diction.keys() and diction['invoice_ref']): filter_invoice_ref = {'tab_invoice.invoice_header_ref_interne': str(diction['invoice_ref'])} qery_match = {'$and': [{"partner_owner_recid": str(my_partner['recid']), 'valide': '1', 'locked': '0'}, filter_invoice_id, filter_invoice_ref, filt_gle_client]} print(" ### relance list : qery_match = ", qery_match) RetObject = [] val_tmp = 0 for New_retVal in MYSY_GV.dbname['relance_client_invoice'].find(qery_match).sort([("_id", pymongo.DESCENDING), ]): user = New_retVal user['id'] = str(val_tmp) val_tmp = val_tmp + 1 RetObject.append(mycommon.JSONEncoder().encode(user)) return True, RetObject except Exception as e: exc_type, exc_obj, exc_tb = sys.exc_info() mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno)) return False, " Impossible de récupérer la liste des relances "