19/08/23 - 20h30

master
cherif 2023-08-19 20:38:17 +02:00
parent e9d1b5dab9
commit df18c5fedd
6 changed files with 1365 additions and 14 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="18/08/23 - 17h30"> <list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="19/08/23 - 15h30">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Inscription_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/Inscription_mgt.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Inscription_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/Inscription_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Log/log_file.log" beforeDir="false" afterPath="$PROJECT_DIR$/Log/log_file.log" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Log/log_file.log" beforeDir="false" afterPath="$PROJECT_DIR$/Log/log_file.log" afterDir="false" />
@ -71,13 +71,6 @@
<option name="presentableId" value="Default" /> <option name="presentableId" value="Default" />
<updated>1680804787304</updated> <updated>1680804787304</updated>
</task> </task>
<task id="LOCAL-00025" summary="22/05/23 - 23h">
<created>1684787274305</created>
<option name="number" value="00025" />
<option name="presentableId" value="LOCAL-00025" />
<option name="project" value="LOCAL" />
<updated>1684787274307</updated>
</task>
<task id="LOCAL-00026" summary="23/05/23 - 23h"> <task id="LOCAL-00026" summary="23/05/23 - 23h">
<created>1684872485100</created> <created>1684872485100</created>
<option name="number" value="00026" /> <option name="number" value="00026" />
@ -414,7 +407,14 @@
<option name="project" value="LOCAL" /> <option name="project" value="LOCAL" />
<updated>1692372578247</updated> <updated>1692372578247</updated>
</task> </task>
<option name="localTasksCounter" value="74" /> <task id="LOCAL-00074" summary="19/08/23 - 15h30">
<created>1692451967068</created>
<option name="number" value="00074" />
<option name="presentableId" value="LOCAL-00074" />
<option name="project" value="LOCAL" />
<updated>1692451967069</updated>
</task>
<option name="localTasksCounter" value="75" />
<servers /> <servers />
</component> </component>
<component name="Vcs.Log.Tabs.Properties"> <component name="Vcs.Log.Tabs.Properties">
@ -429,7 +429,6 @@
</option> </option>
</component> </component>
<component name="VcsManagerConfiguration"> <component name="VcsManagerConfiguration">
<MESSAGE value="23/07/2023 - 21h" />
<MESSAGE value="24/07/23 - 17h" /> <MESSAGE value="24/07/23 - 17h" />
<MESSAGE value="25/07/23 - 21h" /> <MESSAGE value="25/07/23 - 21h" />
<MESSAGE value="26/07/23 - 23h" /> <MESSAGE value="26/07/23 - 23h" />
@ -454,6 +453,7 @@
<MESSAGE value="16/08/23 - 22h" /> <MESSAGE value="16/08/23 - 22h" />
<MESSAGE value="17/08/23 - 17h" /> <MESSAGE value="17/08/23 - 17h" />
<MESSAGE value="18/08/23 - 17h30" /> <MESSAGE value="18/08/23 - 17h30" />
<option name="LAST_COMMIT_MESSAGE" value="18/08/23 - 17h30" /> <MESSAGE value="19/08/23 - 15h30" />
<option name="LAST_COMMIT_MESSAGE" value="19/08/23 - 15h30" />
</component> </component>
</project> </project>

View File

@ -50,12 +50,12 @@ def AddStagiairetoClass(diction):
field_list = ['nom', 'prenom', 'email', 'telephone', 'modefinancement', 'opco', field_list = ['nom', 'prenom', 'email', 'telephone', 'modefinancement', 'opco',
'class_internal_url', 'session_id', 'employeur', 'status', 'price', 'class_internal_url', 'session_id', 'employeur', 'status', 'price',
'inscription_validation_date', 'token', 'client_rattachement_id', 'inscription_validation_date', 'token', 'client_rattachement_id',
'adresse', 'code_postal', 'ville', 'pays'] 'adresse', 'code_postal', 'ville', 'pays', ]
incom_keys = diction.keys() incom_keys = diction.keys()
for val in incom_keys: for val in incom_keys:
if val not in field_list: if val not in field_list:
mycommon.myprint(str(inspect.stack()[0][ mycommon.myprint(str(inspect.stack()[0][
3]) + " - Creation partner account : Le champ '" + val + "' n'est pas autorisé, Creation partenaire annulée") 3]) + " - Creation partner account : Le champ '" + val + "' n'est pas autorisé")
return False, "Impossible de créer le stagiaire. Toutes les informations fournies ne sont pas valables" return False, "Impossible de créer le stagiaire. Toutes les informations fournies ne sont pas valables"
""" """
@ -1640,7 +1640,8 @@ def AddStagiairetoClass_mass(file=None, Folder=None, diction=None):
if (str(df['client_rattachement_nom'].values[n])): if (str(df['client_rattachement_nom'].values[n])):
client_rattachement_nom = str(df['client_rattachement_nom'].values[n]) client_rattachement_nom = str(df['client_rattachement_nom'].values[n])
local_client_retval_qry = {'email':str(client_rattachement_email), 'nom':str(client_rattachement_nom), 'valide':'1', 'locked':'0'} local_client_retval_qry = {'email':str(client_rattachement_email), 'nom':str(client_rattachement_nom), 'valide':'1',
'locked':'0', 'partner_recid' :str(partner_recid)}
local_client_retval_count = MYSY_GV.dbname['partner_client'].count_documents(local_client_retval_qry) local_client_retval_count = MYSY_GV.dbname['partner_client'].count_documents(local_client_retval_qry)
if( local_client_retval_count > 1 ): if( local_client_retval_count > 1 ):
@ -1702,6 +1703,285 @@ def AddStagiairetoClass_mass(file=None, Folder=None, diction=None):
"""
Cette fonction permet d'importer un fichier excel pour les stagiaire de plusieurs session, plusieurs formations
/!\ : Controle session : on va utiliser les colonne : formation code externe et le code de la session
/!\ : controle du client : on va utiliser le mail et le nom du client pour voir si ca concorde.
"""
def AddStagiairetoClass_mass_for_many_session(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]) + " Le champ '" + val + "' n'existe pas, Creation participants annulée")
return False, " Verifier votre API"
'''
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, Toutes les informations techniques ne sont pas fournies"
my_token = ""
if ("token" in diction.keys()):
if diction['token']:
my_token = diction['token']
# Verifier la validité du token
retval = mycommon.check_partner_token_validity("", my_token)
if retval is False:
return "Err_Connexion", " La session de connexion n'est pas valide"
partner_recid = mycommon.get_parnter_recid_from_token(my_token)
if (partner_recid is False):
mycommon.myprint(str(inspect.stack()[0][3]) + " - partner_recid KO : Impossible d'importer la liste des participants ")
return False, " Les information de connexion sont incorrectes. Impossible d'importer la liste des participants"
status, saved_file = mycommon.Upload_Save_CSV_File(file, Folder)
if (status == False):
mycommon.myprint("Impossible de recuperer correctement le fichier à importer")
return False, "Impossible d'importer la liste des participants, 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=';', encoding_errors='ignore')
# Dictionnaire des champs utilisables
'''
# Verification que les noms des colonne sont bien corrects"
'''
field_list = ['formation_code_externe', 'code_session', 'prenom', 'nom', 'employeur',
'telephone', 'email', 'modefinancement', 'opco', 'status', 'prix', 'adresse', 'code_postal',
'ville', 'pays', 'client_rattachement_email', 'client_rattachement_nom']
# Controle du nombre de lignes dans le fichier.
total_rows = len(df)
if( total_rows > MYSY_GV.MAX_PARTICIPANT_BY_CSV ):
mycommon.myprint(
str(inspect.stack()[0][3]) + " Le fichier comporte plus de "+str(MYSY_GV.MAX_PARTICIPANT_BY_CSV)+" lignes.")
return False, " Le fichier comporte plus de "+str(MYSY_GV.MAX_PARTICIPANT_BY_CSV)+" lignes."
#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"
# Verification des champs obligatoires dans le fichier
field_list_obligatoire_file = ['prenom', 'nom', 'email', 'modefinancement', 'status', 'prix']
for val in field_list_obligatoire_file:
if val not in df.columns:
mycommon.myprint(
str(inspect.stack()[0][
3]) + " : Le champ '" + val + "' n'est pas présent dans le fichier. Il est obligatoire")
return False, " Le champ '" + val + "' n'est pas présent dans le fichier. Il est obligatoire "
"""
# Recuperation des info de la session.
session_data = MYSY_GV.dbname['session_formation'].find_one({'formation_session_id':str(session_id)})
if( session_data is None ):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " La session de formation n'existe pas : Impossible d'importer la liste des participants ")
return False, "la session de formation n'existe pas. Impossible d'importer la liste des participants"
#print(" #### session_data = ",session_data)
"""
x = range(0, total_rows)
for n in x:
mydata = {}
class_external_code = str(df['formation_code_externe'].values[n])
#mydata['code_session'] = str(df['code_session'].values[n])
mydata['prenom'] = str(df['prenom'].values[n])
mydata['nom'] = str(df['nom'].values[n])
mydata['employeur'] = str(df['employeur'].values[n])
mydata['telephone'] = str(df['telephone'].values[n])
mydata['email'] = str(df['email'].values[n])
mydata['session_id'] = str(df['code_session'].values[n])
mydata['token'] = str(my_token)
"""
On verifie que le code de le session et le l'external class code correspondent.
En gros : que la formation en question a bien une session du meme code
"""
check_class_session_query = [{'$match': {'code_session':str(df['code_session'].values[n])}},
{'$lookup':
{
'from': 'myclass',
'localField': 'class_internal_url',
'foreignField': 'internal_url',
'pipeline': [{'$match': {'external_code':str(df['formation_code_externe'].values[n])}},
{'$project': {'title': 1, }}],
'as': 'myclass_collection'
}
}
]
print(" ##### myquery GetSessionFormation = " + str(check_class_session_query))
real_class_internal_url = ""
for check_class_session_retval in MYSY_GV.dbname['session_formation'].aggregate(check_class_session_query):
if ('myclass_collection' in check_class_session_retval.keys() and len(check_class_session_retval['myclass_collection']) > 0):
real_class_internal_url = check_class_session_retval['class_internal_url']
if( str(real_class_internal_url) == ""):
mycommon.myprint(
str(inspect.stack()[0][3]) + "Ligne : " + str(
n+2) + ": Le code externe de la formation et le code de la session ne correspondent pas .")
return False, "Ligne : " + str(n+2) + ": Le code externe de la formation et le code de la session ne correspondent pas."
mydata['class_internal_url'] = real_class_internal_url
modefinancement = ""
if ("modefinancement" in df.keys()):
if (str(df['modefinancement'].values[n])):
modefinancement = str(df['modefinancement'].values[n])
mydata['modefinancement'] = modefinancement
opco = ""
if ("opco" in df.keys()):
if (str(df['opco'].values[n])):
opco = str(df['opco'].values[n])
mydata['opco'] = opco
adresse = ""
if ("adresse" in df.keys()):
if (str(df['adresse'].values[n])):
adresse = str(df['adresse'].values[n])
mydata['adresse'] = adresse
code_postal = ""
if ("code_postal" in df.keys()):
if (str(df['code_postal'].values[n])):
code_postal = str(df['code_postal'].values[n])
mydata['code_postal'] = code_postal
ville = ""
if ("ville" in df.keys()):
if (str(df['ville'].values[n])):
ville = str(df['ville'].values[n])
mydata['ville'] = ville
pays = ""
if ("pays" in df.keys()):
if (str(df['pays'].values[n])):
pays = str(df['pays'].values[n])
mydata['pays'] = pays
""""
Gestion du client de rattachement/
Avec l'email et le nom, on va aller recuperer l'_id du client
"""
client_rattachement_email = ""
if ("client_rattachement_email" in df.keys()):
if (str(df['client_rattachement_email'].values[n])):
client_rattachement_email = str(df['client_rattachement_email'].values[n])
client_rattachement_nom = ""
if ("client_rattachement_nom" in df.keys()):
if (str(df['client_rattachement_nom'].values[n])):
client_rattachement_nom = str(df['client_rattachement_nom'].values[n])
local_client_retval_qry = {'email':str(client_rattachement_email), 'nom':str(client_rattachement_nom),
'valide':'1', 'locked':'0', 'partner_recid' :str(partner_recid)}
local_client_retval_count = MYSY_GV.dbname['partner_client'].count_documents(local_client_retval_qry)
if( local_client_retval_count > 1 ):
mycommon.myprint(
str(inspect.stack()[0][3]) +"Ligne : "+str(n+2) +". Plusieurs clients correspondent aux critère de nom :"+str(client_rattachement_nom)+" et email : "+str(client_rattachement_email))
return False, "Ligne : "+str(n+2) +". Plusieurs clients correspondent aux critère de nom :"+str(client_rattachement_nom)+" et email : "+str(client_rattachement_email)
if (local_client_retval_count < 1):
mycommon.myprint(
str(inspect.stack()[0][3]) + "Ligne : "+str(n+2) +". Aucun client ne repond aux critères de nom :" + str(
client_rattachement_nom) + " et email : " + str(client_rattachement_email))
return False, "Ligne : "+str(n+2) +". Aucun client ne repond aux critères de nom :" + str(
client_rattachement_nom) + " et email : " + str(client_rattachement_email)
local_client_retval_data = MYSY_GV.dbname['partner_client'].find_one(local_client_retval_qry)
if( local_client_retval_data is not None ):
mydata['client_rattachement_id'] = local_client_retval_data['_id']
mydata['status'] = str(df['status'].values[n]).strip()
if( str(mydata['status']) != "0" and str(mydata['status']) != "1" and str(mydata['status']) != "2"):
mycommon.myprint(
str(inspect.stack()[0][3]) + " Le champs 'status' de ligne " + str(n) + " est incorrecte. Valeurs acceptées : 0,1,2")
return False, " Le champs status de la ligne " + str(n) + " est incorrecte. Valeurs acceptées : 0,1,2"
if( str(df['status'].values[n]).strip() == "1"):
mydata['inscription_validation_date'] = str(datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
local_price = str(df['prix'].values[n]).strip()
local_status, new_price = mycommon.IsFloat(local_price)
if( local_status is False ):
mycommon.myprint(
str(inspect.stack()[0][ 3]) + " Le champs 'prix' de ligne " + str( n) + " est incorrecte.")
return False, " Le champs prix de ligne " + str(n) + " est incorrecte. "
mydata['price'] = local_price
clean_dict = {k: mydata[k] for k in mydata if ( str(mydata[k]) != "nan") }
print( "#### clean_dict ", clean_dict)
status, retval = AddStagiairetoClass(clean_dict)
if( status is False ):
return status, retval
print(str(total_rows)+" participants ont été inserés")
return True, str(total_rows)+" participants 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'importer les participants en masse "
""" """
Cette fonction permet d'imprimer/telecharger la fichier d'un inscrit à une session. Cette fonction permet d'imprimer/telecharger la fichier d'un inscrit à une session.
Cette fonction va utiliser un template pour imprimer le modele Cette fonction va utiliser un template pour imprimer le modele

File diff suppressed because it is too large Load Diff

View File

@ -1714,3 +1714,4 @@ def Add_Update_SessionFormation_mass_for_many_class(file=None, Folder=None, dict
exc_type, exc_obj, exc_tb = sys.exc_info() exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno)) mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, "Impossible d'importer les sessions de formation en masse " return False, "Impossible d'importer les sessions de formation en masse "

24
main.py
View File

@ -2227,6 +2227,30 @@ def AddStagiairetoClass_mass():
return jsonify(status=localStatus, message=message) return jsonify(status=localStatus, message=message)
"""
API d'import en masse de stagiaire avec pour plusieurs sessions et formations differentes
"""
@app.route('/myclass/api/AddStagiairetoClass_mass_for_many_session/', methods=['POST','GET'])
@crossdomain(origin='*')
def AddStagiairetoClass_mass_for_many_session():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### AddStagiairetoClass_mass_for_many_session payload = ",payload)
#print(request.files)
if request.method == 'POST':
# Create variable for uploaded file
f = request.files['File']
localStatus, message = inscription.AddStagiairetoClass_mass_for_many_session(f, app.config['UPLOAD_FOLDER'], payload)
#status, retval = cm.add_class_mass(f, app.config['UPLOAD_FOLDER'], payload)
return jsonify(status=localStatus, message=message)
""" """
API d'import en masse des sessions de formation API d'import en masse des sessions de formation
""" """

View File

@ -2880,7 +2880,14 @@ def GetAttendeeDetail_perSession(diction):
qry_filter = {'session_id':str(diction['session_id']),'email':str(diction['attendee_email']), qry_filter = {'session_id':str(diction['session_id']),'email':str(diction['attendee_email']),
'class_internal_url':str(diction['internal_url']),} 'class_internal_url':str(diction['internal_url']),}
""""
Verification qu'il n'y a q'une seule inscription pour ce critère
"""
qry_filter_count = MYSY_GV.dbname['inscription'].count_documents(qry_filter)
if( qry_filter_count > 1 ):
myprint(str(inspect.stack()[0][3]) + " - Données d'inscription incohérentes. il y a plus d'une inscription pour les critère "+str(qry_filter))
return False, "Données d'inscription incohérentes"
pipe_qry = ([{'$match':qry_filter}, pipe_qry = ([{'$match':qry_filter},
@ -2917,6 +2924,7 @@ def GetAttendeeDetail_perSession(diction):
'class_internal_url':str(diction['internal_url']),}) 'class_internal_url':str(diction['internal_url']),})
""" """
for local_Insc_retval in MYSY_GV.dbname['inscription'].aggregate(pipe_qry) : for local_Insc_retval in MYSY_GV.dbname['inscription'].aggregate(pipe_qry) :
print(" ### local_Insc_retval == ", local_Insc_retval) print(" ### local_Insc_retval == ", local_Insc_retval)
@ -3055,6 +3063,7 @@ def GetAttendeeDetail_perSession(diction):
RetObject.append(JSONEncoder().encode(my_retrun_dict)) RetObject.append(JSONEncoder().encode(my_retrun_dict))
return True, RetObject return True, RetObject