30/12/2023 - 18h

master
cherif 2023-12-30 18:07:07 +01:00
parent 25db380749
commit 32447fa2bd
12 changed files with 6606 additions and 45 deletions

View File

@ -1,10 +1,17 @@
<?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="28/12/2023- 19h"> <list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="29/12/2023- 12h">
<change afterPath="$PROJECT_DIR$/Dashbord_queries/ressources_humaines_tbd_qries.py" afterDir="false" />
<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$/Dashbord_queries/common_tdb_qries.py" beforeDir="false" afterPath="$PROJECT_DIR$/Dashbord_queries/common_tdb_qries.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Dashbord_queries/formation_tbd_qries.py" beforeDir="false" afterPath="$PROJECT_DIR$/Dashbord_queries/formation_tbd_qries.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Dashbord_queries/session_tbd_qries.py" beforeDir="false" afterPath="$PROJECT_DIR$/Dashbord_queries/session_tbd_qries.py" 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" />
<change beforePath="$PROJECT_DIR$/Session_Formation.py" beforeDir="false" afterPath="$PROJECT_DIR$/Session_Formation.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Session_Formation_Sequence.py" beforeDir="false" afterPath="$PROJECT_DIR$/Session_Formation_Sequence.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/agenda.py" beforeDir="false" afterPath="$PROJECT_DIR$/agenda.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$/prj_common.py" beforeDir="false" afterPath="$PROJECT_DIR$/prj_common.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/prj_common.py" beforeDir="false" afterPath="$PROJECT_DIR$/prj_common.py" afterDir="false" />
</list> </list>
@ -76,13 +83,6 @@
<option name="presentableId" value="Default" /> <option name="presentableId" value="Default" />
<updated>1680804787304</updated> <updated>1680804787304</updated>
</task> </task>
<task id="LOCAL-00134" summary="22/10/2023 - 18h00">
<created>1697992615131</created>
<option name="number" value="00134" />
<option name="presentableId" value="LOCAL-00134" />
<option name="project" value="LOCAL" />
<updated>1697992615134</updated>
</task>
<task id="LOCAL-00135" summary="22/10/2023 - 22h"> <task id="LOCAL-00135" summary="22/10/2023 - 22h">
<created>1698005958434</created> <created>1698005958434</created>
<option name="number" value="00135" /> <option name="number" value="00135" />
@ -419,7 +419,14 @@
<option name="project" value="LOCAL" /> <option name="project" value="LOCAL" />
<updated>1703784242481</updated> <updated>1703784242481</updated>
</task> </task>
<option name="localTasksCounter" value="183" /> <task id="LOCAL-00183" summary="29/12/2023- 12h">
<created>1703848960675</created>
<option name="number" value="00183" />
<option name="presentableId" value="LOCAL-00183" />
<option name="project" value="LOCAL" />
<updated>1703848960676</updated>
</task>
<option name="localTasksCounter" value="184" />
<servers /> <servers />
</component> </component>
<component name="Vcs.Log.Tabs.Properties"> <component name="Vcs.Log.Tabs.Properties">
@ -434,7 +441,6 @@
</option> </option>
</component> </component>
<component name="VcsManagerConfiguration"> <component name="VcsManagerConfiguration">
<MESSAGE value="23/11/2023 - 21h30" />
<MESSAGE value="24/11/2023 - 18h30" /> <MESSAGE value="24/11/2023 - 18h30" />
<MESSAGE value="30/11/2023 - 21h" /> <MESSAGE value="30/11/2023 - 21h" />
<MESSAGE value="01/12/2023 - 23h" /> <MESSAGE value="01/12/2023 - 23h" />
@ -459,6 +465,7 @@
<MESSAGE value="27/12/2023 - 13h" /> <MESSAGE value="27/12/2023 - 13h" />
<MESSAGE value="27/12/2023 - 23h" /> <MESSAGE value="27/12/2023 - 23h" />
<MESSAGE value="28/12/2023- 19h" /> <MESSAGE value="28/12/2023- 19h" />
<option name="LAST_COMMIT_MESSAGE" value="28/12/2023- 19h" /> <MESSAGE value="29/12/2023- 12h" />
<option name="LAST_COMMIT_MESSAGE" value="29/12/2023- 12h" />
</component> </component>
</project> </project>

View File

@ -92,7 +92,7 @@ def Add_To_User_Dashbord(diction):
""" """
Verification des input acceptés Verification des input acceptés
""" """
field_list = ['token', "dashbord_internal_code", "default_filter", "title"] field_list = ['token', "dashbord_internal_code", "default_filter", "title", 'type_event']
incom_keys = diction.keys() incom_keys = diction.keys()
for val in incom_keys: for val in incom_keys:
@ -150,6 +150,10 @@ def Add_To_User_Dashbord(diction):
my_data['dashbord_internal_code'] = str(diction['dashbord_internal_code']) my_data['dashbord_internal_code'] = str(diction['dashbord_internal_code'])
my_data['valide'] = "1" my_data['valide'] = "1"
my_data['locked'] = "0" my_data['locked'] = "0"
my_data['date_update'] = str(datetime.now())
if("type_event" in diction.keys() ):
my_data['type_event'] = str(diction['type_event'])
result = MYSY_GV.dbname['user_dashbord'].find_one_and_update( result = MYSY_GV.dbname['user_dashbord'].find_one_and_update(
{'partner_owner_recid': str(my_partner['recid']), 'connected_id':str(my_partner['_id']), {'partner_owner_recid': str(my_partner['recid']), 'connected_id':str(my_partner['_id']),
@ -299,6 +303,7 @@ def Get_Connected_User_List_Dashbord(diction):
for retval in MYSY_GV.dbname['user_dashbord'].find( qry): for retval in MYSY_GV.dbname['user_dashbord'].find( qry):
""" """
Convertion des filtres en date reelles. Convertion des filtres en date reelles.
Par exemple m0 = mois en cours = 1 du mois en cours à la date du jours. Par exemple m0 = mois en cours = 1 du mois en cours à la date du jours.
@ -334,9 +339,12 @@ def Get_Connected_User_List_Dashbord(diction):
if( "type_event" not in retval.keys() ) :
retval['type_event'] = ""
retval['start_date'] = start_date retval['start_date'] = start_date
retval['end_date'] = end_date retval['end_date'] = end_date
#print(" ### final retval = ", retval) print(" ### final retval = ", retval)
RetObject.append(mycommon.JSONEncoder().encode(retval)) RetObject.append(mycommon.JSONEncoder().encode(retval))
return True, RetObject return True, RetObject

View File

@ -1,5 +1,5 @@
""" """
Ce fichier contient les requetes utilisées dans les tableaux de bord des Formation Ce fichier contient les requetes utilisées dans les tableaux de bord des Formations
""" """
import ast import ast

View File

@ -0,0 +1,479 @@
"""
Ce fichier permet de traiter les tableaux de bord associées aux ressources humaines
"""
import ast
import dateutil
import pymongo
from dateutil.relativedelta import relativedelta
from flask import send_file
from pymongo import MongoClient
import json
from bson import ObjectId
import re
from datetime import datetime, timezone, date
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
from datetime import timedelta
from datetime import timedelta
from operator import itemgetter
"""
Recupération du tableau des ressources humaines en lien avec leur planification
"""
def Get_Humain_Ressource_With_Planning(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'session_start_date', 'session_end_date', 'filter_value', 'tab_rh_id', 'event_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'existe pas")
return False, " Les informations fournies sont incorrectes",
"""
Verification des champs obligatoires
"""
field_list_obligatoire = ['token', 'session_start_date', 'session_end_date' ]
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
# Verfication de la validité du type d'evenement
event_type_filter = {}
if( "event_type" in diction.keys() and diction['event_type']):
if( diction['event_type'] not in MYSY_GV.AGENDA_EVENT_TYPE):
mycommon.myprint(
str(inspect.stack()[0][3]) + " Le type d'évènement est invalide ")
return False, " Le type d'évènement est invalide "
event_type_filter = {'$eq': ["$event_type", str(diction['event_type'])]}
print(" ### event_type_filter = ", event_type_filter)
"""
/!\ : si 'tab_rh_id' == 'all', cela veut dire qu'on prend touts les employés
si non, on va aller filtrer selon les contenus de la tab tab_rh_id
"""
tab_rh_id = []
tab_rh_object_id = []
if( str(diction['tab_rh_id']) == "all" ):
for val in MYSY_GV.dbname['ressource_humaine'].find({'valide': '1',
'locked': '0',
'partner_recid': str(my_partner['recid'])}):
tab_rh_object_id.append(val['_id'])
else : # Verification de la validité de toutes les ressources humaines dans tab_rh_id
tab_rh_id = str(diction['tab_rh_id']).split(',')
for rh_id in tab_rh_id:
if (MYSY_GV.dbname['ressource_humaine'].count_documents({'_id': ObjectId(str(rh_id)),
'valide': '1',
'locked': '0',
'partner_recid': str(
my_partner['recid'])}) != 1):
mycommon.myprint(
str(inspect.stack()[0][3]) + " La ressource humaine :" + str(rh_id) + " n'est pas valide ")
return False, " La session_id :" + str(rh_id) + " n'est pas valide "
tab_rh_object_id.append(ObjectId(str(rh_id)))
filt_session_start_date = ""
if ("session_start_date" in diction.keys() and diction['session_start_date']):
filt_session_start_date = str(diction['session_start_date'])[0:10]
local_status = mycommon.CheckisDate(filt_session_start_date)
if (local_status is False):
mycommon.myprint(str(
inspect.stack()[0][3]) + " Le filtre : 'date de debut de session' n'est pas au format jj/mm/aaaa.")
return False, " Le filtre : 'date de debut de session' n'est pas au format jj/mm/aaaa."
filt_session_end_date = ""
if ("session_end_date" in diction.keys() and diction['session_end_date']):
filt_session_end_date = str(diction['session_end_date'])[0:10]
local_status = mycommon.CheckisDate(filt_session_end_date)
if (local_status is False):
mycommon.myprint(str(
inspect.stack()[0][3]) + " Le filtre : 'date de fin de session' n'est pas au format jj/mm/aaaa.")
return False, " Le filtre : 'date de fin de session' n'est pas au format jj/mm/aaaa."
"""
Si la valeur de 'filter_value' est m0 ou m1, on va aller recuperer les date du mois correspondant.
On ecrase les valeur de filt_session_start_date et filt_session_end_date
"""
if( 'filter_value' in diction.keys() ):
if( str(diction['filter_value']) == "m0"):
# On recupere les date du mois en cours
local_status, start_current_month_date, end_current_month_date = mycommon.Get_Current_Month_Start_End_Date()
if (local_status is False):
return local_status, start_current_month_date
filt_session_start_date = start_current_month_date
filt_session_end_date = end_current_month_date
elif (str(diction['filter_value']) == "m1"):
# On recupere les date du mois en cours
local_status, start_current_month_date, end_current_month_date = mycommon.Get_Previous_Month_Start_End_Date()
if (local_status is False):
return local_status, start_current_month_date
filt_session_start_date = start_current_month_date
filt_session_end_date = end_current_month_date
RetObject = []
val_tmp = 1
filt_session_start_date_ISODATE = datetime.strptime(str(filt_session_start_date), '%d/%m/%Y')
filt_session_end_date_ISODATE = datetime.strptime(str(filt_session_end_date), '%d/%m/%Y')
filt_session_start_date_ISODATE_work = filt_session_start_date_ISODATE
filt_session_end_date_ISODATE_work = filt_session_end_date_ISODATE
interval_date = []
pipe_qry = ( [
{ "$match": {'_id':{'$in':tab_rh_object_id} }},
{'$lookup': {
'from': 'agenda',
"let": {"rh_id": {'$toString': "$_id"}, 'rh_partner_owner_recid':'$partner_recid'},
'pipeline': [
{'$match':
{'$expr':
{'$and':
[
event_type_filter,
{'$eq': ["$valide", "1"]},
{'$eq': ["$related_collection_recid", '$$rh_id']},
{'$eq': ["$partner_owner_recid", '$$rh_partner_owner_recid']},
{'$gte': [{'$toDate': "$event_start" },filt_session_start_date_ISODATE]},
{'$lte': [{'$toDate': "$event_start"}, filt_session_end_date_ISODATE]}
]
}
}
},
],
'as': 'collection_agenda'
}
}
])
print(" ### Get_Humain_Ressource_With_Planning ici pipe_qry = ", pipe_qry)
new_retval_titles = []
new_retval_data = []
local_id = 0
for retval in MYSY_GV.dbname['ressource_humaine'].aggregate(pipe_qry):
## Recuperation des agenda
if( "collection_agenda" in retval.keys() and len(retval['collection_agenda']) > 0 ):
for agenda_retval in retval['collection_agenda'] :
local_id = local_id + 1
new_node = {}
new_node['id'] = str(local_id)
new_node['_id'] = str(retval['_id'])
if ("civilite" in retval.keys()):
new_node['civilite'] = str(retval['civilite'])
else:
new_node['civilite'] = ""
if ("nom" in retval.keys()):
new_node['nom'] = str(retval['nom'])
else:
new_node['nom'] = ""
if ("prenom" in retval.keys()):
new_node['prenom'] = str(retval['prenom'])
else:
new_node['prenom'] = ""
if ("email" in retval.keys()):
new_node['email'] = str(retval['email'])
else:
new_node['email'] = ""
if ("ismanager" in retval.keys()):
new_node['ismanager'] = str(retval['ismanager'])
else:
new_node['ismanager'] = "0"
if ("fonction" in retval.keys()):
new_node['fonction'] = str(retval['fonction'])
else:
new_node['fonction'] = ""
if ("_id" in agenda_retval.keys()):
new_node['agenda_id'] = str(agenda_retval['_id'])
else:
new_node['agenda_id'] = ""
if ("event_title" in agenda_retval.keys()):
new_node['agenda_event_title'] = str(agenda_retval['event_title'])
else:
new_node['agenda_event_title'] = ""
if ("comment" in agenda_retval.keys()):
new_node['agenda_event_code_session'] = str(agenda_retval['comment'])
else:
new_node['agenda_event_code_session'] = ""
if ("sequence_session_id" in agenda_retval.keys()):
new_node['agenda_event_sequence_session_id'] = str(agenda_retval['sequence_session_id'])
else:
new_node['agenda_event_sequence_session_id'] = ""
if ("event_type" in agenda_retval.keys()):
new_node['agenda_event_type'] = str(agenda_retval['event_type'])
else:
new_node['agenda_event_type'] = ""
if ("event_start" in agenda_retval.keys()):
new_node['agenda_date_jour'] = str(datetime.strptime(str(agenda_retval['event_end'])[0:16], '%Y-%m-%dT%H:%M').strftime("%d/%m/%Y"))
new_node['agenda_event_start'] = str(datetime.strptime(str(agenda_retval['event_end'])[0:16], '%Y-%m-%dT%H:%M').strftime("%d/%m/%Y %H:%M"))
else:
new_node['agenda_date_jour'] = ""
new_node['agenda_event_start'] = ""
if ("event_end" in agenda_retval.keys()):
new_node['agenda_event_end'] = str(datetime.strptime(str(agenda_retval['event_end'])[0:16], '%Y-%m-%dT%H:%M').strftime("%d/%m/%Y %H:%M"))
else:
new_node['agenda_event_end'] = ""
event_duration_second = datetime.strptime(str(agenda_retval['event_end'])[0:16], '%Y-%m-%dT%H:%M') - datetime.strptime(str(agenda_retval['event_start'])[0:16],'%Y-%m-%dT%H:%M')
event_duration_second = event_duration_second.total_seconds()
event_duration_hour = round(divmod(event_duration_second, 3600)[0]+divmod(event_duration_second, 3600)[1]/3600, 2)
new_node['event_duration_second'] = str(event_duration_second)
new_node['event_duration_hour'] = str(event_duration_hour)
#print(" ### new_node = ", new_node)
RetObject.append(mycommon.JSONEncoder().encode(new_node))
return True, RetObject
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de récupérer les données "
"""
Cette fonction permet d'experter un dashbord en csv
"""
def TBD_RH_01_Export_Dashbord_To_Csv(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'user_dashbord_id']
incom_keys = diction.keys()
for val in incom_keys:
if val not in field_list and val.startswith('my_') is False:
mycommon.myprint(str(
inspect.stack()[0][3]) + " Le champ '" + val + "' n'existe pas")
return False, " Les informations fournies sont incorrectes",
"""
Verification des champs obligatoires
"""
field_list_obligatoire = ['token', 'user_dashbord_id']
for val in field_list_obligatoire:
if val not in diction:
mycommon.myprint(
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
return False, " Les informations fournies sont incorrectes",
"""
Verification de l'identité et autorisation de l'entité qui
appelle cette API
"""
token = ""
if ("token" in diction.keys()):
if diction['token']:
token = diction['token']
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
if (local_status is not True):
return local_status, my_partner
# Recuperation des données du user_dashbord
my_user_dashbord = MYSY_GV.dbname['user_dashbord'].find_one({'_id': ObjectId(str(diction['user_dashbord_id'])),
'valide': '1',
'locked': '0',
'partner_owner_recid': str(my_partner['recid'])})
if (my_user_dashbord is None):
mycommon.myprint(
str(inspect.stack()[0][3]) + " - L'identifiant du tableau de bord est invalide ")
return False, " L'identifiant du tableau de bord est invalide",
new_retval_data = {}
my_new_diction = {}
my_new_diction['token'] = diction['token']
session_start_date = ""
session_end_date = ""
local_default_filter = ast.literal_eval(str(my_user_dashbord['default_filter']))
if ("session_start_date" in local_default_filter.keys() and "session_end_date" in local_default_filter.keys()):
session_start_date = local_default_filter['session_start_date']
session_end_date = local_default_filter['session_end_date']
elif ("periode" in local_default_filter.keys()):
my_new_diction['filter_value'] = str(local_default_filter['periode'])
if (str(local_default_filter['periode']) == "m0"):
# On recupere les date du mois en cours
local_status, start_current_month_date, end_current_month_date = mycommon.Get_Current_Month_Start_End_Date()
if (local_status is False):
return local_status, start_current_month_date
session_start_date = start_current_month_date
session_end_date = end_current_month_date
elif (str(local_default_filter['periode']) == "m1"):
# On recupere les date du mois en cours
local_status, start_current_month_date, end_current_month_date = mycommon.Get_Previous_Month_Start_End_Date()
if (local_status is False):
return local_status, start_current_month_date
session_start_date = start_current_month_date
session_end_date = end_current_month_date
my_new_diction['session_start_date'] = session_start_date
my_new_diction['session_end_date'] = session_end_date
my_new_diction['tab_rh_id'] = "all"
if (my_user_dashbord['dashbord_internal_code'] == "tbd_rh_01"):
local_status, local_retval = Get_Humain_Ressource_With_Planning(my_new_diction)
if (local_status is False):
return local_status, local_retval
new_retval_data = local_retval
else:
mycommon.myprint(
str(inspect.stack()[0][3]) + " Requête inconnue ")
return False, " Requête inconnue ",
# Recuperation des colonne à exporter
base_config_dashbord_data = MYSY_GV.dbname['base_config_dashbord'].find_one(
{'dashbord_internal_code': str(my_user_dashbord['dashbord_internal_code'])})
tab_exported_fields = []
if ("exported_fields" in base_config_dashbord_data):
tab_exported_fields = base_config_dashbord_data['exported_fields']
# Remettres les dates de filtres en debut de liste
if ("filtre_date_fin" in tab_exported_fields):
tab_exported_fields.remove("filtre_date_fin")
tab_exported_fields.insert(0, "filtre_date_fin")
if ("filtre_date_debut" in tab_exported_fields):
tab_exported_fields.remove("filtre_date_debut")
tab_exported_fields.insert(0, "filtre_date_debut")
tab_exported_fields.insert(0, "date_extraction")
todays_date = str(date.today().strftime("%d/%m/%Y"))
ts = datetime.now().timestamp()
ts = str(ts).replace(".", "").replace(",", "")[-5:]
orig_file_name = "Export_csv_" + str(my_partner['recid']) + "_" + str(ts) + ".csv"
outputFilename = str(MYSY_GV.TEMPORARY_DIRECTORY) + "/" + str(orig_file_name)
with open(outputFilename, 'w', newline='') as outfile:
fields = tab_exported_fields
write = csv.DictWriter(outfile, fieldnames=fields)
write.writeheader()
for answers_record in new_retval_data: # Here we are using 'cursor' as an iterator
flattened_record = {}
for local_fiels in tab_exported_fields:
answers_record_JSON = ast.literal_eval(str(answers_record))
if (str(local_fiels) in answers_record_JSON.keys()):
flattened_record[str(local_fiels)] = answers_record_JSON[str(local_fiels)]
flattened_record['filtre_date_debut'] = str(session_start_date)
flattened_record['filtre_date_fin'] = str(session_end_date)
flattened_record['date_extraction'] = str(todays_date)
write.writerow(flattened_record)
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 csv (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 d'exporter les données "

View File

@ -746,6 +746,8 @@ def Export_Dashbord_To_Csv(diction):
new_retval_data = local_retval new_retval_data = local_retval
else: else:
mycommon.myprint( mycommon.myprint(
str(inspect.stack()[0][3]) + " Requête inconnue ") str(inspect.stack()[0][3]) + " Requête inconnue ")
@ -764,11 +766,11 @@ def Export_Dashbord_To_Csv(diction):
# Remettres les dates de filtres en debut de liste # Remettres les dates de filtres en debut de liste
if( "filtre_date_fin" in tab_exported_fields): if( "filtre_date_fin" in tab_exported_fields):
tab_exported_fields.remove("filtre_date_fin") tab_exported_fields.remove("filtre_date_fin")
tab_exported_fields.insert(0, "filtre_date_fin") tab_exported_fields.insert(0, "filtre_date_fin")
if ("filtre_date_debut" in tab_exported_fields): if ("filtre_date_debut" in tab_exported_fields):
tab_exported_fields.remove("filtre_date_debut") tab_exported_fields.remove("filtre_date_debut")
tab_exported_fields.insert(0, "filtre_date_debut") tab_exported_fields.insert(0, "filtre_date_debut")
tab_exported_fields.insert(0, "date_extraction") tab_exported_fields.insert(0, "date_extraction")

View File

@ -7035,6 +7035,497 @@ def Sent_Convention_Stagiaire_By_Email(tab_files, Folder, diction):
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 d'envoyer la convention par email " return False, " Impossible d'envoyer la convention par email "
"""
Comme la fonction plus haut (Sent_Convention_Stagiaire_By_Email) cette fonction est un clone
qui envoie uniquement et exclusivement les conventions individuelles.
Je les ai separé vu la complexité de la fonction et eviter des effets de bors/
"""
def Sent_Convention_Individuelle_Stagiaire_By_Email(tab_files, Folder, diction):
try:
field_list_obligatoire = ['token', 'inscription_id', 'courrier_template_id', 'email_test', 'email_production']
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"
my_token = ""
if ("token" in diction.keys()):
if diction['token']:
my_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
# Verifier que le stagiaire est bien inscrit. Le statut de l'inscription doit etre "1" et qu'il n'est rattaché à aucun client
is_inscription_valide = MYSY_GV.dbname['inscription'].count_documents(
{'$or': [
{'_id': ObjectId(str(diction['inscription_id'])),
'status': '1',
'partner_owner_recid': str(my_partner['recid']),
'client_rattachement_id': ''},
{'_id': ObjectId(str(diction['inscription_id'])),
'status': '1',
'partner_owner_recid': str(my_partner['recid']),
'client_rattachement_id': {'$exists': False}
}]})
if (is_inscription_valide != 1):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " L'identifiant de l'inscription est invalide ")
return False, " L'identifiant de l'inscription est invalide "
# Recuperation des données du stagaire
inscription_data = MYSY_GV.dbname['inscription'].find_one({'_id': ObjectId(str(diction['inscription_id'])),
'status': '1',
'partner_owner_recid': str(my_partner['recid'])})
# Recupérer la liste des participants concernés
tab_participant = []
tab_participant.append(inscription_data['_id'])
# Traitement de l'eventuel fichier joint
tab_files_to_attache_to_mail = []
# Sauvegarde des fichiers joints depuis le front
tab_saved_file_full_path = []
for file in tab_files:
status, saved_file_full_path = mycommon.Upload_Save_PDF_IMG_File(file, Folder)
if (status is False):
mycommon.myprint("Impossible de récupérer correctement le fichier à importer")
return False, "Impossible de récupérer correctement le fichier à importer"
tab_saved_file_full_path.append(saved_file_full_path)
for saved_file in tab_saved_file_full_path:
"""
status, saved_file = mycommon.Upload_Save_PDF_IMG_File(file, Folder)
if (status is False):
mycommon.myprint("Impossible de récupérer correctement le fichier à importer")
return False, "Impossible de récupérer correctement le fichier à importer"
"""
file_to_attache_to_mail = MIMEBase('application', "octet-stream")
file_to_attache_to_mail.set_payload(open(saved_file, "rb").read())
encoders.encode_base64(file_to_attache_to_mail)
file_to_attache_to_mail.add_header('Content-Disposition',
'attachment; filename="{0}"'.format(os.path.basename(saved_file)))
new_node = {"attached_file": file_to_attache_to_mail}
tab_files_to_attache_to_mail.append(new_node)
# Verification de la validité des adresses email_recu
"""
/!\ : Si l'email de test est repli, alors on considere que c'est un test, on ne prend pas en compte l'email de email_production.
Ceci pour forcer les utilisateur à ne remplir que l'email de prod s'il veulent l'envoyer en prod.
Si l'adresse email_prodution = "defaul", cela veut dire qu'on envoie la convention à :
- l'adresse email du stagiaire et ses tuteurs (si les tuteurs on cochés la case 'inclu com'
"""
send_in_production = 0
tab_emails_destinataire = []
if ("email_test" in diction.keys() and diction['email_test']):
send_in_production = 0
tab_email_test = str(diction['email_test']).replace(";", ",").split(",")
for email in tab_email_test:
email = email.strip()
if (mycommon.isEmailValide(email) is False):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " L'adresse email " + str(email) + " est invalide ")
return False, " L'adresse email " + str(email) + " est invalide "
tab_emails_destinataire = tab_email_test
elif ("email_production" in diction.keys() and diction['email_production']):
send_in_production = 1
if (str(diction['email_production']) != "default"):
tab_email_prod = str(diction['email_production']).replace(";", ",").split(",")
for email in tab_email_prod:
email = email.strip()
if (mycommon.isEmailValide(str(email)) is False):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " L'adresse email '" + str(email) + "' est invalide ")
return False, " L'adresse email " + str(email) + " est invalide "
tab_emails_destinataire = tab_email_prod
else:
send_in_production = 1
# On va chercher les adresse email de communication du
local_dict = {'token': str(diction['token']), '_id': str(diction['inscription_id'])}
local_status, tab_apprenant_contact = Get_Statgiaire_Communication_Contact(local_dict)
if (local_status is False):
return local_status, tab_apprenant_contact
tmp_tab = []
# print(" ### tab_apprenant_contact = ", tab_apprenant_contact)
for tmp in tab_apprenant_contact:
if ("email" in tmp.keys()):
tab_emails_destinataire.append((tmp['email']))
if (len(tab_emails_destinataire) <= 0):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " Aucune adresse email n'a été fourni. ")
return False, " Aucune adresse email n'a été fourni. "
# print(" ### tab_emails_destinataire = ", tab_emails_destinataire)
# Verifier que le 'courrier_template_id' est valide
# Ici le template doit etre un email
courrier_template_data = None
if (str(diction['courrier_template_id']) == "default_mail"):
"""
# Verifier qu'il y a bien un modele de courrier de convention individuelle par defaut
- ref_interne = CONVENTION_STAGIAIRE
- default_version = 1
- edit_by_client = '0' ou n'existe pas
- type_doc = email
"""
is_courrier_template_id_valide = MYSY_GV.dbname['courrier_template'].count_documents({"$or": [
{'valide': '1',
'locked': '0',
'type_doc': 'email',
'partner_owner_recid': str(my_partner['recid']),
'ref_interne': 'CONVENTION_STAGIAIRE',
'default_version': '1',
'edit_by_client': '0'
},
{'valide': '1',
'locked': '0',
'type_doc': 'email',
'partner_owner_recid': str(my_partner['recid']),
'ref_interne': 'CONVENTION_STAGIAIRE',
'default_version': '1',
'edit_by_client': {'$exists': False}
}
]})
if (is_courrier_template_id_valide != 1):
mycommon.myprint(str(inspect.stack()[0][
3]) + " Aucun modèle de courrier PDF par defaut pour les conventions individuelles ")
return False, " Aucun modèle de courrier PDF par defaut pour les conventions individuelles "
# Recupération des données du modèle de document
courrier_template_data = MYSY_GV.dbname['courrier_template'].find_one({"$or": [
{'valide': '1',
'locked': '0',
'type_doc': 'email',
'partner_owner_recid': str(my_partner['recid']),
'ref_interne': 'CONVENTION_STAGIAIRE',
'default_version': '1',
'edit_by_client': '0'
},
{'valide': '1',
'locked': '0',
'type_doc': 'email',
'partner_owner_recid': str(my_partner['recid']),
'ref_interne': 'CONVENTION_STAGIAIRE',
'default_version': '1',
'edit_by_client': {'$exists': False}
}
]})
else:
# Verifier que le 'courrier_template_id' est valide. il doit etre de type PDF
qry = {'_id': ObjectId(str(diction['courrier_template_id'])),
'valide': '1',
'locked': '0',
'type_doc': 'email',
'partner_owner_recid': str(my_partner['recid'])}
is_courrier_template_id_valide = MYSY_GV.dbname['courrier_template'].count_documents(
{'_id': ObjectId(str(diction['courrier_template_id'])),
'valide': '1',
'locked': '0',
'type_doc': 'email',
'partner_owner_recid': str(my_partner['recid'])}
)
if (is_courrier_template_id_valide != 1):
mycommon.myprint(str(inspect.stack()[0][3]) + " L'identifiant du modèle de courrier est invalide ")
return False, " L'identifiant du modèle de courrier est invalide "
# Recupération des données du modèle de document
courrier_template_data = MYSY_GV.dbname['courrier_template'].find_one(
{'_id': ObjectId(str(diction['courrier_template_id'])),
'valide': '1',
'locked': '0',
'type_doc': 'email',
'partner_owner_recid': str(my_partner['recid'])}
)
if (courrier_template_data is None):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " Impossile d'identifier le modèle de courrier ")
return False, " Impossile d'identifier le modèle de courrier "
# Recuperation des eventuelles pièces jointes du modèle que courrier
local_dic = {}
local_dic['token'] = str(diction['token'])
local_dic['object_owner_collection'] = "courrier_template"
local_dic['object_owner_id'] = str(courrier_template_data['_id'])
local_status, local_retval = attached_file_mgt.Get_List_object_owner_collection_Stored_Files(local_dic)
if (local_status is False):
return local_status, local_retval
# print(" ### file stocké = ", local_retval)
# Recuperation des fichiers attachés au modele de courrier, s'il y en a
for file in local_retval:
local_JSON = ast.literal_eval(file)
saved_file = local_JSON['full_path']
file_to_attache_to_mail = MIMEBase('application', "octet-stream")
file_to_attache_to_mail.set_payload(open(saved_file, "rb").read())
encoders.encode_base64(file_to_attache_to_mail)
file_to_attache_to_mail.add_header('Content-Disposition',
'attachment; filename="{0}"'.format(os.path.basename(saved_file)))
new_node = {"attached_file": file_to_attache_to_mail}
tab_files_to_attache_to_mail.append(new_node)
# Recuperations des info de la session de formation
session_data = MYSY_GV.dbname['session_formation'].find_one(
{'_id': ObjectId(str(inscription_data['session_id'])), 'valide': '1',
'partner_owner_recid': str(my_partner['recid'])})
tab_session = []
tab_session.append(session_data['_id'])
# Recuperation du titre de la formation
class_data = MYSY_GV.dbname['myclass'].find_one(
{'internal_url': str(session_data['class_internal_url']), 'valide': '1',
'partner_owner_recid': str(my_partner['recid']), 'locked': '0'})
tab_class = []
tab_class.append(class_data['_id'])
# Creation du dictionnaire d'information à utiliser pour la creation du doc
convention_dictionnary_data = {}
new_diction = {}
new_diction['token'] = diction['token']
new_diction['list_stagiaire_id'] = tab_participant
new_diction['list_session_id'] = tab_session
new_diction['list_class_id'] = tab_class
new_diction['list_client_id'] = []
local_status, local_retval = mycommon.Get_Dictionnary_data_For_Template(new_diction)
if (local_status is False):
return local_status, local_retval
convention_dictionnary_data = local_retval
body = {
"params": convention_dictionnary_data,
}
# Verifier s'il s'agit d'un document à envoyer avec une version de pièce jointe.
if ("joint_pdf" in courrier_template_data.keys() and str(courrier_template_data['joint_pdf']) == "1"):
# Il s'agit bien d'un envoie avec 'contenu_doc' en pièce jointe PDF
"""
1 - Creation du PDF
"""
contenu_doc_Template = jinja2.Template(str(courrier_template_data['contenu_doc']))
sourceHtml = contenu_doc_Template.render(params=body["params"])
todays_date = str(date.today().strftime("%d/%m/%Y"))
ts = datetime.now().timestamp()
ts = str(ts).replace(".", "").replace(",", "")[-5:]
orig_file_name = "Convention_" + str(my_partner['recid']) + "_" + str(ts) + ".pdf"
outputFilename = str(MYSY_GV.TEMPORARY_DIRECTORY) + "/" + str(orig_file_name)
# open output file for writing (truncated binary)
resultFile = open(outputFilename, "w+b")
# convert HTML to PDF
pisaStatus = pisa.CreatePDF(
src=sourceHtml, # the HTML to convert
dest=resultFile) # file handle to receive result
# close output file
resultFile.close()
# Attachement du fichier joint
file_to_attache_to_mail = MIMEBase('application', "octet-stream")
file_to_attache_to_mail.set_payload(open(outputFilename, "rb").read())
encoders.encode_base64(file_to_attache_to_mail)
file_to_attache_to_mail.add_header('Content-Disposition',
'attachment; filename="{0}"'.format(os.path.basename(outputFilename)))
new_node = {"attached_file": file_to_attache_to_mail}
tab_files_to_attache_to_mail.append(new_node)
## Creation du mail au format email
corps_mail_Template = jinja2.Template(str(courrier_template_data['corps_mail']))
sourceHtml = corps_mail_Template.render(params=body["params"])
html_mime = MIMEText(sourceHtml, 'html')
# Creation de l'email à enoyer
msg = MIMEMultipart("alternative")
else:
# Il s'agit d'une simple email
## Creation du mail au format email
contenu_doc_Template = jinja2.Template(str(courrier_template_data['contenu_doc']))
sourceHtml = contenu_doc_Template.render(params=body["params"])
html_mime = MIMEText(sourceHtml, 'html')
# Creation de l'email à enoyer
msg = MIMEMultipart("alternative")
"""
Recuperation des parametre SMTP du partner si le client a decidé d'utiliser son propre smpt
"""
partner_own_smtp_value = "0"
partner_own_smtp = MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(my_partner['recid']),
'config_name': 'partner_smtp',
'valide': '1',
'locked': '0'})
if (partner_own_smtp and "config_value" in partner_own_smtp.keys()):
partner_own_smtp_value = partner_own_smtp['config_value']
if (str(partner_own_smtp_value) == "1"):
partner_SMTP_COUNT_password = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(my_partner['recid']),
'config_name': 'smtp_user_pwd',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_smtpsrv = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(my_partner['recid']),
'config_name': 'smtp_server',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_user = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(my_partner['recid']),
'config_name': 'smtp_user',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_From_User = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(my_partner['recid']),
'config_name': 'smtp_count_from_name',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_port = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(my_partner['recid']),
'config_name': 'smtp_count_port',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
if (str(partner_own_smtp_value) == "1"):
smtpserver = smtplib.SMTP(partner_SMTP_COUNT_smtpsrv, partner_SMTP_COUNT_port)
else:
smtpserver = smtplib.SMTP(MYSY_GV.O365_SMTP_COUNT_smtpsrv, MYSY_GV.O365_SMTP_COUNT_port)
if (str(partner_own_smtp_value) == "1"):
msg.attach(html_mime)
msg['From'] = partner_SMTP_COUNT_From_User
msg['Bcc'] = 'contact@mysy-training.com'
msg['Subject'] = courrier_template_data['sujet']
# msg['to'] = "billardman01@hotmail.com"
toaddrs = ", ".join(tab_emails_destinataire)
msg['to'] = str(toaddrs)
# Attacher l'eventuelle pièces jointes
for myfile in tab_files_to_attache_to_mail:
msg.attach(myfile['attached_file'])
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(partner_SMTP_COUNT_user, partner_SMTP_COUNT_password)
else:
msg.attach(html_mime)
msg['From'] = MYSY_GV.O365_SMTP_COUNT_From_User
msg['Bcc'] = 'contact@mysy-training.com'
msg['Subject'] = courrier_template_data['sujet']
# msg['to'] = "billardman01@hotmail.com"
toaddrs = ", ".join(tab_emails_destinataire)
msg['to'] = str(toaddrs)
for myfile in tab_files_to_attache_to_mail:
msg.attach(myfile['attached_file'])
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(MYSY_GV.O365_SMTP_COUNT_user, MYSY_GV.O365_SMTP_COUNT_password)
val = smtpserver.send_message(msg)
smtpserver.close()
print(" Email envoyé " + str(val))
"""
# Ajout de l'evenement dans l'historique
"""
# L'action n'est loggué pour les envois reels (en prod)
if (send_in_production == 1):
now = str(datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
history_event_dict = {}
history_event_dict['token'] = diction['token']
history_event_dict['related_collection'] = "inscription"
history_event_dict['related_collection_recid'] = str(diction['inscription_id'])
history_event_dict['action_date'] = str(now)
history_event_dict['action_description'] = "Convention envoyée par email à la liste : " + str(
tab_emails_destinataire)
local_status, local_retval = mycommon.Collection_Historique.Add_Historique_Event(history_event_dict)
if (local_status is False):
mycommon.myprint(
" WARNING : Impossible de logguer l'historique pour l'évènement : " + str(history_event_dict))
return True, "L'email a été correctement envoyé "
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 convention par email "
""" """
Cette fonction envoie les convention en masse Cette fonction envoie les convention en masse
Dans cette fonction, les adresse emails de destination sont recuperé dans la fonction. Dans cette fonction, les adresse emails de destination sont recuperé dans la fonction.
@ -7215,25 +7706,94 @@ def Download_Convention_Stagiaire_PDF(diction):
return False, " L'identifiant de l'inscription est invalide " return False, " L'identifiant de l'inscription est invalide "
# Verifier que le 'courrier_template_id' est valide. il doit etre de type PDF courrier_template_data = None
qry = {'_id': ObjectId(str(diction['courrier_template_id'])), if( str(diction['courrier_template_id']) == "default_pdf"):
'valide': '1', """
'locked': '0', # Verifier qu'il y a bien un modele de courrier de convention individuelle par defaut
'type_doc':'pdf', - ref_interne = CONVENTION_STAGIAIRE
'partner_owner_recid': str(my_partner['recid'])} - default_version = 1
- edit_by_client = '0' ou n'existe pas
- type_doc = pdf
"""
is_courrier_template_id_valide = MYSY_GV.dbname['courrier_template'].count_documents({"$or": [
{'valide': '1',
'locked': '0',
'type_doc': 'pdf',
'partner_owner_recid': str(my_partner['recid']),
'ref_interne': 'CONVENTION_STAGIAIRE',
'default_version': '1',
'edit_by_client': '0'
},
{'valide': '1',
'locked': '0',
'type_doc': 'pdf',
'partner_owner_recid': str(my_partner['recid']),
'ref_interne': 'CONVENTION_STAGIAIRE',
'default_version': '1',
'edit_by_client': {'$exists': False}
}
]})
is_courrier_template_id_valide = MYSY_GV.dbname['courrier_template'].count_documents( if (is_courrier_template_id_valide != 1):
{'_id': ObjectId(str(diction['courrier_template_id'])), mycommon.myprint(str(inspect.stack()[0][
'valide': '1', 3]) + " Aucun modèle de courrier PDF par defaut pour les conventions individuelles ")
'locked': '0', return False, " Aucun modèle de courrier PDF par defaut pour les conventions individuelles "
'type_doc': 'pdf',
'partner_owner_recid': str(my_partner['recid'])} # Recupération des données du modèle de document
courrier_template_data = MYSY_GV.dbname['courrier_template'].find_one({"$or": [
{'valide': '1',
'locked': '0',
'type_doc': 'pdf',
'partner_owner_recid': str(my_partner['recid']),
'ref_interne': 'CONVENTION_STAGIAIRE',
'default_version': '1',
'edit_by_client': '0'
},
{'valide': '1',
'locked': '0',
'type_doc': 'pdf',
'partner_owner_recid': str(my_partner['recid']),
'ref_interne': 'CONVENTION_STAGIAIRE',
'default_version': '1',
'edit_by_client': {'$exists': False}
}
]})
else:
# Verifier que le 'courrier_template_id' est valide. il doit etre de type PDF
qry = {'_id': ObjectId(str(diction['courrier_template_id'])),
'valide': '1',
'locked': '0',
'type_doc': 'pdf',
'partner_owner_recid': str(my_partner['recid'])}
is_courrier_template_id_valide = MYSY_GV.dbname['courrier_template'].count_documents(
{'_id': ObjectId(str(diction['courrier_template_id'])),
'valide': '1',
'locked': '0',
'type_doc': 'pdf',
'partner_owner_recid': str(my_partner['recid'])}
) )
if (is_courrier_template_id_valide != 1): if (is_courrier_template_id_valide != 1):
mycommon.myprint(str(inspect.stack()[0][3]) + " L'identifiant du modèle de courrier est invalide ") mycommon.myprint(str(inspect.stack()[0][3]) + " L'identifiant du modèle de courrier est invalide ")
return False, " L'identifiant du modèle de courrier est invalide " return False, " L'identifiant du modèle de courrier est invalide "
# Recupération des données du modèle de document
courrier_template_data = MYSY_GV.dbname['courrier_template'].find_one(
{'_id': ObjectId(str(diction['courrier_template_id'])),
'valide': '1',
'locked': '0',
'type_doc': 'pdf',
'partner_owner_recid': str(my_partner['recid'])}
)
if( courrier_template_data is None ):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " Impossile d'identifier le modèle de courrier ")
return False, " Impossile d'identifier le modèle de courrier "
# Recuperation des données du stagaire # Recuperation des données du stagaire
inscription_data = MYSY_GV.dbname['inscription'].find_one({'_id': ObjectId(str(diction['inscription_id'])), inscription_data = MYSY_GV.dbname['inscription'].find_one({'_id': ObjectId(str(diction['inscription_id'])),
@ -7247,13 +7807,6 @@ def Download_Convention_Stagiaire_PDF(diction):
company_data = local_retval company_data = local_retval
# Recupération des données du modèle de document
courrier_template_data = MYSY_GV.dbname['courrier_template'].find_one(
{'_id': ObjectId(str(diction['courrier_template_id'])),
'valide': '1',
'locked': '0',
'partner_owner_recid': str(my_partner['recid'])}
)
# Recuperations des info de la session de formation # Recuperations des info de la session de formation
tab_session = [] tab_session = []
@ -7346,6 +7899,240 @@ def Download_Convention_Stagiaire_PDF(diction):
return False, " Impossible de générer le fichier PDF (2) " return False, " Impossible de générer le fichier PDF (2) "
"""
Impression d'une convention individuelle en pdf
"""
def Download_Convention_Individuelle_Stagiaire_PDF(diction):
try:
field_list_obligatoire = ['token', 'inscription_id', 'courrier_template_id']
for val in field_list_obligatoire:
if val not in diction:
mycommon.myprint(
str(inspect.stack()[0][
3]) + " La valeur '" + val + "' n'est pas presente dans liste ")
return False, " La valeur '" + val + "' n'est pas presente dans liste"
my_token = ""
if ("token" in diction.keys()):
if diction['token']:
my_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
# Verifier que le stagiaire est bien inscrit. Le statut de l'inscription doit etre "1" et qu'il n'est pas rattaché à un client
is_inscription_valide = MYSY_GV.dbname['inscription'].count_documents({'$or':[
{'_id': ObjectId(str(diction['inscription_id'])),
'status': '1',
'partner_owner_recid': str(my_partner['recid']),
'client_rattachement_id':''},
{'_id': ObjectId(str(diction['inscription_id'])),
'status': '1',
'partner_owner_recid': str(my_partner['recid']),
'client_rattachement_id': {'$exists': False}
}]} )
if (is_inscription_valide != 1):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " L'identifiant de l'inscription est invalide ")
return False, " L'identifiant de l'inscription est invalide "
courrier_template_data = None
if( str(diction['courrier_template_id']) == "default_pdf"):
"""
# Verifier qu'il y a bien un modele de courrier de convention individuelle par defaut
- ref_interne = CONVENTION_STAGIAIRE
- default_version = 1
- edit_by_client = '0' ou n'existe pas
- type_doc = pdf
"""
is_courrier_template_id_valide = MYSY_GV.dbname['courrier_template'].count_documents({"$or": [
{'valide': '1',
'locked': '0',
'type_doc': 'pdf',
'partner_owner_recid': str(my_partner['recid']),
'ref_interne': 'CONVENTION_STAGIAIRE',
'default_version': '1',
'edit_by_client': '0'
},
{'valide': '1',
'locked': '0',
'type_doc': 'pdf',
'partner_owner_recid': str(my_partner['recid']),
'ref_interne': 'CONVENTION_STAGIAIRE',
'default_version': '1',
'edit_by_client': {'$exists': False}
}
]})
if (is_courrier_template_id_valide != 1):
mycommon.myprint(str(inspect.stack()[0][
3]) + " Aucun modèle de courrier PDF par defaut pour les conventions individuelles ")
return False, " Aucun modèle de courrier PDF par defaut pour les conventions individuelles "
# Recupération des données du modèle de document
courrier_template_data = MYSY_GV.dbname['courrier_template'].find_one({"$or": [
{'valide': '1',
'locked': '0',
'type_doc': 'pdf',
'partner_owner_recid': str(my_partner['recid']),
'ref_interne': 'CONVENTION_STAGIAIRE',
'default_version': '1',
'edit_by_client': '0'
},
{'valide': '1',
'locked': '0',
'type_doc': 'pdf',
'partner_owner_recid': str(my_partner['recid']),
'ref_interne': 'CONVENTION_STAGIAIRE',
'default_version': '1',
'edit_by_client': {'$exists': False}
}
]})
else:
# Verifier que le 'courrier_template_id' est valide. il doit etre de type PDF
qry = {'_id': ObjectId(str(diction['courrier_template_id'])),
'valide': '1',
'locked': '0',
'type_doc': 'pdf',
'partner_owner_recid': str(my_partner['recid'])}
is_courrier_template_id_valide = MYSY_GV.dbname['courrier_template'].count_documents(
{'_id': ObjectId(str(diction['courrier_template_id'])),
'valide': '1',
'locked': '0',
'type_doc': 'pdf',
'partner_owner_recid': str(my_partner['recid'])}
)
if (is_courrier_template_id_valide != 1):
mycommon.myprint(str(inspect.stack()[0][3]) + " L'identifiant du modèle de courrier est invalide ")
return False, " L'identifiant du modèle de courrier est invalide "
# Recupération des données du modèle de document
courrier_template_data = MYSY_GV.dbname['courrier_template'].find_one(
{'_id': ObjectId(str(diction['courrier_template_id'])),
'valide': '1',
'locked': '0',
'type_doc': 'pdf',
'partner_owner_recid': str(my_partner['recid'])}
)
if( courrier_template_data is None ):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " Impossile d'identifier le modèle de courrier ")
return False, " Impossile d'identifier le modèle de courrier "
# Recuperation des données du stagaire
inscription_data = MYSY_GV.dbname['inscription'].find_one({'_id': ObjectId(str(diction['inscription_id'])),
'status': '1',
'partner_owner_recid': str(my_partner['recid'])})
tab_participant = []
tab_participant.append(inscription_data['_id'])
# Recuperation des données du partenaire associé à l'utilisateur connecté
local_status, local_retval = mycommon.Get_Connected_User_Partner_Data_From_RecID(my_partner['recid'])
if (local_status is False):
return local_status, local_retval
company_data = local_retval
# Recuperations des info de la session de formation
tab_session = []
session_data = MYSY_GV.dbname['session_formation'].find_one(
{'_id': ObjectId(str(inscription_data['session_id'])), 'valide': '1',
'partner_owner_recid': str(my_partner['recid'])})
tab_session.append(session_data['_id'])
# Recuperation du titre de la formation
class_data = MYSY_GV.dbname['myclass'].find_one(
{'internal_url': str(session_data['class_internal_url']), 'valide': '1',
'partner_owner_recid': str(my_partner['recid']), 'locked': '0'})
tab_class = []
tab_class.append(class_data['_id'])
# Creation du dictionnaire d'information à utiliser pour la creation du doc
convention_dictionnary_data = {}
new_diction = {}
new_diction['token'] = diction['token']
new_diction['list_stagiaire_id'] = tab_participant
new_diction['list_session_id'] = tab_session
new_diction['list_class_id'] = tab_class
new_diction['list_client_id'] = []
local_status, local_retval = mycommon.Get_Dictionnary_data_For_Template(new_diction)
if (local_status is False):
return local_status, local_retval
convention_dictionnary_data = local_retval
#print(" ### convention_dictionnary_data = ", convention_dictionnary_data)
body = {
"params": convention_dictionnary_data,
}
json_formatted_str = json.dumps(body, indent=2)
#print(json_formatted_str)
## Creation du PDF
contenu_doc_Template = jinja2.Template(str(courrier_template_data['contenu_doc']))
sourceHtml = contenu_doc_Template.render(params=body["params"])
todays_date = str(date.today().strftime("%d/%m/%Y"))
ts = datetime.now().timestamp()
ts = str(ts).replace(".", "").replace(",", "")[-5:]
orig_file_name = "Convention_" + str(my_partner['recid']) + "_" + str(ts) + ".pdf"
outputFilename = str(MYSY_GV.TEMPORARY_DIRECTORY) + "/" + str(orig_file_name)
# open output file for writing (truncated binary)
resultFile = open(outputFilename, "w+b")
# convert HTML to PDF
pisaStatus = pisa.CreatePDF(
src=sourceHtml, # the HTML to convert
dest=resultFile) # file handle to receive result
# close output file
resultFile.close()
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 le fichier PDF (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 le fichier PDF (2) "
""" """
Pour les statgiaires rattaché à un client, edite les convetions pour le client Pour les statgiaires rattaché à un client, edite les convetions pour le client
donc avec la liste des participants donc avec la liste des participants
@ -7534,6 +8321,10 @@ def Download_Convention_Stagiaire_PDF_By_Partner_client(diction):
return False, " Impossible de générer le fichier PDF (2) " return False, " Impossible de générer le fichier PDF (2) "
""" """
Envoie par email pour les stagiaires rattachés à un client Envoie par email pour les stagiaires rattachés à un client

File diff suppressed because one or more lines are too long

View File

@ -4532,7 +4532,7 @@ def Prepare_and_Send_Convention_From_Session_By_PDF(diction):
with ZipFile(zip_file_name, 'w') as zip_object: with ZipFile(zip_file_name, 'w') as zip_object:
for pdf_files in list_file_name_to_zip : for pdf_files in list_file_name_to_zip :
print(" ### fichier a zipper = ", pdf_files) #print(" ### fichier a zipper = ", pdf_files)
zip_object.write(str(pdf_files)) zip_object.write(str(pdf_files))
@ -4820,7 +4820,7 @@ def Prepare_and_Send_Default_Convention_From_Session_By_PDF(diction):
local_diction['courrier_template_id'] = default_courrier_template_individuel_data['_id'] local_diction['courrier_template_id'] = default_courrier_template_individuel_data['_id']
local_diction['inscription_id'] = str(val['_id']) local_diction['inscription_id'] = str(val['_id'])
print(" #### Traitemnt de local_diction bb = ", local_diction) #print(" #### Traitemnt de local_diction bb = ", local_diction)
local_status, local_full_file_name = Create_Convention_By_Stagiaire_PDF(local_diction) local_status, local_full_file_name = Create_Convention_By_Stagiaire_PDF(local_diction)
if( local_status is False): if( local_status is False):
return local_status, local_full_file_name return local_status, local_full_file_name
@ -4836,7 +4836,7 @@ def Prepare_and_Send_Default_Convention_From_Session_By_PDF(diction):
with ZipFile(zip_file_name, 'w') as zip_object: with ZipFile(zip_file_name, 'w') as zip_object:
for pdf_files in list_file_name_to_zip : for pdf_files in list_file_name_to_zip :
print(" ### fichier a zipper = ", pdf_files) #print(" ### fichier a zipper = ", pdf_files)
zip_object.write(str(pdf_files)) zip_object.write(str(pdf_files))

View File

@ -100,6 +100,12 @@ def Add_Session_Sequence(diction):
return False, "L'identifiant de la session n'est pas valide " return False, "L'identifiant de la session n'est pas valide "
# Recuperation des données de la session
is_existe_valide_session_id_data = MYSY_GV.dbname["session_formation"].find_one(
{'_id': ObjectId(str(diction['session_id'])),
'partner_owner_recid': str(my_partner['recid']),
'valide': '1'})
# Verifier qu'il n'y a pas de chevauchement de date avec une autre sequence de la meme session. # Verifier qu'il n'y a pas de chevauchement de date avec une autre sequence de la meme session.
@ -193,6 +199,11 @@ def Add_Session_Sequence(diction):
MYSY_GV.dbname['session_formation_sequence'].insert_one(my_data) MYSY_GV.dbname['session_formation_sequence'].insert_one(my_data)
"""
"""
return True, " La séquence a été correctement ajoutée" return True, " La séquence a été correctement ajoutée"
except Exception as e: except Exception as e:

View File

@ -135,6 +135,10 @@ def Add_Update_Agenda_Event(diction):
event_type = str(diction['event_type']) event_type = str(diction['event_type'])
mydata['event_type'] = event_type mydata['event_type'] = event_type
justified = ""
if ("justified" in diction.keys()):
justified = str(diction['justified'])
mydata['justified'] = justified
if( len(str(diction['_id']).strip()) > 0): if( len(str(diction['_id']).strip()) > 0):
# Verifier si l'id de l'evenement existe # Verifier si l'id de l'evenement existe
@ -404,7 +408,6 @@ def get_Agenda_Event_List(diction):
'partner_owner_recid':str(my_partner['recid']), 'valide':'1', 'locked':'0'} 'partner_owner_recid':str(my_partner['recid']), 'valide':'1', 'locked':'0'}
print(" ### qry = ", qry)
for New_retVal in MYSY_GV.dbname['agenda'].find({'related_collection':str(diction['related_collection']), 'related_collection_recid':str(diction['related_collection_recid']), for New_retVal in MYSY_GV.dbname['agenda'].find({'related_collection':str(diction['related_collection']), 'related_collection_recid':str(diction['related_collection_recid']),
'partner_owner_recid':str(my_partner['recid']), 'valide':'1', 'locked':'0'}): 'partner_owner_recid':str(my_partner['recid']), 'valide':'1', 'locked':'0'}):

78
main.py
View File

@ -65,6 +65,8 @@ import base_config_modele_journee as base_config_modele_journee
import Dashbord_queries.session_tbd_qries as session_tbd_qries import Dashbord_queries.session_tbd_qries as session_tbd_qries
import Dashbord_queries.common_tdb_qries as common_tdb_qries import Dashbord_queries.common_tdb_qries as common_tdb_qries
import Dashbord_queries.formation_tbd_qries as formation_tbd_qries import Dashbord_queries.formation_tbd_qries as formation_tbd_qries
import Dashbord_queries.ressources_humaines_tbd_qries as ressources_humaines_tbd_qries
import Collection_Historique as Collection_Historique import Collection_Historique as Collection_Historique
import purchase_prices as purchase_prices import purchase_prices as purchase_prices
import apprenant_mgt as apprenant_mgt import apprenant_mgt as apprenant_mgt
@ -4250,7 +4252,28 @@ def Sent_Convention_Stagiaire_By_Email():
for tmp in request.files.getlist("File") : for tmp in request.files.getlist("File") :
tab_files.append(tmp) tab_files.append(tmp)
status, retval = inscription.Sent_Convention_Stagiaire_By_Email(tab_files, app.config['UPLOAD_FOLDER'], payload) status, retval = inscription.Sent_Convention_Stagiaire_By_Email(tab_files, MYSY_GV.TEMPORARY_DIRECTORY_V2, payload)
return jsonify(status=status, message=retval)
"""
API qui est un clone de l'api (Sent_Convention_Stagiaire_By_Email) a quelques details prets.
Cette separation est du à la complexité de la fonction et au souci de ne pas avoir d'effet de bord
"""
@app.route('/myclass/api/Sent_Convention_Individuelle_Stagiaire_By_Email/', methods=['POST','GET'])
@crossdomain(origin='*')
def Sent_Convention_Individuelle_Stagiaire_By_Email():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Sent_Convention_Individuelle_Stagiaire_By_Email payload = ",payload)
file = []
if request.method == 'POST':
# Create variable for uploaded file
tab_files = []
for tmp in request.files.getlist("File") :
tab_files.append(tmp)
status, retval = inscription.Sent_Convention_Individuelle_Stagiaire_By_Email(tab_files, MYSY_GV.TEMPORARY_DIRECTORY_V2, payload)
return jsonify(status=status, message=retval) return jsonify(status=status, message=retval)
@ -4299,6 +4322,28 @@ def Download_Convention_Stagiaire_PDF(token, inscription_id, courrier_template_i
return False return False
"""
API qui permet de telecharger la convention individuelle en mode PDF
"""
@app.route('/myclass/api/Download_Convention_Individuelle_Stagiaire_PDF/<token>/<inscription_id>/<courrier_template_id>', methods=['POST','GET'])
@crossdomain(origin='*')
def Download_Convention_Individuelle_Stagiaire_PDF(token, inscription_id, courrier_template_id):
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary(request.form.to_dict())
payload['token'] = str(token)
payload['inscription_id'] = str(inscription_id)
payload['courrier_template_id'] = str(courrier_template_id)
print(" ### Download_Convention_Individuelle_Stagiaire_PDF payload = ",payload)
status, retval = inscription.Download_Convention_Individuelle_Stagiaire_PDF(payload)
if (status):
return retval
else:
return False
""" """
Test teclechargement d'un zip Test teclechargement d'un zip
""" """
@ -6415,6 +6460,18 @@ def Get_Qery_Formation_By_Session_By_Periode_Export_CSV(token, user_dashbord_id)
return False return False
"""
API/ TBD / QERY / Ressources Humaines
"""
@app.route('/myclass/api/Get_Humain_Ressource_With_Planning/', methods=['POST','GET'])
@crossdomain(origin='*')
def Get_Humain_Ressource_With_Planning():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Get_Humain_Ressource_With_Planning payload = ",payload)
status, retval = ressources_humaines_tbd_qries.Get_Humain_Ressource_With_Planning(payload)
return jsonify(status=status, message=retval)
""" """
API qui permet d'ajouter une action dans l'historique des évènements d'une entité API qui permet d'ajouter une action dans l'historique des évènements d'une entité
@ -6778,6 +6835,25 @@ def Get_List_Fiche_Apprenant():
status, retval = apprenant_mgt.Get_List_Fiche_Apprenant(payload) status, retval = apprenant_mgt.Get_List_Fiche_Apprenant(payload)
return jsonify(status=status, message=retval) return jsonify(status=status, message=retval)
"""
API pour exporter en csv les donnes du tableau de bord : tbd_rh_01
"""
@app.route('/myclass/api/TBD_RH_01_Export_Dashbord_To_Csv/<token>/<user_dashbord_id>', methods=['POST','GET'])
@crossdomain(origin='*')
def TBD_RH_01_Export_Dashbord_To_Csv(token, user_dashbord_id):
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
payload = {}
payload['token'] = str(token)
payload['user_dashbord_id'] = str(user_dashbord_id)
print(" ### TBD_RH_01_Export_Dashbord_To_Csv payload = ",payload)
status, retval = ressources_humaines_tbd_qries.TBD_RH_01_Export_Dashbord_To_Csv(payload)
if(status ):
return retval
else:
return False

View File

@ -3058,7 +3058,7 @@ def GetAttendeeDetail_perSession(diction):
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 laa== ", local_Insc_retval) print(" ### local_Insc_retval laa== ", local_Insc_retval)
if( local_Insc_retval is None): if( local_Insc_retval is None):
myprint(str(inspect.stack()[0][3]) + " - Impossible de récupérer le recid du partenaire (2)") myprint(str(inspect.stack()[0][3]) + " - Impossible de récupérer le recid du partenaire (2)")
@ -3328,7 +3328,7 @@ def GetAttendeeDetail_perSession(diction):
if ('apprenant_collection' in local_Insc_retval.keys() and len( local_Insc_retval['apprenant_collection']) > 0): if ('apprenant_collection' in local_Insc_retval.keys() and len( local_Insc_retval['apprenant_collection']) > 0):
print(" ### apprenant_collection = ", str(local_Insc_retval['apprenant_collection'][0]) ) print(" ### apprenant_collection = ", str(local_Insc_retval['apprenant_collection'][0]) )
if ("civilite" in local_Insc_retval['apprenant_collection'][0].keys()): if ("civilite" in local_Insc_retval['apprenant_collection'][0].keys()):
my_retrun_dict['civilite'] = str(local_Insc_retval['apprenant_collection'][0]['ville']) my_retrun_dict['civilite'] = str(local_Insc_retval['apprenant_collection'][0]['civilite'])
else: else:
my_retrun_dict['civilite'] = "" my_retrun_dict['civilite'] = ""
@ -3476,6 +3476,7 @@ def GetAttendeeDetail_perSession(diction):
else: else:
my_retrun_dict['tuteur2_include_com'] = "" my_retrun_dict['tuteur2_include_com'] = ""
RetObject.append(JSONEncoder().encode(my_retrun_dict)) RetObject.append(JSONEncoder().encode(my_retrun_dict))
return True, RetObject return True, RetObject