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"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ChangeListManager"> <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$/.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$/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$/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" /> <change beforePath="$PROJECT_DIR$/strype_payement.py" beforeDir="false" afterPath="$PROJECT_DIR$/strype_payement.py" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
@ -350,7 +352,14 @@
<option name="project" value="LOCAL" /> <option name="project" value="LOCAL" />
<updated>1688579855150</updated> <updated>1688579855150</updated>
</task> </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 /> <servers />
</component> </component>
<component name="Vcs.Log.Tabs.Properties"> <component name="Vcs.Log.Tabs.Properties">
@ -365,7 +374,6 @@
</option> </option>
</component> </component>
<component name="VcsManagerConfiguration"> <component name="VcsManagerConfiguration">
<MESSAGE value="28/04/23 - 21h" />
<MESSAGE value="29/04/23 - 21h" /> <MESSAGE value="29/04/23 - 21h" />
<MESSAGE value="05/05/23 - 21h" /> <MESSAGE value="05/05/23 - 21h" />
<MESSAGE value="12/05/23 - 19h" /> <MESSAGE value="12/05/23 - 19h" />
@ -390,6 +398,7 @@
<MESSAGE value="04/07/23 - 17h" /> <MESSAGE value="04/07/23 - 17h" />
<MESSAGE value="05/07/23 - 12h" /> <MESSAGE value="05/07/23 - 12h" />
<MESSAGE value="05/07/23 - 20h" /> <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> </component>
</project> </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 ") str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
return False, " Les informations fournies sont incorrectes", return False, " Les informations fournies sont incorrectes",
""" """
Verification de l'identité et autorisation de l'entité qui Verification de l'identité et autorisation de l'entité qui
appelle cette API appelle cette API
""" """
token = "" token = ""
if ("token" in diction.keys()): if ("token" in diction.keys()):
if diction['token']: if diction['token']:
token = diction['token'] token = diction['token']
# Verifier la validité du token # Verifier la validité du token
retval = mycommon.check_partner_token_validity("", token) retval = mycommon.check_partner_token_validity("", token)
if retval is False: if retval is False:
return "Err_Connexion", " La session de connexion n'est pas valide" return "Err_Connexion", " La session de connexion n'est pas valide"
# Recuperation des données du partenaire # Recuperation des données du partenaire
local_status, my_user = mycommon.get_user_data_from_token(token) local_status, my_user = mycommon.get_user_data_from_token(token)
if (local_status is False): if (local_status is False):
mycommon.myprint(str(inspect.stack()[0][3]) + " - impossible de recuperer les données de l'utilisateur ") 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. " return False, str(inspect.stack()[0][3]) + " - impossible de recuperer les données de l'utilisateur. "
RetObject = [] RetObject = []
nb_val = 0 nb_val = 0

View File

@ -1037,7 +1037,7 @@ def convertHtmlToPdf(diction):
try: try:
field_list_obligatoire =['invoice_nom', 'invoice_adr_street', 'invoice_adr_zip', 'invoice_adr_city', 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', '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: for val in field_list_obligatoire:
if val not in diction: if val not in diction:
@ -1124,6 +1124,8 @@ def convertHtmlToPdf(diction):
email.SendInvoiceEmail(str(diction['invoice_email']), diction ) email.SendInvoiceEmail(str(diction['invoice_email']), diction )
# On deplace la facture vers le serveur ftp # On deplace la facture vers le serveur ftp
'''mycommon.myprint( '''mycommon.myprint(
str(inspect.stack()[0][3]) + " deplacement de la facture vers " + str( 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 # return True on success and False on errors
print(pisaStatus.err, type(pisaStatus.err)) 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 return True
except Exception as e: except Exception as e:

View File

@ -23,6 +23,7 @@ import pytz
import sib_api_v3_sdk import sib_api_v3_sdk
from sib_api_v3_sdk.rest import ApiException from sib_api_v3_sdk.rest import ApiException
import jinja2 import jinja2
import strype_payement as strype_payement
configuration = sib_api_v3_sdk.Configuration() 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', 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', '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: for val in field_list_obligatoire:
if val not in diction: if val not in diction:
@ -2573,3 +2574,123 @@ def Email_Part_Espace_Hosting( diction):
exc_type, exc_obj, exc_tb = sys.exc_info() 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)) 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 " 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) localStatus, message = Stripe.Strip_Get_Customer_Abonnement_Data(payload)
return jsonify(status=localStatus, message=message) 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__': if __name__ == '__main__':

View File

@ -1281,10 +1281,10 @@ def Strip_Get_Customer_Abonnement_Data(diction):
customer=stripe_account_id, 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)) 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_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_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['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) return_data['lines'].append(local_diction)
print(" ## return_data = ", return_data)
RetObject = [] RetObject = []
RetObject.append(mycommon.JSONEncoder().encode(return_data)) RetObject.append(mycommon.JSONEncoder().encode(return_data))
return True, RetObject return True, RetObject