"""
Ce fichier permet de gerer la facturation des commandes des partenaires vers leur client.

Il se base sur les commandes faite à l'aide du fichier "partner_order.py"

"""
import bson
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 csv
import pandas as pd
from pymongo import ReturnDocument
import GlobalVariable as MYSY_GV
from math import isnan
import GlobalVariable as MYSY_GV
import ela_index_bdd_classes as eibdd
import email_mgt as email
import jinja2
from flask import send_file
from xhtml2pdf import pisa
from email.message import EmailMessage
from email.mime.text import MIMEText
from email import encoders
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import partner_order as partner_order

"""
Creation de la facture d'un commande
"""
def Invoice_Partner_Order(diction):
    try:
        diction = mycommon.strip_dictionary(diction)

        """
        Verification des input acceptés
        """
        field_list = ['token',  'order_id', 'order_ref_interne']

        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", False

        """
        Verification des champs obligatoires
        """
        field_list_obligatoire = ['token',  'order_id', 'order_ref_interne']

        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",False

        """
        Verification de l'identité et autorisation de l'entité qui
        appelle cette API
        """
        token = ""
        if ("token" in diction.keys()):
            if diction['token']:
                token = diction['token']

        local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
        if (local_status is not True):
            return local_status, my_partner, False


        # Verification de la validité de la commande à facturer
        order_to_invoice_data_count = MYSY_GV.dbname['partner_order_header'].count_documents(
            {'_id': ObjectId(str(diction['order_id'])), 'order_header_ref_interne': str(diction['order_ref_interne']),
             'partner_owner_recid': my_partner['recid'], 'order_header_type':'commande', 'valide': '1',
             'locked': '0'})

        if( order_to_invoice_data_count < 0 ):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - Les references de la commande sont invalides ")
            return False, " Les references de la commande sont invalides", False

        if (order_to_invoice_data_count > 1):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - Les references correspondent à plusieurs commandes. Facturation annulée. ")
            return False, " Les references correspondent à plusieurs commandes. Facturation annulée.",False




        order_to_invoice_data = MYSY_GV.dbname['partner_order_header'].find_one({'_id':ObjectId(str(diction['order_id'])), 'order_header_ref_interne':str(diction['order_ref_interne']),
                                                                        'partner_owner_recid':my_partner['recid'], 'valide':'1',
                                                                        'locked':'0', 'order_header_type':'commande'})

        print(" #### order_to_invoice_data = ", order_to_invoice_data);
        if( order_to_invoice_data is None or str(order_to_invoice_data['order_header_status']) != "2" ):
            mycommon.myprint(
                str(inspect.stack()[0][
                        3]) + " - La commande n'est pas au statut 'Traité'. Facturation annulée. ")
            return False, "  La commande n'est pas au statut 'Traité'. Facturation annulée.",False


        # Verifier que toutes lignes sont au statut 'traité'
        nb_line_a_facturer = 0
        for order_lines_to_invoice_data in MYSY_GV.dbname['partner_order_line'].find(
            {'order_header_id': str(diction['order_id']), 'order_header_ref_interne': str(diction['order_ref_interne']),
             'partner_owner_recid': my_partner['recid']}):
            nb_line_a_facturer = nb_line_a_facturer +1
            if( str(order_lines_to_invoice_data['order_line_type']) != "commande" or str(order_lines_to_invoice_data['order_line_status']) != "2"
            or str(order_lines_to_invoice_data['valide']) != "1" or str(order_lines_to_invoice_data['locked']) != "0"):
                mycommon.myprint(
                    str(inspect.stack()[0][
                            3]) + " - La ligne de commande "+str(order_lines_to_invoice_data['order_line_formation'])+" avec la Quantite "+ str(order_lines_to_invoice_data['order_line_qty'])+" n'est pas cohérente. Facturation annulée. ")
                return False, " La ligne de commande "+str(order_lines_to_invoice_data['order_line_formation'])+" avec la Quantite "+ str(order_lines_to_invoice_data['order_line_qty'])+" n'est pas cohérente. Facturation annulée.",False

        if( nb_line_a_facturer == 0):
            # Alors il n'y a aucune ligne à facturer
            mycommon.myprint(
                str(inspect.stack()[0][
                        3]) + " - Il n'y a aucune ligne à facturer. Facturation annulée. ")
            return False, "Il n'y a aucune ligne à facturer. Facturation annulée.",False

        # Verification de la validité du client
        is_client_valide = MYSY_GV.dbname['partner_client'].count_documents({'_id':ObjectId(str(order_to_invoice_data['order_header_client_id'])),
                                                                             'valide':'1', 'locked':'0', 'partner_recid':str(my_partner['recid'])})

        if( is_client_valide != 1):
            mycommon.myprint(
                str(inspect.stack()[0][
                        3]) + " - Le client à facturer est invalide. Facturation annulée. ")
            return False, "Le client à facturer est invalide. Facturation annulée.",False

        """
        A présent la commande est valide, on va
        0 - Mettre à jour la commande en mettant le statut "facturé'  ==> comme ca on bloque d'evenuelles modification de la commande
        1 - Relancer un compute de la commande
        2 - copier les données dans la collection 'facture'
        3 - on met à jour les lignes de la commande, pr la mettre à facturé
        """

        #  0 - Mettre à jour la commande en mettant le statut "facturé'  ==> comme ca on bloque d'evenuelles modification de la commande
        order_updated = MYSY_GV.dbname['partner_order_header'].update_one({'_id':ObjectId(str(diction['order_id'])), 'order_header_ref_interne':str(diction['order_ref_interne']),
                                                                        'partner_owner_recid':my_partner['recid'], 'valide':'1',
                                                                        'locked':'0', 'order_header_type':'commande'},
                                                                           {'$set':{'order_header_status':'3'}
                                                                            }
                                                                           )

        if(order_updated.modified_count != 1 ):
            mycommon.myprint(
                str(inspect.stack()[0][
                        3]) + " - Impossible de verrouiller la commande à facturer. Facturation annulée. ")
            return False, "Impossible de verrouiller la commande à facturer. Facturation annulée.",False


        # 1 - Relancer un compute de la commande
        comput_diction = {}
        comput_diction['token'] = diction['token']
        comput_diction['_id'] = diction['order_id']

        local_retval, local_message = partner_order.Compute_Order_Header(comput_diction)
        if (local_retval is False):
            order_updated = MYSY_GV.dbname['partner_order_header'].update_one({{'_id': ObjectId(
                str(diction['order_id'])), 'order_header_ref_interne': str(diction['order_ref_interne']),
                                                                                'partner_owner_recid': my_partner[
                                                                                    'recid'], 'valide': '1',
                                                                                'locked': '0',
                                                                                'order_header_type': 'commande'},
                                                                               {'$set': {'order_header_status': '2'}}
                                                                               })
            mycommon.myprint(
                str(inspect.stack()[0][
                        3]) + " - Impossible de mettre à jour les prix de la commande à facturer. Facturation annulée. ")
            return False, "Impossible de mettre à jour les prix de la commande à facturer. Facturation annulée.",False



        #2 - copier les données dans la collection 'facture'
        """
        /!\ On va recopier les header et line, telqel.
        On fera les changements plus tard si besoin 
        """


        # Rcuperation de la sequence de l'objet "partner_invoice_header" dans la collection : "mysy_sequence"
        retval_sequence_invoice = MYSY_GV.dbname['mysy_sequence'].find_one({'partner_invoice_header': 'partner_order_header',
                                                                          'valide': '1', 'partner_owner_recid': str(
                my_partner['recid'])})

        if (retval_sequence_invoice is None):
            # Il n'y pas de sequence pour le partenaire, on va aller chercher la sequence par defaut
            retval_sequence_invoice = MYSY_GV.dbname['mysy_sequence'].find_one(
                {'related_mysy_object': 'partner_invoice_header',
                 'valide': '1', 'partner_owner_recid': 'default'})

        if (retval_sequence_invoice is None or "current_val" not in retval_sequence_invoice.keys()):
            # Il n'y aucune sequence meme par defaut.
            order_updated = MYSY_GV.dbname['partner_order_header'].update_one({{'_id': ObjectId(
                str(diction['order_id'])), 'order_header_ref_interne': str(diction['order_ref_interne']),
                'partner_owner_recid': my_partner[
                    'recid'], 'valide': '1',
                'locked': '0',
                'order_header_type': 'commande'},
                {'$set': {'order_header_status': '2'}}
            })

            mycommon.myprint(" Impossible de récupérer la sequence 'retval_sequence_invoice' ")
            return False, "Impossible de récupérer la sequence 'retval_sequence_invoice'", False

        current_seq_value = str(retval_sequence_invoice['current_val'])
        new_sequence_value = int(mycommon.tryInt(current_seq_value)) + 1
        new_sequance_data_to_update = {'current_val': new_sequence_value}
        ret_val2 = MYSY_GV.dbname['mysy_sequence'].find_one_and_update(
            {'_id': ObjectId(str(retval_sequence_invoice['_id'])), 'valide': '1'},
            {"$set": new_sequance_data_to_update},
            return_document=ReturnDocument.AFTER,
            upsert=False,
        )
        invoice_date_time = str(datetime.now().strftime("%d/%m/%Y"))
        new_invoice_data_header = MYSY_GV.dbname['partner_order_header'].find_one({'_id':ObjectId(str(diction['order_id'])), 'order_header_ref_interne':str(diction['order_ref_interne']),
                                                                        'partner_owner_recid':my_partner['recid'], 'valide':'1',
                                                                        'locked':'0', 'order_header_type':'commande'}, {'_id':0, 'order_header_type':0, 'order_header_status':0})

        new_invoice_data_header['invoice_header_ref_interne'] = retval_sequence_invoice['prefixe']+str(current_seq_value)
        new_invoice_data_header['invoice_header_type'] = "facture"
        new_invoice_data_header['invoice_date'] = invoice_date_time
        new_invoice_data_header['update_by'] = str(my_partner['_id'])
        inserted_invoice_id = MYSY_GV.dbname['partner_invoice_header'].insert_one(new_invoice_data_header).inserted_id
        if (not inserted_invoice_id):
            order_updated = MYSY_GV.dbname['partner_order_header'].update_one({{'_id': ObjectId(
                str(diction['order_id'])), 'order_header_ref_interne': str(diction['order_ref_interne']),
                'partner_owner_recid': my_partner[
                    'recid'], 'valide': '1',
                'locked': '0',
                'order_header_type': 'commande'},
                {'$set': {'order_header_status': '2'}}
            })
            mycommon.myprint(
                " Impossible de créer l'entete de la facture ")
            return False, "Impossible de créer l'entete de la facture  ", False


        for new_invoice_data_line in MYSY_GV.dbname['partner_order_line'].find(  {'order_header_id': str(diction['order_id']), 'order_header_ref_interne': str(diction['order_ref_interne']),
                                                                             'partner_owner_recid': my_partner['recid']}, {'_id':0, 'order_line_type':0, 'order_line_status':0,
                                                                                                       }):
            new_invoice_data_line['invoice_header_ref_interne'] = retval_sequence_invoice['prefixe']+str(current_seq_value)
            new_invoice_data_line['invoice_line_type'] = "facture"
            new_invoice_data_line['invoice_date'] = invoice_date_time
            new_invoice_data_line['invoice_header_id'] = str(inserted_invoice_id)
            new_invoice_data_line['update_by'] = str(my_partner['_id'])

            #print(" ### on Va inserer la ligne de factue new_invoice_data_line =  ", new_invoice_data_line)

            inserted_line = MYSY_GV.dbname['partner_invoice_line'].insert_one(new_invoice_data_line)

            #print(" ### inserted_line de la ligne inserée  =  ", inserted_line)

            inserted_line_id = inserted_line.inserted_id

            #print(" ### inserted_line_id de la ligne inserée  =  ", inserted_line_id)

            if (not inserted_line_id):

                # Vu quil y a un souci avec l'une des lignes, on fait un roll back complet de la facturation
                order_updated = MYSY_GV.dbname['partner_order_header'].update_one({{'_id': ObjectId(
                    str(diction['order_id'])), 'order_header_ref_interne': str(diction['order_ref_interne']),
                    'partner_owner_recid': my_partner[
                        'recid'], 'valide': '1',
                    'locked': '0',
                    'order_header_type': 'commande'},
                    {'$set': {'order_header_status': '2'}}
                })

                MYSY_GV.dbname['partner_invoice_header'].delete_one({'_id':ObjectId(str(str(inserted_invoice_id)))})
                MYSY_GV.dbname['partner_invoice_line'].delete_many({'invoice_header_id': ObjectId(str(str(inserted_invoice_id)))})


                mycommon.myprint(
                    " Impossible de finaliser la facturation des lignes de  la ligne la commande ")
                return False, "  Impossible de finaliser la facturation des lignes de  la ligne la commande.  ", False


        # 3 - on met à jour les lignes de la commande, pr la mettre à facturé
        qry = {'order_header_id': str(diction['order_id']), 'order_header_ref_interne': str(diction['order_ref_interne']),
              'partner_owner_recid': my_partner['recid'], 'valide': '1',
              'locked': '0', 'order_header_type': 'commande'}

        print(" #### qry = ", qry)

        order_updated = MYSY_GV.dbname['partner_order_line'].update_many(
            {'order_header_id': str(diction['order_id']), 'order_header_ref_interne': str(diction['order_ref_interne']),
              'partner_owner_recid': my_partner['recid'], 'valide': '1',
              'locked': '0', 'order_line_type': 'commande'},
             {'$set': {'order_line_status': '3'}}
             )

        if (order_updated.modified_count <= 0):
            mycommon.myprint(
                str(inspect.stack()[0][
                        3]) + " WARNING - Impossible de mettre les lignes à facturer pour order_header_id =  "+str(str(diction['order_id'])))



        return True, " La commande a été correctement facturée", str(new_invoice_data_header['invoice_header_ref_interne'])

    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 facturer la commande ", False


"""
Recuperation d'une facture donnée
"""
def Get_Given_Partner_Invoice(diction):
    try:

        diction = mycommon.strip_dictionary(diction)

        """
        Verification des input acceptés
        """
        field_list = ['token', '_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'existe pas")
                return False, " Les informations fournies sont incorrectes",

        """
        Verification des champs obligatoires
        """
        field_list_obligatoire = ['token', '_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 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']

        local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
        if (local_status is not True):
            return local_status, my_partner

        """
        Clés de mise à jour 
        """
        data_cle = {}
        data_cle['partner_owner_recid'] = str(my_partner['recid'])
        data_cle['_id'] = ObjectId(str(diction['_id']))

        data_cle['valide'] = "1"
        data_cle['locked'] = "0"

        RetObject = []
        val_tmp = 1

        #print(" ### data_cle = ", data_cle)
        for retval in MYSY_GV.dbname['partner_invoice_header'].find(data_cle):
            user = retval
            user['id'] = str(val_tmp)
            val_tmp = val_tmp + 1

            # Si le champ 'order_header_client_id' alors on va chercher le nom du client
            if ('order_header_client_id' in retval.keys()):
                Client_data = MYSY_GV.dbname['partner_client'].find_one(
                    {'_id': ObjectId(str(retval['order_header_client_id'])), 'valide': '1', 'locked': '0',
                     'partner_recid': str(my_partner['recid'])})

                if (Client_data and 'nom' in Client_data.keys()):
                    user['order_header_client_nom'] = str(Client_data['nom'])

            # Si le champ 'order_header_vendeur_id' alors on va chercher le nom et prenom du vendeur (employe)
            if ('order_header_vendeur_id' in retval.keys()):
                Employee_data = MYSY_GV.dbname['ressource_humaine'].find_one(
                    {'_id': ObjectId(str(retval['order_header_vendeur_id'])), 'valide': '1', 'locked': '0',
                     'partner_recid': str(my_partner['recid'])})

                order_header_vendeur_nom_prenom = ""
                if (Employee_data and 'nom' in Employee_data.keys()):
                    order_header_vendeur_nom_prenom = str(Employee_data['nom'])

                if (Employee_data and 'prenom' in Employee_data.keys()):
                    order_header_vendeur_nom_prenom = str(order_header_vendeur_nom_prenom) + " " + str(
                        Employee_data['prenom'])

                user['order_header_vendeur_nom_prenom'] = str(order_header_vendeur_nom_prenom)

            # Recuperation des ligne associées
            retval_line_data = []
            for retval_line in MYSY_GV.dbname['partner_invoice_line'].find({'invoice_header_id':str(retval['_id']), 'partner_owner_recid':str(my_partner['recid']),
                                                                          'valide':'1', 'locked':'0'}):

                retval_line_data.append(retval_line)


            RetObject.append(mycommon.JSONEncoder().encode(user))

        #print(" ### RetObject = ", 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) + " - Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de récupérer les données de la commande "

"""
Recuperation des lignes d'une facture à partir de l'invoice_header_id, sans entete
"""
def Get_Given_Partner_Invoice_Lines(diction):
    try:

        diction = mycommon.strip_dictionary(diction)

        """
        Verification des input acceptés
        """
        field_list = ['token', 'invoice_header_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'existe pas")
                return False, " Les informations fournies sont incorrectes",

        """
        Verification des champs obligatoires
        """
        field_list_obligatoire = ['token', 'invoice_header_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 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']

        local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
        if (local_status is not True):
            return local_status, my_partner

        """
        Clés de mise à jour 
        """
        data_cle = {}
        data_cle['partner_owner_recid'] = str(my_partner['recid'])
        data_cle['invoice_header_id'] = str(diction['invoice_header_id'])

        data_cle['valide'] = "1"
        data_cle['locked'] = "0"

        RetObject = []
        val_tmp = 1

        filt_class_partner_recid = {'partner_owner_recid': str(my_partner['recid'])}
        filt_invoice_header_id = {'invoice_header_id': str(diction['invoice_header_id'])}

        query = [{'$match': {'$and': [ filt_invoice_header_id,
                                      {'partner_owner_recid': str(my_partner['recid'])}]}},
                 {'$lookup':
                     {
                         'from': 'myclass',
                         'localField': 'order_line_formation',
                         'foreignField': 'internal_url',
                         'pipeline': [{'$match': {'$and': [ filt_class_partner_recid]}},
                                      {'$project': {'title': 1, 'domaine': 1,
                                                    'duration': 1,
                                                    'duration_unit': 1,'external_code':1}}],
                         'as': 'myclass_collection'
                     }
                 }
                 ]
        print("#### Get_Given_Partner_Invoice_Lines  : query pip= ", query)

        for retval in MYSY_GV.dbname['partner_invoice_line'].aggregate(query):
            if ('myclass_collection' in retval.keys() and len(retval['myclass_collection']) > 0):
                user = {}
                user['id'] = str(val_tmp)
                val_tmp = val_tmp + 1
                user['_id'] = retval['_id']
                user['order_line_formation'] = retval['order_line_formation']
                user['order_line_qty'] = retval['order_line_qty']
                user['order_line_prix_unitaire'] = retval['order_line_prix_unitaire']
                user['invoice_header_id'] = retval['invoice_header_id']
                user['invoice_header_ref_interne'] = retval['invoice_header_ref_interne']
                user['invoice_date'] = retval['invoice_date']
                user['valide'] = retval['valide']
                user['locked'] = retval['locked']

                if ("order_line_montant_reduction" in retval.keys()):
                    user['order_line_montant_reduction'] = retval['order_line_montant_reduction']
                else:
                    user['order_line_montant_reduction'] = "0"

                if ("order_line_montant_toutes_taxes" in retval.keys()):
                    user['order_line_montant_toutes_taxes'] = retval['order_line_montant_toutes_taxes']
                else:
                    user['order_line_montant_toutes_taxes'] = "0"

                if ("order_line_tax" in retval.keys()):
                    user['order_line_tax'] = retval['order_line_tax']
                else:
                    user['order_line_tax'] = ""

                if ("order_line_tax_amount" in retval.keys()):
                    user['order_line_tax_amount'] = retval['order_line_tax_amount']
                else:
                    user['order_line_tax_amount'] = "0"

                if ("order_line_type_reduction" in retval.keys()):
                    user['order_line_type_reduction'] = retval['order_line_type_reduction']
                else:
                    user['order_line_montant_reduction'] = ""

                if ("order_line_type_valeur" in retval.keys()):
                    user['order_line_type_valeur'] = retval['order_line_type_valeur']
                else:
                    user['order_line_type_valeur'] = "0"


                if ("order_line_montant_hors_taxes" in retval.keys()):
                    user['order_line_montant_hors_taxes'] = retval['order_line_montant_hors_taxes']
                else:
                    user['order_line_montant_hors_taxes'] = "0"


                user['date_update'] = retval['date_update']
                user['update_by'] = str(my_partner['_id'])
                user['partner_owner_recid'] = retval['partner_owner_recid']
                user['invoice_line_type'] = retval['invoice_line_type']


                if( "order_line_comment" in retval.keys()):
                    user['order_line_comment'] = retval['order_line_comment']
                else:
                    user['order_line_comment'] = ""

                user['title'] = retval['myclass_collection'][0]['title']
                user['order_line_formation_external_code'] = retval['myclass_collection'][0]['external_code']
                user['domaine'] = retval['myclass_collection'][0]['domaine']
                user['duration'] = retval['myclass_collection'][0]['duration']
                user['duration_unit'] = retval['myclass_collection'][0]['duration_unit']

                if (str(retval['myclass_collection'][0]['duration_unit']) == "heure"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " h"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "jour"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " j"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "semaine"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " s"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "mois"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " m"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "annee"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " a"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "user_rythme"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " u"

                else:
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " ?"

                RetObject.append(mycommon.JSONEncoder().encode(user))



        #print(" ### RetObject = ", 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) + " - Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de récupérer les lignes de la facture "



"""
Recuperation des lignes d'une commande à partir de l' invoice_header_ref_interne, sans entete
"""
def Get_Given_Partner_Invoice_Lines_From_Invoice_ref_interne(diction):
    try:

        diction = mycommon.strip_dictionary(diction)

        """
        Verification des input acceptés
        """
        field_list = ['token', 'invoice_header_ref_interne']

        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'existe pas")
                return False, " Les informations fournies sont incorrectes",

        """
        Verification des champs obligatoires
        """
        field_list_obligatoire = ['token', 'invoice_header_ref_interne']
        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
        """
        token = ""
        if ("token" in diction.keys()):
            if diction['token']:
                token = diction['token']

        local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
        if (local_status is not True):
            return local_status, my_partner

        """
        Clés de mise à jour 
        """
        data_cle = {}
        data_cle['partner_owner_recid'] = str(my_partner['recid'])
        data_cle['invoice_header_ref_interne'] = str(diction['invoice_header_ref_interne'])

        data_cle['valide'] = "1"
        data_cle['locked'] = "0"

        RetObject = []
        val_tmp = 1

        filt_class_partner_recid = {'partner_owner_recid': str(my_partner['recid'])}
        filt_invoice_header_id = {'invoice_header_id': str(diction['order_header_id'])}

        query = [{'$match': {'$and': [filt_invoice_header_id,
                                      {'partner_owner_recid': str(my_partner['recid'])}]}},
                 {'$lookup':
                     {
                         'from': 'myclass',
                         'localField': 'order_line_formation',
                         'foreignField': 'internal_url',
                         'pipeline': [{'$match': {'$and': [filt_class_partner_recid]}},
                                      {'$project': {'title': 1, 'domaine': 1,
                                                    'duration': 1,
                                                    'duration_unit': 1, 'external_code': 1}}],
                         'as': 'myclass_collection'
                     }
                 }
                 ]
        print("#### Get_Given_Partner_Invoice_Lines  : query pip= ", query)

        for retval in MYSY_GV.dbname['partner_invoice_line'].aggregate(query):
            if ('myclass_collection' in retval.keys() and len(retval['myclass_collection']) > 0):
                user = {}
                user['id'] = str(val_tmp)
                val_tmp = val_tmp + 1
                user['_id'] = retval['_id']
                user['order_line_formation'] = retval['order_line_formation']
                user['order_line_qty'] = retval['order_line_qty']
                user['order_line_prix_unitaire'] = retval['order_line_prix_unitaire']
                user['invoice_header_id'] = retval['invoice_header_id']
                user['invoice_header_ref_interne'] = retval['invoice_header_ref_interne']
                user['invoice_date'] = retval['invoice_date']
                user['valide'] = retval['valide']
                user['locked'] = retval['locked']

                if ("order_line_montant_reduction" in retval.keys()):
                    user['order_line_montant_reduction'] = retval['order_line_montant_reduction']
                else:
                    user['order_line_montant_reduction'] = "0"

                if ("order_line_montant_toutes_taxes" in retval.keys()):
                    user['order_line_montant_toutes_taxes'] = retval['order_line_montant_toutes_taxes']
                else:
                    user['order_line_montant_toutes_taxes'] = "0"

                if ("order_line_tax" in retval.keys()):
                    user['order_line_tax'] = retval['order_line_tax']
                else:
                    user['order_line_tax'] = ""

                if ("order_line_tax_amount" in retval.keys()):
                    user['order_line_tax_amount'] = retval['order_line_tax_amount']
                else:
                    user['order_line_tax_amount'] = "0"

                if ("order_line_type_reduction" in retval.keys()):
                    user['order_line_type_reduction'] = retval['order_line_type_reduction']
                else:
                    user['order_line_montant_reduction'] = ""

                if ("order_line_type_valeur" in retval.keys()):
                    user['order_line_type_valeur'] = retval['order_line_type_valeur']
                else:
                    user['order_line_type_valeur'] = "0"

                if ("order_line_montant_hors_taxes" in retval.keys()):
                    user['order_line_montant_hors_taxes'] = retval['order_line_montant_hors_taxes']
                else:
                    user['order_line_montant_hors_taxes'] = "0"

                user['date_update'] = retval['date_update']
                user['update_by'] = str(my_partner['_id'])
                user['partner_owner_recid'] = retval['partner_owner_recid']
                user['invoice_line_type'] = retval['invoice_line_type']

                if ("order_line_comment" in retval.keys()):
                    user['order_line_comment'] = retval['order_line_comment']
                else:
                    user['order_line_comment'] = ""

                user['title'] = retval['myclass_collection'][0]['title']
                user['order_line_formation_external_code'] = retval['myclass_collection'][0]['external_code']
                user['domaine'] = retval['myclass_collection'][0]['domaine']
                user['duration'] = retval['myclass_collection'][0]['duration']
                user['duration_unit'] = retval['myclass_collection'][0]['duration_unit']

                if (str(retval['myclass_collection'][0]['duration_unit']) == "heure"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " h"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "jour"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " j"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "semaine"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " s"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "mois"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " m"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "annee"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " a"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "user_rythme"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " u"

                else:
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " ?"

                RetObject.append(mycommon.JSONEncoder().encode(user))

        #print(" ### RetObject = ", 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) + " - Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de récupérer les lignes de commande "




"""
Recuperation de la liste des factures d'un partner
"""
def Get_List_Partner_Invoice_no_filter(diction):
    try:
        diction = mycommon.strip_dictionary(diction)

        """
        Verification des input acceptés
        """
        field_list = ['token', ]

        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'existe pas")
                return False, " Les informations fournies sont incorrectes",

        """
        Verification des champs obligatoires
        """
        field_list_obligatoire = ['token', ]
        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans 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']

        local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
        if (local_status is not True):
            return local_status, my_partner



        find_qry = {'$and': [{'partner_owner_recid': str(my_partner['recid']), 'valide': '1', 'locked': '0'}, {}, ]}

        new_myquery_find_invoice = [{'$match': find_qry},
                                  { '$sort': {'_id': -1}},
                                  {"$addFields": {"partner_invoice_header_Id": {"$toString": "$_id"}}},
                                  {'$lookup':
                                      {
                                          'from': 'partner_order_line',
                                          'localField': "partner_invoice_header_Id",
                                          'foreignField': 'invoice_header_id',
                                          'pipeline': [{'$match': {'$and': [{}, {
                                              'partner_owner_recid': str(my_partner['recid'])}, {'valide': '1'}]}}, ],
                                          'as': 'partner_invoice_line_collection'
                                      }
                                  }
                                  ]


        print(" ### orders  new_myquery_find_invoice = ", new_myquery_find_invoice)
        RetObject = []
        val_tmp = 1

        for New_retVal in MYSY_GV.dbname['partner_invoice_header'].aggregate(new_myquery_find_invoice):
            user = New_retVal
            user['id'] = str(val_tmp)
            val_tmp = val_tmp + 1

            # Convertir la date facture en jj/mm/aaaa
            if( 'invoice_date' in New_retVal.keys()):
                date_jjmmaaa = str(New_retVal['invoice_date'])[0:10]
                #print(" ### date_jjmmaaa = ", date_jjmmaaa)
                #date_jjmmaaa = datetime.strptime(date_jjmmaaa, '%d/%m/%Y')
                #New_retVal['invoice_date'] = str(date_jjmmaaa)


            # Si le champ 'order_header_client_id' alors on va chercher le nom du client
            if( 'order_header_client_id' in New_retVal.keys()):
                Client_data = MYSY_GV.dbname['partner_client'].find_one({'_id':ObjectId(str(New_retVal['order_header_client_id'])), 'valide':'1', 'locked':'0',
                                                                         'partner_recid':str(my_partner['recid'])})

                if( Client_data and 'nom' in Client_data.keys() ):
                    user['order_header_client_nom'] = str(Client_data['nom'])

            # Si le champ 'order_header_vendeur_id' alors on va chercher le nom et prenom du vendeur (employe)
            if ('order_header_vendeur_id' in New_retVal.keys()):
                Employee_data = MYSY_GV.dbname['ressource_humaine'].find_one(
                    {'_id': ObjectId(str(New_retVal['order_header_vendeur_id'])), 'valide': '1', 'locked': '0',
                     'partner_recid': str(my_partner['recid'])})

                order_header_vendeur_nom_prenom = ""
                if (Employee_data and 'nom' in Employee_data.keys()):
                    order_header_vendeur_nom_prenom = str(Employee_data['nom'])

                if (Employee_data and 'prenom' in Employee_data.keys()):
                    order_header_vendeur_nom_prenom = str(order_header_vendeur_nom_prenom)+" "+str(Employee_data['prenom'])

                user['order_header_vendeur_nom_prenom'] = str(order_header_vendeur_nom_prenom)

            RetObject.append(mycommon.JSONEncoder().encode(user))

        return True, RetObject


    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de récupérer la liste des factures "

"""
Recuperation de la liste des factures avec des filtres.
les filtres acceptés sont : 
- ref_interne_cmd (commande)
- ref_interne_invoice
- ref_externe
- invoice_date entre date_debut et date_fin  
- nom_client
"""
def Get_List_Partner_Invoice_with_filter(diction):
    try:
        diction = mycommon.strip_dictionary(diction)

        """
        Verification des input acceptés. les filtres accepté sont : 
        - ref_interne, 
        """
        field_list = ['token', 'date_facture_debut', 'date_facture_fin', 'client_nom', 'ref_interne_cmd',
                     'ref_interne_invoice', 'ref_externe', 'formation']

        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'existe pas")
                return False, " Les informations fournies sont incorrectes",

        """
        Verification des champs obligatoires
        """
        field_list_obligatoire = ['token', ]
        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans 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']

        local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
        if (local_status is not True):
            return local_status, my_partner

        filt_client_nom = {}
        sub_filt_client_nom = {}
        Lists_partner_client_id = []
        if ("client_nom" in diction.keys()):
            sub_filt_client_nom = {'nom': {'$regex': str(diction['client_nom']), "$options": "i"}, 'partner_recid':str(my_partner['recid']), 'valide':'1', 'locked':'0'}
            # Recuperation des '_id' des clients dont le nom match en regexp
            #print(" ### sub_filt_client_nom = ", sub_filt_client_nom)
            for List_Client_Data in MYSY_GV.dbname['partner_client'].find(sub_filt_client_nom, {'_id':1}):
                Lists_partner_client_id.append(str(List_Client_Data['_id']))

            filt_client_nom =  {'order_header_client_id': {'$in': Lists_partner_client_id, }}
            #print(' ### filt_client_nom = ', filt_client_nom)



        filt_formation_external_code = {}
        sub_filt_formation_external_code = {}
        Lists_partner_formation_internal_url = []
        if ("formation" in diction.keys()):
            sub_filt_formation_external_code = {'external_code': {'$regex': str(diction['formation']), "$options": "i"},
                                   'partner_owner_recid': str(my_partner['recid']), 'valide': '1', 'locked': '0'}

            # Recuperation des '_id' des formation dont le nom match en regexp
            print(" ### sub_filt_formation_external_code = ", sub_filt_formation_external_code)
            for Lists_partner_formation_Data in MYSY_GV.dbname['myclass'].find(sub_filt_formation_external_code, {'internal_url': 1}):
                Lists_partner_formation_internal_url.append(str(Lists_partner_formation_Data['internal_url']))

            filt_formation_external_code = {'order_line_formation': {'$in': Lists_partner_formation_internal_url }}



        filt_ref_interne_cmd = {}
        if ("ref_interne_cmd" in diction.keys()):
            filt_ref_interne_cmd = {
                'order_header_ref_interne': {'$regex': str(diction['ref_interne_cmd']), "$options": "i"}}

        filt_ref_interne_invoice = {}
        if ("ref_interne_invoice" in diction.keys()):
            filt_ref_interne_cmd = {
                'invoice_header_ref_interne': {'$regex': str(diction['ref_interne_invoice']), "$options": "i"}}


        filt_ref_externe = {}
        if ("ref_externe" in diction.keys()):
            filt_ref_externe = {
                'order_header_ref_client': {'$regex': str(diction['ref_externe']), "$options": "i"}}



        find_qry = {'$and': [{'partner_owner_recid': str(my_partner['recid']), 'valide': '1', 'locked': '0'}, filt_client_nom, filt_ref_interne_cmd, filt_ref_interne_invoice, filt_ref_externe]}

        new_myquery_find_order = [{'$match': find_qry},
                                  {"$addFields": {"partner_invoice_header_Id": {"$toString": "$_id"}}},
                                  {'$lookup':
                                      {
                                          'from': 'partner_invoice_line',
                                          'localField': "partner_invoice_header_Id",
                                          'foreignField': 'invoice_header_id',
                                          'pipeline': [{'$match': {'$and': [filt_formation_external_code, {
                                              'partner_owner_recid': str(my_partner['recid'])}, {'valide': '1'}]}}, ],
                                          'as': 'partner_invoice_line_collection'
                                      }
                                  }
                                  ]


        print(" ### Get_List_Partner_Order_with_filter orders  new_myquery_find_order = ", new_myquery_find_order)
        RetObject = []
        val_tmp = 1

        filter_date_debut = ""
        if ("date_facture_debut" in diction.keys()):
            if diction['date_facture_debut']:
                filter_date_debut = str(diction['date_facture_debut'])[0:10]
                local_status = mycommon.CheckisDate(filter_date_debut)
                if (local_status is False):
                    mycommon.myprint(
                        str(inspect.stack()[0][
                                3]) + " La date de debut (filtre) n'est pas au format 'jj/mm/aaaa' ")
                    return False, " La date de debut (filtre) n'est pas au format 'jj/mm/aaaa'"

        filter_date_fin = ""
        if ("date_facture_fin" in diction.keys()):
            if diction['date_facture_fin']:
                filter_date_fin = str(diction['date_facture_fin'])[0:10]
                local_status = mycommon.CheckisDate(filter_date_fin)
                if (local_status is False):
                    mycommon.myprint(
                        str(inspect.stack()[0][
                                3]) + " La date de fin (filtre) n'est pas au format 'jj/mm/aaaa' ")
                    return False, " La date de fin (filtre) n'est pas au format 'jj/mm/aaaa'"



        for New_retVal in MYSY_GV.dbname['partner_invoice_header'].aggregate(new_myquery_find_order):

            if ('partner_invoice_line_collection' in New_retVal.keys() and len( New_retVal['partner_invoice_line_collection']) > 0):
                user = New_retVal
                # Si le champ 'order_header_client_id' alors on va chercher le nom du client
                if ('order_header_client_id' in New_retVal.keys()):
                    Client_data = MYSY_GV.dbname['partner_client'].find_one(
                        {'_id': ObjectId(str(New_retVal['order_header_client_id'])), 'valide': '1', 'locked': '0',
                         'partner_recid': str(my_partner['recid'])})

                    if (Client_data and 'nom' in Client_data.keys()):
                        user['order_header_client_nom'] = str(Client_data['nom'])

                # Si le champ 'order_header_vendeur_id' alors on va chercher le nom et prenom du vendeur (employe)
                if ('order_header_vendeur_id' in New_retVal.keys()):
                    Employee_data = MYSY_GV.dbname['ressource_humaine'].find_one(
                        {'_id': ObjectId(str(New_retVal['order_header_vendeur_id'])), 'valide': '1', 'locked': '0',
                         'partner_recid': str(my_partner['recid'])})

                    order_header_vendeur_nom_prenom = ""
                    if (Employee_data and 'nom' in Employee_data.keys()):
                        order_header_vendeur_nom_prenom = str(Employee_data['nom'])

                    if (Employee_data and 'prenom' in Employee_data.keys()):
                        order_header_vendeur_nom_prenom = str(order_header_vendeur_nom_prenom) + " " + str(
                            Employee_data['prenom'])

                    user['order_header_vendeur_nom_prenom'] = str(order_header_vendeur_nom_prenom)


                if( filter_date_debut and filter_date_fin ):
                    if ( datetime.strptime(str(New_retVal['invoice_date'])[0:10], '%d/%m/%Y') >= datetime.strptime(str(filter_date_debut)[0:10], '%d/%m/%Y') and
                    datetime.strptime(str(New_retVal['invoice_date'])[0:10], '%d/%m/%Y') <= datetime.strptime(str(filter_date_fin)[0:10], '%d/%m/%Y') ):
                        user['id'] = str(val_tmp)
                        val_tmp = val_tmp + 1

                        RetObject.append(mycommon.JSONEncoder().encode(user))

                elif ( filter_date_debut ):
                    if ( datetime.strptime(str(New_retVal['invoice_date'])[0:10], '%d/%m/%Y') >= datetime.strptime(str(filter_date_debut)[0:10], '%d/%m/%Y')  ):
                        user['id'] = str(val_tmp)
                        val_tmp = val_tmp + 1
                        RetObject.append(mycommon.JSONEncoder().encode(user))

                elif ( filter_date_fin ):
                    if ( datetime.strptime(str(New_retVal['invoice_date'])[0:10], '%d/%m/%Y') <= datetime.strptime(str(filter_date_fin)[0:10], '%d/%m/%Y') ):
                        user['id'] = str(val_tmp)
                        val_tmp = val_tmp + 1
                        RetObject.append(mycommon.JSONEncoder().encode(user))

                else:
                    user['id'] = str(val_tmp)
                    val_tmp = val_tmp + 1
                    RetObject.append(mycommon.JSONEncoder().encode(user))


        #print(" ####  nb_result = ", val_tmp)
        return True, RetObject


    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de récupérer la liste des factures "



"""
Cette fonction permet de récupérer une ligne de detail d'une facture donnée
c'est a dire, une ligne de la collection 'partner_invoice_line' 
"""
def Get_Given_Line_Of_Partner_Invoice_Lines(diction):
    try:

        diction = mycommon.strip_dictionary(diction)

        """
        Verification des input acceptés
        """
        field_list = ['token', 'invoice_line_id', 'invoice_header_ref_interne']

        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'existe pas")
                return False, " Les informations fournies sont incorrectes",

        """
        Verification des champs obligatoires
        """
        field_list_obligatoire = ['token', 'invoice_line_id', 'invoice_header_ref_interne']
        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
        """
        token = ""
        if ("token" in diction.keys()):
            if diction['token']:
                token = diction['token']

        local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
        if (local_status is not True):
            return local_status, my_partner

        """
        Clés de mise à jour 
        """
        data_cle = {}
        data_cle['partner_owner_recid'] = str(my_partner['recid'])
        data_cle['invoice_line_id'] = str(diction['invoice_line_id'])
        data_cle['invoice_header_ref_interne'] = str(diction['invoice_header_ref_interne'])

        data_cle['valide'] = "1"
        data_cle['locked'] = "0"

        RetObject = []
        val_tmp = 1

        filt_class_partner_recid = {'partner_owner_recid': str(my_partner['recid'])}
        filt_invoice_line_id = {'_id': ObjectId(str(diction['invoice_line_id']))}
        filt_invoice_line_header_ref_interne = {'invoice_header_ref_interne': str(diction['invoice_header_ref_interne'])}

        query = [{'$match': {'$and': [ filt_invoice_line_id, filt_invoice_line_header_ref_interne,
                                      {'partner_owner_recid': str(my_partner['recid'])}]}},
                 {'$lookup':
                     {
                         'from': 'myclass',
                         'localField': 'order_line_formation',
                         'foreignField': 'internal_url',
                         'pipeline': [{'$match': {'$and': [ filt_class_partner_recid]}},
                                      {'$project': {'title': 1, 'domaine': 1,
                                                    'duration': 1,
                                                    'duration_unit': 1,
                                                    'external_code':1}}],
                         'as': 'myclass_collection'
                     }
                 }
                 ]
        print("#### Get_Given_Partner_Invoice_Lines  : query pip= ", query)

        for retval in MYSY_GV.dbname['partner_invoice_line'].aggregate(query):
            if ('myclass_collection' in retval.keys() and len(retval['myclass_collection']) > 0):
                user = {}
                user['id'] = str(val_tmp)
                val_tmp = val_tmp + 1
                user['_id'] = retval['_id']

                user['order_line_formation'] = retval['order_line_formation']
                user['order_line_qty'] = retval['order_line_qty']
                user['order_line_prix_unitaire'] = retval['order_line_prix_unitaire']
                user['order_header_id'] = retval['order_header_id']
                user['order_header_ref_interne'] = retval['order_header_ref_interne']

                user['invoice_header_ref_interne'] = retval['invoice_header_ref_interne']
                user['invoice_line_type'] = retval['invoice_line_type']
                user['invoice_date'] = retval['invoice_date']
                user['invoice_header_id'] = retval['invoice_header_id']


                if ("order_line_montant_reduction" in retval.keys()):
                    user['order_line_montant_reduction'] = retval['order_line_montant_reduction']
                else:
                    user['order_line_montant_reduction'] = "0"

                if ("order_line_montant_toutes_taxes" in retval.keys()):
                    user['order_line_montant_toutes_taxes'] = retval['order_line_montant_toutes_taxes']
                else:
                    user['order_line_montant_toutes_taxes'] = "0"

                if ("order_line_tax" in retval.keys()):
                    user['order_line_tax'] = retval['order_line_tax']
                else:
                    user['order_line_tax'] = ""

                if ("order_line_tax_amount" in retval.keys()):
                    user['order_line_tax_amount'] = retval['order_line_tax_amount']
                else:
                    user['order_line_tax_amount'] = "0"

                if ("order_line_type_reduction" in retval.keys()):
                    user['order_line_type_reduction'] = retval['order_line_type_reduction']
                else:
                    user['order_line_montant_reduction'] = ""

                if ("order_line_type_valeur" in retval.keys()):
                    user['order_line_type_valeur'] = retval['order_line_type_valeur']
                else:
                    user['order_line_type_valeur'] = "0"

                if ("order_line_montant_hors_taxes" in retval.keys()):
                    user['order_line_montant_hors_taxes'] = retval['order_line_montant_hors_taxes']
                else:
                    user['order_line_montant_hors_taxes'] = "0"


                user['valide'] = retval['valide']
                user['locked'] = retval['locked']
                user['date_update'] = retval['date_update']
                user['update_by'] = str(my_partner['_id'])
                user['partner_owner_recid'] = retval['partner_owner_recid']


                if( "order_line_comment" in retval.keys()):
                    user['order_line_comment'] = retval['order_line_comment']
                else:
                    user['order_line_comment'] = ""

                user['title'] = retval['myclass_collection'][0]['title']
                user['order_line_formation_external_code'] = retval['myclass_collection'][0]['external_code']
                user['domaine'] = retval['myclass_collection'][0]['domaine']
                user['duration'] = retval['myclass_collection'][0]['duration']
                user['duration_unit'] = retval['myclass_collection'][0]['duration_unit']

                if (str(retval['myclass_collection'][0]['duration_unit']) == "heure"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " h"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "jour"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " j"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "semaine"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " s"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "mois"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " m"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "annee"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " a"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "user_rythme"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " u"

                else:
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " ?"

                RetObject.append(mycommon.JSONEncoder().encode(user))



        #print(" ### RetObject = ", 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) + " - Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de récupérer les lignes de facture "


"""
Impression PDF d'une facture 
"""

def GerneratePDF_Partner_Invoice(diction):
    try:
        field_list = ['invoice_id', 'token', ]
        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]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Les informations fournies sont incorrectes"

        """
                Verification de la liste des champs obligatoires
                """
        field_list_obligatoire = ['invoice_id', '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, "Les informations fournies sont incorrectes"

        query_get_data = {}
        mytoken = ""
        if ("token" in diction.keys()):
            if diction['token']:
                mytoken = diction['token']

        local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
        if (local_status is not True):
            return local_status, my_partner

        # Verification de la validité de la facture
        qry = {'_id': ObjectId(str(diction['invoice_id'])), 'valide': '1', 'locked': '0',
               'partner_owner_recid': str(my_partner['recid'])}
        #print(" ### qry = ", qry)

        is_invoice_Existe_Count = 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_invoice_Existe_Count != 1):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - La facture n'est pas valide ")
            return False, " La facture n'est pas valide",

        Order_header_data = MYSY_GV.dbname['partner_invoice_header'].find_one({'_id': ObjectId(str(diction['invoice_id'])),
                                                                             'valide': '1', 'locked': '0',
                                                                             'partner_owner_recid': str(
                                                                                 my_partner['recid'])})

        partner_document_INVOICE_data_qry = {'partner_owner_recid': str(my_partner['recid']),
                                                      'valide': '1', 'locked': '0', 'ref_interne': 'PART_INVOICE', 'type_doc':'pdf'}

        print(" ### partner_document_INVOICE_data_qry = ", partner_document_INVOICE_data_qry)
        partner_document_INVOICE_data = MYSY_GV.dbname['courrier_template'].find_one(
            {'partner_owner_recid': str(my_partner['recid']),
             'valide': '1', 'locked': '0', 'ref_interne': 'PART_INVOICE', 'type_doc':'pdf'})

        if (partner_document_INVOICE_data is None):
            # Il n'existe pas de personnalisation de la preinscription pour ce partenaire, on va aller récupérer la presinscription pa defaut
            partner_document_INVOICE_data = MYSY_GV.dbname['courrier_template'].find_one(
                {'partner_owner_recid': 'default',
                 'valide': '1', 'locked': '0', 'ref_interne': 'PART_INVOICE', 'type_doc':'pdf'})

        if (partner_document_INVOICE_data is None):
            mycommon.myprint(
                str(inspect.stack()[0][
                        3]) + "Aucun document parametré ")
            return False, "Aucun document parametré "

        if ("contenu_doc" not in partner_document_INVOICE_data or len(
                str(partner_document_INVOICE_data['contenu_doc'])) <= 0):
            mycommon.myprint(str(inspect.stack()[0][
                                     3]) + " - Le parametrage du document  est invalide")
            return False, " Le parametrage du document  est invalide "

        # Recuperation des données du client
        if ("order_header_client_id" in Order_header_data.keys()):
            Order_header_client_data = MYSY_GV.dbname['partner_client'].find_one(
                {'_id': ObjectId(str(Order_header_data['order_header_client_id'])),
                 'partner_recid': str(my_partner['recid']), 'valide': '1', 'locked': '0'})

            if (Order_header_client_data is None):
                mycommon.myprint(str(inspect.stack()[0][
                                         3]) + " - Le client est invalide")
                return False, " Le client est invalide"

        ### Ajout des données du client sur l'entete de la commande, exemple : le nom, email, etc
        if("raison_sociale" in Order_header_client_data.keys() ):
            Order_header_data['client_raison_sociale'] = Order_header_client_data['raison_sociale']

        if ("nom" in Order_header_client_data.keys()):
            Order_header_data['client_nom'] = Order_header_client_data['nom']

        if ("email" in Order_header_client_data.keys()):
            Order_header_data['client_email'] = Order_header_client_data['email']

        # Ajout d'un parametre pour le data time du jour de l'edition (c'est une data static qui peut servir pour l'horodatage
        Order_header_data['current_date_time'] = str(datetime.now().strftime("%d/%m/%Y, %H:%M:%S") )


        # Recuperation des details de lignes de : partner_invoice_line
        filt_class_partner_recid = {'partner_owner_recid': str(my_partner['recid'])}
        filt_order_header_order_id = {'invoice_header_id': str(diction['invoice_id'])}

        query = [{'$match': {'$and': [filt_order_header_order_id,
                                      {'partner_owner_recid': str(my_partner['recid'])}]}},
                 {'$lookup':
                     {
                         'from': 'myclass',
                         'localField': 'order_line_formation',
                         'foreignField': 'internal_url',
                         'pipeline': [{'$match': {'$and': [filt_class_partner_recid]}},
                                      {'$project': {'title': 1, 'domaine': 1,
                                                    'duration': 1,
                                                    'duration_unit': 1,
                                                    'external_code':1}}],
                         'as': 'myclass_collection'
                     }
                 }
                 ]
        #print("#### Get_Given_Partner_Order_Lines_From_order_ref_interne  : query pip= ", query)
        val_tmp = 0
        Order_header_lines_data = []
        for retval in MYSY_GV.dbname['partner_invoice_line'].aggregate(query):
            if ('myclass_collection' in retval.keys() and len(retval['myclass_collection']) > 0):
                user = {}
                user['id'] = str(val_tmp)
                val_tmp = val_tmp + 1
                user['_id'] = retval['_id']
                user['order_line_formation'] = retval['order_line_formation']
                user['order_line_qty'] = retval['order_line_qty']
                user['order_line_prix_unitaire'] = retval['order_line_prix_unitaire']
                user['order_header_id'] = retval['order_header_id']
                user['order_header_ref_interne'] = retval['order_header_ref_interne']
                user['invoice_header_ref_interne'] = retval['invoice_header_ref_interne']
                user['invoice_line_type'] = retval['invoice_line_type']
                user['invoice_date'] = retval['invoice_date']

                user['valide'] = retval['valide']
                user['locked'] = retval['locked']

                if ("order_line_montant_reduction" in retval.keys()):
                    user['order_line_montant_reduction'] = retval['order_line_montant_reduction']
                else:
                    user['order_line_montant_reduction'] = "0"

                if ("order_line_montant_toutes_taxes" in retval.keys()):
                    user['order_line_montant_toutes_taxes'] = retval['order_line_montant_toutes_taxes']
                else:
                    user['order_line_montant_toutes_taxes'] = "0"

                if ("order_line_tax" in retval.keys()):
                    user['order_line_tax'] = retval['order_line_tax']
                else:
                    user['order_line_tax'] = ""

                if ("order_line_tax_amount" in retval.keys()):
                    user['order_line_tax_amount'] = retval['order_line_tax_amount']
                else:
                    user['order_line_tax_amount'] = "0"

                if ("order_line_type_reduction" in retval.keys()):
                    user['order_line_type_reduction'] = retval['order_line_type_reduction']
                else:
                    user['order_line_montant_reduction'] = ""

                if ("order_line_type_valeur" in retval.keys()):
                    user['order_line_type_valeur'] = retval['order_line_type_valeur']
                else:
                    user['order_line_type_valeur'] = "0"

                if ("order_line_montant_hors_taxes" in retval.keys()):
                    user['order_line_montant_hors_taxes'] = retval['order_line_montant_hors_taxes']
                else:
                    user['order_line_montant_hors_taxes'] = "0"

                user['date_update'] = retval['date_update']
                user['update_by'] = str(my_partner['_id'])
                user['partner_owner_recid'] = retval['partner_owner_recid']

                if ("order_line_comment" in retval.keys()):
                    user['order_line_comment'] = retval['order_line_comment']
                else:
                    user['order_line_comment'] = ""

                user['title'] = retval['myclass_collection'][0]['title']
                user['order_line_formation_external_code'] = retval['myclass_collection'][0]['external_code']
                user['domaine'] = retval['myclass_collection'][0]['domaine']
                user['duration'] = retval['myclass_collection'][0]['duration']
                user['duration_unit'] = retval['myclass_collection'][0]['duration_unit']

                if (str(retval['myclass_collection'][0]['duration_unit']) == "heure"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " h"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "jour"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " j"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "semaine"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " s"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "mois"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " m"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "annee"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " a"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "user_rythme"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " u"

                else:
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " ?"

                Order_header_lines_data.append(user)

        if (len(Order_header_lines_data) <= 0):
            mycommon.myprint(str(inspect.stack()[0][
                                     3]) + " - Aucune ligne de détail pour cette facture ")
            return False, " Aucune ligne de détail pour cette facture "

        #print(" ### Order_header_lines_data =  ", Order_header_lines_data)


        contenu_doc_Template = jinja2.Template(str(partner_document_INVOICE_data['contenu_doc']))

        #print(" #### Order_header_data = ", Order_header_data)
        #sourceHtml = contenu_doc_Template.render(params=Order_header_data)

        #print(" ### Order_header_data =  ", Order_header_data)
        #print(" ### Order_header_lines_data =  ", Order_header_lines_data)

        sourceHtml = contenu_doc_Template.render(params=Order_header_data, param_order_lines=Order_header_lines_data)


        orig_file_name = "Partner_Invoice_"+str(Order_header_data['invoice_header_ref_interne'])+".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()

        # 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()
        print(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, False


"""
Envoie de la facture par email
"""
def Send_Partner_Invoice_By_Email(diction):
    try:
        field_list = ['invoice_id', 'token', ]
        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]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, "Les informations fournies sont incorrectes"

        """
                Verification de la liste des champs obligatoires
                """
        field_list_obligatoire = ['invoice_id', '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, " Les informations fournies sont incorrectes "

        query_get_data = {}
        mytoken = ""
        if ("token" in diction.keys()):
            if diction['token']:
                mytoken = diction['token']

        local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
        if (local_status is not True):
            return local_status, my_partner

        # Verification de la validité de l'order
        qry = {'_id': ObjectId(str(diction['invoice_id'])), 'valide': '1', 'locked': '0',
               'partner_owner_recid': str(my_partner['recid'])}
        print(" ### qry = ", qry)

        is_Invoice_Existe_Count = 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_Invoice_Existe_Count != 1):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - La facture n'est pas valide is_Invoice_Existe_Count = "+str(is_Invoice_Existe_Count))
            return False, " La facture n'est pas valide",

        Order_header_data = MYSY_GV.dbname['partner_invoice_header'].find_one({'_id': ObjectId(str(diction['invoice_id'])),
                                                                             'valide': '1', 'locked': '0',
                                                                             'partner_owner_recid': str(
                                                                                 my_partner['recid'])})

        partner_document_INVOICE_data_qry = {'partner_owner_recid': str(my_partner['recid']),
                                                      'valide': '1', 'locked': '0', 'ref_interne': 'PART_INVOICE', 'type_doc':'email'}

        print(" ### partner_document_CONF_ORDER_data_qry = ", partner_document_INVOICE_data_qry)
        partner_document_INVOICE_data = MYSY_GV.dbname['courrier_template'].find_one(
            {'partner_owner_recid': str(my_partner['recid']),
             'valide': '1', 'locked': '0', 'ref_interne': 'PART_INVOICE', 'type_doc':'email'})

        if (partner_document_INVOICE_data is None):
            # Il n'existe pas de personnalisation de la preinscription pour ce partenaire, on va aller récupérer la presinscription pa defaut
            partner_document_INVOICE_data = MYSY_GV.dbname['courrier_template'].find_one(
                {'partner_owner_recid': 'default',
                 'valide': '1', 'locked': '0', 'ref_interne': 'PART_INVOICE', 'type_doc':'email'})

        if (partner_document_INVOICE_data is None):
            mycommon.myprint(
                str(inspect.stack()[0][
                        3]) + "Aucun document parametré ")
            return False, "Aucun document parametré "

        if ("contenu_doc" not in partner_document_INVOICE_data or len(
                str(partner_document_INVOICE_data['contenu_doc'])) <= 0):
            mycommon.myprint(str(inspect.stack()[0][
                                     3]) + " - Le parametrage du document  est invalide")
            return False, " Le parametrage du document  est invalide "


        # Recuperation des données du client
        if( "order_header_client_id" in Order_header_data.keys() ):
            Order_header_client_data = MYSY_GV.dbname['partner_client'].find_one({'_id':ObjectId(str(Order_header_data['order_header_client_id'])),
                                                                                  'partner_recid':str(my_partner['recid']), 'valide':'1', 'locked':'0'})

            if( Order_header_client_data is None):
                mycommon.myprint(str(inspect.stack()[0][
                                         3]) + " - Le client est invalide")
                return False, " Le client est invalide"

        ### Ajout des données du client sur l'entete de la commande, exemple : le nom, email, etc
        if ("raison_sociale" in Order_header_client_data.keys()):
            Order_header_data['client_raison_sociale'] = Order_header_client_data['raison_sociale']

        if ("nom" in Order_header_client_data.keys()):
            Order_header_data['client_nom'] = Order_header_client_data['nom']

        if ("email" in Order_header_client_data.keys()):
            Order_header_data['client_email'] = Order_header_client_data['email']

        # Ajout d'un parametre pour le data time du jour de l'edition (c'est une data static qui peut servir pour l'horodatage
        Order_header_data['current_date_time'] = str(datetime.now().strftime("%d/%m/%Y, %H:%M:%S"))

        # Recuperation des details de lignes de : partner_order_line
        filt_class_partner_recid = {'partner_owner_recid': str(my_partner['recid'])}
        filt_order_header_order_id= {'invoice_header_id': str(diction['invoice_id'])}

        query = [{'$match': {'$and': [filt_order_header_order_id,
                                      {'partner_owner_recid': str(my_partner['recid'])}]}},
                 {'$lookup':
                     {
                         'from': 'myclass',
                         'localField': 'order_line_formation',
                         'foreignField': 'internal_url',
                         'pipeline': [{'$match': {'$and': [filt_class_partner_recid]}},
                                      {'$project': {'title': 1, 'domaine': 1,
                                                    'duration': 1,
                                                    'duration_unit': 1,
                                                    'external_code':1}}],
                         'as': 'myclass_collection'
                     }
                 }
                 ]
        #print("#### Get_Given_Partner_Order_Lines_From_order_ref_interne  : query pip= ", query)
        val_tmp = 0
        Order_header_lines_data = []
        for retval in MYSY_GV.dbname['partner_invoice_line'].aggregate(query):
            if ('myclass_collection' in retval.keys() and len(retval['myclass_collection']) > 0):
                user = {}
                user['id'] = str(val_tmp)
                val_tmp = val_tmp + 1
                user['_id'] = retval['_id']
                user['order_line_formation'] = retval['order_line_formation']
                user['order_line_qty'] = retval['order_line_qty']
                user['order_line_prix_unitaire'] = retval['order_line_prix_unitaire']
                user['order_header_id'] = retval['order_header_id']
                user['order_header_ref_interne'] = retval['order_header_ref_interne']

                user['invoice_header_ref_interne'] = retval['invoice_header_ref_interne']
                user['invoice_line_type'] = retval['invoice_line_type']
                user['invoice_date'] = retval['invoice_date']
                user['invoice_header_id'] = retval['invoice_header_id']

                user['valide'] = retval['valide']
                user['locked'] = retval['locked']

                if ("order_line_montant_reduction" in retval.keys()):
                    user['order_line_montant_reduction'] = retval['order_line_montant_reduction']
                else:
                    user['order_line_montant_reduction'] = "0"

                if ("order_line_montant_toutes_taxes" in retval.keys()):
                    user['order_line_montant_toutes_taxes'] = retval['order_line_montant_toutes_taxes']
                else:
                    user['order_line_montant_toutes_taxes'] = "0"

                if ("order_line_tax" in retval.keys()):
                    user['order_line_tax'] = retval['order_line_tax']
                else:
                    user['order_line_tax'] = ""

                if ("order_line_tax_amount" in retval.keys()):
                    user['order_line_tax_amount'] = retval['order_line_tax_amount']
                else:
                    user['order_line_tax_amount'] = "0"

                if ("order_line_type_reduction" in retval.keys()):
                    user['order_line_type_reduction'] = retval['order_line_type_reduction']
                else:
                    user['order_line_montant_reduction'] = ""

                if ("order_line_type_valeur" in retval.keys()):
                    user['order_line_type_valeur'] = retval['order_line_type_valeur']
                else:
                    user['order_line_type_valeur'] = "0"

                if ("order_line_montant_hors_taxes" in retval.keys()):
                    user['order_line_montant_hors_taxes'] = retval['order_line_montant_hors_taxes']
                else:
                    user['order_line_montant_hors_taxes'] = "0"

                user['date_update'] = retval['date_update']
                user['update_by'] = str(my_partner['_id'])
                user['partner_owner_recid'] = retval['partner_owner_recid']

                if ("order_line_comment" in retval.keys()):
                    user['order_line_comment'] = retval['order_line_comment']
                else:
                    user['order_line_comment'] = ""

                user['title'] = retval['myclass_collection'][0]['title']
                user['order_line_formation_external_code'] = retval['myclass_collection'][0]['external_code']
                user['domaine'] = retval['myclass_collection'][0]['domaine']
                user['duration'] = retval['myclass_collection'][0]['duration']
                user['duration_unit'] = retval['myclass_collection'][0]['duration_unit']

                if (str(retval['myclass_collection'][0]['duration_unit']) == "heure"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " h"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "jour"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " j"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "semaine"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " s"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "mois"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " m"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "annee"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " a"

                elif (str(retval['myclass_collection'][0]['duration_unit']) == "user_rythme"):
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " u"

                else:
                    user['duration_concat'] = str(retval['myclass_collection'][0]['duration']) + " ?"

                Order_header_lines_data.append(user)


        if(len(Order_header_lines_data) <= 0 ):
            mycommon.myprint(str(inspect.stack()[0][
                                     3]) + " - Aucune ligne de détail pour cette facture ")
            return False, " Aucune ligne de détail pour cette facture "


        #print(" ### Order_header_lines_data =  ", Order_header_lines_data)



        contenu_doc_Template = jinja2.Template(str(partner_document_INVOICE_data['contenu_doc']))

        contenu_doc_Template_subject = jinja2.Template(str(partner_document_INVOICE_data['sujet']))

        #print(" #### Order_header_data = ", Order_header_data)
        sourceHtml = contenu_doc_Template.render(params=Order_header_data,  param_order_lines=Order_header_lines_data)
        sujetHtml = contenu_doc_Template_subject.render(params=Order_header_data)

        #print(" #### sourceHtml = ", sourceHtml)


        print("debut envoi mail de test ")
        msg = EmailMessage()
        msg.set_content(sourceHtml, subtype='html')


        """
        Recuperation des parametre SMTP du partner si le client a decidé d'utiliser son propre smpt
        """
        partner_own_smtp_value = "0"
        partner_own_smtp = MYSY_GV.dbname['base_partner_setup'].find_one(
            {'partner_owner_recid': str(my_partner['recid']),
             'config_name': 'partner_smtp',
             'valide': '1',
             'locked': '0'})

        if( partner_own_smtp and "config_value" in partner_own_smtp.keys()):
            partner_own_smtp_value = partner_own_smtp['config_value']

            if( str(partner_own_smtp_value) == "1"):
                partner_SMTP_COUNT_password = str(MYSY_GV.dbname['base_partner_setup'].find_one(
                    {'partner_owner_recid': str(my_partner['recid']),
                     'config_name': 'smtp_user_pwd',
                     'valide': '1',
                     'locked': '0'}, {'config_value':1} )['config_value'])



                partner_SMTP_COUNT_smtpsrv = str(MYSY_GV.dbname['base_partner_setup'].find_one(
                    {'partner_owner_recid': str(my_partner['recid']),
                     'config_name': 'smtp_server',
                     'valide': '1',
                     'locked': '0'}, {'config_value':1})['config_value'])

                partner_SMTP_COUNT_user = str(MYSY_GV.dbname['base_partner_setup'].find_one(
                    {'partner_owner_recid': str(my_partner['recid']),
                     'config_name': 'smtp_user',
                     'valide': '1',
                     'locked': '0'}, {'config_value':1})['config_value'])

                partner_SMTP_COUNT_From_User = str(MYSY_GV.dbname['base_partner_setup'].find_one(
                    {'partner_owner_recid': str(my_partner['recid']),
                     'config_name': 'smtp_count_from_name',
                     'valide': '1',
                     'locked': '0'}, {'config_value':1})['config_value'])

                partner_SMTP_COUNT_port = str(MYSY_GV.dbname['base_partner_setup'].find_one(
                    {'partner_owner_recid': str(my_partner['recid']),
                     'config_name': 'smtp_count_port',
                     'valide': '1',
                     'locked': '0'}, {'config_value':1})['config_value'])


        if (str(partner_own_smtp_value) == "1"):
            smtpserver = smtplib.SMTP(partner_SMTP_COUNT_smtpsrv, partner_SMTP_COUNT_port)
        else:
            smtpserver = smtplib.SMTP(MYSY_GV.O365_SMTP_COUNT_smtpsrv, MYSY_GV.O365_SMTP_COUNT_port)

        """
               La commande est envoyée à l'adresse email qui se trouve sur la commande, le champ : 'order_header_email_client'.

               Si ce champ est vide alors on regarde si il y a un email sur la fiche client.
               """
        client_main_mail_tmp = ""

        if ("order_header_email_client" in Order_header_data.keys() and Order_header_data['order_header_email_client']):
            client_main_mail_tmp = str(Order_header_data['order_header_email_client'])

            if (mycommon.isEmailValide(client_main_mail_tmp) is True):
                msg['To'] = client_main_mail_tmp

            else:
                mycommon.myprint(str(inspect.stack()[0][
                                         3]) + " - L'adresse email sur la commande n'est pas valide ")
                return False, " L'adresse email sur la commande n'est pas valide "

        else:
            mycommon.myprint(str(inspect.stack()[0][
                                     3]) + " - Aucune adresse email  sur la commande ")
            return False, " Aucune adresse email  sur la commande "




        if (str(partner_own_smtp_value) == "1"):
            msg['From'] = partner_SMTP_COUNT_From_User
            msg['Bcc'] = 'contact@mysy-training.com'
            msg['Subject'] = sujetHtml

            smtpserver.ehlo()
            smtpserver.starttls()
            smtpserver.login(partner_SMTP_COUNT_user, partner_SMTP_COUNT_password)

        else:
            msg['From'] = MYSY_GV.O365_SMTP_COUNT_From_User
            msg['Bcc'] = 'contact@mysy-training.com'
            msg['Subject'] = sujetHtml

            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, " La facture a été envoyée par email à  :'"+str(client_main_mail_tmp)+"' "
    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, "Impossible d'envoyer la facture par email"



