Elyos_FI_Back_Office/ela_factures_mgt.py

1088 lines
44 KiB
Python

"""
Ce fichier permet de gerer les factures client et les methodes de payement
"""
import pymongo
from pymongo import MongoClient
import json
from bson import ObjectId
import re
from datetime import datetime
import prj_common as mycommon
import secrets
import inspect
import sys, os
import shutil
import csv
import pandas as pd
from pymongo import ReturnDocument
from math import isnan
import GlobalVariable as MYSY_GV
import email_mgt as email
from dateutil import tz
import pytz
from xhtml2pdf import pisa
import jinja2
import ftplib
import pysftp
from flask import send_file
from dateutil.relativedelta import relativedelta
import class_mgt as class_mgt
import strype_payement as Stripe
class JSONEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, ObjectId):
return str(o)
return json.JSONEncoder.default(self, o)
def get_invoice_by_customer(diction):
try:
field_list = ['token',]
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, Creation formation annulée")
return False, " Impossible de recuperer les factures"
'''
Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
On controle que les champs obligatoires sont presents dans la liste
'''
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 liste ")
return False, " Impossible de recuperer les factures"
# recuperation des paramettre
my_token = ""
user_recid = ""
if ("token" in diction.keys()):
if diction['token']:
my_token = diction['token']
user_recid = "None"
# Verification de la validité du token/mail dans le cas des user en mode connecté
if (len(str(my_token)) > 0):
retval = mycommon.check_partner_token_validity("", my_token)
if retval is False:
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token n'est pas valide")
return False, " Impossible de recuperer les factures"
# Recuperation du recid de l'utilisateur
user_recid = mycommon.get_parnter_recid_from_token(my_token)
if user_recid is False:
mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le token de l'utilisateur")
return False, " Impossible de recuperer les factures"
if (len(str(my_token)) <= 0):
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token est vide")
return False, " Impossible de recuperer les factures"
RetObject = []
coll_facture = MYSY_GV.dbname['factures']
for retVal in coll_facture.find({'client_recid':user_recid, 'valide': '1'},
{'invoice_nom':1, 'total_ht':1, 'total_tva':1, 'total_ttc':1,
'order_id':1, 'invoice_id':1, 'due_date':1, 'invoice_date':1,
}
)\
.sort([("invoice_date", pymongo.DESCENDING), ("invoice_id", pymongo.DESCENDING), ]):
user = retVal
if ("_id" in user.keys()):
user['class_id'] = user.pop('_id')
user['lien_pdf'] = str(MYSY_GV.INVOICE_FTP_DIRECTORY)+str("invoice_")+str(user['invoice_id'])+str(".pdf")
RetObject.append(JSONEncoder().encode(user))
#print(" les facture du client = "+str(RetObject))
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) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, "Impossible de recuperer les factures"
'''
Cette API enregistre la methode de payement.
/!\ un client a une seule mode de payement
ceci est enregistré dans la collection : payement_mode
'''
def add_payement_mode(diction):
try:
field_list = ['token', 'pwd', 'secret', 'nom_carte', 'num_carte', 'date_exp_carte', 'cvv_carte', 'nom_compte',
'iban', 'bic','type' ]
incom_keys = diction.keys()
for val in incom_keys:
if val not in field_list:
mycommon.myprint(str(inspect.stack()[0][
3]) + " - Creation partner account : Le champ '" + val + "' n'existe pas, Creation formation annulée")
return False, "Impossible d'ajouter le mode de payement"
'''
Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
On controle que les champs obligatoires sont presents dans la liste
'''
field_list_obligatoire = ['token', 'pwd', 'secret', 'type']
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, "Impossible d'ajouter le mode de payement"
# recuperation des paramettre
my_token = ""
user_recid = ""
my_pwd = ""
my_secret = ""
if ("pwd" in diction.keys()):
if diction['pwd']:
my_pwd = diction['pwd']
if ("secret" in diction.keys()):
if diction['secret']:
my_secret = diction['secret']
if ("token" in diction.keys()):
if diction['token']:
my_token = diction['token']
# Verification de la validité du pwd et du secret
coll_tmp = MYSY_GV.dbname['partnair_account']
tmp_count = coll_tmp.count_documents({'pwd': str(my_pwd), 'active': '1', 'token':str(my_secret)})
if (tmp_count <= 0):
return False, "Les identifiants sont incorrectes"
tmp_account = coll_tmp.find({'pwd': str(my_pwd), 'active': '1', 'token':str(my_secret)})
"""
Stripe : recuperation du stripe_account_id
"""
partner_stripe_account_id = tmp_account[0]['stripe_account_id']
"""
Recuperation du PaymentMethod s'il en a un : 'stripe_paymentmethod_id'
"""
stripe_paymentmethod_id = ""
if ("stripe_paymentmethod_id" in tmp_account[0].keys()):
if tmp_account[0]['stripe_paymentmethod_id']:
stripe_paymentmethod_id = tmp_account[0]['stripe_paymentmethod_id']
user_recid = "None"
# Verification de la validité du token/mail dans le cas des user en mode connecté
if (len(str(my_token)) > 0):
retval = mycommon.check_partner_token_validity("", my_token)
if retval is False:
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token n'est pas valide")
return False, "Impossible d'ajouter le mode de payement"
# Recuperation du recid de l'utilisateur
user_recid = mycommon.get_parnter_recid_from_token(my_token)
if user_recid is False:
mycommon.myprint(
str(inspect.stack()[0][3]) + " - Impossible de recuperer le token de l'utilisateur")
return False, "Impossible d'ajouter le mode de payement"
if (len(str(my_token)) <= 0):
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token est vide")
return False, "Impossible d'ajouter le mode de payement"
coll_name = MYSY_GV.dbname['payement_mode']
new_data = {}
new_data['valide'] = "1"
now = datetime.now()
new_data['date_update'] = str(now)
# initialisation pr nettoyer l'existant (faire comme un delete)
new_data['nom_carte'] = ""
new_data['num_carte'] = ""
new_data['date_exp_carte'] = ""
new_data['cvv_carte'] = ""
new_data['nom_compte'] = ""
new_data['iban'] = ""
new_data['bic'] = ""
if ("nom_carte" in diction.keys()):
if diction['nom_carte']:
new_data['nom_carte'] = diction['nom_carte']
if ("num_carte" in diction.keys()):
if diction['num_carte']:
new_data['num_carte'] = diction['num_carte']
if ("type" in diction.keys()):
if diction['type']:
new_data['type'] = diction['type']
if ("date_exp_carte" in diction.keys()):
if diction['date_exp_carte']:
new_data['date_exp_carte'] = diction['date_exp_carte']
if ("cvv_carte" in diction.keys()):
if diction['cvv_carte']:
new_data['cvv_carte'] = diction['cvv_carte']
if ("nom_compte" in diction.keys()):
if diction['nom_compte']:
new_data['nom_compte'] = diction['nom_compte']
if ("iban" in diction.keys()):
if diction['iban']:
new_data['iban'] = diction['iban']
if ("nom_compte" in diction.keys()):
if diction['nom_compte']:
new_data['nom_compte'] = diction['nom_compte']
if ("bic" in diction.keys()):
if diction['bic']:
new_data['bic'] = diction['bic']
print("mode de payement data :"+str(new_data))
#print("str(new_data['num_carte']) = "+str(new_data['num_carte']) +" len = "+str(len(str(new_data['num_carte']))) )
#print("str(new_data['nom_carte']) = " + str(new_data['nom_carte']) +" len ="+str(len(str(new_data['nom_carte']))) )
if( str(new_data['type']) == "cb"):
if( len(str(new_data['num_carte'])) <= 0 or len(str(new_data['nom_carte'])) <= 0
or len(str(new_data['date_exp_carte'])) <= 0 or len(str(new_data['cvv_carte'])) <= 0 ):
mycommon.myprint(
str(inspect.stack()[0][3]) + " : Les données de la carte sont incorrectes")
return False, "Impossible d'ajouter le mode de paiement. Les données de la carte sont incorrectes"
# SI stripe_paymentmethod_id est vide alors on créé la carte
print(" #### Creation de la carte dans STRIPE")
tmp_tab = str(new_data['date_exp_carte']).split("/")
if( len(tmp_tab) != 2):
mycommon.myprint(
str(inspect.stack()[0][3]) + " : La date d'expiration de la carte est incorrecte")
return False, "Impossible d'ajouter le mode de paiement. Les données de la carte sont incorrectes"
new_stripe_card = {}
new_stripe_card['customerid'] = partner_stripe_account_id
new_stripe_card['number'] = new_data['num_carte']
new_stripe_card['name'] = new_data['nom_carte']
new_stripe_card['exp_month'] = str(tmp_tab[0])
new_stripe_card['exp_year'] = str(tmp_tab[1])
new_stripe_card['cvc'] = new_data['cvv_carte']
new_stripe_card['stripe_paymentmethod_id'] = stripe_paymentmethod_id
print("### la carte à créer est "+str(new_stripe_card))
local_status, created_stripe_cart = Stripe.create_update_payment_card(new_stripe_card)
if( local_status is False):
mycommon.myprint(
str(inspect.stack()[0][3]) + " : Impossible de créer la carte de payement dans Stripe")
return False, "Impossible d'ajouter le mode de paiement."
print(" ### la carte est créée : "+str(created_stripe_cart))
if (str(new_data['type']) == "sepa"):
if (len(str(new_data['iban'])) <= 0 or len(str(new_data['bic']) <= 0)
or len(str(new_data['nom_compte'])) <= 0):
mycommon.myprint(
str(inspect.stack()[0][3]) + " : Les données bancaires sont incorrectes")
return False, "Impossible d'ajouter le mode de paiement. Les données bancaires sont incorrectes"
new_data['stripe_paymentmethod_id'] = str(created_stripe_cart.id)
ret_val = coll_name.find_one_and_update(
{'client_recid': user_recid, 'valide': '1'},
{"$set": new_data},
upsert=True,
return_document=ReturnDocument.AFTER
)
if (ret_val['_id'] is False):
mycommon.myprint(
str(inspect.stack()[0][3]) + " : Impossible d'ajouter le mode de payement")
return False, "Impossible d'ajouter le mode de payement"
'''
Une fois que le mode de payement est ajouté, alors valide le compte partenaire
en mettant : ispending à 0
'''
coll_name = MYSY_GV.dbname['partnair_account']
data_update = {'date_update':str(datetime.now()), 'ispending':'0', 'stripe_paymentmethod_id':str(created_stripe_cart.id)}
ret_val = coll_name.find_one_and_update(
{'recid': user_recid, },
{"$set": data_update},
upsert=False,
return_document=ReturnDocument.AFTER
)
if (ret_val['_id'] is False):
mycommon.myprint(
str(inspect.stack()[0][3]) + " : Impossible de mettre à jour (ispending':'1') le compte partenaire")
return False, "Impossible d'ajouter le mode de payement"
return True, " Le mode de payement a bien ete ajouté"
except Exception as e:
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'ajouter le mode de payement"
'''
Cette fonction recuperer le mode de payement par defaut d'un client
'''
def get_payement_mode(diction):
try:
field_list = ['token', ]
incom_keys = diction.keys()
for val in incom_keys:
if val not in field_list:
mycommon.myprint(str(inspect.stack()[0][
3]) + " - Creation partner account : Le champ '" + val + "' n'existe pas, Creation formation annulée")
return False, " Impossible de recuperer les mode de payement"
'''
Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
On controle que les champs obligatoires sont presents dans la liste
'''
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 liste ")
return False, " Impossible de recuperer les mode de payement"
# recuperation des paramettre
my_token = ""
user_recid = ""
if ("token" in diction.keys()):
if diction['token']:
my_token = diction['token']
user_recid = "None"
# Verification de la validité du token/mail dans le cas des user en mode connecté
if (len(str(my_token)) > 0):
retval = mycommon.check_partner_token_validity("", my_token)
if retval is False:
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token n'est pas valide")
return False, " Impossible de recuperer les mode de payement"
# Recuperation du recid de l'utilisateur
user_recid = mycommon.get_parnter_recid_from_token(my_token)
if user_recid is False:
mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le token de l'utilisateur")
return False, " Impossible de recuperer les mode de payement"
if (len(str(my_token)) <= 0):
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token est vide")
return False, " Impossible de recuperer les mode de payement"
"""
Recuperation du stripe_account_id
"""
stripe_account_id = mycommon.get_parnter_stripe_account_id_from_recid(user_recid)
if stripe_account_id is False:
mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le stripe_account_id de l'utilisateur")
return False, " Impossible de recuperer les modes de payement"
"""
Recuperation de clé de payement stripe : stripe_paymentmethod_id
"""
stripe_paymentmethod_id = mycommon.get_parnter_stripe_stripe_paymentmethod_id_from_recid(user_recid)
if stripe_paymentmethod_id is False:
mycommon.myprint(
str(inspect.stack()[0][3]) + " - Impossible de recuperer le stripe_paymentmethod_id de l'utilisateur")
return False, " Impossible de recuperer les modes de payement"
RetObject_stripe = []
tmp_diction = {}
tmp_diction['stripe_account_id'] = str(stripe_account_id)
print("## recherche mod de payement stripe_account_id = "+str(stripe_account_id)
)
localStatus, payment_cards = Stripe.get_customer_payement_cards(tmp_diction)
val_tmp = {}
for tmp in payment_cards:
# RetObject.append(JSONEncoder().encode(user))
val_tmp = tmp
RetObject_stripe.append(val_tmp)
#RetObject_stripe.append(JSONEncoder().encode(tmp))
print(" #### mode de payement via stripe = "+str(RetObject_stripe))
RetObject = []
coll_facture = MYSY_GV.dbname['payement_mode']
for retVal in coll_facture.find({'client_recid': user_recid, 'valide': '1'}):
user = retVal
user['stripe_paymentmethod_id'] = stripe_paymentmethod_id
RetObject.append(JSONEncoder().encode(user))
return True, RetObject_stripe
except Exception as e:
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 de recuperer les mode de payement"
"""
Cette fonction crée une facture dans la collecion : factures.
"""
def createOrder(diction):
try:
order_id = ""
nb_line = 0
num_facture = ""
'''field_list = ['token', 'nb_product']
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, Creation formation annulée")
return False, " Impossible de créer la facture"
'''
'''
Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
On controle que les champs obligatoires sont presents dans la liste
'''
field_list_obligatoire = ['token', 'nb_product', 'periodicite']
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, " Impossible de créer la facture"
# recuperation des paramettre
my_token = ""
user_recid = ""
if ("token" in diction.keys()):
if diction['token']:
my_token = diction['token']
user_recid = "None"
# Verification de la validité du token/mail dans le cas des user en mode connecté
if (len(str(my_token)) > 0):
retval = mycommon.check_partner_token_validity("", my_token)
if retval is False:
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token n'est pas valide")
return False, " Impossible de créer la facture"
# Recuperation du recid de l'utilisateur
user_recid = mycommon.get_parnter_recid_from_token(my_token)
if user_recid is False:
mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le token de l'utilisateur")
return False," Impossible de créer la facture"
if (len(str(my_token)) <= 0):
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token est vide")
return False, " Impossible de créer la facture"
new_data = {}
if ("nb_product" in diction.keys()):
if diction['nb_product']:
nb_line = mycommon.tryInt(diction['nb_product'])
if ("periodicite" in diction.keys()):
if diction['periodicite']:
new_data['periodicite'] = diction['periodicite']
if ("end_date" in diction.keys()):
if diction['end_date']:
new_data['end_date'] = diction['end_date']
# Recuperation des données client
new_data['client_recid'] = user_recid
coll_part_account = MYSY_GV.dbname['partnair_account']
# print(" myquery pr demo_account = " + str(myquery))
tmp_count = coll_part_account.count_documents({'recid':user_recid, 'active':'1'})
if (tmp_count <= 0):
mycommon.myprint(
str(inspect.stack()[0][3]) + "Aucune donnée client, Impossible de créer la commande ")
return False, "Aucune donnée client, Impossible de créer la commande ", None
part_account = coll_part_account.find({'recid':user_recid, 'active':'1'})
if ("invoice_nom" in part_account[0].keys()):
if part_account[0]['invoice_nom']:
new_data['invoice_nom'] = part_account[0]['invoice_nom']
if ("invoice_adr_city" in part_account[0].keys()):
if part_account[0]['invoice_adr_city']:
new_data['invoice_adr_city'] = part_account[0]['invoice_adr_city']
if ("invoice_adr_country" in part_account[0].keys()):
if part_account[0]['invoice_adr_country']:
new_data['invoice_adr_country'] = part_account[0]['invoice_adr_country']
if ("invoice_adr_street" in part_account[0].keys()):
if part_account[0]['invoice_adr_street']:
new_data['invoice_adr_street'] = part_account[0]['invoice_adr_street']
if ("invoice_adr_zip" in part_account[0].keys()):
if part_account[0]['invoice_adr_zip']:
new_data['invoice_adr_zip'] = part_account[0]['invoice_adr_zip']
if ("invoice_adr_street" in part_account[0].keys()):
if part_account[0]['invoice_adr_street']:
new_data['invoice_adr_street'] = part_account[0]['invoice_adr_street']
if ("invoice_email" in part_account[0].keys()):
if part_account[0]['invoice_email']:
new_data['invoice_email'] = part_account[0]['invoice_email']
if ("invoice_vat_num" in part_account[0].keys()):
if part_account[0]['invoice_vat_num']:
new_data['invoice_vat_num'] = part_account[0]['invoice_vat_num']
if ("invoice_telephone" in part_account[0].keys()):
if part_account[0]['invoice_telephone']:
new_data['invoice_telephone'] = part_account[0]['invoice_telephone']
total_ht = 0
# Recuperation ds données de payement
coll_part_payment = MYSY_GV.dbname['payement_mode']
part_account = coll_part_payment.find({'client_recid': user_recid, 'valide': '1'})
new_data['nb_product'] = str(nb_line)
i = 0
while (i < nb_line):
#print("PRODUIT N° " + str((i + 1)) + " : " )
line_dict = json.loads(diction[str(i)])
#print(" line = "+str(line_dict)+" -- le type est : "+str(type(line_dict)))
#print(" code = "+str( line_dict['code'] ))
#print(" prix = " + str(line_dict['prix']))
#print(" qty = " + str(line_dict['qty']))
#print(" les produits du pack = " + str(line_dict['pack_products']))
montant_line = mycommon.tryFloat(str(line_dict['prix'])) * mycommon.tryInt(str(line_dict['qty']))
#print(" montant_line = " + str(montant_line))
total_ht = total_ht + montant_line
new_data_item = {}
new_data_item['code'] = line_dict['code']
new_data_item['prix'] = line_dict['prix']
new_data_item['qty'] = line_dict['qty']
new_data_item['pack_products'] = line_dict['pack_products']
new_data_item['amount'] = str(montant_line)
row = "item_"+str(i)
new_data[str(row)] = new_data_item
i = i + 1
new_data['total_ht'] = total_ht
new_data['total_tva'] = mycommon.tryFloat(str(total_ht)) * MYSY_GV.TVA_TAUX
new_data['total_ttc'] = mycommon.tryFloat(str(total_ht)) + mycommon.tryFloat(str(new_data['total_tva']))
total_ttc_float = mycommon.tryFloat(str(new_data['total_ttc']))
#print("str(new_data['total_ttc']) === " + str(total_ttc_float))
if (tmp_count <= 0 and total_ttc_float > 0):
mycommon.myprint(
str(inspect.stack()[0][3]) + " Aucune donnée de payement, Impossible de créer la commande ")
return False, " Aucune donnée de payement,, Impossible de créer la commande ", None
#print(" new_data['total_ht'] = "+str(new_data['total_ht']) + " -- new_data['total_tva'] "
# +str(new_data['total_tva'])+ " -- new_data['total_ttc'] = "+ str(new_data['total_ttc']))
# Les données de payement ne sont utilisées que si le montant > 0
if (total_ttc_float > 0):
if ("type" in part_account[0].keys()):
if part_account[0]['type']:
new_data['type_payment'] = part_account[0]['type']
if ("bic" in part_account[0].keys()):
if part_account[0]['bic']:
new_data['bic_payment'] = part_account[0]['bic']
if ("cvv_carte" in part_account[0].keys()):
if part_account[0]['cvv_carte']:
new_data['cvv_carte_payment'] = part_account[0]['cvv_carte']
if ("date_exp_carte" in part_account[0].keys()):
if part_account[0]['date_exp_carte']:
new_data['date_exp_carte_payment'] = part_account[0]['date_exp_carte']
if ("iban" in part_account[0].keys()):
if part_account[0]['iban']:
new_data['iban_payment'] = part_account[0]['iban']
if ("nom_carte" in part_account[0].keys()):
if part_account[0]['nom_carte']:
new_data['nom_carte_payment'] = part_account[0]['nom_carte']
if ("nom_compte" in part_account[0].keys()):
if part_account[0]['nom_compte']:
new_data['nom_compte_payment'] = part_account[0]['nom_compte']
if ("num_carte" in part_account[0].keys()):
if part_account[0]['num_carte']:
new_data['num_carte_payment'] = part_account[0]['num_carte']
new_data['valide'] = "1"
now = datetime.now()
new_data['date_update'] = str(now)
new_data['order_date'] = str(now.strftime("%d/%m/%Y, %H:%M:%S"))
new_data['order_id'] = "MySy_00"+str(mycommon.create_order_id())
#print(" la line à facturer est ::::: "+str(new_data))
# Enregistrement de la commande dans la systeme
coll_order = MYSY_GV.dbname['sales_order']
ret_val = coll_order.insert_one(new_data)
if ret_val and ret_val.inserted_id:
#print( "str(new_data['invoice_email']) = "+str(new_data['invoice_email']))
# Envoie de l'email
email.SalesOrderConfirmationEmail(str(new_data['invoice_email']), new_data )
# Mise à jour du partenaire (ajouter le nouveau pack)
if ("pack" in diction.keys()):
if diction['pack']:
mypack = diction['pack']
coll_partner = MYSY_GV.dbname['partnair_account']
ret_val = coll_partner.find_one_and_update(
{'recid': str(user_recid), },
{"$set": {'pack_service':str(mypack)}},
upsert=False,
return_document=ReturnDocument.AFTER
)
# Apres la creation du nouvelle abonnement, il faut aller cloturer l'ancien abonnement actif
today_tmp = datetime.today().date()
ret_val_cloture = coll_order.update_many({'order_id': {'$ne' : str(new_data['order_id'])}, 'valide': '1',
'client_recid':str(user_recid)},
{"$set": {'end_date': str(today_tmp), 'date_update': str(datetime.now())}},
)
# Facturation de la commande
#print(" ######## lancement de la facturation total_ttc_float = " + str(total_ttc_float))
if (total_ttc_float > 0):
CreateInvoice(new_data)
# Apres la facturation, on met à jour le display_ranking des formations du partenaire.
tmp_diction = {"partnaire_recid":str(user_recid), "new_pack_na"
"me":str(mypack)}
class_mgt.UpdataPartnerRankingClass(tmp_diction)
return True, "la commande été correctement créee", str(new_data['order_id'])
else:
mycommon.myprint(
str(inspect.stack()[0][3]) + "Impossible de créer la commande ")
return False, "Impossible de créer la commande ", None
except Exception as e:
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 de créer la facture"
"""
Cette fontion recuperer l'id de la dernière facture
"""
def Get_Last_Invoice_ID():
try:
last_invoice_id = 0
coll_invoice = MYSY_GV.dbname["factures"]
tmp_val = coll_invoice.count_documents({})
if( tmp_val ):
last_invoice_id = tmp_val
return True, last_invoice_id
except Exception as e:
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 de recuperer l'ID de la dernière facture "
"""
Cette fonction créer une facture
"""
def CreateInvoice(diction):
try:
field_list_obligatoire = ['client_recid', 'invoice_nom', 'order_id', 'order_date', 'total_ttc','total_tva','total_ht','item_0']
for val in field_list_obligatoire:
if val not in diction:
mycommon.myprint(str(inspect.stack()[0][
3]) + " - Le champ '" + val + "' n'existe pas, Creation facture annulée")
return False, " Impossible de créer la facture"
order_id = ""
status_tmp, last_invoice_id = Get_Last_Invoice_ID()
if( status_tmp is False):
mycommon.myprint(str(inspect.stack()[0][
3]) + " Impossible de recuperer Get_Last_Invoice_ID ")
return False, " Impossible de créer la facture"
#print(" ######## last_invoice_id = "+str(last_invoice_id))
last_invoice_id = last_invoice_id + 1
now = datetime.now()
prefix = "FACT_"+str(now.year)[-2:]+str(now.month)+str("000")
Order_Invoice = str(prefix)+str(last_invoice_id)
diction['invoice_id']= str(Order_Invoice)
diction['due_date'] = str(now.strftime("%d/%m/%Y"))
diction['invoice_date'] = str(now.strftime("%d/%m/%Y"))
diction['printed'] = "0"
#print(" collection de facture = "+str(diction))
coll_facture = MYSY_GV.dbname['factures']
ret_val = coll_facture.insert_one(diction)
if ret_val and ret_val.inserted_id:
print("str(new_data['invoice_email']) = " + str(diction['invoice_email']))
print("str(diction['invoice_id']) = " + str(diction['invoice_id']))
# Envoie de l'email de la facture
PrintAndSendInvoices(str(diction['invoice_id']))
#email.SalesOrderConfirmationEmail(str(new_data['invoice_email']), new_data)
"""
Mise à jour de la commande avec le prochaine date de facturation """
next_invoice_date = ""
if ("next_invoice_date" in diction.keys()):
if diction['next_invoice_date']:
local_status, tmp_date = mycommon.TryToDateYYYMMDD(diction['next_invoice_date'])
print(" apres conversion tmp_date = "+str(tmp_date))
if( local_status and str(diction['periodicite']).lower() == "mensuel" ):
next_invoice_date = (tmp_date + relativedelta(months=+1)).date()
print(" ### next_invoice_date = "+str(next_invoice_date))
elif (local_status is False):
print(" ### IMPOSSIBLE DE FACTURER la COMMANDE")
return False
if (local_status and str(diction['periodicite']).lower() == "annuel"):
next_invoice_date = (tmp_date + relativedelta(years=+1)).date()
print(" ### next_invoice_date = " + str(next_invoice_date))
elif (local_status is False):
print(" ### IMPOSSIBLE DE FACTURER la COMMANDE")
return False
elif( str(diction['periodicite']).lower() == "mensuel" ):
next_invoice_date = datetime.today().date() + relativedelta(months=+1)
elif (str(diction['periodicite']).lower() == "annuel"):
next_invoice_date = datetime.today().date() + relativedelta(years=+1)
print(" ####### prochaine facturation de la commande : "+str(diction['order_id'])+" LE : "+str(next_invoice_date))
coll_orders = MYSY_GV.dbname['sales_order']
ret_val_order = coll_orders.find_one_and_update(
{'order_id': str(diction['order_id']) }, {"$set": {'next_invoice_date': str(next_invoice_date)}},
upsert=False,
return_document=ReturnDocument.AFTER
)
if (ret_val_order['_id'] is False):
mycommon.myprint(
" Impression de mettre à jour la date de la prochaine facturation de la commande : ° " + str(diction['order_id']) + " ")
return True,
except Exception as e:
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 de facturer la commande N° "+str(order_id)+" "
"""
Cette fonction recupere toutes le factures non imprimé (c'est a dire que le pdf n'est pas créé)
1 - Crée le fichier PDF
2 - Envoie l'email avec la facture
"""
def PrintAndSendInvoices(invoice_id=None):
try:
i = 0
query = {'printed':'0'}
if ( invoice_id and len(str(invoice_id)) > 0):
query = {'printed':'0','factures':str(invoice_id) }
coll_invoice = MYSY_GV.dbname['factures']
for val in coll_invoice.find({'printed':'0'}):
i = i +1
if( convertHtmlToPdf( val ) is False ):
mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible d'imprimer la facture N° "+
str(val['invoice_id']))
else:
mycommon.myprint(" Impression facture N° " +str(val['invoice_id'])+" OK")
ret_val = coll_invoice.find_one_and_update(
{'invoice_id': str(val['invoice_id'])}, {"$set": {'printed':'1'}},
upsert=False,
return_document=ReturnDocument.AFTER
)
if (ret_val['_id'] is False):
mycommon.myprint(" Impression facture N° " +str(val['invoice_id'])+" ==> Impossible de mettre à jour la facture")
return True, str(i)+" Factures ont été traitées"
except Exception as e:
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'imprimer les factures "
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',]
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, " Impossible d'imprimer les factures"
templateLoader = jinja2.FileSystemLoader(searchpath="./")
templateEnv = jinja2.Environment(loader=templateLoader)
TEMPLATE_FILE = "Template/invoice.html"
template = templateEnv.get_template(TEMPLATE_FILE)
# This data can come from database query
body = {
"data": {
"client_name": str(diction['invoice_nom']),
"client_address": str(diction['invoice_adr_street']),
"client_zip_ville": str(diction['invoice_adr_zip'])+" "+str(diction['invoice_adr_city']),
"client_pays": str(diction['invoice_adr_country']),
"invoice_id": str(diction['invoice_id']),
"invoice_date": str(diction['invoice_date']),
"due_date": str(diction['due_date']),
"orign_order": str(diction['order_id']),
"packs": str(diction['item_0']['code']),
"qty": str(diction['item_0']['qty']),
"unit_price": str(diction['item_0']['prix']),
"montant": str(diction['item_0']['amount']),
"total_ht": str(diction['total_ht']),
"tva": str(diction['total_tva']),
"total_ttc": str(diction['total_ttc']),
}
}
sourceHtml = template.render(json_data=body["data"])
orig_file_name = "invoice_"+str(diction['invoice_id'])+".pdf"
outputFilename = str(MYSY_GV.INVOICE_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()
#mycommon.myprint(str(inspect.stack()[0][3]) +" debut envoie de la factureeee "+diction['invoice_id'])
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(
outputFilename))
'''
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection(host=MYSY_GV.MYSY_FTP_HOST, username=MYSY_GV.MYSY_FTP_LOGIN, password=MYSY_GV.MYSY_FTP_PWD, cnopts=cnopts) as session:
print("Connection successfully established ... ")
localFilePath = outputFilename
remoteFilePath = str(MYSY_GV.INVOICE_FTP_LOCAL_STORAGE_DIRECTORY)+str(orig_file_name)
#print(" DEPLACEMENT DE " + str(localFilePath) + " VERS " + str(remoteFilePath) + " AVANTTT TRAITEMENT")
# Use put method to upload a file
session.put(localFilePath, remoteFilePath)
# Switch to a remote directory
mycommon.myprint(
str(inspect.stack()[0][3])+" DEPLACEMENT DE "+str(localFilePath)+" VERS "+str(remoteFilePath)+" EST OKKKK")
# return True on success and False on errors
print(pisaStatus.err, type(pisaStatus.err))
return True
except Exception as e:
mycommon.myprint(
str(inspect.stack()[0][3]) +"Exception when calling SMTPApi->send_transac_email: %s\n" % e)
return False
"""
Cette fonction la facture PDF d'un client
"""
def GetCustomerInvoice(diction):
try:
'''
Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
On controle que les champs obligatoires sont presents dans la liste
'''
field_list_obligatoire = ['token', 'invoiceid']
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, " Impossible de recuperer la facture"
user_recid = "None"
my_token = ""
my_invoiceid = ""
my_invoice_name = ""
if ("token" in diction.keys()):
if diction['token']:
my_token = diction['token']
if ("invoiceid" in diction.keys()):
if diction['invoiceid']:
my_invoiceid = diction['invoiceid']
my_invoice_name = 'invoice_'+str(my_invoiceid)+".pdf"
#print(" on cherche la facure :"+my_invoice_name)
# Verification de la validité du token/mail dans le cas des user en mode connecté
if (len(str(my_token)) > 0):
retval = mycommon.check_partner_token_validity("", my_token)
if retval is False:
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token n'est pas valide")
return False, " Impossible de recuperer la formation"
# Recuperation du recid de l'utilisateur
user_recid = mycommon.get_parnter_recid_from_token(my_token)
if user_recid is False:
mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le token de l'utilisateur")
return False, " Impossible de recuperer la formation"
if (len(str(my_token)) <= 0):
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token est vide")
return False, " Impossible de recuperer la facture"
# Recuperation de la facture depuis le serveur sFTP
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection(host=MYSY_GV.MYSY_FTP_HOST, username=MYSY_GV.MYSY_FTP_LOGIN,
password=MYSY_GV.MYSY_FTP_PWD, cnopts=cnopts) as session:
#print("Connection successfully established ... ")
session.chdir(MYSY_GV.INVOICE_FTP_LOCAL_STORAGE_DIRECTORY)
#print('our current working directory is: ', session.pwd)
session.get(my_invoice_name, './temp_direct/'+str(my_invoice_name))
if os.path.exists("./temp_direct/"+str(my_invoice_name)):
path = "./temp_direct/"+str(my_invoice_name)
return send_file(path, as_attachment=True)
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
print(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, "KO"
"""
Cette fonction va créer toutes les facture pour les commandes
dont la date facturation est arrivée à échéance (colonne : next_invoice_date)
IMPORTANT : Meme la facturation n'est pas faire le meme jours, on qu'on a un retard de X jours, ceci
n'est pas grave tant que X < 1 mois.
- le end date doit etre vide
Car à la facturation, la date prochaine facturation se mettra à date de dernière facture + 1 mois ou un 1 an.
"""
"""
Cette fonction créer une facture
"""
def AutoamticCreateInvoice():
try:
field_list_obligatoire = ['client_recid', 'invoice_nom', 'order_id', 'order_date', 'total_ttc','total_tva','total_ht','item_0']
coll_order = MYSY_GV.dbname['sales_order']
today = datetime.today().date()
i = 0
for diction in coll_order.find({"next_invoice_date" : { '$lte' : str(today) },
'end_date': { '$exists': False }},{'_id':0}):
i = i +1
print(' Facturation de la commande '+str(diction['order_id'])+" -- "+str(diction['next_invoice_date']))
CreateInvoice(diction)
return True, str(i)+" Factures ont été créées"
except Exception as e:
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 de créer les factures automatiques"