07/04/2024 - 13h19
parent
d4fc6a3227
commit
514e48d8b5
|
@ -1,12 +1,9 @@
|
||||||
<?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="04/04/24 - 21h30">
|
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="06/04/2024 - 21h19">
|
||||||
<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$/GlobalVariable.py" beforeDir="false" afterPath="$PROJECT_DIR$/GlobalVariable.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" />
|
||||||
<change beforePath="$PROJECT_DIR$/Session_Formation.py" beforeDir="false" afterPath="$PROJECT_DIR$/Session_Formation.py" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/formulaire_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/formulaire_mgt.py" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/survey_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/survey_mgt.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/survey_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/survey_mgt.py" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
|
@ -78,13 +75,6 @@
|
||||||
<option name="presentableId" value="Default" />
|
<option name="presentableId" value="Default" />
|
||||||
<updated>1680804787304</updated>
|
<updated>1680804787304</updated>
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00209" summary="02/02/2024 - 17h">
|
|
||||||
<created>1706890019271</created>
|
|
||||||
<option name="number" value="00209" />
|
|
||||||
<option name="presentableId" value="LOCAL-00209" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1706890019272</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00210" summary="02/02/2024 - 23h">
|
<task id="LOCAL-00210" summary="02/02/2024 - 23h">
|
||||||
<created>1706911273733</created>
|
<created>1706911273733</created>
|
||||||
<option name="number" value="00210" />
|
<option name="number" value="00210" />
|
||||||
|
@ -421,7 +411,14 @@
|
||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1712258561443</updated>
|
<updated>1712258561443</updated>
|
||||||
</task>
|
</task>
|
||||||
<option name="localTasksCounter" value="258" />
|
<task id="LOCAL-00258" summary="06/04/2024 - 21h19">
|
||||||
|
<created>1712431177613</created>
|
||||||
|
<option name="number" value="00258" />
|
||||||
|
<option name="presentableId" value="LOCAL-00258" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1712431177614</updated>
|
||||||
|
</task>
|
||||||
|
<option name="localTasksCounter" value="259" />
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="Vcs.Log.Tabs.Properties">
|
<component name="Vcs.Log.Tabs.Properties">
|
||||||
|
@ -463,7 +460,6 @@
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="VcsManagerConfiguration">
|
<component name="VcsManagerConfiguration">
|
||||||
<MESSAGE value="01/03/2024 - 23h30" />
|
|
||||||
<MESSAGE value="02/03/2024 - 23h20" />
|
<MESSAGE value="02/03/2024 - 23h20" />
|
||||||
<MESSAGE value="sss" />
|
<MESSAGE value="sss" />
|
||||||
<MESSAGE value="04/03/2024 - 22h15" />
|
<MESSAGE value="04/03/2024 - 22h15" />
|
||||||
|
@ -488,6 +484,7 @@
|
||||||
<MESSAGE value="03/04/24 - 21h30" />
|
<MESSAGE value="03/04/24 - 21h30" />
|
||||||
<MESSAGE value="04/04/24 - 19h30" />
|
<MESSAGE value="04/04/24 - 19h30" />
|
||||||
<MESSAGE value="04/04/24 - 21h30" />
|
<MESSAGE value="04/04/24 - 21h30" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value="04/04/24 - 21h30" />
|
<MESSAGE value="06/04/2024 - 21h19" />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="06/04/2024 - 21h19" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
1500
Log/log_file.log
1500
Log/log_file.log
File diff suppressed because it is too large
Load Diff
27
main.py
27
main.py
|
@ -8370,6 +8370,33 @@ def Send_Survey_TabIds():
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
API pour exporter les reponse à un questionnaire données
|
||||||
|
avec les filter :
|
||||||
|
- 'session_id',
|
||||||
|
- 'formulaire_type'
|
||||||
|
"""
|
||||||
|
|
||||||
|
@app.route('/myclass/api/Export_To_Excel_Survey_with_filter/<token>/<session_id>/<formulaire_type>/', methods=['POST','GET'])
|
||||||
|
@crossdomain(origin='*')
|
||||||
|
def Export_To_Excel_Survey_with_filter(token, session_id, formulaire_type):
|
||||||
|
# On recupere le corps (payload) de la requete
|
||||||
|
payload = mycommon.strip_dictionary (request.form.to_dict())
|
||||||
|
payload = {}
|
||||||
|
payload['token'] = str(token)
|
||||||
|
payload['session_id'] = str(session_id)
|
||||||
|
payload['formulaire_type'] = str(formulaire_type)
|
||||||
|
|
||||||
|
print(" ### Export_To_Excel_Survey_with_filter payload = ",payload)
|
||||||
|
|
||||||
|
status, retval = survey_mgt.Export_To_Excel_Survey_with_filter(payload)
|
||||||
|
if(status ):
|
||||||
|
return retval
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print(" debut api")
|
print(" debut api")
|
||||||
context = SSL.Context(SSL.SSLv23_METHOD)
|
context = SSL.Context(SSL.SSLv23_METHOD)
|
||||||
|
|
315
survey_mgt.py
315
survey_mgt.py
|
@ -6,6 +6,7 @@ import ast
|
||||||
|
|
||||||
import bson
|
import bson
|
||||||
import pymongo
|
import pymongo
|
||||||
|
import xlsxwriter
|
||||||
from pymongo import MongoClient
|
from pymongo import MongoClient
|
||||||
import json
|
import json
|
||||||
from bson import ObjectId
|
from bson import ObjectId
|
||||||
|
@ -196,6 +197,27 @@ def Record_Survey_Data_No_Token(diction):
|
||||||
str(inspect.stack()[0][3]) + " L'identifiant de l'enquête est invalide ")
|
str(inspect.stack()[0][3]) + " L'identifiant de l'enquête est invalide ")
|
||||||
return False, " L'identifiant de l'enquête est invalide "
|
return False, " L'identifiant de l'enquête est invalide "
|
||||||
|
|
||||||
|
"""
|
||||||
|
Recuperation des données du formulaire
|
||||||
|
"""
|
||||||
|
survey_data = MYSY_GV.dbname['survey'].find_one(qry)
|
||||||
|
|
||||||
|
form_data_qry = { 'valide': '1', 'locked': '0', '_id': ObjectId(str(survey_data['formulaire_id'])),
|
||||||
|
'partner_owner_recid':str(survey_data['partner_owner_recid'])}
|
||||||
|
|
||||||
|
form_data = MYSY_GV.dbname['formulaire'].find_one(form_data_qry)
|
||||||
|
if( form_data is None ):
|
||||||
|
mycommon.myprint(
|
||||||
|
str(inspect.stack()[0][3]) + " L'identifiant du formulaire est invalide ")
|
||||||
|
return False, " L'identifiant du formulaire est invalide "
|
||||||
|
|
||||||
|
if( "list_questions" not in form_data.keys() ):
|
||||||
|
mycommon.myprint(
|
||||||
|
str(inspect.stack()[0][3]) + " Le questionnaire du formulaire est invalide ")
|
||||||
|
return False, " Le questionnaire du formulaire est invalide "
|
||||||
|
|
||||||
|
|
||||||
|
form_list_question = form_data['list_questions']
|
||||||
|
|
||||||
JSON_user_response = ast.literal_eval(diction['list_response'])
|
JSON_user_response = ast.literal_eval(diction['list_response'])
|
||||||
list_keys = list(JSON_user_response.keys())
|
list_keys = list(JSON_user_response.keys())
|
||||||
|
@ -203,7 +225,12 @@ def Record_Survey_Data_No_Token(diction):
|
||||||
for my_key in list_keys:
|
for my_key in list_keys:
|
||||||
question_id = my_key
|
question_id = my_key
|
||||||
response = JSON_user_response[my_key]
|
response = JSON_user_response[my_key]
|
||||||
node = {"question_id":question_id, "response":response}
|
|
||||||
|
"""
|
||||||
|
On va recuperer la question ayant l'_id = question_id
|
||||||
|
"""
|
||||||
|
associated_question = [x for x in form_list_question if x['_id'] == question_id][0]['question']
|
||||||
|
node = {"question_id":question_id, "question":str(associated_question), "response":response}
|
||||||
global_response.append(node)
|
global_response.append(node)
|
||||||
|
|
||||||
|
|
||||||
|
@ -868,3 +895,289 @@ def Get_List_Survey_with_filter(diction):
|
||||||
exc_type, exc_obj, exc_tb = sys.exc_info()
|
exc_type, exc_obj, exc_tb = sys.exc_info()
|
||||||
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
|
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
|
||||||
return False, " Impossible de récupérer la liste des formulaires "
|
return False, " Impossible de récupérer la liste des formulaires "
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Cette fonction pour exporter les resultat d'une enquete dans une fichier excel
|
||||||
|
"""
|
||||||
|
def Export_To_Excel_Survey_with_filter(diction):
|
||||||
|
try:
|
||||||
|
diction = mycommon.strip_dictionary(diction)
|
||||||
|
|
||||||
|
"""
|
||||||
|
Verification des input acceptés
|
||||||
|
"""
|
||||||
|
field_list = ['token', 'session_id', 'formulaire_type' ]
|
||||||
|
|
||||||
|
incom_keys = diction.keys()
|
||||||
|
for val in incom_keys:
|
||||||
|
if val not in field_list and val.startswith('my_') is False:
|
||||||
|
mycommon.myprint(str(
|
||||||
|
inspect.stack()[0][3]) + " Le champ '" + val + "' n'est pas autorisé")
|
||||||
|
return False, " Les informations fournies sont incorrectes"
|
||||||
|
|
||||||
|
"""
|
||||||
|
Verification des champs obligatoires
|
||||||
|
"""
|
||||||
|
field_list_obligatoire = ['token',]
|
||||||
|
|
||||||
|
for val in field_list_obligatoire:
|
||||||
|
if val not in diction:
|
||||||
|
mycommon.myprint(
|
||||||
|
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
|
||||||
|
return False, " Les informations fournies sont incorrectes"
|
||||||
|
|
||||||
|
"""
|
||||||
|
Verification de l'identité et autorisation de l'entité qui
|
||||||
|
appelle cette API
|
||||||
|
"""
|
||||||
|
token = ""
|
||||||
|
if ("token" in diction.keys()):
|
||||||
|
if diction['token']:
|
||||||
|
token = diction['token']
|
||||||
|
|
||||||
|
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
|
||||||
|
if (local_status is not True):
|
||||||
|
return local_status, my_partner
|
||||||
|
|
||||||
|
|
||||||
|
filt_session_id = {}
|
||||||
|
if ("session_id" in diction.keys()):
|
||||||
|
filt_session_id = {'session_id': str(diction['session_id'])}
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Recuperer les données de la session
|
||||||
|
"""
|
||||||
|
my_session_data = MYSY_GV.dbname['session_formation'].find_one({'_id':ObjectId(str(diction['session_id'])),
|
||||||
|
'valide':'1',
|
||||||
|
'partner_owner_recid':str(my_partner['recid'])})
|
||||||
|
|
||||||
|
if(my_session_data is None):
|
||||||
|
mycommon.myprint(
|
||||||
|
str(inspect.stack()[0][3]) + " L'identifiant de la session de formation est invalide ")
|
||||||
|
return False, " L'identifiant de la session de formation est invalide "
|
||||||
|
|
||||||
|
"""
|
||||||
|
Recuperer les données de la formation
|
||||||
|
"""
|
||||||
|
my_class_data = MYSY_GV.dbname['myclass'].find_one({'internal_url': str(my_session_data['class_internal_url']),
|
||||||
|
'valide': '1',
|
||||||
|
'partner_owner_recid': str(
|
||||||
|
my_partner['recid'])}, {'title':1})
|
||||||
|
|
||||||
|
if (my_class_data is None):
|
||||||
|
mycommon.myprint(
|
||||||
|
str(inspect.stack()[0][3]) + " L'identifiant de la formation est invalide ")
|
||||||
|
return False, " L'identifiant de la formation est invalide "
|
||||||
|
|
||||||
|
|
||||||
|
RetObject = []
|
||||||
|
val_tmp = 0
|
||||||
|
|
||||||
|
qry = {"partner_owner_recid": str(my_partner['recid']), 'valide': '1', 'locked': '0'}
|
||||||
|
query_with_filter = {'$and': [qry, filt_session_id]}
|
||||||
|
|
||||||
|
pipe_qry = ([
|
||||||
|
{'$match': query_with_filter },
|
||||||
|
{'$project': { 'valide': 0, 'locked': 0, }},
|
||||||
|
{'$lookup': {
|
||||||
|
'from': 'formulaire',
|
||||||
|
"let": {'formulaire_id': "$formulaire_id",
|
||||||
|
'partner_owner_recid': '$partner_owner_recid'},
|
||||||
|
'pipeline': [
|
||||||
|
{'$match':
|
||||||
|
{'$expr':
|
||||||
|
{'$and':
|
||||||
|
[
|
||||||
|
|
||||||
|
{'$eq': ["$_id", {'$convert': {
|
||||||
|
'input': "$$formulaire_id",
|
||||||
|
'to': "objectId",
|
||||||
|
'onError': {'error': 'true'},
|
||||||
|
'onNull': {'isnull': 'true'}
|
||||||
|
}}]},
|
||||||
|
|
||||||
|
{'$eq': ["$valide", "1"]},
|
||||||
|
{'$eq': ["$type", str(diction['formulaire_type'])]},
|
||||||
|
{'$eq': ["$partner_owner_recid", '$$partner_owner_recid']}
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
],
|
||||||
|
'as': 'formulaire'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'$unwind': '$formulaire'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
#print(" ### pipe_qry = ", pipe_qry)
|
||||||
|
|
||||||
|
ts = datetime.now().timestamp()
|
||||||
|
ts = str(ts).replace(".", "").replace(",", "")[-5:]
|
||||||
|
|
||||||
|
orig_file_name = "Export_Reponse_" + str(ts) + ".xlsx"
|
||||||
|
outputFilename = str(MYSY_GV.TEMPORARY_DIRECTORY) + "/" + str(orig_file_name)
|
||||||
|
|
||||||
|
tab_exported_fields_header = ["formation", "code_session", "date_debut_session",
|
||||||
|
"date_fin_session", "email", "nom", "prenom", "type questionnaire", "date_envoi",
|
||||||
|
"date_reponse", "question", "reponse"]
|
||||||
|
|
||||||
|
tab_exported_fields = ["formation", "code_session", "date_debut_session",
|
||||||
|
"date_fin_session", "email", "nom", "prenom", "date_envoi",
|
||||||
|
"date_reponse", "question", "reponse"]
|
||||||
|
|
||||||
|
# Create a workbook and add a worksheet.
|
||||||
|
workbook = xlsxwriter.Workbook(outputFilename)
|
||||||
|
worksheet = workbook.add_worksheet()
|
||||||
|
|
||||||
|
row = 0
|
||||||
|
column = 0
|
||||||
|
|
||||||
|
"""
|
||||||
|
Creation de l'entete du fichier excel
|
||||||
|
"""
|
||||||
|
|
||||||
|
for header_item in tab_exported_fields_header:
|
||||||
|
worksheet.write(row, column, header_item)
|
||||||
|
column += 1
|
||||||
|
|
||||||
|
"""
|
||||||
|
Creation des data du fichier excel
|
||||||
|
"""
|
||||||
|
for Survey_Data in MYSY_GV.dbname['survey'].aggregate(pipe_qry):
|
||||||
|
column = 0
|
||||||
|
row = row + 1
|
||||||
|
|
||||||
|
# Champ : Titre de la formation
|
||||||
|
no_html_title = ""
|
||||||
|
if ("title" in my_class_data.keys()):
|
||||||
|
no_html_title = my_class_data['title']
|
||||||
|
|
||||||
|
worksheet.write(row, column, no_html_title)
|
||||||
|
column += 1
|
||||||
|
|
||||||
|
# Champ : Code session
|
||||||
|
code_session = ""
|
||||||
|
if ("code_session" in my_session_data.keys()):
|
||||||
|
code_session = my_session_data['code_session']
|
||||||
|
|
||||||
|
worksheet.write(row, column, code_session)
|
||||||
|
column += 1
|
||||||
|
|
||||||
|
# Champ : Date debut session
|
||||||
|
date_debut_session = ""
|
||||||
|
if ("code_session" in my_session_data.keys()):
|
||||||
|
date_debut_session = my_session_data['date_debut']
|
||||||
|
|
||||||
|
worksheet.write(row, column, date_debut_session)
|
||||||
|
column += 1
|
||||||
|
|
||||||
|
# Champ : Date fin session
|
||||||
|
date_fin_session = ""
|
||||||
|
if ("date_fin" in my_session_data.keys()):
|
||||||
|
date_fin_session = my_session_data['date_fin']
|
||||||
|
|
||||||
|
worksheet.write(row, column, date_fin_session)
|
||||||
|
column += 1
|
||||||
|
|
||||||
|
# Champ : Email
|
||||||
|
email = ""
|
||||||
|
if ("email" in Survey_Data.keys()):
|
||||||
|
email = Survey_Data['email']
|
||||||
|
|
||||||
|
worksheet.write(row, column, email)
|
||||||
|
column += 1
|
||||||
|
|
||||||
|
# Champ : nom
|
||||||
|
nom = ""
|
||||||
|
if ("nom" in Survey_Data.keys()):
|
||||||
|
nom = Survey_Data['nom']
|
||||||
|
|
||||||
|
worksheet.write(row, column, nom)
|
||||||
|
column += 1
|
||||||
|
|
||||||
|
# Champ : prenom
|
||||||
|
prenom = ""
|
||||||
|
if ("prenom" in Survey_Data.keys()):
|
||||||
|
prenom = Survey_Data['prenom']
|
||||||
|
|
||||||
|
worksheet.write(row, column, prenom)
|
||||||
|
column += 1
|
||||||
|
|
||||||
|
# Champ : survey_type
|
||||||
|
worksheet.write(row, column, str(diction['formulaire_type']))
|
||||||
|
column += 1
|
||||||
|
|
||||||
|
# Champ : date_envoi
|
||||||
|
date_envoi = ""
|
||||||
|
if ("date_envoi" in Survey_Data.keys()):
|
||||||
|
date_envoi = str(Survey_Data['date_envoi'])[0:16]
|
||||||
|
|
||||||
|
worksheet.write(row, column, date_envoi)
|
||||||
|
column += 1
|
||||||
|
|
||||||
|
# Champ : date_reponse
|
||||||
|
date_reponse = ""
|
||||||
|
if ("date_reponse" in Survey_Data.keys()):
|
||||||
|
date_reponse = str(Survey_Data['date_reponse'])[0:16]
|
||||||
|
|
||||||
|
worksheet.write(row, column, date_reponse)
|
||||||
|
column += 1
|
||||||
|
|
||||||
|
|
||||||
|
# Gestion des question et reponse
|
||||||
|
|
||||||
|
if( "user_response" in Survey_Data.keys() ):
|
||||||
|
question_num = 1
|
||||||
|
for user_response in Survey_Data['user_response']:
|
||||||
|
|
||||||
|
worksheet.write(0, column, "question_"+str(question_num))
|
||||||
|
question = ""
|
||||||
|
if ("question" in user_response.keys()):
|
||||||
|
question = str(user_response['question'])
|
||||||
|
|
||||||
|
worksheet.write(row, column, question)
|
||||||
|
column += 1
|
||||||
|
|
||||||
|
worksheet.write(0, column, "response_"+str(question_num))
|
||||||
|
response = ""
|
||||||
|
if ("response" in user_response.keys()):
|
||||||
|
response = str(user_response['response'])
|
||||||
|
|
||||||
|
worksheet.write(row, column, response)
|
||||||
|
column += 1
|
||||||
|
question_num += 1
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
question = "---"
|
||||||
|
worksheet.write(row, column, question)
|
||||||
|
column += 1
|
||||||
|
|
||||||
|
|
||||||
|
response = "---"
|
||||||
|
worksheet.write(row, column, response)
|
||||||
|
column += 1
|
||||||
|
|
||||||
|
|
||||||
|
workbook.close()
|
||||||
|
if os.path.exists(outputFilename):
|
||||||
|
# print(" ### ok os.path.exists(outputFilename) "+str(outputFilename))
|
||||||
|
return True, send_file(outputFilename, as_attachment=True)
|
||||||
|
|
||||||
|
|
||||||
|
return False, "Impossible de générer l'export (2) "
|
||||||
|
|
||||||
|
|
||||||
|
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 générer l'export "
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue