'''
Ce fichier traite tout ce qui est liée à la gestion des formations

'''
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


class JSONEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, ObjectId):
            return str(o)
        return json.JSONEncoder.default(self, o)



'''
Cette fonction ajoute une formation
elle verifie le token de l'entité qui ajoute la formation.
'''

def add_class(diction):
    try:
        '''
        # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
        # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
        # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
        # field_list.
        '''
        field_list = ['external_code', 'title', 'description', 'trainer', 'institut_formation', 'distantiel', 'presentiel',
                        'price', 'url','duration', 'duration_unit', 'token', 'plus_produit', 'mots_cle','domaine',
                      'internal_url', 'zone_diffusion', 'metier', 'date_lieu', 'published', 'img_url', 'objectif',
                      'programme', 'prerequis', 'note', 'cpf', 'certif', 'class_inscription_url', 'pourqui',
                      'support', 'img_banner_detail_class']

        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint(str(inspect.stack()[0][3])+" - Creation formation : Le champ  '" + val + "' n'est pas autorisé, Creation formation annulée")
                return False, " Le champ  '" + val + "' n'est pas autorisé, Creation formation annulée "

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['external_code', 'title', 'description', 'trainer', 'distantiel', 'presentiel', '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, " La valeur '" + val + "' n'est pas presente dans liste"


        '''
        Verification si le token et l'email sont valident
        '''

        # recuperation des paramettre
        mydata = {}

        if ("token" in diction.keys()):
            if diction['token']:
                mydata['token'] = diction['token']

        # Verification de la validité du token
        '''
        Important : pour créer une formation, il faut obligatoirement avoir un token.
        PAS DE CREATION DE FORMATION EN MODE NON CONNECTE.

        CONCERNANT LES CREEES PAR NOS SYSTEME AUTOMATIQUE, IL FAUDRA LEUR PASSER UNE VALEUR MALGRE TOUT

        '''
        retval = mycommon.check_partner_token_validity("", str(mydata['token']))

        if retval is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token n'est pas valide")
            return False, "Les informations d'identification ne sont pas valident"

        # Recuperation du recid du partenaire
        user_recid = mycommon.get_parnter_recid_from_token(str(mydata['token']))
        if user_recid is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le recid du partenaire")
            return False, " Les informations d'identification sont incorrectes"



        part_status, part_pack, part_pack_nb_training_auto = mycommon.Partner_Get_pack_nbTraining(user_recid)
        if( part_status is False):
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le pack et le nombre de formation du partenaire")
            return False, " Les informations d'identification sont incorrectes"
        """
        Recuperation du nombre de formations actif de ce partner
        """
        part_status2, part_nb_active_training = mycommon.Get_partner_nb_active_training(user_recid)
        if (part_status2 is False):
            mycommon.myprint(str(
                inspect.stack()[0][3]) + " - Impossible de recuperer le pack et le nombre de formation du partenaire")
            return False, " Les informations d'identification sont incorrectes"

        if( mycommon.tryInt(part_nb_active_training) >= mycommon.tryInt(part_pack_nb_training_auto) ):
            mycommon.myprint(str(
                inspect.stack()[0][3]) + " - Vous avez atteint le nombre maximum de formation autorisé")
            return False, " Vous avez atteint le nombre maximum de formation autorisé ("+str(part_pack_nb_training_auto)+"" \
                                                                                                                    "). La formation '"+str(diction['external_code'])+"' n'a pas été enregistrée"

        mydata['partner_owner_recid'] = user_recid

        class_internal_url = ""
        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                class_internal_url = diction['internal_url']

        '''
        Si l'internal_url reste à vide, alors le système va créer une internal url de la formation
        '''
        if( len(class_internal_url) <= 0 ):
            status, class_internal_url = mycommon.CreateInternalUrl(diction['title'])

        mydata['internal_url'] = class_internal_url

        if ("external_code" in diction.keys()):
            if diction['external_code']:
                mydata['external_code'] = diction['external_code']

        if ("title" in diction.keys()):
            if diction['title']:
                mydata['title'] = diction['title']

        if ("note" in diction.keys()):
            if diction['note']:
                mydata['note'] = diction['note']

        if ("cpf" in diction.keys()):
            if diction['cpf']:
                mydata['cpf'] = diction['cpf']

        if ("class_inscription_url" in diction.keys()):
            if diction['class_inscription_url']:
                mydata['class_inscription_url'] = diction['class_inscription_url']
                

        if ("certif" in diction.keys()):
            if diction['certif']:
                mydata['certif'] = diction['certif']

        if ("objectif" in diction.keys()):
            if diction['objectif']:
                mydata['objectif'] = diction['objectif']

        if ("programme" in diction.keys()):
            if diction['programme']:
                mydata['programme'] = diction['programme']

        if ("prerequis" in diction.keys()):
            if diction['prerequis']:
                mydata['prerequis'] = diction['prerequis']

        if ("description" in diction.keys()):
            if diction['description']:
                mydata['description'] = diction['description']


        if ("metier" in diction.keys()):
            if diction['metier']:
                mydata['metier'] = diction['metier']


        if ("pourqui" in diction.keys()):
            if diction['pourqui']:
                mydata['pourqui'] = diction['pourqui']

        if ("support" in diction.keys()):
            if diction['support']:
                mydata['support'] = str(diction['support']).lower().strip()

        if ("img_banner_detail_class" in diction.keys()):
            if diction['img_banner_detail_class']:
                mydata['img_banner_detail_class'] = diction['img_banner_detail_class']


        if ("trainer" in diction.keys()):
            if diction['trainer']:
                mydata['trainer'] = diction['trainer']

        if ("published" in diction.keys()):
            if diction['published']:
                mydata['published'] = diction['published']

        if ("plus_produit" in diction.keys()):
            if diction['plus_produit']:
                mydata['plus_produit'] = diction['plus_produit']

        if ("institut_formation" in diction.keys()):
            if diction['institut_formation']:
                mydata['institut_formation'] = diction['institut_formation']

        my_presentiel = "0"
        my_distantiel = "0"

        if ("distantiel" in diction.keys()):
            if diction['distantiel']:
                my_distantiel = diction['distantiel']

        if ("presentiel" in diction.keys()):
            if diction['presentiel']:
                my_presentiel = diction['presentiel']

        mydata['presentiel'] = {'presentiel': my_presentiel, 'distantiel': my_distantiel}

        if ("price" in diction.keys()):
            if diction['price']:
                mydata['price'] = mycommon.tryFloat(str(diction['price']))

        if ("url" in diction.keys()):
            if diction['url']:
                mydata['url'] = diction['url']

        if ("duration" in diction.keys()):
            if diction['duration']:
                mydata['duration'] = float(str(diction['duration']))

        if ("plus_produit" in diction.keys()):
            if diction['plus_produit']:
                mydata['plus_produit'] = diction['plus_produit']


        if ("mots_cle" in diction.keys()):
            if diction['mots_cle']:
                mydata['mots_cle'] = diction['mots_cle']
                '''
                Verification du nombre de mots clée : limite MYSY_GV.MAX_KEYWORD (3)
                '''
                nb_keyword = mydata['mots_cle'].split(";")
                if( len(nb_keyword) > MYSY_GV.MAX_KEYWORD ):
                    mycommon.myprint(
                        str(inspect.stack()[0][3]) + " : La formation "+str(mydata['external_code'])+" a plus de "+ str(MYSY_GV.MAX_KEYWORD)+" mots clés")
                    return False, " La formation "+str(mydata['external_code'])+" a plus de "+ str(MYSY_GV.MAX_KEYWORD)+" mots clés"


        if ("domaine" in diction.keys()):
            if diction['domaine']:
                mydata['domaine'] = diction['domaine']

        # Traitement de l'url imag
        if ("img_url" in diction.keys()):
            if diction['img_url']:
                # Verifier si l'image existe
                status_tmp, img = mycommon.TryUrlImage(str(diction['img_url']))
                if( status_tmp is False):
                    mycommon.myprint(
                        str(inspect.stack()[0][3]) + " : l'url de l'image de la formation " + str(
                            mydata['external_code']) + " est incorrecte ")
                    return False, " l'url de l'image de la formation " + str(mydata['external_code']) + " est incorrecte "

                mydata['img_url'] = diction['img_url']


        if ("duration_unit" in diction.keys()):
            if diction['duration_unit']:
                mydata['duration_unit'] = diction['duration_unit']


        if ("zone_diffusion" in diction.keys()):
            if diction['zone_diffusion'] and len(str(diction['zone_diffusion'])) > 0:
                tmp_str2 = str(diction['zone_diffusion']).lower().replace(",", ";").replace("\r\n", "")

                if (not tmp_str2.endswith(";")):
                    tmp_str2 = tmp_str2 + ";"

                #print("tmp_str2 =  " + tmp_str2)


                if (";" not in tmp_str2):
                    mycommon.myprint(str(inspect.stack()[0][3]) + " - la zone de diffusion de la formation : A" + str(
                        diction['external_code']) + " est incorrecte")
                    return False, "La zone de diffusion de la formation " + str(diction['external_code']) + " est incorrecte"


                tmp_str = tmp_str2.split(";")   #==> ce qui va donner un tableau de : Country_Code-City : ['fr-paris', 'fr-marseille', 'bn-cotonou']
                cpt = 0
                tab_country = []
                tab_city = []
                for val in tmp_str:
                    #print(" val = "+str(val))
                    if( len(str(val)) <= 0 ):
                        continue

                    if( "-" not in str(val)):
                        mycommon.myprint(str(inspect.stack()[0][3]) + " - la zone de diffusion de la formation : B" + str( diction['external_code']) + " est incorrecte")
                        return False, "La zone de diffusion de la formation " + str(diction['external_code']) + " est incorrecte"


                    tab_val = len(val.split("-"))
                    if( len(val.split("-")) != 1 and len(val.split("-")) != 2 ):
                        mycommon.myprint( str(inspect.stack()[0][3]) + " - la zone de diffusion de la formation : C" + str(diction['external_code'])+" est incorrecte")
                        return False, "La zone de diffusion de la formation " + str(diction['external_code'])+" est incorrecte"

                    if( val.split("-")[0]):
                        tab_country.append(val.split("-")[0])
                    else:
                        tab_country.append("")

                    if(val.split("-")[1]):
                        tab_city.append(val.split("-")[1])
                    else:
                        tab_city.append("")


                mydata['zone_diffusion'] = {'country':tab_country, 'city':tab_city}


        '''
        Traitement date_lieu. 
        Date_lieu definit une session et au format :
        date_du;data_au;ville;code_postal; adresse
        '''
        mydata['datelieu'] = ""

        if ("date_lieu" in diction.keys()):
            if diction['date_lieu'] and len(str(diction['date_lieu'])) > 0 :
                tmp_str2 = str(diction['date_lieu']).lower().replace(",", ";").replace("\r\n", "")

                print(" ### tmp_str2 = "+str(tmp_str2))

                if (not tmp_str2.endswith(";")):
                    tmp_str2 = tmp_str2 + ";"

                # print("tmp_str2 =  " + tmp_str2)

                if (";" not in tmp_str2):
                    mycommon.myprint(str(inspect.stack()[0][3]) + " - les dates et lieux de la formation : " + str(
                        diction['external_code']) + " sont incorrectes 1")
                    return False, "Les Dates et Lieux de la formation " + str(
                        diction['external_code']) + " sont incorrectes. Le format attendu : " \
                                                    "jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse;jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse"

                tmp_str = tmp_str2.split(
                    ";")  # ==> ce qui va donner un tableau de : Country_Code-City : ['11/02/2012-paris-75001', '24/04/2022-marseille-13002',]

                i = 0
                for tmp_val in tmp_str:
                    tmp_str[i] = str(tmp_str[i]).strip()
                    i = i +1

                dl_cpt = 0
                tab_dl = []
                for tmp_dl in tmp_str:
                    #print(" ##### tmp_dl = "+str(tmp_dl))
                    if (len(str(tmp_dl)) > 0 and ("-" in tmp_dl)):
                        #print(" ###### DATE LIEU = "+str(tmp_dl))
                        tab_date_lieu = tmp_dl.split('-')
                        if (len(tab_date_lieu) != 5):
                            return False, "Les Dates et Lieux de la formation " + str(
                                diction['external_code']) + " sont incorrectes. Le format attendu : " \
                                                            "jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse;jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse"

                        isdate = mycommon.CheckisDate(str(tab_date_lieu[0]))
                        if (isdate is False):
                            mycommon.myprint(
                                str(inspect.stack()[0][3]) + " - les dates et lieux de la formation : A" + str(
                                    diction['external_code']) + " sont incorrectes 2")
                            return False, "Les Dates et Lieux de la formation " + str(
                                diction['external_code']) + " sont incorrectes. Le format attendu : " \
                                                            "jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse;jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse 3"

                        isdate_au = mycommon.CheckisDate(str(tab_date_lieu[1]))
                        if (isdate is False):
                            mycommon.myprint(
                                str(inspect.stack()[0][3]) + " - les dates et lieux de la formation : A" + str(
                                    diction['external_code']) + " sont incorrectes 3")
                            return False, "Les Dates et Lieux de la formation " + str(
                                diction['external_code']) + " sont incorrectes. Le format attendu : " \
                                                            "jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse;jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse 2"

                        #print("### isdate = '" + str(tab_date_lieu[0]) + "'  CM isdate_au = '" + str(tab_date_lieu[1])+"' ")


                        if (datetime.strptime(str(tab_date_lieu[0]).strip(), '%d/%m/%Y') > datetime.strptime(
                                str(tab_date_lieu[1]).strip(), '%d/%m/%Y')):
                            mycommon.myprint(
                                str(inspect.stack()[0][
                                        3]) + " - la date debut est posterieure à la date de fin pour la formation : " + str(
                                    diction['external_code']) + " ")
                            return False, " La date debut est posterieure à la date de fin pour la formation : " + str(
                                diction['external_code']) + " "

                        mytoday = datetime.today().strftime("%d/%m/%Y")
                        if (datetime.strptime(str(tab_date_lieu[0]).strip(), '%d/%m/%Y') < datetime.strptime(str(mytoday).strip(),
                                                                                                     '%d/%m/%Y')):
                            mycommon.myprint(
                                str(inspect.stack()[0][
                                        3]) + " - la date debut est posterieure à la date du jour  pour la formation : " + str(
                                    diction['external_code']) + " ")
                            return False, " La date debut est posterieure à la date du jour pour la formation : " + str(
                                diction['external_code']) + " "

                        # On créé un identifiant unique par session
                        #session_id = mycommon.create_token_urlsafe()
                        """
                        On créé un identifiant unique par session
                        Session_id = date_du+date_au+code_postal+adresse
                        """

                        session_id = str(str(tab_date_lieu[0]) + str(tab_date_lieu[1]) + str(tab_date_lieu[3]) + str(
                            tab_date_lieu[4])).replace(' ', '')
                        session_id = mycommon.remove_non_ascii(session_id)
                        session_id = re.sub(r'[^a-zA-Z0-9]', '', session_id)

                        ## Verifier si le CP n'est composé que de "0", au quel cas il s'agit d'une formation en ligne.
                        local_cp = str(tab_date_lieu[3]).replace("0", "").strip()
                        class_cp = ""
                        if (local_cp == ""):
                            class_cp = "0"
                        else:
                            class_cp = str(tab_date_lieu[3]).strip()


                        val_dl = {'date_du': str(tab_date_lieu[0]).strip(), 'date_au': str(tab_date_lieu[1]).strip(),
                                  'ville': str(tab_date_lieu[2]).strip(), 'code_postal': str(class_cp).strip(),
                                  'adresse': str(tab_date_lieu[4]).strip(), 'session_id': str(session_id).strip()}


                        tab_dl.append(val_dl)
                        # mydata['date_lieu'][dl_cpt] = {'date': str(tab_date_lieu[0]), 'ville': str(tab_date_lieu[1])}
                        # print(str(mydata['date_lieu'] ))
                        # print(" #########  date_lieu = " + str(tab_date_lieu[0]) + " ----- " + str(tab_date_lieu[1]))

                        dl_cpt = dl_cpt + 1

                    elif (len(str(tmp_dl)) > 0 and ("-" not in tmp_dl)):
                        return False, "Les Dates et Lieux de la formation " + str(
                            diction['external_code']) + " sont incorrectes. Le format attendu : " \
                                                        "jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse;jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse 1"

                mydata['datelieu'] = tab_dl

        mydata['valide'] = '1'
        mydata['locked'] = '0'
        mydata['indexed'] = '0'
        mydata['indexed_title'] = '0'
        mydata['indexed_desc'] = '0'
        mydata['indexed_obj'] = '0'

        # A supprimer apres
        mydata['freeacces'] = '1'
        # fin à supprimer

        # Create internal ref. of class
        mydata['internal_code'] = mycommon.Create_internal_call_ref()

        """ Gestion des ajout pr les compte utilisateur de type demo """

        coll_partner_account = MYSY_GV.dbname['partnair_account']
        myquery = {"recid": str(mydata['partner_owner_recid']), "active": "1",
                   "demo_account": "1"}

        #print(" myquery pr demo_account = " + str(myquery))
        tmp = coll_partner_account.count_documents(myquery)

        if (tmp > 0):
            mydata['display_rank']  = str(MYSY_GV.DEMO_RANKING_VALUE)
            mydata['isalaune'] = "1"
            #print(" myquery pr demo_account 222 = " + str(tmp))

        else:
            # Ce n'est pas un compte demo, il faut donc recuperer le display rank tu pack - part_pack
            coll_pack = MYSY_GV.dbname['pack']
            local_tmp = coll_pack.find({'code_pack': str(part_pack)})

            if (local_tmp[0] and "ranking" in local_tmp[0].keys()):
                if local_tmp[0]['ranking']:
                    #print(" ### le ranking du pack est " + str(local_tmp[0]['ranking']))
                    mydata['display_rank'] = str(local_tmp[0]['ranking'])


        coll_name = MYSY_GV.dbname['myclass']

        '''
        Verification si cette formation exite deja .
        la clé est : external_code
        '''
        #tmp = coll_name.find({'external_code':  str(mydata['external_code'])}).count()
        tmp = coll_name.count_documents({'external_code':  str(mydata['external_code'])})

        #mycommon.myprint(" TMP = " + str(tmp))
        '''if (tmp > 0):
            mycommon.myprint(str(inspect.stack()[0][3])+" -la formation avec l'external code " +  str(mydata['external_code']) + "' existe deja, impossible de créer la formation ")
            return False, "la formation avec l'external code " +  str(mydata['external_code']) + "' existe deja. Impossible de créer la formation "
        '''

        #coll_name.insert_one(mydata)

        ret_val = coll_name.find_one_and_update(
            {'external_code': str(mydata['external_code']), },
            {"$set": mydata},
            upsert=True,
            return_document=ReturnDocument.AFTER
            )

        if ret_val and ret_val['_id']:
            #Indexation Title de la nouvelle formation ajoutée
            training_to_index_title = {}
            training_to_index_title['internal_url'] = mydata['internal_url']
            training_to_index_title['reindex_all'] = '0'
            eibdd.ela_index_given_classes_title(training_to_index_title)

            # Indexation Title des mots clées
            eibdd.ela_index_given_classes_keywords(training_to_index_title)


            return True, "La formation a bien été ajoutée"
        else:
            mycommon.myprint(" Impossible d'ajouter la formation "+str(str(mydata['external_code'])))
            return False, " Impossible d'ajouter la formation "+str(str(mydata['external_code']))

    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, "Impossible d'ajouter la formation"+ str(e)


'''
cette fontion met à jour une formation
la clé est : l'external code.

seules les formation "valide" et non "locked" sont modifiable
'''
def update_class(diction):
    try:

        '''
        # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
        # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
        # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
        # field_list.
        '''
        field_list = ['external_code', 'title', 'description', 'trainer', 'institut_formation', 'distantiel',
                      'presentiel','price', 'url', 'duration', 'token','plus_produit', 'mots_cle',
                      'domaine', 'internal_code', 'internal_url','zone_diffusion', 'metier',
                      'date_lieu', 'published', 'img_url', 'objectif', 'programme', 'prerequis', 'note',
                      'cpf', 'certif', 'class_inscription_url','pourqui', 'support', 'img_banner_detail_class']

        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint(
                    str(inspect.stack()[0][3])+" - Creation partner account : Le champ  '" + val + "' n'est pas accepté, Creation formation annulée")
                return False, " Impossible de mettre à jour la formation"

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['internal_url', 'token']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(str(inspect.stack()[0][3])+" - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de mettre à jour la formation"

        # recuperation des paramettre
        mydata = {}
        my_external_code = ""

        if ("token" in diction.keys()):
            if diction['token']:
                mydata['token'] = diction['token']

            # Verification de la validité du token
        '''
        Important : pour modifier une formation, il faut obligatoirement avoir un token.
        PAS DE CREATION / MODIFICATION DE FORMATION EN MODE NON CONNECTE.

        CONCERNANT CELLES CREEES PAR NOS SYSTEME AUTOMATIQUE, IL FAUDRA LEUR PASSER UNE VALEUR MALGRE TOUT

        '''
        retval = mycommon.check_partner_token_validity("", str(mydata['token']))

        if retval is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token ne sont pas valident")
            return False, "L'email ou le token ne sont pas valident"

        # Recuperation du recid de l'utilisateur
        user_recid = mycommon.get_parnter_recid_from_token(str(mydata['token']))
        if user_recid is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le recid de l'utilisateur")
            return False, " Les informations d'identification sont incorrectes"

        partner_recid = user_recid
        my_internal_code = ""

        if ("internal_code" in diction.keys()):
            my_internal_code = diction['internal_code']

        my_internal_url = ""
        if ("internal_url" in diction.keys()):
            my_internal_url = diction['internal_url']


        if ("external_code" in diction.keys()):
            my_external_code = diction['external_code']

        if ("title" in diction.keys()):
            mydata['title'] = diction['title']

        if ("class_inscription_url" in diction.keys()):
            mydata['class_inscription_url'] = diction['class_inscription_url']

        if ("note" in diction.keys()):
            mydata['note'] = diction['note']

        if ("objectif" in diction.keys()):
            mydata['objectif'] = diction['objectif']

        if ("programme" in diction.keys()):
            mydata['programme'] = diction['programme']

        if ("cpf" in diction.keys()):
            mydata['cpf'] = diction['cpf']

        if ("pourqui" in diction.keys()):
            mydata['pourqui'] = diction['pourqui']

        if ("support" in diction.keys()):
            mydata['support'] = str(diction['support']).lower().strip()

        if ("img_banner_detail_class" in diction.keys()):
            mydata['img_banner_detail_class'] = diction['img_banner_detail_class']


        if ("certif" in diction.keys()):
            mydata['certif'] = diction['certif']

        if ("prerequis" in diction.keys()):
            mydata['prerequis'] = diction['prerequis']

        if ("img_url" in diction.keys()):
            if diction['img_url']:
                # Verifier si l'image existe
                status_tmp, img = mycommon.TryUrlImage(str(diction['img_url']))
                if (status_tmp is False):
                    mycommon.myprint(
                        str(inspect.stack()[0][3]) + " : l'url de l'image de la formation " + str(my_internal_code) + " est incorrecte ")
                    return False, " l'url de l'image de la formation " + str(my_internal_code) + " est incorrecte "


            mydata['img_url'] = diction['img_url']


        if ("description" in diction.keys()):
            mydata['description'] = diction['description']

        if ("trainer" in diction.keys()):
            mydata['trainer'] = diction['trainer']

        if ("metier" in diction.keys()):
            mydata['metier'] = diction['metier']

        if ("published" in diction.keys()):
            mydata['published'] = diction['published']


        if ("institut_formation" in diction.keys()):
            mydata['institut_formation'] = diction['institut_formation']

        my_presentiel = "0"
        my_distantiel = "0"

        if ("distantiel" in diction.keys()):
            my_distantiel = diction['distantiel']

        if ("presentiel" in diction.keys()):
            my_presentiel = diction['presentiel']

        mydata['presentiel'] = {'presentiel': my_presentiel, 'distantiel': my_distantiel}

        if ("price" in diction.keys()):
            if( diction['price']):
                mydata['price'] =  mycommon.tryFloat(str(diction['price']))

        if ("url" in diction.keys()):
            mydata['url'] = diction['url']

        if ("duration" in diction.keys()):
            mydata['duration'] = mycommon.tryFloat(str(diction['duration']))


        if ("plus_produit" in diction.keys()):
            mydata['plus_produit'] = diction['plus_produit']


        if ("mots_cle" in diction.keys()):
            mydata['mots_cle'] = diction['mots_cle']

        if ("domaine" in diction.keys()):
            if diction['domaine']:
                mydata['domaine'] = diction['domaine']

        if ("zone_diffusion" in diction.keys()):

            if(len(str(diction['zone_diffusion'])) == 0 ):
                mydata['zone_diffusion'] = {}
            else:
                tmp_str2 = str(diction['zone_diffusion']).lower().replace(",", ";").replace("\r\n", "")

                if( not tmp_str2.endswith(";")):
                    tmp_str2 = tmp_str2+";"

                #print("tmp_str2 =  " + tmp_str2)

                if (";" not in tmp_str2):
                    mycommon.myprint(str(inspect.stack()[0][3]) + " - la zone de diffusion de la formation 0: " + str(
                        my_external_code) + " est incorrecte")
                    return False, "La zone de diffusion de la formation " + str(my_external_code) + " est incorrecte"


                tmp_str = tmp_str2.split(";")   #==> ce qui va donner un tableau de : Country_Code-City : ['fr-paris', 'fr-marseille', 'bn-cotonou']
                cpt = 0
                tab_country = []
                tab_city = []
                for val in tmp_str:

                    if (len(str(val)) <= 0):
                        continue


                    if( "-" not in str(val)):
                        mycommon.myprint(str(inspect.stack()[0][3]) + " - la zone de diffusion de la formation 1: " + str( my_external_code) + " est incorrecte")
                        return False, "La zone de diffusion de la formation " + str(my_external_code) + " est incorrecte"


                    tab_val = len(val.split("-"))
                    if( len(val.split("-")) != 1 and len(val.split("-")) != 2 ):
                        mycommon.myprint( str(inspect.stack()[0][3]) + " - la zone de diffusion de la formation 2: " + str(my_external_code)+" est incorrecte")
                        return False, "La zone de diffusion de la formation " + str(my_external_code)+" est incorrecte"

                    if( val.split("-")[0]):
                        tab_country.append(val.split("-")[0])
                    else:
                        tab_country.append("")

                    if(val.split("-")[1]):
                        tab_city.append(val.split("-")[1])
                    else:
                        tab_city.append("")


                    mydata['zone_diffusion'] = {'country':tab_country, 'city':tab_city}

        '''
        Traitement date_lieu. 
        Date_lieu definit une session et au format :
        date_du;data_au;ville;code_postal; adresse
        '''
        mydata['datelieu'] = ""
        if ("date_lieu" in diction.keys()):
            if(len(str(diction['date_lieu'])) == 0 ):
                mydata['datelieu'] = {}

            else:
                tmp_str2 = str(diction['date_lieu']).lower().replace(",", ";").replace("\r\n", "")

                if (not tmp_str2.endswith(";")):
                    tmp_str2 = tmp_str2 + ";"

                # print("tmp_str2 =  " + tmp_str2)

                if (";" not in tmp_str2):
                    mycommon.myprint(str(inspect.stack()[0][3]) + " - les dates et lieux de la formation : " + str(
                        diction['external_code']) + " sont incorrectes 1")
                    return False, "Les Dates et Lieux de la formation " + str(
                        diction['external_code']) + " sont incorrectes. Le format attendu : " \
                                                    "jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse;jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse"

                tmp_str = tmp_str2.split(
                    ";")  # ==> ce qui va donner un tableau de : Country_Code-City : ['11/02/2012-paris-75001', '24/04/2022-marseille-13002',]

                i = 0
                for tmp_val in tmp_str:
                    tmp_str[i] = str(tmp_str[i]).strip()
                    i = i + 1

                dl_cpt = 0
                tab_dl = []
                for tmp_dl in tmp_str:
                    #print(" ### tmp_dl = "+str(tmp_dl))
                    if (len(str(tmp_dl)) > 0 and ("-" in tmp_dl)):
                        # print(" ###### DATE LIEU = "+tmp_dl)
                        #tab_date_lieu = tmp_dl.split('-')
                        tab_date_lieu = [x.strip() for x in tmp_dl.split('-')]
                        if (len(tab_date_lieu) != 5):
                            return False, "Les Dates et Lieux de la formation " + str(
                                diction['external_code']) + " sont incorrectes. Le format attendu : " \
                                                            "jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse;jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse"

                        isdate = mycommon.CheckisDate(str(tab_date_lieu[0]))
                        if (isdate is False):
                            mycommon.myprint(
                                str(inspect.stack()[0][3]) + " - les dates et lieux de la formation : A" + str(
                                    diction['external_code']) + " sont incorrectes 2")
                            return False, "Les Dates et Lieux de la formation " + str(
                                diction['external_code']) + " sont incorrectes. Le format attendu : " \
                                                            "jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse;jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse 3"

                        isdate_au = mycommon.CheckisDate(str(tab_date_lieu[1]))
                        if (isdate is False):
                            mycommon.myprint(
                                str(inspect.stack()[0][3]) + " - les dates et lieux de la formation : A" + str(
                                    diction['external_code']) + " sont incorrectes 3")
                            return False, "Les Dates et Lieux de la formation " + str(
                                diction['external_code']) + " sont incorrectes. Le format attendu : " \
                                                            "jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse;jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse 2"


                        #print("### isdate = " + str(tab_date_lieu[0]) + "  CM isdate_au = " + str(tab_date_lieu[1]))
                        if (datetime.strptime(str(tab_date_lieu[0]).strip(), '%d/%m/%Y')  > datetime.strptime(str(tab_date_lieu[1]).strip(), '%d/%m/%Y')):
                            mycommon.myprint(
                                str(inspect.stack()[0][
                                        3]) + " - la date debut est posterieure à la date de fin pour la formation : " + str(
                                    diction['external_code']) + " ")
                            return False, " La date debut est posterieure à la date de fin pour la formation : " + str(
                                diction['external_code']) + " "

                        mytoday = datetime.today().strftime("%d/%m/%Y")
                        if (datetime.strptime(str(tab_date_lieu[0]), '%d/%m/%Y') < datetime.strptime(str(mytoday), '%d/%m/%Y')):
                            mycommon.myprint(
                                str(inspect.stack()[0][
                                        3]) + " - la date debut est posterieure à la date du jour  pour la formation : " + str(
                                    diction['external_code']) + " ")
                            return False, " La date debut est posterieure à la date du jour pour la formation : " + str(
                                diction['external_code']) + " "

                        """
                          On créé un identifiant unique par session
                          Session_id = date_du+date_au+code_postal+adresse
                          """

                        session_id = str(str(tab_date_lieu[0]) + str(tab_date_lieu[1]) + str(tab_date_lieu[3]) + str(
                            tab_date_lieu[4])).replace(' ','')

                        session_id = mycommon.remove_non_ascii(session_id)
                        session_id =   re.sub(r'[^a-zA-Z0-9]', '', session_id)

                        ## Verifier si le CP n'est composé que de "0", au quel cas il s'agit d'une formation en ligne.
                        local_cp = str(tab_date_lieu[3]).replace("0", "").strip()
                        class_cp = ""
                        if (local_cp == ""):
                            class_cp = "0"
                        else:
                            class_cp = str(tab_date_lieu[3]).strip()

                        val_dl = {'date_du': str(tab_date_lieu[0]).strip(), 'date_au': str(tab_date_lieu[1]).strip(),
                                  'ville': str(tab_date_lieu[2]).strip(), 'code_postal': str(class_cp).strip(),
                                  'adresse': str(tab_date_lieu[4]).strip(), 'session_id':str(session_id).strip()}
                        tab_dl.append(val_dl)
                        # mydata['date_lieu'][dl_cpt] = {'date': str(tab_date_lieu[0]), 'ville': str(tab_date_lieu[1])}
                        # print(str(mydata['date_lieu'] ))
                        # print(" #########  date_lieu = " + str(tab_date_lieu[0]) + " ----- " + str(tab_date_lieu[1]))

                        dl_cpt = dl_cpt + 1

                    elif (len(str(tmp_dl)) > 0 and ("-" not in tmp_dl)):
                        return False, "Les Dates et Lieux de la formation " + str(
                            diction['external_code']) + " sont incorrectes. Le format attendu : " \
                                                        "jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse;jj/mm/aaaa-jj/mm/aaaa-ville-code_postale-adresse 1"

                mydata['datelieu'] = tab_dl

        mydata['date_update'] = str(datetime.now())

        # A supprimer apres
        mydata['freeacces'] = '1'
        # fin à supprimer

        mydata['indexed'] = '0'
        mydata['indexed_title'] = '0'
        mydata['indexed_desc'] = '0'
        mydata['indexed_obj'] = '0'

        """ Gestion des ajout pr les compte utilisateur de type demo """

        coll_partner_account = MYSY_GV.dbname['partnair_account']
        myquery = {"recid": str(user_recid), "active": "1",
                   "demo_account": "1"}

        #print(" myquery pr demo_account = " + str(myquery))
        tmp = coll_partner_account.count_documents(myquery)

        if (tmp > 0):
            mydata['display_rank'] = str(MYSY_GV.DEMO_RANKING_VALUE)
            mydata['isalaune'] = "1"
            #print(" myquery pr demo_account 222 = " + str(tmp))

        else:
            #Ce n'est pas un compte demo, il faut donc recuperer le display rank tu pack - part_pack
            part_status, part_pack, part_pack_nb_training_auto = mycommon.Partner_Get_pack_nbTraining(user_recid)
            if (part_status is False):
                mycommon.myprint(str(inspect.stack()[0][
                                         3]) + " - Impossible de recuperer le pack et le nombre de formation du partenaire")
                return False, " Les informations d'identification sont incorrectes"


            coll_pack = MYSY_GV.dbname['pack']
            local_tmp = coll_pack.find({'code_pack':str(part_pack)})

            if (local_tmp[0] and "ranking" in local_tmp[0].keys()):
                if local_tmp[0]['ranking']:
                    print(" ### le ranking du pack est "+str(local_tmp[0]['ranking']) )
                    mydata['display_rank'] = str(local_tmp[0]['ranking'])



        coll_name = MYSY_GV.dbname['myclass']


        # seules les formation avec locked = 0 et valide=1 sont modifiables
        ret_val = coll_name.find_one_and_update({'internal_url': str(my_internal_url), 'partner_owner_recid':partner_recid, 'locked': '0', 'valide': '1'},
                                                    {"$set": mydata},
                                                    return_document=ReturnDocument.AFTER
                                                    )

        if (ret_val and ret_val['_id']):
            nb_doc = str(ret_val['_id'])
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - La formation a bin ete mise à jour =" + str(nb_doc))

            # Indexation Title de la nouvelle formation ajoutée
            training_to_index_title = {}
            training_to_index_title['internal_url'] = ret_val['internal_url']
            training_to_index_title['reindex'] = '1'
            eibdd.ela_index_given_classes_title(training_to_index_title)

            # Indexation Title des mots clées
            eibdd.ela_index_given_classes_keywords(training_to_index_title)

            return True,  " La formation a été mise à jour"

        else:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de mettre à jour la formation : "+str(my_external_code) )
            return False, "Impossible de mettre à jour la formation "+str(my_external_code)


    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de mettre à jour la formation "




'''
Desactivation d'une formation 

Disable a training, set  mydata['valide'] = '0'
'''
def disable_class(diction):
    try:

        '''
                # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
                # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
                # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
                # field_list.
                '''
        field_list = ['internal_url', 'token']
        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint(
                    str(inspect.stack()[0][3])+" - Creation partner account : Le champ  '" + val + "' n'existe pas, Creation formation annulée")
                return False, " Impossible de mettre à jour la formation"

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['internal_url', 'token']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(str(inspect.stack()[0][3])+" - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de mettre à jour la formation"

        # recuperation des paramettre
        mydata = {}
        my_internal_url = ""

        if ("token" in diction.keys()):
            if diction['token']:
                mydata['token'] = diction['token']

            # Verification de la validité du token
        '''
        Important : pour modifier une formation, il faut obligatoirement avoir un token.
        PAS DE CREATION / MODIFICATION DE FORMATION EN MODE NON CONNECTE.

        CONCERNANT CELLES CREEES PAR NOS SYSTEME AUTOMATIQUE, IL FAUDRA LEUR PASSER UNE VALEUR MALGRE TOUT

        '''
        retval = mycommon.check_partner_token_validity("", str(mydata['token']))

        if retval is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token ne sont pas valident")
            return False, "L'email ou le token ne sont pas valident"

        # Recuperation du recid de l'utilisateur
        user_recid = mycommon.get_parnter_recid_from_token(str(mydata['token']))
        if user_recid is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le recid de l'utilisateur")
            return False, " Les informations d'identification sont incorrectes"

        partner_recid = user_recid

        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                my_internal_url = diction['internal_url']


        mydata['date_update'] = str(datetime.now())

        mydata['valide'] = '0'
        coll_name = MYSY_GV.dbname['myclass']



        # seules les formation avec locked = 0 et valide=1 sont modifiables
        ret_val = coll_name.find_one_and_update(
            {'internal_url': str(my_internal_url), 'partner_owner_recid': partner_recid, 'locked': '0',
             'valide': '1'},
            {"$set": mydata},
            return_document=ReturnDocument.AFTER
            )

        if (ret_val and ret_val['_id']):
            nb_doc = str(ret_val['_id'])
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - La formation a bin ete mise à jour =" + str(nb_doc))

            return True,  " La formation "+str(my_internal_url)+"a été desactivée"

        else:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de desactivier  : " +str(my_internal_url) )
            return False, " Impossible de desactivier  la formation : "+str(my_internal_url)



    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de desactivier  la formation "


'''
reactivation  d'une formation 

Enable a training  set  mydata['valide'] = '1'
'''
def enable_class(diction):
    try:

        '''
                # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
                # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
                # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
                # field_list.
                '''
        field_list = ['internal_url', 'token']
        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint(
                    str(inspect.stack()[0][3])+" - Creation partner account : Le champ  '" + val + "' n'existe pas, Creation formation annulée")
                return False, " Impossible de mettre à jour la formation"

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['internal_url', 'token']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(str(inspect.stack()[0][3])+" - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de mettre à jour la formation"

        # recuperation des paramettre
        mydata = {}
        my_internal_url = ""

        if ("token" in diction.keys()):
            if diction['token']:
                mydata['token'] = diction['token']

            # Verification de la validité du token
        '''
        Important : pour modifier une formation, il faut obligatoirement avoir un token.
        PAS DE CREATION / MODIFICATION DE FORMATION EN MODE NON CONNECTE.

        CONCERNANT CELLES CREEES PAR NOS SYSTEME AUTOMATIQUE, IL FAUDRA LEUR PASSER UNE VALEUR MALGRE TOUT

        '''
        retval = mycommon.check_partner_token_validity("", str(mydata['token']))

        if retval is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token ne sont pas valident")
            return False, "L'email ou le token ne sont pas valident"

        # Recuperation du recid de l'utilisateur
        user_recid = mycommon.get_parnter_recid_from_token(str(mydata['token']))
        if user_recid is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le recid de l'utilisateur")
            return False, " Les informations d'identification sont incorrectes"

        partner_recid = user_recid

        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                my_internal_url = diction['internal_url']

        mydata['date_update'] = str(datetime.now())

        mydata['valide'] = '1'


        coll_name = MYSY_GV.dbname['myclass']

        # seules les formation avec locked = 0 et valide=1 sont modifiables
        ret_val = coll_name.find_one_and_update(
            {'internal_url': str(my_internal_url), 'partner_owner_recid': partner_recid, 'locked': '0',
             'valide': '0'},
            {"$set": mydata},
            return_document=ReturnDocument.AFTER
        )

        if (ret_val and ret_val['_id']):
            nb_doc = str(ret_val['_id'])
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - La formation a bien ete reactivée =" + str(nb_doc))
            return True, " La formation " + str(my_internal_url) + "a été reactivée"

        else:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de desactivier  : " + str(my_internal_url))
            return False, " Impossible de reactivée  la formation : " + str(my_internal_url)

    except Exception as e:
        mycommon.myprint(str(inspect.stack()[0][3])+" - " +str(e))
        return False, " Impossible de reactiver la formation"



'''
Desactivation d'une formation 

unlock a training  set  mydata['locked'] = '0'
'''
def unlock_class(diction):
    try:

        '''
                # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
                # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
                # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
                # field_list.
                '''
        field_list = ['internal_url', 'token']
        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint(
                    str(inspect.stack()[0][3])+" - Creation partner account : Le champ  '" + val + "' n'existe pas, Creation formation annulée")
                return False, " Impossible de mettre à jour la formation"

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['internal_url', 'token']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(str(inspect.stack()[0][3])+" - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de mettre à jour la formation"

        # recuperation des paramettre
        mydata = {}
        my_internal_url = ""

        if ("token" in diction.keys()):
            if diction['token']:
                mydata['token'] = diction['token']

            # Verification de la validité du token
        '''
        Important : pour modifier une formation, il faut obligatoirement avoir un token.
        PAS DE CREATION / MODIFICATION DE FORMATION EN MODE NON CONNECTE.

        CONCERNANT CELLES CREEES PAR NOS SYSTEME AUTOMATIQUE, IL FAUDRA LEUR PASSER UNE VALEUR MALGRE TOUT

        '''
        retval = mycommon.check_partner_token_validity("", str(mydata['token']))

        if retval is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token ne sont pas valident")
            return False, "L'email ou le token ne sont pas valident"

        # Recuperation du recid de l'utilisateur
        user_recid = mycommon.get_parnter_recid_from_token(str(mydata['token']))
        if user_recid is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le recid de l'utilisateur")
            return False, " Les informations d'identification sont incorrectes"

        partner_recid = user_recid



        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                my_internal_url = diction['internal_url']

        mydata['date_update'] = str(datetime.now())

        mydata['locked'] = '0'

        coll_name = MYSY_GV.dbname['myclass']

        # seules les formation avec locked = 1 et valide=1 sont 'unlockable'
        ret_val = coll_name.find_one_and_update(
            {'internal_url': str(my_internal_url), 'partner_owner_recid': partner_recid, 'locked': '1',
             'valide': '1'},
            {"$set": mydata},
            return_document=ReturnDocument.AFTER
        )

        if (ret_val and ret_val['_id']):
            nb_doc = str(ret_val['_id'])
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - La formation a bien ete debloquée =" + str(nb_doc))
            return True, " La formation " + str(my_internal_url) + "a été debloquée"

        else:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de debloquer  : " + str(my_internal_url))
            return False, " Impossible de debloquer  la formation : " + str(my_internal_url)



    except Exception as e:
        mycommon.myprint(str(inspect.stack()[0][3])+" - " +str(e))
        return False, " Impossible de mettre à jour la formation"


'''
Verrouillage d'une formation 

lock a training  set  mydata['locked'] = '1'
'''
def lock_class(diction):
    try:

        '''
                # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
                # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
                # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
                # field_list.
                '''
        field_list = ['internal_url', 'token']
        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint(
                    str(inspect.stack()[0][
                            3]) + " - Creation partner account : Le champ  '" + val + "' n'existe pas, Creation formation annulée")
                return False, " Impossible de mettre à jour la formation"

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['internal_url', 'token']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de mettre à jour la formation"

        # recuperation des paramettre
        mydata = {}
        my_internal_url = ""

        if ("token" in diction.keys()):
            if diction['token']:
                mydata['token'] = diction['token']

            # Verification de la validité du token
        '''
        Important : pour modifier une formation, il faut obligatoirement avoir un token.
        PAS DE CREATION / MODIFICATION DE FORMATION EN MODE NON CONNECTE.

        CONCERNANT CELLES CREEES PAR NOS SYSTEME AUTOMATIQUE, IL FAUDRA LEUR PASSER UNE VALEUR MALGRE TOUT

        '''
        retval = mycommon.check_partner_token_validity("", str(mydata['token']))

        if retval is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token ne sont pas valident")
            return False, "L'email ou le token ne sont pas valident"

        # Recuperation du recid de l'utilisateur
        user_recid = mycommon.get_parnter_recid_from_token(str(mydata['token']))
        if user_recid is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le recid de l'utilisateur")
            return False, " Les informations d'identification sont incorrectes"

        partner_recid = user_recid

        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                my_internal_url = diction['internal_url']

        mydata['date_update'] = str(datetime.now())

        mydata['locked'] = '1'

        coll_name = MYSY_GV.dbname['myclass']

        # seules les formation avec locked = 1 et valide=1 sont 'unlockable'
        print( "str(my_internal_url) = "+str(my_internal_url)+" --- partner_recid = "
               +partner_recid+" mydata = "+str(mydata))


        ret_val = coll_name.find_one_and_update(
            {'internal_url': str(my_internal_url), 'partner_owner_recid': partner_recid, 'locked': '0',
             'valide': '1'},
            {"$set": mydata},
            return_document=ReturnDocument.AFTER
        )

        if (ret_val and ret_val['_id']):
            nb_doc = str(ret_val['_id'])
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - La formation a bien ete verrouillée =" + str(nb_doc))
            return True, " La formation " + str(my_internal_url) + "a été verrouillée"

        else:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de verrouiller la formation  : " + str(my_internal_url))
            return False, " Impossible de verrouiller la formation  : " + str(my_internal_url)

    except Exception as e:
        mycommon.myprint(str(inspect.stack()[0][3]) + " - " + str(e))
        return False, " Impossible de mettre à jour la formation"


'''
Cette fonction publie une formation
elle met la valeur "published" à 1
'''
def pusblish_class(diction):
    try:

        '''
                # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
                # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
                # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
                # field_list.
                '''
        field_list = ['internal_url', 'token']
        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint(
                    str(inspect.stack()[0][
                            3]) + " - Creation partner account : Le champ  '" + val + "' n'existe pas, Creation formation annulée")
                return False, " Impossible de mettre à jour la formation"

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['internal_url', 'token']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de mettre à jour la formation"

        # recuperation des paramettre
        mydata = {}
        my_internal_url = ""

        if ("token" in diction.keys()):
            if diction['token']:
                mydata['token'] = diction['token']

            # Verification de la validité du token
        '''
        Important : pour modifier une formation, il faut obligatoirement avoir un token.
        PAS DE CREATION / MODIFICATION DE FORMATION EN MODE NON CONNECTE.

        CONCERNANT CELLES CREEES PAR NOS SYSTEME AUTOMATIQUE, IL FAUDRA LEUR PASSER UNE VALEUR MALGRE TOUT

        '''
        retval = mycommon.check_partner_token_validity("", str(mydata['token']))

        if retval is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token ne sont pas valident")
            return False, "L'email ou le token ne sont pas valident"

        # Recuperation du recid de l'utilisateur
        user_recid = mycommon.get_parnter_recid_from_token(str(mydata['token']))
        if user_recid is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le recid de l'utilisateur")
            return False, " Les informations d'identification sont incorrectes"

        partner_recid = user_recid

        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                my_internal_url = diction['internal_url']

        mydata['date_update'] = str(datetime.now())

        mydata['published'] = '1'

        coll_name = MYSY_GV.dbname['myclass']

        # seules les formation avec locked = 1 et valide=1 sont 'publiable'
        print( "str(my_internal_url) = "+str(my_internal_url)+" --- partner_recid = "
               +partner_recid+" mydata = "+str(mydata))

        '''
        ret_val = coll_name.find_one_and_update(
            {'internal_url': str(my_internal_url), 'partner_owner_recid': partner_recid, 'locked': '0',
             'valide': '1'},
            {"$set": mydata},
            return_document=ReturnDocument.AFTER
        )
        '''
        ret_val = coll_name.update_many( {'internal_url': str(my_internal_url), 'partner_owner_recid': partner_recid, 'locked': '0',
             'valide': '1'}, {"$set": mydata},  )

        if (ret_val.matched_count > 0):
            nb_doc = str(my_internal_url)
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - La formation a bien ete publiée =" + str(nb_doc))
            return True, " La formation " + str(my_internal_url) + "a été publiée"

        else:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de publier la formation  : " + str(my_internal_url))
            return False, " Impossible de publier la formation  : " + str(my_internal_url)

    except Exception as e:
        mycommon.myprint(str(inspect.stack()[0][3]) + " - " + str(e))
        return False, " Impossible de publier la formation"


'''
Cette fonction Depublie une formation 
1 - Elle met "published" à 0
'''
def unpublish_class(diction):
    try:

        '''
                # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
                # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
                # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
                # field_list.
                '''
        field_list = ['internal_url', 'token']
        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint(
                    str(inspect.stack()[0][3])+" -  Le champ  '" + val + "' n'existe pas, Creation formation annulée")
                return False, " Impossible de mettre à jour la formation"

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['internal_url', 'token']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(str(inspect.stack()[0][3])+" - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de depublier la formation"

        # recuperation des paramettre
        mydata = {}
        my_internal_url = ""

        if ("token" in diction.keys()):
            if diction['token']:
                mydata['token'] = diction['token']

            # Verification de la validité du token
        '''
        Important : pour modifier une formation, il faut obligatoirement avoir un token.
        PAS DE CREATION / MODIFICATION DE FORMATION EN MODE NON CONNECTE.

        CONCERNANT CELLES CREEES PAR NOS SYSTEME AUTOMATIQUE, IL FAUDRA LEUR PASSER UNE VALEUR MALGRE TOUT

        '''
        retval = mycommon.check_partner_token_validity("", str(mydata['token']))

        if retval is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token ne sont pas valident")
            return False, "L'email ou le token ne sont pas valident"

        # Recuperation du recid de l'utilisateur
        user_recid = mycommon.get_parnter_recid_from_token(str(mydata['token']))
        if user_recid is False:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le recid de l'utilisateur")
            return False, " Les informations d'identification sont incorrectes"

        partner_recid = user_recid

        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                my_internal_url = diction['internal_url']

        mydata['date_update'] = str(datetime.now())

        mydata['published'] = '0'

        coll_name = MYSY_GV.dbname['myclass']

        # seules les formation avec locked = 1 et valide=1 sont 'depupliable'
        print( " str(my_internal_url) = "+str(my_internal_url)+" partner_recid = "+partner_recid+
               " mydata = "+str(mydata) )

        '''
        ret_val = coll_name.find_one_and_update(
            {'internal_url': str(my_internal_url), 'partner_owner_recid': partner_recid, 'locked': '0',
             'valide': '1'},
            {"$set": mydata},
            return_document=ReturnDocument.AFTER
        )
        '''

        ret_val = coll_name.update_many(
            {'internal_url': str(my_internal_url), 'partner_owner_recid': partner_recid, 'locked': '0',
             'valide': '1'}, {"$set": mydata}, )

        if (ret_val.matched_count > 0):
            nb_doc = str(my_internal_url)
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - La formation a bien ete depubliée =" + str(nb_doc))
            return True, " La formation " + str(my_internal_url) + "a été depubliée"

        else:
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de depublier la formation  : " + str(my_internal_url))
            return False, " Impossible de depublier  la formation : " + str(my_internal_url)



    except Exception as e:
        mycommon.myprint(str(inspect.stack()[0][3])+" - " +str(e))
        return False, " Impossible de depublier la formation"


'''
cette fonction recherche et retour une formation.
la clé est : l'external code.
- le token du partenaire

Seules les formation "locked = 0 et valide = 1" sont recuperables par l'API
'''
def get_class(diction):
    try:
        '''
                # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
                # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
                # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
                # field_list.
                '''
        field_list = ['internal_url', 'token', 'title', 'valide', 'locked', 'user_ip', 'user_country_code', 'user_country_name', 'user_city',
		'user_postal', 'user_latitude', 'user_longitude', 'user_state']

        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint( str(inspect.stack()[0][3])+ "  - Creation partner account : Le champ  '" + val + "' n'existe pas, Creation formation annulée")
                return False, " Impossible de recuperer la formation"

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['token']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(str(inspect.stack()[0][3])+" - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de recuperer la formation"

            # recuperation des paramettre
        mydata = {}
        my_internal_url = ""
        my_token = ""


        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                my_internal_url = diction['internal_url']

        if ("token" in diction.keys()):
            if diction['token']:
                my_token = diction['token']


        '''
        Gestion des filters.
        '''

        internal_url_crit = {}
        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                internal_url_crit['internal_url'] = diction['internal_url']

        title_crit = {}
        if ("title" in diction.keys()):
            if diction['title']:
                title_crit['title'] = diction['title']


        coll_name = MYSY_GV.dbname['myclass']

        # verifier que le token et l'email sont ok
        coll_token = MYSY_GV.dbname['user_token']

        # Verification de la validité du token dans le cas des user en mode connecté
        '''
        /!\ Important : si le token est vide, alors c'est une recherche faite en mode non-connecté.
        on doit l'accepter.

        le controle de la validé du token est faite que ce dernier n'est pas vide.
        '''

        user_recid = "None"
        coll_search_result = MYSY_GV.dbname['user_recherche_result']

        # Verification de la validité du token/mail dans le cas des user en mode connecté
        if (len(str(my_token)) > 0):
            retval = mycommon.check_token_validity("", my_token)

            if retval is False:
                mycommon.myprint( str(inspect.stack()[0][3])+" - Le token n'est pas valide")
                return False, " Impossible de recuperer la formation"

            # Recuperation du recid de l'utilisateur
            user_recid = mycommon.get_user_recid_from_token(my_token)
            if user_recid is False:
                mycommon.myprint(str(inspect.stack()[0][3])+" - Impossible de recuperer le token de l'utilisateur")
                return False, " Impossible de recuperer la formation"

        RetObject = []
        filt_external_code = {}
        internal_url = ""
        if ("internal_url" in diction.keys()):
            filt_external_code = {'internal_url':str(diction['internal_url'])}
            internal_url = str(diction['internal_url'])

            #print(' ICICICIC '+str(filt_external_code))

        filt_title = {}
        if ("title" in diction.keys()):
            filt_title = {'title': {'$regex': str(diction['title'])}}


        print(" #### avant requete get partner_owner_recid laa ="+str(user_recid)+
              " internal_url =  "+str(my_internal_url)+
              " filt_title = "+str(filt_title))

        for retVal in coll_name.find({'valide':'1','locked':'0','internal_url':internal_url, 'published':'1'},
                                     {"_id": 0, "indexed": 0, "indexed_desc": 0, "indexed_obj": 0, "indexed_title": 0,
                                      "valide": 0, "locked": 0, "partner_owner_recid": 0, }
                                     ).limit(1):

            #print('ICI retVal = '+str(retVal))
            my_recid = {}
            my_recid['user_rec_id'] = str(user_recid)
            mydict_combined = {**diction, **retVal, **my_recid}
            mydict_combined['date_update'] = str(datetime.now())
            mydict_combined['type_view'] = "detail"

            if ("_id" in mydict_combined.keys()):
                mydict_combined['class_id'] = mydict_combined.pop('_id')

            #mycommon.myprint("COMBINED = " + str(mydict_combined))

            '''
            Statistique : Insertion du recherche - resultat '''
            ret_val_tmp = coll_search_result.insert_one(mydict_combined)

            if (ret_val_tmp is False):
                mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de mettre à jour la table des resultat"
                                                              " d'une recherche de formation. Voir _id = ")
                return False, "Impossible de faire un affichage detaillé "

            if ("description" in retVal.keys()):
                tmp_str = retVal['description']
                if (len(retVal['description']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['description'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."


            if ("objectif" in retVal.keys()):
                tmp_str = retVal['objectif']
                if (len(retVal['objectif']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['objectif'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."


            if ("programme" in retVal.keys()):
                tmp_str = retVal['programme']
                if (len(retVal['programme']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['programme'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."


            if ("pedagogie" in retVal.keys()):
                tmp_str = retVal['pedagogie']
                if (len(retVal['pedagogie']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['pedagogie'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."


            #mycommon.myprint(" #### "+str(retVal))
            user = retVal
            RetObject.append(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 recuperer la formation"


'''
Cette API retour une formation "coup de coeur".
elle effectue les controles necessaires et retour la formation
'''
def get_class_coup_de_coeur(diction):
    try:
        '''
                # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
                # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
                # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
                # field_list.
                '''
        field_list = ['internal_url', 'token', 'title', 'valide', 'locked', 'user_ip', 'user_country_code', 'user_country_name', 'user_city',
		'user_postal', 'user_latitude', 'user_longitude', 'user_state']

        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint( str(inspect.stack()[0][3])+ "  - Creation partner account : Le champ  '" + val + "' n'existe pas, Creation formation annulée")
                return False, " Impossible de recuperer la formation"

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['token']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(str(inspect.stack()[0][3])+" - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de recuperer la formation"

            # recuperation des paramettre
        mydata = {}
        my_internal_url = ""
        my_token = ""


        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                my_internal_url = diction['internal_url']

        if ("token" in diction.keys()):
            if diction['token']:
                my_token = diction['token']



        coll_name = MYSY_GV.dbname['myclass']


        RetObject = []
        filt_external_code = {}
        internal_url = ""
        if ("internal_url" in diction.keys()):
            internal_url = str(diction['internal_url'])


        for retVal in coll_name.find({'valide':'1','locked':'0','internal_url':internal_url, 'coeur':'1', 'published':'1'},
                                     {"_id": 0, "indexed": 0, "indexed_desc": 0, "indexed_obj": 0, "indexed_title": 0,
                                      "valide": 0, "locked": 0, "partner_owner_recid": 0, }
                                     ):

            print(" retval "+str(retVal))

            if ("description" in retVal.keys()):
                tmp_str = retVal['description']
                if (len(retVal['description']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['description'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."


            if ("objectif" in retVal.keys()):
                tmp_str = retVal['objectif']
                if (len(retVal['objectif']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['objectif'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."



            if ("programme" in retVal.keys()):
                tmp_str = retVal['programme']
                if (len(retVal['programme']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['programme'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."


            if ("pedagogie" in retVal.keys()):
                tmp_str = retVal['pedagogie']
                if (len(retVal['pedagogie']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['pedagogie'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."


            #mycommon.myprint(str(retVal))
            user = retVal
            RetObject.append(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 recuperer la formation"




'''
cette fonction recherche et retour une formation dont le proprietaire est le partenaire "partenaire_rec_id"
la clé est : l'external code.
- le token du partenaire. le token permet d'aller chercher le "rec_id"

Seules les formation "locked = 0 et valide = 1" sont recuperables par l'API
'''
def get_partner_class(diction):
    try:
        '''
        # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
        # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
        # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
        # field_list.
                '''
        field_list = ['internal_url', 'token', 'title', 'valide', 'locked', 'external_code']
        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint( str(inspect.stack()[0][3])+ "  - get_partner_class : Le champ  '" + val + "' n'existe pas, Creation formation annulée")
                return False, " Impossible de recuperer la formation"

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['token']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(str(inspect.stack()[0][3])+" - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de recuperer la formation"

            # recuperation des paramettre
        mydata = {}
        my_external_code = ""
        my_token = ""
        my_internal_url = ""

        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                my_internal_url = diction['internal_url']


        if ("external_code" in diction.keys()):
            if diction['external_code']:
                my_external_code = diction['external_code']

        if ("token" in diction.keys()):
            if diction['token']:
                my_token = diction['token']

        '''
        Gestion des filters.
        '''

        internal_url_crit = {}
        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                internal_url_crit['internal_url'] = diction['internal_url']

        external_code_crit = {}
        if ("external_code" in diction.keys()):
            if diction['external_code']:
                external_code_crit['external_code'] = diction['external_code']

        title_crit = {}
        if ("title" in diction.keys()):
            if diction['title']:
                title_crit['title'] = diction['title']


        coll_name = MYSY_GV.dbname['myclass']

        # verifier que le token et l'email sont ok
        coll_token = MYSY_GV.dbname['user_token']

        # Verification de la validité du token dans le cas des user en mode connecté
        '''
            /!\ Important : le token ne doit jamais etre vide car cette fonction a pour objectif
            de retourner les formation edité par un partenaire.
             
            Il dont obligatoirement est en mode connecté
                '''

        user_recid = "None"
        # Verification de la validité du token/mail dans le cas des user en mode connecté
        if (len(str(my_token)) > 0):
            retval = mycommon.check_partner_token_validity("", my_token)

            if retval is False:
                mycommon.myprint( str(inspect.stack()[0][3])+" - Le token n'est pas valide")
                return False, " Impossible de recuperer la formation"

            # Recuperation du recid de l'utilisateur
            user_recid = mycommon.get_parnter_recid_from_token(my_token)
            if user_recid is False:
                mycommon.myprint(str(inspect.stack()[0][3])+" - Impossible de recuperer le token de l'utilisateur")
                return False, " Impossible de recuperer la formation"

        if (len(str(my_token)) <= 0):
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token est vide")
            return False, " Impossible de recuperer la formation"


        RetObject = []
        filt_external_code= {}
        if ("external_code" in diction.keys()):
            filt_external_code = {'external_code':str(diction['external_code'])}
            #print(" GRRRRRRRRRRRRR "+str(filt_external_code))

        filt_title = {}
        if ("title" in diction.keys()):
            filt_title = {'title': {'$regex': str(diction['title'])}}

        filt_internal_url = {}
        if ("internal_url" in diction.keys()):
            filt_internal_url = {'internal_url': {'$regex': str(diction['internal_url'])}}
            #print(" filt_internal_url GRRRRRRRRRRRRRRRRRRRRrr  "+str(filt_internal_url))


        print(" ATTTTENNTION : GESTION DU CAS OU LA PERSONNE QUI CHERCHE LE COURS EST UN UTILISATEUR : PB avec : partner_owner_recid ")
        print(" #### avant requete get partner_owner_recid ="+str(user_recid)+
              " filt_external_code =  "+str(filt_external_code)+
              " filt_internal_url =  " + str(filt_internal_url) +
              " filt_title = "+str(filt_title))

        val_tmp = 1
        for retVal in coll_name.find( {"$and":[ {'valide':'1'},{'locked':'0'},
                                           {'partner_owner_recid':user_recid} ,
                                      filt_external_code, filt_title, filt_internal_url]},
                                      ):
            #mycommon.myprint(str(retVal))
            user = retVal
            user['id'] = str(val_tmp)

            '''
            Pour des facilité d'affichage coté front
            on va reformater le champ  "zone_diffusion" de sorte à le renvoyer
            sous la forme "code_pays-ville" 
            '''
            i = 0
            tmp_zone_diffusion = ""
            if( "zone_diffusion" in user.keys()):
                if( user['zone_diffusion'] and user['zone_diffusion']["city"]):
                    for tmp_val in user['zone_diffusion']["city"]:
                        tmp_zone_diffusion = tmp_zone_diffusion + str(user['zone_diffusion']["country"][i])+"-"+str(user['zone_diffusion']["city"][i])+";"
                        i = i+1

            user['zone_diffusion_str'] =  str(tmp_zone_diffusion[:-1])
            RetObject.append(JSONEncoder().encode(user))
            val_tmp = val_tmp + 1

        #print(str(RetObject))
        return True, RetObject


    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e)+" - Line : "+ str(exc_tb.tb_lineno) )
        return False, " Impossible de recuperer la formation"


"""
Cette fonction recherche des formations avec une recherche large (like %value%)
"""


def find_partner_class_like(diction):
    try:
        '''
        # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
        # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
        # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
        # field_list.
                '''
        field_list = ['internal_url', 'token', 'title', 'valide', 'locked', 'external_code']
        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint(str(inspect.stack()[0][
                                         3]) + "  - get_partner_class : Le champ  '" + val + "' n'existe pas, Creation formation annulée")
                return False, " Impossible de recuperer la formation"

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['token']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de recuperer la formation"

            # recuperation des paramettre
        mydata = {}
        my_external_code = ""
        my_token = ""
        my_internal_url = ""

        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                my_internal_url = diction['internal_url']

        if ("external_code" in diction.keys()):
            if diction['external_code']:
                my_external_code = diction['external_code']

        if ("token" in diction.keys()):
            if diction['token']:
                my_token = diction['token']

        '''
        Gestion des filters.
        '''

        internal_url_crit = {}
        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                internal_url_crit['internal_url'] = diction['internal_url']

        external_code_crit = {}
        if ("external_code" in diction.keys()):
            if diction['external_code']:
                external_code_crit['external_code'] = diction['external_code']

        title_crit = {}
        if ("title" in diction.keys()):
            if diction['title']:
                title_crit['title'] = diction['title']

        coll_name = MYSY_GV.dbname['myclass']

        # verifier que le token et l'email sont ok
        coll_token = MYSY_GV.dbname['user_token']

        # Verification de la validité du token dans le cas des user en mode connecté
        '''
            /!\ Important : le token ne doit jamais etre vide car cette fonction a pour objectif
            de retourner les formation edité par un partenaire.

            Il dont obligatoirement est en mode connecté
                '''

        user_recid = "None"
        # Verification de la validité du token/mail dans le cas des user en mode connecté
        if (len(str(my_token)) > 0):
            retval = mycommon.check_partner_token_validity("", my_token)

            if retval is False:
                mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token n'est pas valide")
                return False, " Impossible de recuperer la formation"

            # Recuperation du recid de l'utilisateur
            user_recid = mycommon.get_parnter_recid_from_token(my_token)
            if user_recid is False:
                mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le token de l'utilisateur")
                return False, " Impossible de recuperer la formation"

        if (len(str(my_token)) <= 0):
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token est vide")
            return False, " Impossible de recuperer la formation"

        RetObject = []
        filt_external_code = {}
        if ("external_code" in diction.keys()):
            filt_external_code = {'external_code':{'$regex': str(diction['external_code'])}}
            # print(" GRRRRRRRRRRRRR "+str(filt_external_code))

        filt_title = {}
        if ("title" in diction.keys()):
            filt_title = {'title': {'$regex': str(diction['title'])}}

        filt_internal_url = {}
        if ("internal_url" in diction.keys()):
            filt_internal_url = {'internal_url': {'$regex': str(diction['internal_url'])}}
            # print(" filt_internal_url GRRRRRRRRRRRRRRRRRRRRrr  "+str(filt_internal_url))

        print(
            " ATTTTENNTION : GESTION DU CAS OU LA PERSONNE QUI CHERCHE LE COURS EST UN UTILISATEUR : PB avec : partner_owner_recid ")
        print(" #### avant requete get partner_owner_recid =" + str(user_recid) +
              " filt_external_code =  " + str(filt_external_code) +
              " filt_internal_url =  " + str(filt_internal_url) +
              " filt_title = " + str(filt_title))

        val_tmp = 1
        for retVal in coll_name.find({"$and": [{'valide': '1'}, {'locked': '0'},
                                               {'partner_owner_recid': user_recid},
                                               filt_external_code, filt_title, filt_internal_url]},
                                     ):
            # mycommon.myprint(str(retVal))
            user = retVal
            user['id'] = str(val_tmp)

            '''
            Pour des facilité d'affichage coté front
            on va reformater le champ  "zone_diffusion" de sorte à le renvoyer
            sous la forme "code_pays-ville" 
            '''
            i = 0
            tmp_zone_diffusion = ""
            if ("zone_diffusion" in user.keys()):
                if (user['zone_diffusion'] and user['zone_diffusion']["city"]):
                    for tmp_val in user['zone_diffusion']["city"]:
                        tmp_zone_diffusion = tmp_zone_diffusion + str(user['zone_diffusion']["country"][i]) + "-" + str(
                            user['zone_diffusion']["city"][i]) + ";"
                        i = i + 1

            user['zone_diffusion_str'] = str(tmp_zone_diffusion[:-1])
            RetObject.append(JSONEncoder().encode(user))
            val_tmp = val_tmp + 1

        # print(str(RetObject))
        return True, RetObject


    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de recuperer la formation"


"""
Cette fonction retrourne 
- le code externe, 
- internal_url
des formations d'un partner 
"""

def get_partner_class_external_code(diction):
    try:
        '''
        # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
        # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
        # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
        # field_list.
                '''
        field_list = ['internal_url', 'token', 'title', 'valide', 'locked', 'external_code']
        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint(str(inspect.stack()[0][
                                         3]) + "  - get_partner_class : Le champ  '" + val + "' n'existe pas, Creation formation annulée")
                return False, " Impossible de recuperer la formation"

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['token']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de recuperer la formation"

            # recuperation des paramettre
        mydata = {}
        my_external_code = ""
        my_token = ""
        my_internal_url = ""

        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                my_internal_url = diction['internal_url']

        if ("external_code" in diction.keys()):
            if diction['external_code']:
                my_external_code = diction['external_code']

        if ("token" in diction.keys()):
            if diction['token']:
                my_token = diction['token']

        '''
        Gestion des filters.
        '''

        internal_url_crit = {}
        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                internal_url_crit['internal_url'] = diction['internal_url']

        external_code_crit = {}
        if ("external_code" in diction.keys()):
            if diction['external_code']:
                external_code_crit['external_code'] = diction['external_code']

        title_crit = {}
        if ("title" in diction.keys()):
            if diction['title']:
                title_crit['title'] = diction['title']

        coll_name = MYSY_GV.dbname['myclass']

        # verifier que le token et l'email sont ok
        coll_token = MYSY_GV.dbname['user_token']

        # Verification de la validité du token dans le cas des user en mode connecté
        '''
            /!\ Important : le token ne doit jamais etre vide car cette fonction a pour objectif
            de retourner les formation edité par un partenaire.

            Il dont obligatoirement est en mode connecté
                '''

        user_recid = "None"
        # Verification de la validité du token/mail dans le cas des user en mode connecté
        if (len(str(my_token)) > 0):
            retval = mycommon.check_partner_token_validity("", my_token)

            if retval is False:
                mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token n'est pas valide")
                return False, " Impossible de recuperer la formation"

            # Recuperation du recid de l'utilisateur
            user_recid = mycommon.get_parnter_recid_from_token(my_token)
            if user_recid is False:
                mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de recuperer le token de l'utilisateur")
                return False, " Impossible de recuperer la formation"

        if (len(str(my_token)) <= 0):
            mycommon.myprint(str(inspect.stack()[0][3]) + " - Le token est vide")
            return False, " Impossible de recuperer la formation"

        RetObject = []
        filt_external_code = {}
        if ("external_code" in diction.keys()):
            filt_external_code = {'external_code': str(diction['external_code'])}
            # print(" GRRRRRRRRRRRRR "+str(filt_external_code))

        filt_title = {}
        if ("title" in diction.keys()):
            filt_title = {'title': {'$regex': str(diction['title'])}}

        filt_internal_url = {}
        if ("internal_url" in diction.keys()):
            filt_internal_url = {'internal_url': {'$regex': str(diction['internal_url'])}}
            # print(" filt_internal_url GRRRRRRRRRRRRRRRRRRRRrr  "+str(filt_internal_url))

        print(
            " ATTTTENNTION : GESTION DU CAS OU LA PERSONNE QUI CHERCHE LE COURS EST UN UTILISATEUR : PB avec : partner_owner_recid ")
        print(" #### avant requete get partner_owner_recid =" + str(user_recid) +
              " filt_external_code =  " + str(filt_external_code) +
              " filt_internal_url =  " + str(filt_internal_url) +
              " filt_title = " + str(filt_title))

        val_tmp = 1
        for retVal in coll_name.find_one({"$and": [{'valide': '1'}, {'locked': '0'},
                                               {'partner_owner_recid': user_recid},
                                               filt_external_code, filt_title, filt_internal_url]},
                                     {'external_code':1, 'internal_url':1},
                                     ).sort([("external_code",pymongo.ASCENDING),]):
            # mycommon.myprint(str(retVal))
            user = retVal
            user['id'] = str(val_tmp)

            '''
            Pour des facilité d'affichage coté front
            on va reformater le champ  "zone_diffusion" de sorte à le renvoyer
            sous la forme "code_pays-ville" 
            '''
            i = 0
            tmp_zone_diffusion = ""
            if ("zone_diffusion" in user.keys()):
                if (user['zone_diffusion'] and user['zone_diffusion']["city"]):
                    for tmp_val in user['zone_diffusion']["city"]:
                        tmp_zone_diffusion = tmp_zone_diffusion + str(user['zone_diffusion']["country"][i]) + "-" + str(
                            user['zone_diffusion']["city"][i]) + ";"
                        i = i + 1

            user['zone_diffusion_str'] = str(tmp_zone_diffusion[:-1])
            RetObject.append(JSONEncoder().encode(user))
            val_tmp = val_tmp + 1

        # print(str(RetObject))
        return True, RetObject


    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible de recuperer la formation"


def get_class_global_search(search_string):
    try:
        mycommon.myprint(" search_string", search_string)

        coll_name = MYSY_GV.dbname['myclass']

        val = re.compile(r".*"+search_string+".*")
        my_regex =  "/.*"+search_string+".*/"

        insertObject = []
        for x in coll_name.find({'myindex': { '$regex': re.compile(r".*"+search_string+".*")  }}):
            mycommon.myprint(x)
            user = x
            insertObject.append(JSONEncoder().encode(user))

        #mycommon.myprint(" insertObject = ", insertObject)
        return insertObject
    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False



def get_all_class_by_attribut(attribut, value):
    try:
        mycommon.myprint(" attribut", attribut, " value = ",value)

        coll_name = MYSY_GV.dbname['myclass']

        insertObject = []
        for x in coll_name.find({attribut: value}, {"_id": 0}):
            mycommon.myprint(x)
            user = x
            insertObject.append(JSONEncoder().encode(user))

        #mycommon.myprint(" insertObject = ", insertObject)
        return insertObject


    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False




'''
Cette fontion import un fichier excel de formation
'''

def add_class_mass(file=None, Folder=None, diction=None):
    try:

        '''
        # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
        # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
        # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
        # field_list.
        '''
        field_list = ['token']
        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint(str(inspect.stack()[0][3]) + " - Creation formation : Le champ  '" + val + "' n'existe pas, Creation formation annulée")
                return False, " Le champ  '" + val + "' n'existe pas, Creation formation annulée"

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['token']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Verifier votre API"


        status, saved_file = mycommon.Upload_Save_CSV_File(file, Folder)
        if (status == False):
            return False, "Impossible d'inserer les formation en masse, le nom du fichier est incorrect "

        #" Lecture du fichier "
        #print(" Lecture du fichier : "+saved_file)
        nb_line = 0

        df = pd.read_csv(saved_file, encoding='utf8',  on_bad_lines='skip', sep=';')

        # Dictionnaire des champs utilisables
        '''
        # Verification que les noms des colonne sont bien corrects"
        '''
        field_list = ['external_code', 'titre', 'description', 'formateur', 'institut_formation',
                      'distantiel', 'presentiel', 'prix', 'domaine', 'url','duree', 'plus_produit',
                      'mots_cle', 'zone_diffusion', 'metier', 'date_lieu', 'publie', 'img_url',
                      'objectif', 'programme', 'prerequis', 'formateur', 'note', 'cpf', 'certif',
                      'class_inscription_url', 'pourqui', 'support', 'img_banner_detail_class']

        total_rows = len(df)

        #print(df.columns)
        for val in df.columns:
            if str(val).lower()  not in field_list:
                mycommon.myprint(
                    str(inspect.stack()[0][3])+" : entete du fichier csv. '" + val + "' n'est pas acceptée")
                return False, " Entete du fichier csv. '" + val + "' n'est pas acceptée"

        # Recuperation du recid de l'utilisateur
        user_recid = mycommon.get_parnter_recid_from_token(diction['token'])
        if user_recid is False:
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - Impossible de recuperer le token du partenaire")
            return False,  " Les informations d'identification sont incorrectes"

        part_status, part_pack, part_pack_nb_training_auto = mycommon.Partner_Get_pack_nbTraining(user_recid)
        if (part_status is False):
            mycommon.myprint(str(
                inspect.stack()[0][3]) + " - Impossible de recuperer le pack et le nombre de formations du partenaire")
            return False, " Les informations d'identification sont incorrectes"

        """
               Recuperation du nombre de formations actif de ce partner
               """
        part_status2, part_nb_active_training = mycommon.Get_partner_nb_active_training(user_recid)
        if (part_status2 is False):
            mycommon.myprint(str(
                inspect.stack()[0][3]) + " - Impossible de recuperer le pack et le nombre de formations du partenaire")
            return False, " Les informations d'identification sont incorrectes"

        new_nb_active = mycommon.tryInt(part_nb_active_training) + total_rows
        if ( new_nb_active > mycommon.tryInt(part_pack_nb_training_auto) ):
            mycommon.myprint(str(
                inspect.stack()[0][3]) + " - Vous avez atteint le nombre maximum de formation autorisé")
            return False, " Vous avez atteint le nombre maximum de formation autorisé (" + str(
                new_nb_active) + "). "

        x = range(0, total_rows)


        for n in x:
            mydata = {}

            if ("external_code" not in df.keys()):
                mycommon.myprint(str(
                    inspect.stack()[0][
                        3]) + " - Absence de 'external_code' pour la formation à la ligne "+str(n))
                return False, "  Absence de 'external_code' pour la formation à la ligne "+str(n)

            if ("titre" not in df.keys()):
                mycommon.myprint(str(
                    inspect.stack()[0][
                        3]) + " - Absence de 'titre' pour la formation à la ligne "+str(n))
                return False, "  Absence de 'titre' pour la formation à la ligne "+str(n)


            if ("domaine" not in df.keys()):
                mycommon.myprint(str(
                    inspect.stack()[0][
                        3]) + " - Absence de 'domaine' pour la formation à la ligne "+str(n))
                return False, "  Absence de 'domaine' pour la formation à la ligne "+str(n)


            if ("domaine" not in df.keys()):
                mycommon.myprint(str(
                    inspect.stack()[0][
                        3]) + " - Absence de 'description' pour la formation à la ligne "+str(n))
                return False, "  Absence de 'description' pour la formation à la ligne "+str(n)


            mydata['external_code'] = str(df['external_code'].values[n]).strip()
            mydata['title'] = str(df['titre'].values[n]).strip()
            mydata['domaine'] = str(df['domaine'].values[n]).strip()
            mydata['description'] = str(df['description'].values[n]).strip()


            formateur = ""
            if ("formateur" in df.keys()):
                if (str(df['formateur'].values[n])):
                    formateur = str(df['formateur'].values[n]).strip()
            mydata['trainer'] = formateur


            institut_formation = ""
            if ("institut_formation" in df.keys()):
                if (str(df['institut_formation'].values[n])):
                    institut_formation = str(df['institut_formation'].values[n]).strip()
            mydata['institut_formation'] = institut_formation


            #mydata['duration'] = float(str(df['duree'].values[n]))

            url = ""
            if ("url" in df.keys()):
                if (str(df['url'].values[n])):
                    url = str(df['url'].values[n]).strip()
            mydata['url'] = url

            duration = "0"
            if ("duree" in df.keys()):
                if (str(df['duree'].values[n])):
                    duration = str(df['duree'].values[n]).strip()
            mydata['duration'] = duration


            plus_produit = ""
            if ("plus_produit" in df.keys()):
                if (str(df['plus_produit'].values[n])):
                    plus_produit = str(df['plus_produit'].values[n]).strip()
            mydata['plus_produit'] = plus_produit

            mots_cle = ""
            if ("mots_cle" in df.keys()):
                if (str(df['mots_cle'].values[n])):
                    mots_cle = str(df['mots_cle'].values[n]).strip()
            mydata['mots_cle'] = mots_cle


            presentiel = "0"
            if ("presentiel" in df.keys()):
                if (str(df['presentiel'].values[n])):
                    presentiel = str(df['presentiel'].values[n]).strip()
            mydata['presentiel'] = presentiel

            distantiel = "0"
            if ("distantiel" in df.keys()):
                if (str(df['distantiel'].values[n])):
                    distantiel = str(df['distantiel'].values[n]).strip()
            mydata['distantiel'] = distantiel


            price = "0"
            if ("prix" in df.keys()):
                if (str(df['prix'].values[n])):
                    price = str(df['prix'].values[n]).strip()
            mydata['price'] = price


            metier = ""
            if ("metier" in df.keys()):
                if (str(df['metier'].values[n])):
                    metier = str(df['metier'].values[n]).strip()
            mydata['metier'] = metier


            published = "1"
            if ("published" in df.keys()):
                if (str(df['published'].values[n])):
                    published = str(df['published'].values[n]).strip()
            mydata['published'] = published


            mycpf = "0"
            if ("cpf" in df.keys()):
                if (str(df['cpf'].values[n])):
                    mycpf = str(df['cpf'].values[n]).strip()
            mydata['cpf'] = mycpf

            class_inscription_url = ""
            if ("class_inscription_url" in df.keys()):
                if (str(df['class_inscription_url'].values[n])):
                    class_inscription_url = str(df['class_inscription_url'].values[n]).strip()
            mydata['class_inscription_url'] = class_inscription_url

            certif = "0"
            if ("certif" in df.keys()):
                if (str(df['certif'].values[n])):
                    certif = str(df['certif'].values[n]).strip()
            mydata['certif'] = certif

            objectif = ""
            if ("objectif" in df.keys()):
                if (str(df['objectif'].values[n])):
                    objectif = str(df['objectif'].values[n]).strip()
            mydata['objectif'] = objectif

            note = ""
            if ("note" in df.keys()):
                if (str(df['note'].values[n])):
                    note = str(df['note'].values[n]).strip()
            mydata['note'] = note

            programme = ""
            if ("programme" in df.keys()):
                if (str(df['programme'].values[n])):
                    programme = str(df['programme'].values[n]).strip()
            mydata['programme'] = programme

            prerequis = ""
            if ("prerequis" in df.keys()):
                if (str(df['prerequis'].values[n])):
                    prerequis = str(df['prerequis'].values[n]).strip()
            mydata['prerequis'] = prerequis

            pourqui = ""
            if ("pourqui" in df.keys()):
                if (str(df['pourqui'].values[n])):
                    pourqui = str(df['pourqui'].values[n]).strip()
            mydata['pourqui'] = pourqui

            support = ""
            if ("support" in df.keys()):
                if (str(df['support'].values[n])):
                    support = str(df['support'].values[n]).strip()
            mydata['support'] = support

            img_banner_detail_class = ""
            if ("img_banner_detail_class" in df.keys()):
                if (str(df['img_banner_detail_class'].values[n])):
                    img_banner_detail_class = str(df['img_banner_detail_class'].values[n]).strip()
            mydata['img_banner_detail_class'] = img_banner_detail_class


            '''
            Verification de l'image
            '''
            if ("img_url" in df.keys()):
                mydata['img_url'] = str(df['img_url'].values[n]).strip()
                if (str(df['img_url'].values[n]) == 'nan'):
                    mydata['img_url'] = ""


                #print(" ### mydata['img_url'] = '"+str(mydata['img_url'])+"' ")
                if( len(str(mydata['img_url'])) > 0 ):
                    # Verifier si l'image existe
                    status_tmp, img = mycommon.TryUrlImage(str(mydata['img_url']))
                    if (status_tmp is False):
                        mycommon.myprint(
                            str(inspect.stack()[0][3]) + " : l'url de l'image de la formation " + str(
                                mydata['external_code']) + " est incorrecte ")
                        return False, " l'url de l'image de la formation " + str(mydata['external_code']) + " est incorrecte "


            '''
            Verification du nombre de mots clée : limite MYSY_GV.MAX_KEYWORD (3)
            '''
            nb_keyword = mydata['mots_cle'].split(";")
            if( len(nb_keyword) > MYSY_GV.MAX_KEYWORD ):
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " : La formation "+str(mydata['external_code'])+" a plus de "+ str(MYSY_GV.MAX_KEYWORD)+" mots clés")
                return False, " La formation "+str(mydata['external_code'])+" a plus de "+ str(MYSY_GV.MAX_KEYWORD)+" mots clés"


            ''' 
            Traitement de la zone de diffusion
            '''
            zone_diffusion = ""
            if ("zone_diffusion" in df.keys()):
                if(str(df['zone_diffusion'].values[n])):
                    zone_diffusion =str(df['zone_diffusion'].values[n]).strip()

            mydata['zone_diffusion'] = zone_diffusion

            '''
            Traitement des date et lieu de la formation
            '''
            date_lieu = ""
            if ("date_lieu" in df.keys()):
                if(str(df['date_lieu'].values[n])):
                    date_lieu =str(df['date_lieu'].values[n]).strip()

            mydata['date_lieu'] = date_lieu


            if ("token" in diction.keys()):
                if diction['token']:
                    mydata['token'] = diction['token']

            mydata['duration_unit'] = "jour"

            clean_dict = {k: mydata[k] for k in mydata if ( str(mydata[k]) != "nan") }

            #print( clean_dict)
            status, retval = add_class(clean_dict)

            if( status is False ):
                return status, retval

        print(str(total_rows)+" formations ont été inserées")

        return True, str(total_rows)+" formations ont été inserées / Mises à jour"

    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, "Impossible d'inserer les formation en masse  -" + str(e)



'''
Cette fonction retourne les formation par metier
- la thématique est defini par un nouveau champ appelé "metier"
'''
def get_class_by_metier(diction):
    try:

        '''
                       # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
                       # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
                       # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
                       # field_list.
                       '''
        field_list = ['metier', 'token','user_ip', 'user_country_code',
                      'user_country_name', 'user_city', 'user_postal', 'user_latitude', 'user_longitude', 'user_state']

        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint(str(inspect.stack()[0][
                                         3]) + "  - Creation partner account : Le champ  '" + val + "' n'existe pas, Creation formation annulée")
                return False, " Impossible de recuperer la formation"

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['token', 'metier']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de recuperer la formation"

            # recuperation des paramettre
        mydata = {}
        my_metier = ""
        my_token = ""

        if ("metier" in diction.keys()):
            if diction['metier']:
                my_metier = str(diction['metier']).lower()

        if ("token" in diction.keys()):
            if diction['token']:
                my_token = diction['token']

        coll_name = MYSY_GV.dbname['myclass']

        RetObject = []

        for retVal in coll_name.find({'valide': '1', 'locked': '0', 'metier': str(my_metier), 'published':'1'},
                                     {"_id": 0, "indexed": 0, "indexed_desc": 0, "indexed_obj": 0, "indexed_title": 0,
                                      "valide": 0, "locked": 0, "partner_owner_recid": 0, }
                                     ).sort([("display_rank", pymongo.DESCENDING), ("price", pymongo.ASCENDING), ("date_update", pymongo.DESCENDING), ]):

            #print(" retval " + str(retVal))

            if ("description" in retVal.keys()):
                tmp_str = retVal['description']
                if (len(retVal['description']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['description'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."

            if ("objectif" in retVal.keys()):
                tmp_str = retVal['objectif']
                if (len(retVal['objectif']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['objectif'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."

            if ("programme" in retVal.keys()):
                tmp_str = retVal['programme']
                if (len(retVal['programme']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['programme'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."

            if ("pedagogie" in retVal.keys()):
                tmp_str = retVal['pedagogie']
                if (len(retVal['pedagogie']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['pedagogie'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."

            # mycommon.myprint(str(retVal))
            user = retVal
            RetObject.append(JSONEncoder().encode(user))
            # print(" 22222 ")
            retVal_for_stat = retVal
            retVal_for_stat['search_by_metier'] =  str(my_metier)
            mycommon.InsertStatistic(retVal_for_stat, "summary", mydata)

        return True, RetObject

    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, "Impossible de recuperer les formations par metier"




""" 
Cette fonction modifier le ranking des formations d'un partenaire en masse.
Par exemple, lorqu'il change d'abonnement et passe 
du standard au gold, toutes ses formation prenne le ranking des golds.

/!\ : Si le compte utilisateur est un compte de demo, le display_ranking prendra
une valeur max de 50. ceci pour que ses formations soient visibles tout de suite.
"""
def UpdataPartnerRankingClass(diction):
    try:

        '''
              Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
              On controle que les champs obligatoires sont presents dans la liste 
              '''
        field_list_obligatoire = ['partnaire_recid', 'new_pack_name']


        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(
                    str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, "Impossible de mettre à jour le rang des formations"


        # Recuperation du rang associé au pack

        new_ranking_value = ""
        coll_pack = MYSY_GV.dbname["pack"]
        tmp = coll_pack.count_documents({"code_pack":str(diction["new_pack_name"]).lower()})

        if( tmp <= 0 ):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - le pack "+str(diction["new_pack_name"]).lower()+ " n'est pas paramettré corretement")
            return False, "Impossible de mettre à jour le rang des formations"

        ranking_tab = None

        ranking_tab = coll_pack.find({"code_pack":str(diction["new_pack_name"]).lower()})


        if( ranking_tab and ranking_tab[0] and ranking_tab[0]["ranking"] ):
            new_ranking_value = str(ranking_tab[0]["ranking"])
        else:
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - le pack " + str(
                    diction["new_pack_name"]) + " n'est pas paramettré corretement - V2")
            return False, "Impossible de mettre à jour le rang des formations"

        """
        Verification si le compte utilisateur est un compte de demo, ceci pour mettre
        le display ranking aux max de 50
        """

        coll_partner_account = MYSY_GV.dbname['partnair_account']
        myquery = {"recid": str(diction['partnaire_recid']), "active": "1",
                                                    "demo_account": "1"}

        #print(" myquery pr demo_account = "+str(myquery))
        tmp = coll_partner_account.count_documents(myquery)

        if (tmp > 0):
            new_ranking_value = MYSY_GV.DEMO_RANKING_VALUE
            #print(" myquery pr demo_account 222 = " + str(tmp))


        coll_class = MYSY_GV.dbname['myclass']

        now = datetime.now()
        update_data = {"display_rank":str(new_ranking_value), "date_update":str(now)}
        if( tmp > 0 ):
            update_data['isalaune'] = "1"

        ret_val = coll_class.update_many(
            {"partner_owner_recid": str(diction['partnaire_recid']), "valide":"1"},
            {"$set": update_data}, )

        mycommon.myprint(
            str(inspect.stack()[0][3]) + " - Le RANKING de "+str(ret_val.matched_count)+" ont été mise à jour avec la valeur "+str(update_data))


        return True, " Mise à jour du display_rank OK"

    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
        return False, "Impossible de mettre à jour le rang des formations"


"""
Cette fonction retourne les X formations du meme organisme de formations
associé à une formation données : current_internal_code

limit : X
condition : internal_url != current_internal_code
partner_owner_recid = current_partner_owner_recid

"""
def get_associated_class_of_partnair(diction):
    try:
        '''
                # Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
                # Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
                # Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
                # field_list.
                '''
        field_list = ['internal_url', 'token', 'title', 'valide', 'locked', 'user_ip', 'user_country_code', 'user_country_name', 'user_city',
		'user_postal', 'user_latitude', 'user_longitude', 'user_state']

        incom_keys = diction.keys()
        for val in incom_keys:
            if val not in field_list:
                mycommon.myprint( str(inspect.stack()[0][3])+ "  - Creation partner account : Le champ  '" + val + "' n'existe pas, Creation formation annulée")
                return False, " Impossible de recuperer la formation"

        '''
        Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
        On controle que les champs obligatoires sont presents dans la liste 
        '''
        field_list_obligatoire = ['internal_url']

        for val in field_list_obligatoire:
            if val not in diction:
                mycommon.myprint(str(inspect.stack()[0][3])+" - La valeur '" + val + "' n'est pas presente dans liste ")
                return False, " Impossible de recuperer la formation"

            # recuperation des paramettre
        mydata = {}
        my_internal_url = ""
        my_token = ""


        if ("internal_url" in diction.keys()):
            if diction['internal_url']:
                my_internal_url = diction['internal_url']

        coll_name = MYSY_GV.dbname['myclass']

        # verifier que le token et l'email sont ok
        coll_token = MYSY_GV.dbname['user_token']

        # Verification de la validité du token dans le cas des user en mode connecté
        '''
        /!\ Important : si le token est vide, alors c'est une recherche faite en mode non-connecté.
        on doit l'accepter.

        le controle de la validé du token est faite que ce dernier n'est pas vide.
        '''

        partner_recid = "None"

        # Recuperation du partner_owner_recid de la formation
        query = {'internal_url':my_internal_url}
        tmp = coll_name.count_documents(query)
        if( tmp <= 0 ):
            mycommon.myprint(str(inspect.stack()[0][3]) + " - La valeur : internal_url '" + my_internal_url + "' est KOO dans la myclass")
            return False, " Impossible de recuperer la formation"

        tmp_val = coll_name.find_one({'internal_url':my_internal_url},{'partner_owner_recid':1})
        #print(str(tmp_val))
        if( tmp_val and  tmp_val['partner_owner_recid']):
            partner_recid = tmp_val['partner_owner_recid']
        else:
            mycommon.myprint(str(inspect.stack()[0][
                                     3]) + " - La valeur :tmp_val and tmp_val[0] and tmp_val[0]['partner_owner_recid']   est KOO dans la myclass")
            return False, " Impossible de recuperer la formation"



        RetObject = []
        filt_external_code = {}
        internal_url = ""
        if ("internal_url" in diction.keys()):
            filt_external_code = {'internal_url':str(diction['internal_url'])}
            internal_url = str(diction['internal_url'])

            #print(' ICICICIC '+str(filt_external_code))

        filt_title = {}
        if ("title" in diction.keys()):
            filt_title = {'title': {'$regex': str(diction['title'])}}


        print(" #### avant requete get partner_owner_recid laa ="+str(partner_recid)+
              " internal_url =  "+str(my_internal_url)+
              " filt_title = "+str(filt_title))

        for retVal in coll_name.find({'valide':'1','locked':'0','internal_url': { '$ne': internal_url },
                                      'partner_owner_recid':partner_recid, 'published':'1'},
                                     {"_id": 0, "indexed": 0, "indexed_desc": 0, "indexed_obj": 0, "indexed_title": 0,
                                      "valide": 0, "locked": 0, "partner_owner_recid": 0, }
                                     ).limit(MYSY_GV.LIMIT_ASSOCIATED_TRAINING):



            if ("description" in retVal.keys()):
                tmp_str = retVal['description']
                if (len(retVal['description']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['description'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."


            if ("objectif" in retVal.keys()):
                tmp_str = retVal['objectif']
                if (len(retVal['objectif']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['objectif'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."



            if ("programme" in retVal.keys()):
                tmp_str = retVal['programme']
                if (len(retVal['programme']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['programme'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."


            if ("pedagogie" in retVal.keys()):
                tmp_str = retVal['pedagogie']
                if (len(retVal['pedagogie']) > MYSY_GV.MAX_CARACT_DETAIL):
                    retVal['pedagogie'] = tmp_str[:MYSY_GV.MAX_CARACT_DETAIL] + " ..."


            #mycommon.myprint(str(retVal))
            user = retVal
            RetObject.append(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 recuperer la formation"



"""
Cette fonction est utilisée pour la demande d'information sur une formation.
Depuis le site, lorqu'un utilisateur souhaite se renseigner sur une formation. 
c'est la fonction : "je me renseigne"
"""
def RenseignementClass(diction):
    try:
        field_list_obligatoire = ['nom', 'prenom', 'email', 'telephone', 'employeur',
                                  'message', 'class_internal_url']

        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, " : La valeur '" + val + "' n'est pas presente dans liste "


        """
        Recuperation des informations de la formation et du formation (adresse email) 
        """
        local_class_info = MYSY_GV.dbname['myclass'].find_one({'internal_url':str(diction['class_internal_url'])})

        if( not local_class_info['partner_owner_recid'] ):
            mycommon.myprint( str(inspect.stack()[0][3]) + " - Impossible de recuperer les informations de la formation ")
            return False, " Impossible de recuperer les informations de la formation "

        local_partner_info = MYSY_GV.dbname['partnair_account'].find_one({'recid': str(local_class_info['partner_owner_recid'])})
        if (not local_partner_info['email']):
            mycommon.myprint(
                str(inspect.stack()[0][3]) + " - Impossible de recuperer les informaton du formateur ")
            return False, " Impossible de recuperer les informaton du formateur "

        diction['class_title'] = local_class_info['title']
        diction['email_partnair'] = local_partner_info['email']

        #print(" #### diction demande info = "+str(diction))
        email.EmailDemandeInfoClass(diction)


        return True, " La demande d'information a bien été envoyée"

    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
        return False, " Impossible d'envoyer la demande d'information pour une formation"

