09/07/23 - 16h

master
cherif 2023-07-09 15:57:29 +02:00
parent 27b1f14139
commit f7f538c346
7 changed files with 1465 additions and 29 deletions

View File

@ -1,11 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="05/07/23 - 20h">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="08/07/23 - 20h">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" 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$/appel_offre.py" beforeDir="false" afterPath="$PROJECT_DIR$/appel_offre.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ela_factures_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/ela_factures_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/email_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/email_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/prj_common.py" beforeDir="false" afterPath="$PROJECT_DIR$/prj_common.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/strype_payement.py" beforeDir="false" afterPath="$PROJECT_DIR$/strype_payement.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
@ -350,7 +352,14 @@
<option name="project" value="LOCAL" />
<updated>1688579855150</updated>
</task>
<option name="localTasksCounter" value="41" />
<task id="LOCAL-00041" summary="08/07/23 - 20h">
<created>1688846277129</created>
<option name="number" value="00041" />
<option name="presentableId" value="LOCAL-00041" />
<option name="project" value="LOCAL" />
<updated>1688846277129</updated>
</task>
<option name="localTasksCounter" value="42" />
<servers />
</component>
<component name="Vcs.Log.Tabs.Properties">
@ -365,7 +374,6 @@
</option>
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="28/04/23 - 21h" />
<MESSAGE value="29/04/23 - 21h" />
<MESSAGE value="05/05/23 - 21h" />
<MESSAGE value="12/05/23 - 19h" />
@ -390,6 +398,7 @@
<MESSAGE value="04/07/23 - 17h" />
<MESSAGE value="05/07/23 - 12h" />
<MESSAGE value="05/07/23 - 20h" />
<option name="LAST_COMMIT_MESSAGE" value="05/07/23 - 20h" />
<MESSAGE value="08/07/23 - 20h" />
<option name="LAST_COMMIT_MESSAGE" value="08/07/23 - 20h" />
</component>
</project>

File diff suppressed because one or more lines are too long

View File

@ -346,26 +346,26 @@ def Get_Appel_Offre(diction):
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
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']
"""
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']
# Verifier la validité du token
retval = mycommon.check_partner_token_validity("", token)
# Verifier la validité du token
retval = mycommon.check_partner_token_validity("", token)
if retval is False:
return "Err_Connexion", " La session de connexion n'est pas valide"
if retval is False:
return "Err_Connexion", " La session de connexion n'est pas valide"
# Recuperation des données du partenaire
local_status, my_user = mycommon.get_user_data_from_token(token)
if (local_status is False):
mycommon.myprint(str(inspect.stack()[0][3]) + " - impossible de recuperer les données de l'utilisateur ")
return False, str(inspect.stack()[0][3]) + " - impossible de recuperer les données de l'utilisateur. "
# Recuperation des données du partenaire
local_status, my_user = mycommon.get_user_data_from_token(token)
if (local_status is False):
mycommon.myprint(str(inspect.stack()[0][3]) + " - impossible de recuperer les données de l'utilisateur ")
return False, str(inspect.stack()[0][3]) + " - impossible de recuperer les données de l'utilisateur. "
RetObject = []
nb_val = 0

View File

@ -1037,7 +1037,7 @@ def convertHtmlToPdf(diction):
try:
field_list_obligatoire =['invoice_nom', 'invoice_adr_street', 'invoice_adr_zip', 'invoice_adr_city',
'invoice_adr_country', 'invoice_id', 'invoice_date', 'due_date', 'order_id', 'item_0',
'total_ht', 'total_tva', 'total_ttc',]
'total_ht', 'total_tva', 'total_ttc','client_recid']
for val in field_list_obligatoire:
if val not in diction:
@ -1124,6 +1124,8 @@ def convertHtmlToPdf(diction):
email.SendInvoiceEmail(str(diction['invoice_email']), diction )
# On deplace la facture vers le serveur ftp
'''mycommon.myprint(
str(inspect.stack()[0][3]) + " deplacement de la facture vers " + str(
@ -1147,6 +1149,13 @@ def convertHtmlToPdf(diction):
# return True on success and False on errors
print(pisaStatus.err, type(pisaStatus.err))
""" update du 09/07/23 - test envoie info prochaine facture"""
local_diction = {}
local_diction['recid'] = diction['client_recid']
email.Strip_Get_Customer_Upcoming_Invoice(local_diction)
return True
except Exception as e:

View File

@ -23,6 +23,7 @@ import pytz
import sib_api_v3_sdk
from sib_api_v3_sdk.rest import ApiException
import jinja2
import strype_payement as strype_payement
configuration = sib_api_v3_sdk.Configuration()
@ -1565,7 +1566,7 @@ def SendInvoiceEmail(account_mail, diction):
'''
field_list_obligatoire = ['invoice_nom', 'invoice_adr_street', 'invoice_adr_zip', 'invoice_adr_city',
'invoice_adr_country', 'invoice_id', 'invoice_date', 'due_date', 'order_id', 'item_0',
'total_ht', 'total_tva', 'total_ttc', ]
'total_ht', 'total_tva', 'total_ttc', 'client_recid' ]
for val in field_list_obligatoire:
if val not in diction:
@ -2573,3 +2574,123 @@ def Email_Part_Espace_Hosting( diction):
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, " Impossible d'envoyer les identifiants de connexion à la plateforme d'hébergement par email "
"""
Cette fonction envoie un email avec les informations
sur la prochaine facturation du client.
Cette fonction est utilisée :
1 - En cas de changement d'abonnement
2 - eventuellement connaitre le montant de la prochaine facture du client
"""
import json
def Strip_Get_Customer_Upcoming_Invoice(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['recid', ]
incom_keys = diction.keys()
for val in incom_keys:
if val not in field_list:
mycommon.myprint(str(
inspect.stack()[0][3]) + " Le champ '" + val + "' n'existe pas")
return False, " Les informations fournies sont incorrectes",
"""
Verification des champs obligatoires
"""
field_list_obligatoire = ['recid',]
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 liste ")
return False, " Les informations fournies sont incorrectes",
"""
Verification de l'identité et autorisation de l'entité qui
appelle cette API
"""
recid = ""
if ("recid" in diction.keys()):
if diction['recid']:
recid = diction['recid']
# Recuperation des données du partenaire
local_status, my_partner = mycommon.get_partner_data_from_recid(recid)
if (local_status is False):
mycommon.myprint(
str(inspect.stack()[0][3]) + " - impossible de recuperer les données de l'utilisateur ")
return False, str(inspect.stack()[0][3]) + " - impossible de recuperer les données de l'utilisateur. "
data = {}
data['recid'] = my_partner['recid']
local_status, local_retval = strype_payement.Strip_Get_Customer_Abonnement_Data(data)
if (local_status is False):
mycommon.myprint(
str(inspect.stack()[0][3]) + " - impossible de recuperer les données de facturation ")
return False, str(inspect.stack()[0][3]) + " - impossible de recuperer les données de facturation. "
print(" ### local_retval[0] = ", local_retval[0])
local_retval_JSON = json.loads(str(local_retval[0]))
local_retval_JSON['user_name'] = my_partner['nom']
# On verifie que les informations retournées contiennent tous les champs
local_champs_obligatoire = ['recid', 'period_start', 'period_end', 'total', 'main_description', 'lines', 'user_name']
for val in local_champs_obligatoire:
if val not in local_retval_JSON.keys():
mycommon.myprint(
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste (2)")
return False, " Les informations fournies sont incorrectes (2)",
local_retval_JSON['tva'] = round(mycommon.tryFloat(str(local_retval_JSON["total"])) * 0.2, 2)
local_retval_JSON['total_ttc'] = round(mycommon.tryFloat(str(local_retval_JSON["total"])) * 1.2, 2)
smtpserver = smtplib.SMTP(MYSY_GV.O365_SMTP_COUNT_smtpsrv, MYSY_GV.O365_SMTP_COUNT_port)
# msg = MIMEMultipart("alternative")
msg = EmailMessage()
# JINJA2
templateLoader = jinja2.FileSystemLoader(searchpath="./")
templateEnv = jinja2.Environment(loader=templateLoader)
TEMPLATE_FILE = "Template/MySy_Next_Invoice_Info_tpl.html"
template = templateEnv.get_template(TEMPLATE_FILE)
# This data can come from database query
body = {
"params": local_retval_JSON,
}
sourceHtml = template.render(params=body["params"])
msg.set_content(sourceHtml, subtype='html')
msg['From'] = MYSY_GV.O365_SMTP_COUNT_From_User
msg['Bcc'] = 'contact@mysy-training.com'
msg['Subject'] = "[MySy Training Technology] : Information Facture à venir. "
msg['To'] = str(my_partner['email'])
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(MYSY_GV.O365_SMTP_COUNT_user, MYSY_GV.O365_SMTP_COUNT_password)
val = smtpserver.send_message(msg)
smtpserver.close()
print(" Email envoyé " + str(val))
return True, " email envoyé ok"
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 les informations de la prochaines factures "

11
main.py
View File

@ -3078,6 +3078,17 @@ def Strip_Get_Customer_Abonnement_Data():
localStatus, message = Stripe.Strip_Get_Customer_Abonnement_Data(payload)
return jsonify(status=localStatus, message=message)
"""
API d'envoie de l'email avec les infos de la prochaine facturation
"""
@app.route('/myclass/api/Strip_Get_Customer_Upcoming_Invoice/', methods=['POST','GET'])
@crossdomain(origin='*')
def Strip_Get_Customer_Upcoming_Invoice():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Strip_Get_Customer_Upcoming_Invoice : payload = ",payload)
localStatus, message = emails.Strip_Get_Customer_Upcoming_Invoice(payload)
return jsonify(status=localStatus, message=message)
if __name__ == '__main__':

View File

@ -1281,10 +1281,10 @@ def Strip_Get_Customer_Abonnement_Data(diction):
customer=stripe_account_id,
)
print(" #### local_ret_val : ", str(local_ret_val))
#print(" #### local_ret_val : ", str(local_ret_val))
lines_to_invoice = local_ret_val.lines.list(limit=5)
lines_to_invoice = local_ret_val.lines.list()
stripe_account_id_JSON = json.loads(str(local_ret_val))
@ -1330,17 +1330,23 @@ def Strip_Get_Customer_Abonnement_Data(diction):
local_diction['period_end'] = str(datetime.fromtimestamp(period['end']).strftime("%d/%m/%Y-%H:%M:%S"))
local_diction['period_start'] = str(datetime.fromtimestamp(period['start']).strftime("%d/%m/%Y-%H:%M:%S"))
local_diction['period_end_month'] = str(datetime.fromtimestamp(period['end']).strftime("%m"))
local_diction['unit_amount'] = str(val['price']['unit_amount'])
local_diction['unit_amount'] = mycommon.tryFloat(str(val['price']['unit_amount'])) / 100
local_diction['quantity'] = str(val['quantity'])
local_diction['description'] = str(val['description'])
local_diction['description'] = str(val['description']).replace("Unused time on", "Temps non utilisé sur").replace("Remaining time on", "Temps restant sur").replace("after", "apres")
local_diction['amount'] = str(val['amount'])
local_diction['amount'] = mycommon.tryFloat(str(val['amount'])) / 100
return_data['lines'].append(local_diction)
print(" ## return_data = ", return_data)
RetObject = []
RetObject.append(mycommon.JSONEncoder().encode(return_data))
return True, RetObject