07/04/2026 - 14h

Signed-off-by: Cherif <cbalde@mysy-training.com>
master_Elyos_FI
Cherif 2026-04-07 16:30:07 +02:00
parent 8258b97469
commit f31de6542d
7 changed files with 4049 additions and 33 deletions

View File

@ -4,19 +4,14 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="23/03/26 - 20h">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="04/04/26 - 20h">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Dashbord_queries/ressources_humaines_tbd_qries.py" beforeDir="false" afterPath="$PROJECT_DIR$/Dashbord_queries/ressources_humaines_tbd_qries.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/GlobalVariable.py" beforeDir="false" afterPath="$PROJECT_DIR$/GlobalVariable.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$/Session_Formation.py" beforeDir="false" afterPath="$PROJECT_DIR$/Session_Formation.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/agenda.py" beforeDir="false" afterPath="$PROJECT_DIR$/agenda.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apprenant_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/apprenant_mgt.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$/email_inscription_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/email_inscription_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/emargement.py" beforeDir="false" afterPath="$PROJECT_DIR$/emargement.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/partner_client.py" beforeDir="false" afterPath="$PROJECT_DIR$/partner_client.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/partners.py" beforeDir="false" afterPath="$PROJECT_DIR$/partners.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -460,7 +455,7 @@
<option name="project" value="LOCAL" />
<updated>1747251650255</updated>
</task>
<option name="localTasksCounter" value="557" />
<option name="localTasksCounter" value="558" />
<servers />
</component>
<component name="Vcs.Log.Tabs.Properties">
@ -502,7 +497,6 @@
</option>
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="12/02/26 - 10h30" />
<MESSAGE value="15/02/26 - 18h30" />
<MESSAGE value="16/02/26 - 18h30" />
<MESSAGE value="18/02/2026 - 18h" />
@ -527,6 +521,7 @@
<MESSAGE value="25/03/2026 - 20h" />
<MESSAGE value="26/03/2026 - 12h" />
<MESSAGE value="23/03/26 - 20h" />
<option name="LAST_COMMIT_MESSAGE" value="23/03/26 - 20h" />
<MESSAGE value="04/04/26 - 20h" />
<option name="LAST_COMMIT_MESSAGE" value="04/04/26 - 20h" />
</component>
</project>

View File

@ -8079,6 +8079,11 @@ def AcceptAttendeeInscription(diction):
email_data['token'] = str(diction['token'])
email_data['class_inscription_directe'] = class_inscription_directe
if ("_id" in local_session.keys()):
email_data['session_id'] = str(local_session['_id'])
else:
email_data['session_id'] = ""
if( "code_session" in local_session.keys()):
email_data['code_session'] = local_session['code_session']
@ -8090,15 +8095,29 @@ def AcceptAttendeeInscription(diction):
else:
email_data['date_debut'] = ""
if ("distantiel" in local_session.keys()):
email_data['distantiel'] = local_session['distantiel']
else:
email_data['distantiel'] = ""
session_presentiel = ""
session_distantiel = ""
session_hybrid = ""
if ("mode_animation" in local_session.keys() and local_session['mode_animation']):
if (str(local_session['mode_animation']) == "1"):
session_presentiel = ""
session_distantiel = "1"
session_hybrid = ""
elif (str(local_session['mode_animation']) == "2"):
session_presentiel = ""
session_distantiel = ""
session_hybrid = "1"
elif (str(local_session['mode_animation']) == "0"):
session_presentiel = "1"
session_distantiel = ""
session_hybrid = ""
email_data['distantiel'] = str(session_distantiel)
email_data['presentiel'] = str(session_presentiel)
email_data['hybrid'] = str(session_hybrid)
if ("presentiel" in local_session.keys()):
email_data['presentiel'] = local_session['presentiel']
else:
email_data['presentiel'] = ""
if ("session_ondemande" in local_session.keys()):
email_data['session_ondemande'] = local_session['session_ondemande']
@ -17040,7 +17059,7 @@ def Create_Emargement_Send_Email_From_Inscription(diction):
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(partner_SMTP_COUNT_user, partner_SMTP_COUNT_password)
else:
smtpserver = smtplib.SMTP(MYSY_GV.O365_SMTP_COUNT_smtpsrv, MYSY_GV.O365_SMTP_COUNT_port)
@ -17335,9 +17354,688 @@ def Create_Emargement_QR_Code_From_Inscription(diction):
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de créer le QR code "
"""
06/04/2026
Cette fonction permet d'initialiser le tableau d'émargement
et de créer le QR Code dans la foulée.
Ainsi au lieu de faire le process en 2 étapes, il sera fait en 1 étapes.
La fonction prends en argument la sequence_id, la durée de vie du QR code
(xxx minute apres la fin de la sequence. Si xxx < 0, alors pas de durée
ou durée = toujours)
"""
def Init_Emargement_And_Create_QR_Code_From_Inscription(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'session_id', 'tab_sequence_ids', 'qr_time_valide' ]
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', 'session_id', 'tab_sequence_ids', ]
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 la liste des arguments ")
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
qr_time_valide = -1
if( "qr_time_valide" in diction.keys() and diction['qr_time_valide'] ):
Isfloat_status, Isfloat_retval = mycommon.IsFloat(str(diction['qr_time_valide']))
if (Isfloat_status is False):
mycommon.myprint(
str(inspect.stack()[0][3]) + " Le temps de validité de l'émargement est incorrecte ")
return False, " Le temps de validité de l'émargement est incorrecte "
qr_time_valide = round(float(Isfloat_retval), 2)
# Verifier que la session est valide
is_session_id_valide = MYSY_GV.dbname['session_formation'].count_documents(
{'_id': ObjectId(str(diction['session_id'])),
'valide': '1',
'partner_owner_recid': str(my_partner['recid'])})
if (is_session_id_valide != 1):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " L'identifiant de la session est invalide ")
return False, " L'identifiant de la session est invalide "
# Verifier que les sequences sont valides
tab_sequence_ids = []
tab_sequence_ids_ObjectId = []
tab_sequence_ids_work = str(diction['tab_sequence_ids']).split(",")
for local_sequence in tab_sequence_ids_work:
if(local_sequence ):
is_valide_sequence = MYSY_GV.dbname['session_formation_sequence'].count_documents({'_id':ObjectId(str(local_sequence)),
'session_id':str(diction['session_id']),
'partner_owner_recid':str(my_partner['recid']),
'valide':'1',
'locked':'0'})
if( is_valide_sequence != 1):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " L'identifiant de la séquence "+str(local_sequence)+" est invalide ")
return False, "L'identifiant de la séquence "+str(local_sequence)+" est invalide "
tab_sequence_ids.append(str(local_sequence))
tab_sequence_ids_ObjectId.append(ObjectId(str(local_sequence)))
tab_my_emargement_ids = []
# Creation d'une clé securisé
my_safe_token = mycommon.create_user_recid()
now_v2 = str(datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
for local_sequence_id in tab_sequence_ids:
local_sequence_data = MYSY_GV.dbname['session_formation_sequence'].find_one({'_id':ObjectId(str(local_sequence_id)),
'partner_owner_recid': str(my_partner['recid']),
'valide':'1',
'locked':'0' })
"""
Récuperer la liste inscrit (groupe d'etudiant associé)
"""
tab_grp_apprenant_ids = []
if ("tab_grp_apprenant_ids" in local_sequence_data.keys()):
for local_tab_grp_apprenant_ids in local_sequence_data['tab_grp_apprenant_ids']:
tab_grp_apprenant_ids.append(str(local_tab_grp_apprenant_ids['_id']))
"""
Pour chaque inscrit appartenant à tab_grp_apprenant_ids
"""
now = str(datetime.now())
for local_inscrit in MYSY_GV.dbname['groupe_inscription_membre'].find({'groupe_inscription_id':{'$in':tab_grp_apprenant_ids},
'partner_owner_recid': str(my_partner['recid']),
'valide': '1',
'locked': '0'
}):
for tmp_val in MYSY_GV.dbname['inscription'].find({"$and": [{'session_id': str(diction['session_id']),
'status': '1',
'partner_owner_recid': str(my_partner['recid'])},
{'_id': ObjectId(local_inscrit['inscription_id'])}
]}):
query_key = {}
query_key['inscription_id'] = str(tmp_val['_id'])
query_key['session_id'] = tmp_val['session_id']
query_key['class_internal_url'] = tmp_val['class_internal_url']
query_key['session_formation_sequence_id'] = str(local_sequence_data['_id'])
new_my_local_data = {}
new_my_local_data['session_formation_sequence_id'] = str(local_sequence_data['_id'])
new_my_local_data['inscription_id'] = str(tmp_val['_id'])
new_my_local_data['email'] = tmp_val['email']
new_my_local_data['nom'] = tmp_val['nom']
new_my_local_data['prenom'] = tmp_val['prenom']
new_my_local_data['session_id'] = tmp_val['session_id']
new_my_local_data['class_internal_url'] = tmp_val['class_internal_url']
new_my_local_data['sequence_start'] = str(local_sequence_data['sequence_start'])
new_my_local_data['sequence_end'] = str(local_sequence_data['sequence_end'])
new_my_local_data['qr_time_valide'] = str(qr_time_valide)
new_my_local_data['update_date'] = now
query_key['date'] = str(local_sequence_data['sequence_start'])[0:10]
new_my_local_data['is_present'] = False
new_my_local_data['matin'] = False
new_my_local_data['apresmidi'] = False
new_my_local_data['sequence_title'] = str(local_sequence_data['sequence_title'])
if ("volume_theorique" in local_sequence_data.keys() and local_sequence_data['volume_theorique']):
new_my_local_data['time_in_hour'] = str(local_sequence_data['volume_theorique'])
else:
if ("time_in_hour" in local_sequence_data.keys()):
new_my_local_data['time_in_hour'] = local_sequence_data['time_in_hour']
else:
delta_time = datetime.strptime(str(local_sequence_data['sequence_end']),
'%d/%m/%Y %H:%M') - datetime.strptime(
str(local_sequence_data['sequence_start']), '%d/%m/%Y %H:%M')
delta_time_converted_in_hour = round(float(delta_time.total_seconds() / 3600), 2)
new_my_local_data['time_in_hour'] = str(delta_time_converted_in_hour)
new_my_local_data['statut'] = "1"
new_my_local_data['date_envoi'] = str(now_v2)
new_my_local_data['update_date'] = str(datetime.now())
new_my_local_data['update_by'] = str(my_partner['recid'])
new_my_local_data['valide'] = "1"
new_my_local_data['locked'] = "0"
new_my_local_data['partner_owner_recid'] = str(my_partner['recid'])
new_my_local_data['emargement_qr_safe_token'] = str(my_safe_token)
new_my_local_data['date_dernier_relance_auto'] = str(datetime.now().strftime("%d/%m/%Y")),
new_my_local_data['mode_envoi'] = "qr"
# print("### emargement insertion de : "+str(new_my_local_data))
local_ret_val = MYSY_GV.dbname['emargement'].find_one_and_update(
query_key,
{"$set": new_my_local_data},
upsert=True,
return_document=ReturnDocument.AFTER
)
if( local_ret_val and '_id' in local_ret_val.keys()):
tab_my_emargement_ids.append(str(local_ret_val['_id']))
"""
Mettre à jour l'inscription avec la , et on met le statut à "1" pour dire qu'on a demarré le process
"""
now = str(datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
url_for_qr_code = str(MYSY_GV.CLIENT_URL_BASE)+"qr_emargement/"+str(diction['session_id'])+"/"+str(my_partner['recid'])+"/"+str(my_safe_token)+"/"
ts = datetime.now().timestamp()
ts = str(ts).replace(".", "").replace(",", "")[-3:]
qr_code_img_file = str(MYSY_GV.TEMPORARY_DIRECTORY_V2) + "qr_code_" + str(ts) + ".png"
qrcode = segno.make_qr(str(url_for_qr_code))
qrcode.save(
qr_code_img_file,
scale=5,
dark="darkblue",
)
print(" ### Create_Emargement_QR_Code_From_Inscription url_for_qr_code = ", url_for_qr_code)
"""
25/01/2024 : Apres l'envoi de la demande
d'emargement, on log une action dans la collection ==> courrier_template_tracking_history
"""
for my_emargement_id in tab_my_emargement_ids:
val_emarge = MYSY_GV.dbname['emargement'].find_one({'_id':ObjectId(str(my_emargement_id)), 'valide':'1', 'locked':'0',
'partner_owner_recid':my_partner['recid']})
local_status, local_retval = module_editique.Editic_Log_History_Action_From_courrier_template_type_document_ref_interne(
my_partner, "EMARGEMENT_FORMATION", str(val_emarge['session_id']), "inscription", str(val_emarge['inscription_id']),
"")
"""
On met à jour la séquence pour dire quand est ce qu'on a lancé
le dernier emargement -
"""
MYSY_GV.dbname['session_formation_sequence'].update_many({'_id':{'$in':tab_sequence_ids_ObjectId},
'partner_owner_recid':my_partner['recid']},
{'$set':{'last_emargement_request_date':now}})
if os.path.exists(qr_code_img_file):
return True, send_file(qr_code_img_file, as_attachment=True)
return False, " Impossible de générer l'émargement par QR Code (1) "
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'émargement par QR Code "
"""
06/04/2026
Cette fonction permet d'initialiser le tableau d'émargement
et d'envoyer l'email dans la foulée.
Ainsi au lieu de faire le process en 2 étapes, il sera fait en 1 étapes.
La fonction prends en argument la sequence_id, la durée de vie du QR code
(xxx minute apres la fin de la sequence. Si xxx < 0, alors pas de durée
ou durée = toujours)
"""
def Init_Emargement_And_Send_Email_Code_From_Inscription(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'session_id', 'tab_sequence_ids', 'qr_time_valide' ]
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', 'session_id', 'tab_sequence_ids', ]
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 la liste des arguments ")
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 du modèle de courrier pour la demande d'emargement
"""
local_diction = {}
local_diction['ref_interne'] = "EMARGEMENT_FORMATION"
local_diction['type_doc'] = "email"
local_diction['partner_owner_recid'] = str(my_partner['recid'])
courrier_data_status, courrier_data_retval = mycommon.Get_Courrier_Template_Include_Default_Data(local_diction)
if (courrier_data_status is False):
return courrier_data_status, courrier_data_retval
# Recuperation des donnes smtp
local_stpm_status, partner_SMTP_COUNT_smtpsrv, partner_own_smtp_value, partner_SMTP_COUNT_password, partner_SMTP_COUNT_user, partner_SMTP_COUNT_From_User, partner_SMTP_COUNT_port = mycommon.Get_Partner_SMTP_Param(
my_partner['recid'])
if (local_stpm_status is False):
return local_stpm_status, partner_SMTP_COUNT_smtpsrv
qr_time_valide = -1
if( "qr_time_valide" in diction.keys() and diction['qr_time_valide'] ):
Isfloat_status, Isfloat_retval = mycommon.IsFloat(str(diction['qr_time_valide']))
if (Isfloat_status is False):
mycommon.myprint(
str(inspect.stack()[0][3]) + " Le temps de validité de l'émargement est incorrecte ")
return False, " Le temps de validité de l'émargement est incorrecte "
qr_time_valide = round(float(Isfloat_retval), 2)
# Verifier que la session est valide
is_session_id_valide = MYSY_GV.dbname['session_formation'].count_documents(
{'_id': ObjectId(str(diction['session_id'])),
'valide': '1',
'partner_owner_recid': str(my_partner['recid'])})
if (is_session_id_valide != 1):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " L'identifiant de la session est invalide ")
return False, " L'identifiant de la session est invalide "
# Verifier que les sequences sont valides
tab_sequence_ids = []
tab_sequence_ids_ObjectId = []
tab_sequence_ids_work = str(diction['tab_sequence_ids']).split(",")
for local_sequence in tab_sequence_ids_work:
if(local_sequence ):
is_valide_sequence = MYSY_GV.dbname['session_formation_sequence'].count_documents({'_id':ObjectId(str(local_sequence)),
'session_id':str(diction['session_id']),
'partner_owner_recid':str(my_partner['recid']),
'valide':'1',
'locked':'0'})
if( is_valide_sequence != 1):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " L'identifiant de la séquence "+str(local_sequence)+" est invalide ")
return False, "L'identifiant de la séquence "+str(local_sequence)+" est invalide "
tab_sequence_ids.append(str(local_sequence))
tab_sequence_ids_ObjectId.append(ObjectId(str(local_sequence)))
tab_my_emargement_ids = []
# Creation d'une clé securisé
my_safe_token = mycommon.create_user_recid()
now_v2 = str(datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
for local_sequence_id in tab_sequence_ids:
local_sequence_data = MYSY_GV.dbname['session_formation_sequence'].find_one({'_id':ObjectId(str(local_sequence_id)),
'partner_owner_recid': str(my_partner['recid']),
'valide':'1',
'locked':'0' })
"""
Récuperer la liste inscrit (groupe d'etudiant associé)
"""
tab_grp_apprenant_ids = []
if ("tab_grp_apprenant_ids" in local_sequence_data.keys()):
for local_tab_grp_apprenant_ids in local_sequence_data['tab_grp_apprenant_ids']:
tab_grp_apprenant_ids.append(str(local_tab_grp_apprenant_ids['_id']))
"""
Pour chaque inscrit appartenant à tab_grp_apprenant_ids
"""
now = str(datetime.now())
for local_inscrit in MYSY_GV.dbname['groupe_inscription_membre'].find({'groupe_inscription_id':{'$in':tab_grp_apprenant_ids},
'partner_owner_recid': str(my_partner['recid']),
'valide': '1',
'locked': '0'
}):
for tmp_val in MYSY_GV.dbname['inscription'].find({"$and": [{'session_id': str(diction['session_id']),
'status': '1',
'partner_owner_recid': str(my_partner['recid'])},
{'_id': ObjectId(local_inscrit['inscription_id'])}
]}):
query_key = {}
query_key['inscription_id'] = str(tmp_val['_id'])
query_key['session_id'] = tmp_val['session_id']
query_key['class_internal_url'] = tmp_val['class_internal_url']
query_key['session_formation_sequence_id'] = str(local_sequence_data['_id'])
new_my_local_data = {}
new_my_local_data['session_formation_sequence_id'] = str(local_sequence_data['_id'])
new_my_local_data['inscription_id'] = str(tmp_val['_id'])
new_my_local_data['email'] = tmp_val['email']
new_my_local_data['nom'] = tmp_val['nom']
new_my_local_data['prenom'] = tmp_val['prenom']
new_my_local_data['session_id'] = tmp_val['session_id']
new_my_local_data['class_internal_url'] = tmp_val['class_internal_url']
new_my_local_data['sequence_start'] = str(local_sequence_data['sequence_start'])
new_my_local_data['sequence_end'] = str(local_sequence_data['sequence_end'])
new_my_local_data['qr_time_valide'] = str(qr_time_valide)
new_my_local_data['update_date'] = now
query_key['date'] = str(local_sequence_data['sequence_start'])[0:10]
new_my_local_data['is_present'] = False
new_my_local_data['matin'] = False
new_my_local_data['apresmidi'] = False
new_my_local_data['sequence_title'] = str(local_sequence_data['sequence_title'])
if ("volume_theorique" in local_sequence_data.keys() and local_sequence_data['volume_theorique']):
new_my_local_data['time_in_hour'] = str(local_sequence_data['volume_theorique'])
else:
if ("time_in_hour" in local_sequence_data.keys()):
new_my_local_data['time_in_hour'] = local_sequence_data['time_in_hour']
else:
delta_time = datetime.strptime(str(local_sequence_data['sequence_end']),
'%d/%m/%Y %H:%M') - datetime.strptime(
str(local_sequence_data['sequence_start']), '%d/%m/%Y %H:%M')
delta_time_converted_in_hour = round(float(delta_time.total_seconds() / 3600), 2)
new_my_local_data['time_in_hour'] = str(delta_time_converted_in_hour)
new_my_local_data['statut'] = "1"
new_my_local_data['date_envoi'] = str(now_v2)
new_my_local_data['update_date'] = str(datetime.now())
new_my_local_data['update_by'] = str(my_partner['recid'])
new_my_local_data['valide'] = "1"
new_my_local_data['locked'] = "0"
new_my_local_data['partner_owner_recid'] = str(my_partner['recid'])
new_my_local_data['emargement_qr_safe_token'] = str(my_safe_token)
new_my_local_data['date_dernier_relance_auto'] = str(datetime.now().strftime("%d/%m/%Y")),
new_my_local_data['mode_envoi'] = "qr"
# print("### emargement insertion de : "+str(new_my_local_data))
local_ret_val = MYSY_GV.dbname['emargement'].find_one_and_update(
query_key,
{"$set": new_my_local_data},
upsert=True,
return_document=ReturnDocument.AFTER
)
if( local_ret_val and '_id' in local_ret_val.keys()):
tab_my_emargement_ids.append(str(local_ret_val['_id']))
"""
Mettre à jour l'inscription avec la , et on met le statut à "1" pour dire qu'on a demarré le process
"""
now = str(datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
url_for_qr_code = str(MYSY_GV.CLIENT_URL_BASE)+"qr_emargement/"+str(diction['session_id'])+"/"+str(my_partner['recid'])+"/"+str(my_safe_token)+"/"
ts = datetime.now().timestamp()
ts = str(ts).replace(".", "").replace(",", "")[-3:]
qr_code_img_file = str(MYSY_GV.TEMPORARY_DIRECTORY_V2) + "qr_code_" + str(ts) + ".png"
qrcode = segno.make_qr(str(url_for_qr_code))
qrcode.save(
qr_code_img_file,
scale=5,
dark="darkblue",
)
print(" ### Create_Emargement_QR_Code_From_Inscription url_for_qr_code = ", url_for_qr_code)
"""
25/01/2024 : Apres l'envoi de la demande
d'emargement, on log une action dans la collection ==> courrier_template_tracking_history
"""
"""
Debut de la procedure d'envoie de l'email
"""
convention_dictionnary_data = {}
new_diction = {}
new_diction['token'] = diction['token']
new_diction['list_stagiaire_id'] = []
new_diction['list_session_id'] = [ObjectId(str(diction['session_id']))]
new_diction['list_class_id'] = []
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
if ("company_data" in local_retval.keys() and "societe_nom" in local_retval['company_data'].keys()):
company_name = local_retval['company_data']['societe_nom']
emargement_dictionnary_data = local_retval
emargement_dictionnary_data['mysyurl'] = url_for_qr_code
smtpserver = None
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)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(partner_SMTP_COUNT_user, partner_SMTP_COUNT_password)
tab_inscription_id_emargement_send = []
cpt_email_envoye = 0
for my_emargement_id in tab_my_emargement_ids:
my_emargement_data = MYSY_GV.dbname['emargement'].find_one({'_id':ObjectId(str(my_emargement_id)), 'valide':'1', 'locked':'0',
'partner_owner_recid':my_partner['recid']})
local_status, local_retval = module_editique.Editic_Log_History_Action_From_courrier_template_type_document_ref_interne(
my_partner, "EMARGEMENT_FORMATION", str(my_emargement_data['session_id']), "inscription", str(my_emargement_data['inscription_id']),
"")
if (str(my_emargement_data['inscription_id']) not in tab_inscription_id_emargement_send):
tab_inscription_id_emargement_send.append(str(my_emargement_data['inscription_id']))
cpt_email_envoye = cpt_email_envoye + 1
# Recuperation des données de l'inscrit
local_inscrit_data = mycommon.Get_Inscrit_And_Apprenant_Data(
{'token': str(diction['token']), 'inscrit_id': str(my_emargement_data['inscription_id'])})
emargement_dictionnary_data['emargement_inscrit_data'] = local_inscrit_data
# Recuperation des données de la formation
myclass_data = MYSY_GV.dbname['myclass'].find_one(
{'internal_url': str(my_emargement_data['class_internal_url']),
'partner_owner_recid': my_partner['recid']}, {'title': 1})
emargement_dictionnary_data['emargement_class_data'] = myclass_data
emargement_dictionnary_data['emargement_data'] = my_emargement_data
body = {
"params": emargement_dictionnary_data,
}
# print( " ### emargement_dictionnary_data ===== ", emargement_dictionnary_data)
# Traitement du sujet du mail
sujet_mail_Template = jinja2.Template(str(courrier_data_retval['sujet']))
sujetHtml = sujet_mail_Template.render(params=body["params"])
# Traitement du corps du mail
contenu_doc_Template = jinja2.Template(str(courrier_data_retval['contenu_doc']))
sourceHtml = contenu_doc_Template.render(params=body["params"])
html_mime = MIMEText(sourceHtml, 'html')
# Creation de l'email à enoyer
msg = MIMEMultipart("alternative")
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'] = sujetHtml
msg['to'] = str(my_emargement_data['email'])
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(partner_SMTP_COUNT_user, partner_SMTP_COUNT_password)
val = smtpserver.send_message(msg)
#print(" Email demande emargement envoyé " + str(val))
else:
msg.attach(html_mime)
# msg['From'] = MYSY_GV.O365_SMTP_COUNT_From_User
if (company_name):
msg['From'] = str(company_name) + " <" + str(MYSY_GV.O365_SMTP_COUNT_From_User) + ">"
else:
msg['From'] = str(MYSY_GV.O365_SMTP_COUNT_From_User)
msg['Bcc'] = 'contact@mysy-training.com'
msg['Subject'] = sujetHtml
msg['to'] = str(my_emargement_data['email'])
val = smtpserver.send_message(msg)
#print(" Email demande emargement envoyé " + str(val))
"""
Gestion des emails via mail_queu et internal email
"""
tab_email_bcc = []
tab_email_bcc.append("contact@mysy-training.com")
"""
IMPORTANT : Cette section sera utilisée une fois que le module de Queu de message est ok
"""
queue_mail_diction = {}
queue_mail_diction['token'] = diction['token']
queue_mail_diction['tab_email_cc'] = []
queue_mail_diction['tab_email_bcc'] = tab_email_bcc
if (sujetHtml):
queue_mail_diction['email_sujet'] = sujetHtml
else:
queue_mail_diction['email_sujet'] = "[MySy Training]: Demande d'émargement"
queue_mail_diction['message'] = sourceHtml
queue_mail_diction['smtp_account_password'] = partner_SMTP_COUNT_password
queue_mail_diction['smtp_account_smtpsrv'] = partner_SMTP_COUNT_smtpsrv
queue_mail_diction['smtp_account_user'] = partner_SMTP_COUNT_user
queue_mail_diction['smtp_account_From_User'] = partner_SMTP_COUNT_From_User
queue_mail_diction['smtp_account_port'] = partner_SMTP_COUNT_port
queue_mail_diction['tab_files_to_attache_to_mail'] = []
queue_mail_diction['email_to'] = str(my_emargement_data['email'])
queue_and_internal_mail_status, queue_and_internal_mail_status = email_mgt.Individual_Mail_Store_Queu_And_Internal_Mail(
queue_mail_diction)
if (queue_and_internal_mail_status is False):
print(" ## WARNING queue_mail_retval = ", queue_and_internal_mail_status)
smtpserver.close()
print(" NB_email envoyé = ", cpt_email_envoye)
"""
On met à jour la séquence pour dire quand est ce qu'on a lancé
le dernier emargement -
"""
MYSY_GV.dbname['session_formation_sequence'].update_many({'_id':{'$in':tab_sequence_ids_ObjectId},
'partner_owner_recid':my_partner['recid']},
{'$set':{'last_emargement_request_date':now}})
return True, str(cpt_email_envoye)+" Email(s) d'émargement envoyé(s) "
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'émargement par email "
"""
Verifier qu'un QR code est valide avec le mail de la personne.
C'est le controle qui est fait avant acces à l'emargemnt
07/06/26 - avec le champs 'qr_time_valide', il va etre possible de gérer
la durée de validité d'un QR code.
regle :
si qr_time_valide < 0 ==> Valide pour toujours
si qr_time_valide >= 0 (miniute), on compare avec la colonne 'sequence_end'
"""
def Check_Emargement_QR_Code_From_Inscription_No_Token(diction):
@ -17378,9 +18076,11 @@ def Check_Emargement_QR_Code_From_Inscription_No_Token(diction):
return local_status, my_partner
# Verifier que les info sont valide
is_emargement_valide_count = MYSY_GV.dbname['emargement'].count_documents({'session_id': str(diction['session_id']),
'emargement_qr_safe_token': str(diction['my_safe_token']),
'email': str( diction['user_email']),
'email': str(diction['user_email']).lower().strip(),
'partner_owner_recid': str(diction['partner_owner_recid']),
'statut': '1'})
@ -17395,7 +18095,7 @@ def Check_Emargement_QR_Code_From_Inscription_No_Token(diction):
for retval in MYSY_GV.dbname['emargement'].find(
{'session_id': str(diction['session_id']),
'emargement_qr_safe_token': str(diction['my_safe_token']),
'email': str(diction['user_email']),
'email': str(diction['user_email']).lower().strip(),
'partner_owner_recid': str(diction['partner_owner_recid']),
'statut': '1'}):
@ -17407,6 +18107,29 @@ def Check_Emargement_QR_Code_From_Inscription_No_Token(diction):
class_interna_url = ""
class_title = ""
sequence_title = ""
qr_time_valide = "-1"
"""
07/04/26 - gestion de la durée de validité du QR code
"""
if( "qr_time_valide" in retval.keys() and retval['qr_time_valide'] and "sequence_end" in retval.keys() and retval['sequence_end']):
qr_time_valide = mycommon.tryFloat(str(retval['qr_time_valide']))
print(" ### qr_time_valide = ", str(qr_time_valide))
if( qr_time_valide >= 0 ):
today_date_heure_minute = datetime.now().strftime("%d/%m/%Y %H:%M")
limite_validite_qr_code = datetime.strptime(str(retval['sequence_end']).strip(), '%d/%m/%Y %H:%M')+ timedelta(minutes=qr_time_valide)
"""print(" ### CONTROLE LIMITE VALIDITE ")
print(" ### today_date_heure_minute = ", str(today_date_heure_minute))
print(" ### qr_time_valide = ", str(qr_time_valide))
print(" ### Fin Sequence = ", str(retval['sequence_end']))
print(" ### limite_validite_qr_code = ", str(limite_validite_qr_code.strftime("%d/%m/%Y %H:%M")))"""
if( today_date_heure_minute < limite_validite_qr_code.strftime("%d/%m/%Y %H:%M")):
mycommon.myprint(
str(inspect.stack()[0][3]) + " Oups, ce QR code nest plus valide 😅, Contactez le gestionnaire pour en obtenir un nouveau. ")
return False, "Oups, ce QR code nest plus valide 😅, Contactez le gestionnaire pour en obtenir un nouveau. "
if( "session_formation_sequence_id" in retval.keys() ):
session_formation_sequence_data = MYSY_GV.dbname['session_formation_sequence'].find_one({'_id':ObjectId(str(retval['session_formation_sequence_id'])),

File diff suppressed because it is too large Load Diff

View File

@ -1718,7 +1718,7 @@ def Update_Session_Sequence(diction):
"""
if( new_unite_enseignement_planif_id != old_unite_enseignement_planif_id ):
if( new_unite_enseignement_planif_id and new_unite_enseignement_planif_id != old_unite_enseignement_planif_id ):
# Deprogrammation de l'ancien
update_data = {}
update_data['update_date'] = str(datetime.now())

View File

@ -55,7 +55,7 @@ def incription_training_confirmation_mail(diction):
"""
Verification de la liste des champs obligatoires
"""
field_list_obligatoire = ['nom', 'prenom', 'email', 'title']
field_list_obligatoire = ['nom', 'prenom', 'email', 'title', ]
for val in field_list_obligatoire:
if val not in diction:
mycommon.myprint(
@ -69,6 +69,8 @@ def incription_training_confirmation_mail(diction):
print("debut envoi mail de test ")
"""
Verification si c'est une formation en ligne.
auquel cas, l'adresse est du type : enligne"""
@ -122,6 +124,11 @@ def incription_training_confirmation_mail(diction):
if diction['presentiel']:
local_presentiel = diction['presentiel']
local_hybrid = ""
if ("hybrid" in diction.keys()):
if diction['hybrid']:
local_hybrid = diction['hybrid']
local_formateur = ""
if ("formateur" in diction.keys()):
if diction['formateur']:
@ -200,6 +207,7 @@ def incription_training_confirmation_mail(diction):
"ville": str(local_ville),
"distantiel": str(local_distantiel),
"presentiel": str(local_presentiel),
"hybrid": str(local_hybrid),
"formateur": str(local_formateur),
"session_ondemande": str(session_ondemande),
"mode_animation_detail_organisation": str(mode_animation_detail_organisation),
@ -210,7 +218,7 @@ def incription_training_confirmation_mail(diction):
},
}
#print(" ### BODY DATA = ", body)
print(" ### BODY DATA = ", body)
#sourceHtml = template.render(params=body["params"])
@ -1119,6 +1127,8 @@ def Pre_incription_training_confirmation_mail(diction):
},
}
sourceHtml = template.render(params=body["params"])
msg.set_content(sourceHtml, subtype='html')

View File

@ -227,8 +227,6 @@ le statut de l'émargement :
1 ==> Envoyé
2 ==> Validé
"""
def CreateTableauEmargement_From_Sequence(diction):
try:
@ -507,6 +505,7 @@ def CreateTableauEmargement_From_Sequence(diction):
20/03/2026 -
Creation des émargements pour la formation initiale.
Ici on va aller chercher les personnes qui sont dans les groupes associé à la séquence
"""
def CreateTableauEmargement_From_Sequence_FI(diction):
@ -744,14 +743,17 @@ def CreateTableauEmargement_From_Sequence_FI(diction):
'valide':'1',
'partner_owner_recid':str(partner_recid)}, filt_sequence_for_sequence_collection]} ):
query_key = {}
query_key['email'] = tmp_val['email']
query_key['inscription_id'] = str(tmp_val['_id'])
query_key['session_id'] = tmp_val['session_id']
query_key['class_internal_url'] = tmp_val['class_internal_url']
query_key['session_formation_sequence_id'] = str(session_sequence['_id'])
"""
query_key['date'] = str(session_sequence['sequence_start'])[0:10]
query_key['sequence_start'] = str(session_sequence['sequence_start'])
query_key['sequence_end'] = str(session_sequence['sequence_end'])
query_key['date'] = str(session_sequence['sequence_start'])[0:10]
"""
new_my_local_data = {}
new_my_local_data['session_formation_sequence_id'] = str(session_sequence['_id'])
@ -762,14 +764,12 @@ def CreateTableauEmargement_From_Sequence_FI(diction):
new_my_local_data['session_id'] = tmp_val['session_id']
new_my_local_data['class_internal_url'] = tmp_val['class_internal_url']
new_my_local_data['update_date'] = str(datetime.now())
query_key['date'] = str(session_sequence['sequence_start'])[0:10]
new_my_local_data['is_present'] = False
new_my_local_data['matin'] = False
new_my_local_data['apresmidi'] = False
new_my_local_data['sequence_title'] = str(session_sequence['sequence_title'])
if( "volume_theorique" in session_sequence.keys() and session_sequence['volume_theorique']):
new_my_local_data['time_in_hour'] = str(session_sequence['volume_theorique'])
else:
@ -789,7 +789,7 @@ def CreateTableauEmargement_From_Sequence_FI(diction):
new_my_local_data['valide'] = "1"
new_my_local_data['locked'] = "0"
new_my_local_data['partner_owner_recid'] = str(str(partner_recid))
new_my_local_data['partner_owner_recid'] = str(partner_recid)
#print("### emargement insertion de : "+str(new_my_local_data))

41
main.py
View File

@ -2328,7 +2328,7 @@ def CreateTableauEmargement():
Cette API Crée la liste d'emargement en partant des sequences déjà crée
23/11/2023 : Evolution en prenant les sequences.
Evolution de la fonction de création du tableau d'emargement.
Dans cette evolution, on plutot recuperer les sequence déjà créesq
Dans cette evolution, on plutot recuperer les sequence déjà crées
"""
@app.route('/myclass/api/CreateTableauEmargement_From_Sequence/', methods=['POST','GET'])
@crossdomain(origin='*')
@ -12433,6 +12433,45 @@ def Create_Emargement_QR_Code_From_Inscription(token, session_id, tab_emargement
"""
API pour créer les ligne d'émargement et le fichier QR code pour
les émargements en meme temps
"""
@app.route('/myclass/api/Init_Emargement_And_Create_QR_Code_From_Inscription/<token>/<session_id>/<tab_sequence_ids>/<qr_time_valide>', methods=['POST','GET'])
@crossdomain(origin='*')
def Init_Emargement_And_Create_QR_Code_From_Inscription(token, session_id, tab_sequence_ids, qr_time_valide):
# 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['tab_sequence_ids'] = str(tab_sequence_ids)
payload['qr_time_valide'] = str(qr_time_valide)
print(" ### Init_Emargement_And_Create_QR_Code_From_Inscription : payload = ",str(payload))
localStatus, response= inscription.Init_Emargement_And_Create_QR_Code_From_Inscription(payload)
if(localStatus ):
return response
else:
return False
"""
API pour créer les ligne d'émargement et d'envoyer l'email de de demande d'émargement en meme temps
"""
@app.route('/myclass/api/Init_Emargement_And_Send_Email_Code_From_Inscription/', methods=['POST','GET'])
@crossdomain(origin='*')
def Init_Emargement_And_Send_Email_Code_From_Inscription():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Init_Emargement_And_Send_Email_Code_From_Inscription payload = ",payload)
status, retval = inscription.Init_Emargement_And_Send_Email_Code_From_Inscription(payload)
return jsonify(status=status, message=retval)
"""
API pour créer un fichier QR code pour les demandes d'évaluation
"""