09/05/2025 - 20h30

Signed-off-by: Cherif <cbalde@mysy-training.com>
master_Elyos_FI
Cherif 2026-05-09 20:35:08 +02:00
parent 6f81ec23e5
commit fa27fdcc3b
9 changed files with 7363 additions and 67 deletions

View File

@ -4,17 +4,16 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="07/05/2026 - 17h">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="08/05/2026 - 17h">
<change afterPath="$PROJECT_DIR$/Relance_client_facture.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Dashbord_queries/factures_tbd_qries.py" beforeDir="false" afterPath="$PROJECT_DIR$/Dashbord_queries/factures_tbd_qries.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Inscription_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/Inscription_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Log/log_file.log" beforeDir="false" afterPath="$PROJECT_DIR$/Log/log_file.log" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Session_Formation.py" beforeDir="false" afterPath="$PROJECT_DIR$/Session_Formation.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Session_Formation_Sequence.py" beforeDir="false" afterPath="$PROJECT_DIR$/Session_Formation_Sequence.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apprenant_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/apprenant_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/invoice_paiement_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/invoice_paiement_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/partner_client.py" beforeDir="false" afterPath="$PROJECT_DIR$/partner_client.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/partner_invoice.py" beforeDir="false" afterPath="$PROJECT_DIR$/partner_invoice.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/partners.py" beforeDir="false" afterPath="$PROJECT_DIR$/partners.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -458,7 +457,7 @@
<option name="project" value="LOCAL" />
<updated>1747251650255</updated>
</task>
<option name="localTasksCounter" value="575" />
<option name="localTasksCounter" value="576" />
<servers />
</component>
<component name="Vcs.Log.Tabs.Properties">
@ -500,7 +499,6 @@
</option>
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="18/03/2026 - 22h" />
<MESSAGE value="20/03/2026 - 9h" />
<MESSAGE value="20/03/2026 - 20h" />
<MESSAGE value="23/03/2026 - 20h" />
@ -525,6 +523,7 @@
<MESSAGE value="04/05/2026 - 19h" />
<MESSAGE value="05/05/2026 - 19h" />
<MESSAGE value="07/05/2026 - 17h" />
<option name="LAST_COMMIT_MESSAGE" value="07/05/2026 - 17h" />
<MESSAGE value="08/05/2026 - 17h" />
<option name="LAST_COMMIT_MESSAGE" value="08/05/2026 - 17h" />
</component>
</project>

File diff suppressed because one or more lines are too long

872
Relance_client_facture.py Normal file
View File

@ -0,0 +1,872 @@
"""
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]
}
}
},
)
"""
# 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]
}
}
},
)
"""
# 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"

View File

@ -11981,6 +11981,8 @@ def Invoice_Partner_From_Session( diction):
partner_invoice_header_data['total_header_toutes_taxes'] = str(round(total_ht + (tva_value * total_ht)/100, 2))
partner_invoice_header_data['invoice_header_type'] = "facture"
partner_invoice_header_data['reste_to_paye'] = str(partner_invoice_header_data['total_header_toutes_taxes'])
# Récuperation de la sequence de l'objet "partner_invoice_header" dans la collection : "mysy_sequence"
retval_sequence_invoice = MYSY_GV.dbname['mysy_sequence'].find_one(
{'related_mysy_object': 'partner_invoice_header',
@ -14486,6 +14488,8 @@ def Invoice_Partner_From_Session_By_Inscription_Id( diction):
partner_invoice_header_data['total_header_toutes_taxes'] = str(round(total_ht + (tva_value * total_ht)/100, 2))
partner_invoice_header_data['invoice_header_type'] = "facture"
partner_invoice_header_data['reste_to_paye'] = str(partner_invoice_header_data['total_header_toutes_taxes'])
# Récuperation de la sequence de l'objet "partner_invoice_header" dans la collection : "mysy_sequence"
@ -15149,6 +15153,8 @@ def Invoice_Splited_Partner_From_Session_By_Inscription_Id( diction):
partner_invoice_header_data['total_header_toutes_taxes'] = str(round(split_invoice_part_FLOAT + (tva_value * split_invoice_part_FLOAT)/100, 2))
partner_invoice_header_data['invoice_header_type'] = "facture"
partner_invoice_header_data['reste_to_paye'] = str(partner_invoice_header_data['total_header_toutes_taxes'])
text_comment = "Montant total HT = "+str(total_ht)
if( str(split_type) == "percent"):
text_comment = text_comment + "\nType partage facture : POURCENTAGE \nMontant de la facture = "+str(split_invoice_part)

View File

@ -59,7 +59,7 @@ def Add_Invoice_Paiement(diction):
Verification des input acceptés
"""
field_list = ['token', 'invoice_id', 'paiement_amount', 'paiement_mode', 'paiement_ref',
'paiement_date', 'commentaire']
'paiement_date', 'commentaire', 'client_id', 'invoice_ref']
incom_keys = diction.keys()
@ -159,7 +159,7 @@ def Add_Invoice_Paiement(diction):
if( "total_header_toutes_taxes" in is_existe_invoice_data.keys() ):
total_invoice_amount = is_existe_invoice_data['total_header_toutes_taxes']
print(" ### 00 total_invoice_amount = ", total_invoice_amount)
#print(" ### 00 total_invoice_amount = ", total_invoice_amount)
local_status, local_retval = mycommon.IsFloat(total_invoice_amount)
if (local_status is False):
@ -169,18 +169,20 @@ def Add_Invoice_Paiement(diction):
total_invoice_amount_float = local_retval
print(" ### 00 local_retval (is float) = ", local_retval)
#print(" ### 00 local_retval (is float) = ", local_retval)
"""
Récuprer les paiement déjà effectué
"""
local_diction = {"token": str(diction['token']), "invoice_id": str(diction['invoice_id'])}
local_list_paiement_status, local_list_paiement_retval = Get_Invoice_Liste_Payement_And_Total_Amount(local_diction)
local_list_paiement_status, local_list_paiement_retval, local_total_payed = Get_Invoice_Liste_Payement_And_Total_Amount(local_diction)
if( local_list_paiement_status is False ):
return local_list_paiement_status, local_list_paiement_retval
#print(" Les payement = ", local_list_paiement_retval)
#print(" local_total_payed = ", local_total_payed)
list_payment = ast.literal_eval(local_list_paiement_retval[0])
@ -226,6 +228,8 @@ def Add_Invoice_Paiement(diction):
new_data['update_date'] = str(datetime.now())
new_data['update_by'] = str(my_partner['_id'])
new_data['partner_owner_recid'] = str(my_partner['recid'])
new_data['client_id'] = str(is_existe_invoice_data['order_header_client_id'])
new_data['invoice_ref'] = str(is_existe_invoice_data['invoice_header_ref_interne'])
inserted_id = MYSY_GV.dbname['invoice_paiement'].insert_one(new_data).inserted_id
if (not inserted_id):
@ -584,6 +588,7 @@ def Update_Invoice_Paiement(diction):
"""
Cette fonction permet de retourner la liste des payements valides
avec le total associé.
Filter : Client, Facture
"""
def Get_Invoice_Liste_Payement(diction):
@ -593,7 +598,7 @@ def Get_Invoice_Liste_Payement(diction):
"""
Verification des input acceptés
"""
field_list = ['token', 'invoice_id', ]
field_list = ['token', 'invoice_id', 'client_info', 'client_id', 'invoice_ref']
incom_keys = diction.keys()
for val in incom_keys:
@ -605,7 +610,7 @@ def Get_Invoice_Liste_Payement(diction):
"""
Verification des champs obligatoires
"""
field_list_obligatoire = ['token', 'invoice_id', ]
field_list_obligatoire = ['token', ]
for val in field_list_obligatoire:
if val not in diction:
@ -628,27 +633,71 @@ def Get_Invoice_Liste_Payement(diction):
# Verifier que la facture existe et est valide
is_existe_invoice = MYSY_GV.dbname['partner_invoice_header'].count_documents({'_id':ObjectId(str(diction['invoice_id'])),
'valide':'1',
'locked':'0',
'partner_owner_recid':str(my_partner['recid'])})
if ("invoice_id" in diction.keys() and diction['invoice_id']):
is_existe_invoice = MYSY_GV.dbname['partner_invoice_header'].count_documents({'_id':ObjectId(str(diction['invoice_id'])),
'valide':'1',
'locked':'0',
'partner_owner_recid':str(my_partner['recid'])})
if( is_existe_invoice != 1 ):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'identifiant de la facture est invalide ")
return False, " L'identifiant de la facture est invalide "
if( is_existe_invoice != 1 ):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'identifiant de la facture est invalide ")
return False, " L'identifiant de la facture est invalide "
"""
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 = {'invoice_id':str(diction['invoice_id'])}
filter_invoice_ref = {}
if ("invoice_ref" in diction.keys() and diction['invoice_ref']):
filter_invoice_ref = {'invoice_ref': 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]}
RetObject = []
val_tmp = 0
payed_amount = 0
for retval in MYSY_GV.dbname['invoice_paiement'].find({'invoice_id':str(diction['invoice_id']),
'partner_owner_recid':str(my_partner['recid']),
'valide':'1',
'locked':'0'}).sort([("_id", pymongo.DESCENDING), ]):
for retval in MYSY_GV.dbname['invoice_paiement'].find(qery_match).sort([("_id", pymongo.DESCENDING), ]):
user = retval
user['id'] = str(val_tmp)
@ -674,8 +723,6 @@ def Get_Invoice_Liste_Payement(diction):
"""
Cette fonction permet de retourner la liste des payements valides
avec le total associé.
@ -688,25 +735,25 @@ def Get_Invoice_Liste_Payement_And_Total_Amount(diction):
"""
Verification des input acceptés
"""
field_list = ['token', 'invoice_id', ]
field_list = ['token', 'invoice_id', 'client_info', 'client_id', 'invoice_ref']
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"
return False, " Les informations fournies sont incorrectes", False
"""
Verification des champs obligatoires
"""
field_list_obligatoire = ['token', 'invoice_id', ]
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"
return False, " Les informations fournies sont incorrectes", False
"""
Verification de l'identité et autorisation de l'entité qui
@ -719,31 +766,73 @@ def Get_Invoice_Liste_Payement_And_Total_Amount(diction):
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
if (local_status is not True):
return local_status, my_partner
return local_status, my_partner, False
# Verifier que la facture existe et est valide
is_existe_invoice = MYSY_GV.dbname['partner_invoice_header'].count_documents({'_id':ObjectId(str(diction['invoice_id'])),
'valide':'1',
'locked':'0',
'partner_owner_recid':str(my_partner['recid'])})
if( "invoice_id" in diction.keys() and diction['invoice_id']):
is_existe_invoice = MYSY_GV.dbname['partner_invoice_header'].count_documents({'_id':ObjectId(str(diction['invoice_id'])),
'valide':'1',
'locked':'0',
'partner_owner_recid':str(my_partner['recid'])})
if( is_existe_invoice != 1 ):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'identifiant de la facture est invalide ")
return False, " L'identifiant de la facture est invalide "
if( is_existe_invoice != 1 ):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'identifiant de la facture est invalide ")
return False, " L'identifiant de la facture est invalide ", False
"""
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 = {'invoice_id': str(diction['invoice_id'])}
filter_invoice_ref = {}
if ("invoice_ref" in diction.keys() and diction['invoice_ref']):
filter_invoice_ref = {'invoice_ref': 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]}
RetObject = []
val_tmp = 0
payed_amount = 0
for retval in MYSY_GV.dbname['invoice_paiement'].find({'invoice_id':str(diction['invoice_id']),
'partner_owner_recid':str(my_partner['recid']),
'valide':'1',
'locked':'0'}).sort([("_id", pymongo.DESCENDING), ]):
for retval in MYSY_GV.dbname['invoice_paiement'].find(qery_match).sort([("_id", pymongo.DESCENDING), ]):
user = retval
user['id'] = str(val_tmp)
@ -759,16 +848,12 @@ def Get_Invoice_Liste_Payement_And_Total_Amount(diction):
RetObject.append(mycommon.JSONEncoder().encode(user))
total_node = {"total_payed":str(payed_amount)}
RetObject.append(mycommon.JSONEncoder().encode(total_node))
return True, RetObject
return True, RetObject, str(payed_amount)
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écuperer les paiements de la facture "
return False, " Impossible de récuperer les paiements de la facture ", False
@ -1170,20 +1255,17 @@ def Delete_Given_Invoice_Paiement(diction):
Récuprer les paiement déjà effectué
"""
local_diction = {"token": str(diction['token']), "invoice_id": str(invoice_data['_id'])}
local_list_paiement_status, local_list_paiement_retval = Get_Invoice_Liste_Payement_And_Total_Amount(
local_list_paiement_status, local_list_paiement_retval, payed_amount = Get_Invoice_Liste_Payement_And_Total_Amount(
local_diction)
if (local_list_paiement_status is False):
return local_list_paiement_status, local_list_paiement_retval
# print(" Les payement = ", local_list_paiement_retval)
list_payment = ast.literal_eval(local_list_paiement_retval[0])
# print(" Les payement JSON = ", list_payment)
total_payed_amount = "0"
if ("total_payed" in list_payment.keys()):
total_payed_amount = list_payment['total_payed']
total_payed_amount = str(payed_amount)
local_status, local_retval = mycommon.IsFloat(total_payed_amount)
if (local_status is False):
@ -1202,13 +1284,15 @@ def Delete_Given_Invoice_Paiement(diction):
# Cette fois-ci on gere autrement. que les precdent
if (total_payed_amount_float == 0):
update_data['invoice_paiement_status'] = "0"
update_data['invoice_paiement_status'] = "2"
update_data['reste_to_paye'] = str(total_relicat)
else:
update_data['invoice_paiement_status'] = "1"
update_data['reste_to_paye'] = str(total_relicat)
result = MYSY_GV.dbname['partner_invoice_header'].find_one_and_update(
{'_id': ObjectId(str(diction['_id'])),
{'_id': ObjectId(str(paiement_data['invoice_id'])),
'valide': '1',
'locked': '0',
'partner_owner_recid': str(my_partner['recid'])},

49
main.py
View File

@ -119,6 +119,7 @@ import Type_apprenant_mgt as Type_apprenant_mgt
import Finance_mode_mgt as Finance_mode_mgt
import Categorie_apprenant as Categorie_apprenant
import Type_groupe_inscrit_mgt as Type_groupe_inscrit_mgt
import Relance_client_facture as Relance_client_facture
import base_document_automatic_setup as base_document_automatic_setup
@ -11531,8 +11532,8 @@ def Get_Invoice_Liste_Payement_And_Total_Amount():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Get_Invoice_Liste_Payement_And_Total_Amount payload = ",payload)
status, retval = invoice_paiement_mgt.Get_Invoice_Liste_Payement_And_Total_Amount(payload)
return jsonify(status=status, message=retval)
status, retval, total_payed_amount = invoice_paiement_mgt.Get_Invoice_Liste_Payement_And_Total_Amount(payload)
return jsonify(status=status, message=retval, total_payed_amount=total_payed_amount)
@ -17757,6 +17758,50 @@ def Get_Given_Type_Groupe_Inscrit():
return jsonify(status=status, message=retval)
"""
API pour créer une relance pour un client données PDF
"""
@app.route('/myclass/api/Create_Relance_Client_Facture_Given_Client_PDF/<token>/<client_id>', methods=['POST','GET'])
@crossdomain(origin='*')
def Create_Relance_Client_Facture_Given_Client_PDF(token, client_id):
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
payload = {}
payload['token'] = str(token)
payload['client_id'] = str(client_id)
print(" ### Create_Relance_Client_Facture_Given_Client_PDF : payload = ",str(payload))
localStatus, response= Relance_client_facture.Create_Relance_Client_Facture_Given_Client_PDF(payload)
if(localStatus ):
return response
else:
return False
"""
API pour créer une relance pour un client données email
"""
@app.route('/myclass/api/Create_Relance_Client_Facture_Given_Client_Email/', methods=['POST','GET'])
@crossdomain(origin='*')
def Create_Relance_Client_Facture_Given_Client_Email():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Create_Relance_Client_Facture_Given_Client_Email payload = ",payload)
file = []
tab_files = []
if request.method == 'POST':
# Create variable for uploaded file
for tmp in request.files.getlist("File"):
tab_files.append(tmp)
status, retval = Relance_client_facture.Create_Relance_Client_Facture_Given_Client_Email(tab_files, MYSY_GV.TEMPORARY_DIRECTORY_V2, payload)
return jsonify(status=status, message=retval)
if __name__ == '__main__':
print(" debut api")

View File

@ -54,7 +54,8 @@ def Add_Partner_Client(diction):
'contact_civilite', 'contact_nom', 'contact_prenom', 'contact_email', 'is_contact_communication',
'contact_fonction', 'contact_mobile', 'contact_phone', 'contact_adresse', 'contact_code_postal',
'contact_ville',
'contact_pays', 'contact_siret', 'contact_tva', 'archive', 'client_facturation_id']
'contact_pays', 'contact_siret', 'contact_tva', 'archive', 'client_facturation_id',
'responsable_compte_id']
@ -671,7 +672,7 @@ def Add_Partner_Prospect(diction):
'invoice_tva', 'invoice_condition_paiement_id', 'invoice_adresse', 'invoice_ville',
'invoice_code_postal', 'invoice_pays', "client_type_id",
'is_fournisseur', 'is_client', 'is_financeur', 'is_company', 'invoice_automatique',
'partner_groupe_client_id'
'partner_groupe_client_id', 'responsable_compte_id'
]
incom_keys = diction.keys()
@ -1165,7 +1166,7 @@ def Update_Partner_Client(diction):
'invoice_code_postal', 'invoice_pays', 'invoice_telephone', 'client_type_id',
'is_fournisseur', 'is_client', 'is_financeur', 'is_company', 'invoice_automatique',
'type_financeur_id', 'type_pouvoir_public_id', 'partner_groupe_client_id', 'archive',
'client_facturation_id']
'client_facturation_id', 'responsable_compte_id']
incom_keys = diction.keys()
for val in incom_keys:

View File

@ -255,6 +255,12 @@ def Invoice_Partner_Order(diction):
new_invoice_data_header['invoice_date'] = invoice_date_time
new_invoice_data_header['update_by'] = str(my_partner['_id'])
if( 'total_header_toutes_taxes' in new_invoice_data_header.keys() ):
new_invoice_data_header['reste_to_paye'] = str(new_invoice_data_header['total_header_toutes_taxes'])
else:
new_invoice_data_header['reste_to_paye'] = '0'
"""
Calcul de la date d'échance de la facture :
@ -5326,6 +5332,8 @@ def Create_Invoice_Avoir_Total(diction):
local_credit_note['update_by'] = str(my_partner['_id'])
local_credit_note['partner_owner_recid'] = str(my_partner['recid'])
local_credit_note['reste_to_paye'] = "0"
if( "_id" in local_credit_note.keys() ):
del local_credit_note['_id']
@ -5359,14 +5367,14 @@ def Create_Invoice_Avoir_Total(diction):
invoice_header_inserted_id = inserted_id
"""
Mettre à jour la facture avec la reference de l'avoir
Mettre à jour la facture avec la reference de l'avoir et on met le rest a payer a 0
"""
result = MYSY_GV.dbname['partner_invoice_header'].find_one_and_update(
{'_id': ObjectId(str(diction['_id'])),
'partner_owner_recid': my_partner['recid'],
'valide': '1',
'locked': '0'},
{"$set": {"credit_note_ref":credit_notes_reference}},
{"$set": {"credit_note_ref":credit_notes_reference, 'reste_to_paye':'0'}},
upsert=False,
return_document=ReturnDocument.AFTER
)

View File

@ -2846,8 +2846,6 @@ def Lock_PF_partner_account_And_Sub_Accound_from_id(diction):
"""
# Ajout de l'evenement dans l'historique
"""
now = str(datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
history_event_dict = {}
history_event_dict['token'] = diction['token']