10/10/2025 - 17:30

Signed-off-by: Cherif <cbalde@mysy-training.com>
master_Elyos_FI
Cherif 2025-10-10 17:31:26 +02:00
parent 672197b62c
commit 1e5a1207e2
28 changed files with 49416 additions and 662 deletions

View File

@ -4,9 +4,10 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="10/08/2025 - 10h">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="sss">
<change afterPath="$PROJECT_DIR$/internal_email_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Collection_Historique.py" beforeDir="false" afterPath="$PROJECT_DIR$/Collection_Historique.py" 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$/Job_Cron.py" beforeDir="false" afterPath="$PROJECT_DIR$/Job_Cron.py" afterDir="false" />
@ -14,179 +15,24 @@
<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$/Template/invoice_RIB_PortCities_perso_tpl.html" beforeDir="false" afterPath="$PROJECT_DIR$/Template/invoice_RIB_PortCities_perso_tpl.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/base_partner_catalog_config.py" beforeDir="false" afterPath="$PROJECT_DIR$/base_partner_catalog_config.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/class_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/class_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/competence.py" beforeDir="false" afterPath="$PROJECT_DIR$/competence.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/base_class_calcul_note.py" beforeDir="false" afterPath="$PROJECT_DIR$/base_class_calcul_note.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/base_document_automatic_setup.py" beforeDir="false" afterPath="$PROJECT_DIR$/base_document_automatic_setup.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/base_partner_session_step.py" beforeDir="false" afterPath="$PROJECT_DIR$/base_partner_session_step.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$/email_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/email_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/email_queu/email_queu_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/email_queu/email_queu_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/emargement.py" beforeDir="false" afterPath="$PROJECT_DIR$/emargement.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/formulaire_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/formulaire_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/invoice_paiement_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/invoice_paiement_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ent_student_common.py" beforeDir="false" afterPath="$PROJECT_DIR$/ent_student_common.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/jury_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/jury_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/note_evaluation_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/note_evaluation_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/partner_base_setup.py" beforeDir="false" afterPath="$PROJECT_DIR$/partner_base_setup.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/partner_invoice.py" beforeDir="false" afterPath="$PROJECT_DIR$/partner_invoice.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/partner_order.py" beforeDir="false" afterPath="$PROJECT_DIR$/partner_order.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/partners.py" beforeDir="false" afterPath="$PROJECT_DIR$/partners.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/prj_common.py" beforeDir="false" afterPath="$PROJECT_DIR$/prj_common.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ressources_humaines.py" beforeDir="false" afterPath="$PROJECT_DIR$/ressources_humaines.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/survey_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/survey_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Attestation_Ftion435_00131.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Attestation_Ftion435_06813.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Attestation_Ftion435_22148.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Attestation_Ftion435_25049.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Attestation_Ftion435_32089.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Attestation_Ftion435_36537.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Attestation_Ftion435_50348.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Attestation_Ftion435_50552.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Attestation_Ftion435_58238.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Attestation_Ftion435_63595.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Attestation_Ftion435_65539.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Attestation_Ftion435_72236.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Attestation_Ftion435_73741.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Attestation_Ftion435_90018.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Attestation_Ftion435_95298.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Bulletin_Note_part nom4_client_part 4_059.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Bulletin_Note_part nom4_client_part 4_231.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Bulletin_Note_part nom4_client_part 4_355.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Bulletin_Note_part nom4_client_part 4_388.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Bulletin_Note_part nom5_client_part 5_692.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Bulletin_Note_part nom6_client_part 6_172.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Bulletin_Note_part nom6_client_part 6_365.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Convention_43598_07617.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Convention_43598_29744.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Convention_43598_79438.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Convocation_43598_78339.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/CorrigeTD01_20250719121019.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/CorrigeTD01_20250719122448.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/CorrigeTD01_20250719122621.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/CorrigeTD01_20250719122706.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/CorrigeTD01_20250719122840.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/CorrigeTD01_20250719165517.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Evaluation_SNP_SESS_Juil_fsdgdf_341.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Evaluation_SNP_SESS_Juil_test01_308.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Attestation_373.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Attestation_459.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Attestation_462.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Attestation_469.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Attestation_593.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Attestation_633.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Attestation_777.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Attestation_798.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Attestation_905.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Bulletin_Notes_199.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Bulletin_Notes_487.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Bulletin_Notes_534.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Bulletin_Notes_857.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Convention_session_6873727a54e2e1ffed1e5f6f_306.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Convention_session_6873727a54e2e1ffed1e5f6f_459.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Convention_session_6873727a54e2e1ffed1e5f6f_664.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Convocation_session_6873727a54e2e1ffed1e5f6f_366.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Evaluation_728.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/List_Evaluation_992.zip" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Partner_Invoice_Invoice_637.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Partner_Invoice_Invoice_638.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Partner_Invoice_Invoice_639.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Partner_Invoice_Invoice_640.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Partner_Invoice_Invoice_642.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Partner_Invoice_Invoice_643.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Partner_Invoice_Invoice_644.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Partner_Invoice_Invoice_645.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Partner_Invoice_Invoice_646.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Partner_Invoice_Invoice_647.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/Partner_Invoice_Invoice_648.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/SessionformationenDEV_20250729105445.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/StagiairesIfodesenvdemo2412_20250713104724.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/StagiairesIfodesenvdemo2412_20250713105210.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/StagiairesIfodesenvdemoCopie_20250711110826.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/StagiairesIfodesenvdemoCopie_20250711111047.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_3414911.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_3767923.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_4080269.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_4415201.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_4506392.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_4537286.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_4759173.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_4928765.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_5032964.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_5071841.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_5153013.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_5336363.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_5755279.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_5892864.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_5977022.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_6442143.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_6626887.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_6835163.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_6846929.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_7541682.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/graph_8870142.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/importstagiairesJMJ_20250720162531.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/pdfexemple01_20250719165517.pdf" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_024.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_052.png" beforeDir="false" afterPath="$PROJECT_DIR$/temp_direct/qr_code_052.png" afterDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_109.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_155.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_256.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_387.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_395.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_399.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_418.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_505.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_553.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_607.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_666.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_675.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_727.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_806.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_849.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_926.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/qr_code_959.png" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportapprenant_20250720162121.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportapprenantcb_20250721132250.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportapprenantcb_20250721132308.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclient_20250709131055.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclient_20250709151553.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclient_20250709151925.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclient_20250709152108.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclient_20250709152303.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclient_20250709152423.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclient_20250709152748.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientall_20250718183707.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientall_20250718183943.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientall_20250718184031.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientall_20250718184127.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientall_20250718184224.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientalllot2_20250718183411.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientlot1_20250718174706.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientlot1_20250718174745.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientlot1_20250718174829.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientlot1_20250718175221.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientlot1_20250718175351.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientlot1_20250718175529.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientlot1_20250718180247.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientlot1_20250718180343.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientlot1_20250718180526.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientlot1_20250718181540.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientlot1_20250718182221.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientlot1_20250718182843.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientlot1test_20250718180837.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientlot1test_20250718181115.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportclientlot1test_20250718181222.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportsessionformation2_20250718125020.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportsessionformation2_20250718125059.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportsessionformation_20250718124650.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportsessionformation_20250718124833.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportstagiairesall_20250718145256.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportstagiairescbv2_20250721133846.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportstagiairescbv2_20250721135053.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportstagiairescbv2_20250721135149.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportstagiairescbv2_20250721135211.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportstagiairescbv2_20250721135223.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportstagiairescbv2_20250721135243.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportstagiairescbv2_20250721135300.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/temp_direct/templateimportstagiairescbv2_20250721135322.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/tools_cherif/tools_cherif.py" beforeDir="false" afterPath="$PROJECT_DIR$/tools_cherif/tools_cherif.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/unite_enseignement_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/unite_enseignement_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/wrapper.py" beforeDir="false" afterPath="$PROJECT_DIR$/wrapper.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -629,7 +475,7 @@
<option name="project" value="LOCAL" />
<updated>1747251650255</updated>
</task>
<option name="localTasksCounter" value="495" />
<option name="localTasksCounter" value="497" />
<servers />
</component>
<component name="Vcs.Log.Tabs.Properties">
@ -671,7 +517,6 @@
</option>
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="Init - 29/05/2025" />
<MESSAGE value="Init - 29/05/2025 - FI" />
<MESSAGE value="31/05/2025 - 20h" />
<MESSAGE value="02/06/2025 - 20h" />
@ -696,6 +541,7 @@
<MESSAGE value="qsd" />
<MESSAGE value="30/07/2025 -18h" />
<MESSAGE value="10/08/2025 - 10h" />
<option name="LAST_COMMIT_MESSAGE" value="10/08/2025 - 10h" />
<MESSAGE value="sss" />
<option name="LAST_COMMIT_MESSAGE" value="sss" />
</component>
</project>

View File

@ -200,12 +200,13 @@ def Get_Humain_Ressource_With_Planning(diction):
}
])
print(" ### Get_Humain_Ressource_With_Planning ici pipe_qry = ", pipe_qry)
print(" ### Get_Humain_Ressource_With_Planning ici pipe_qry uu= ", pipe_qry)
new_retval_titles = []
new_retval_data = []
local_id = 0
tab_ressource_humaine_data = []
total_duration = 0
for retval in MYSY_GV.dbname['ressource_humaine'].aggregate(pipe_qry):
@ -311,9 +312,10 @@ def Get_Humain_Ressource_With_Planning(diction):
node_duration = {"total_duration":str(total_duration)}
#print(' ### node_duration = ', node_duration)
RetObject.append(mycommon.JSONEncoder().encode(node_duration))
RetObject_total_duration = []
RetObject_total_duration.append(mycommon.JSONEncoder().encode(node_duration))
return True, RetObject
return True, RetObject, RetObject_total_duration
except Exception as e:
@ -818,9 +820,9 @@ def Get_Humain_Ressource_With_Planning_And_Cost(diction):
#print(" ### Final Line : ", json_formatted_str)
tab_lines_employe_by_contract.append(retval)
local_status, local_retval = Format_employee_contrat_agenda_events(tab_lines_employe_by_contract)
local_status, local_retval, node_total_duration, node_total_cost = Format_employee_contrat_agenda_events(tab_lines_employe_by_contract)
if (local_status is False):
return local_status, local_retval
return local_status, local_retval, False, False
RetObject = []
@ -834,8 +836,18 @@ def Get_Humain_Ressource_With_Planning_And_Cost(diction):
#print(" RetObject = ", RetObject)
#print(' on a ' + str(cpt) + ' lignes ')
local_tmp = []
retval_node_total_duration = []
node_tmp = {}
node_tmp['total_duration'] = node_total_duration
retval_node_total_duration.append(mycommon.JSONEncoder().encode(node_tmp))
return True, RetObject
retval_node_total_cost = []
node_tmp_cost = {}
node_tmp_cost['total_cost'] = node_total_cost
retval_node_total_cost.append(mycommon.JSONEncoder().encode(node_tmp_cost))
return True, RetObject, retval_node_total_duration, retval_node_total_cost
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
@ -1036,22 +1048,21 @@ def Format_employee_contrat_agenda_events(tab_diction):
return_tab.append(new_node)
total_duration = round(total_duration, 2)
node_total_duration = {'total_duration':str(total_duration)}
return_tab.append(node_total_duration)
#return_tab.append(node_total_duration)
total_cost = round(total_cost, 2)
node_total_cost = {'total_cost':str(total_cost)}
return_tab.append(node_total_cost)
#return_tab.append(node_total_cost)
#print(" #### total_duration = ", total_duration)
#print(" #### total_cost = ", total_cost)
return True, return_tab
return True, return_tab, str(total_duration), str(total_cost)
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 reformater et de normer le tableau des tâches et coûts "
return False, " Impossible de reformater et de normer le tableau des tâches et coûts ", False, False
"""

View File

@ -708,6 +708,12 @@ Les types de location pour une session (intra ou extra ou autre)
TRAINING_LOCATION_TYPE = ['intra', 'extra', 'autre', '']
"""
On definit les entrée scolaires autorisées
"""
TRAINING_ENTREE_SCOLAIRE = ['2024', '2025', '2026','2027', '2028', '2029', '']
"""
Gestion des champs spécifique : Type de champs autorisé
"""

View File

@ -1380,7 +1380,8 @@ def UpdateStagiairetoClass(diction):
local_insc_status, local_insc_retval = mycommon.Is_Partnair_Inscription_Notification(
{'token': diction['token']})
if (local_insc_status and local_insc_retval == "1"):
local_status, local_message = email_session.incription_training_confirmation_mail(email_data)
print(" ### 1er envoie emailll email_data = ", email_data)
#local_status, local_message = email_session.incription_training_confirmation_mail(email_data)
message_for_historic = message_for_historic + " : Email Inscription "
"""
@ -1788,15 +1789,15 @@ def SendInscriptionConfirmation(diction):
date_du = ""
if ("date_du" in local_info_session[0].keys()):
if local_info_session[0]['date_du']:
date_du = local_info_session[0]['date_du']
if ("date_debut" in local_info_session[0].keys()):
if local_info_session[0]['date_debut']:
date_du = local_info_session[0]['date_debut']
data_mail['date_du'] = str(date_du)[0:10]
date_au = ""
if ("date_au" in local_info_session[0].keys()):
if local_info_session[0]['date_au']:
date_au = local_info_session[0]['date_au']
if ("date_fin" in local_info_session[0].keys()):
if local_info_session[0]['date_fin']:
date_au = local_info_session[0]['date_fin']
data_mail['date_au'] = str(date_au)[0:10]
adresse = ""
@ -1817,6 +1818,12 @@ def SendInscriptionConfirmation(diction):
code_session = local_info_session[0]['code_session']
data_mail['code_session'] = code_session
session_id = ""
if ("session_id" in local_info_session[0].keys()):
if local_info_session[0]['_id']:
session_id = str(local_info_session[0]['session_id'])
data_mail['session_id'] = session_id
data_mail['partner_owner_recid'] = str(partner_recid)
"""
@ -1827,6 +1834,8 @@ def SendInscriptionConfirmation(diction):
local_insc_status, local_insc_retval = mycommon.Is_Partnair_Inscription_Notification(
{'token': diction['token']})
if (local_insc_status and local_insc_retval == "1"):
local_status, local_message = email_session.incription_training_confirmation_mail(data_mail)
return local_status, "La confirmation d'inscription a bien ete envoyée"
else:
@ -6825,7 +6834,7 @@ def AcceptAttendeeInscription(diction):
else:
email_data['ville'] = ""
print(" ### 2izmmm er envoie emailll email_data = ", email_data)
local_status, local_message = email_session.incription_training_confirmation_mail(email_data)
if( local_status is False ):
mycommon.myprint(str(
@ -13732,7 +13741,7 @@ def Get_List_Inscrit_OF_UE_And_Type_Evaluation_with_filter(diction):
d'emargement de manière securisée, à l'image de la gestion des QR code
"""
"""
Cette fonction prends une liste d'inscription et une session
Cette fonction prends une liste d'emargement et une session
pui créer un QR pour l'emargement
"""
@ -13808,12 +13817,12 @@ def Create_Emargement_Send_Email_From_Inscription(diction):
if (local_stpm_status is False):
return local_stpm_status, partner_own_smtp_value
print(" ### local_stpm_status = ", local_stpm_status)
"""print(" ### local_stpm_status = ", local_stpm_status)
print(" ### partner_SMTP_COUNT_smtpsrv = ", partner_SMTP_COUNT_smtpsrv)
print(" ### partner_SMTP_COUNT_password = ", partner_SMTP_COUNT_password)
print(" ### partner_SMTP_COUNT_user = ", partner_SMTP_COUNT_user)
print(" ### partner_SMTP_COUNT_From_User = ", partner_SMTP_COUNT_From_User)
print(" ### partner_SMTP_COUNT_port = ", partner_SMTP_COUNT_port)
print(" ### partner_SMTP_COUNT_port = ", partner_SMTP_COUNT_port)"""
# Verifier que les inscriptions sont valides
@ -13855,7 +13864,6 @@ def Create_Emargement_Send_Email_From_Inscription(diction):
tab_my_emargement_ids = str(my_emargement_ids).split(",")
for my_emargement_id in tab_my_emargement_ids:
ret_val2 = MYSY_GV.dbname['emargement'].find_one_and_update(
{'session_id': str(diction['session_id']),
'_id': ObjectId(str(my_emargement_id)),
@ -13864,7 +13872,9 @@ def Create_Emargement_Send_Email_From_Inscription(diction):
'locked': '0'
},
{"$set": {'emargement_qr_safe_token':str(my_safe_token), 'statut':'1',
'date_envoi':str(now), 'update_by':str(my_partner['_id'])}},
'date_envoi':str(now), 'update_by':str(my_partner['_id']),
'date_dernier_relance_auto':str(datetime.now().strftime("%d/%m/%Y")),
'mode_envoi':'email'}},
return_document=ReturnDocument.AFTER,
upsert=False,
)
@ -14132,7 +14142,10 @@ def Create_Emargement_QR_Code_From_Inscription(diction):
'partner_owner_recid': str(my_partner['recid']),
'valide':'1','locked':'0'},
{"$set": {'emargement_qr_safe_token':str(my_safe_token), 'statut':'1',
'date_envoi':str(now), 'update_by':str(my_partner['_id'])}},
'date_envoi':str(now), 'update_by':str(my_partner['_id']),
'date_dernier_relance_auto': str(datetime.now().strftime("%d/%m/%Y")),
'mode_envoi': 'qr'
}},
return_document=ReturnDocument.AFTER,
upsert=False,
)

View File

@ -1862,7 +1862,8 @@ def Cron_Session_Convocation_Sending(diction):
"""
CRON :
Cette fonction permet de faire la relance des questionnaires de positionnement
Cette fonction permet de faire la relance tous les SURVEY (positionnement, evaluation, etc)
"""
def Cron_Survey_Questionnaires_Relance():
@ -1910,118 +1911,327 @@ def Cron_Survey_Questionnaires_Relance():
if ("partner_owner_recid" in relance_setp.keys() and relance_setp['partner_owner_recid']):
local_partner_owner_recid = str(relance_setp['partner_owner_recid'])
# Aller chercher tous les questionnaires à relancer
devis_qery_match = {'$and': [{'partner_owner_recid': str(local_partner_owner_recid),
'valide': '1',
'locked': '0', 'statut': '1', 'type': '1',
'date_dernier_relance_auto': {'$exists': True,}
}
]}
pipe_qry = ([
{'$match': devis_qery_match},
])
print(" ## pipe_qry Cron_Survey_Questionnaires_Relance = ", pipe_qry)
for local_questionnaire in MYSY_GV.dbname['survey'].aggregate(pipe_qry):
#print("### local_questionnaire a traiter = ", local_questionnaire)
relance_done = 0
if ("nb_relance" in local_questionnaire.keys() and local_questionnaire['nb_relance']):
relance_done = mycommon.tryInt(str(local_questionnaire['nb_relance']))
if ("partner_owner_recid" in relance_setp.keys() and relance_setp['partner_owner_recid']):
local_partner_owner_recid = str(relance_setp['partner_owner_recid'])
date_derniere_relance_auto = "01/12/2099"
if ("date_dernier_relance_auto" in local_questionnaire.keys() and local_questionnaire['date_dernier_relance_auto']):
date_derniere_relance_auto = str(local_questionnaire['date_dernier_relance_auto'])[0:10]
# Aller chercher tous les questionnaires à relancer
devis_qery_match = {'$and': [{'partner_owner_recid': str(local_partner_owner_recid),
'valide': '1',
'locked': '0', 'statut': '1', 'type': '1',
},
]}
date_derniere_relance_auto_ISODATE = datetime.strptime(str(date_derniere_relance_auto), '%d/%m/%Y')
pipe_qry = ([
{'$match': devis_qery_match},
])
print(" ## pipe_qry Cron_Survey_Questionnaires_Relance = ", pipe_qry)
for local_questionnaire in MYSY_GV.dbname['survey'].aggregate(pipe_qry):
#print("### local_questionnaire a traiter = ", local_questionnaire)
relance_done = 0
if ("nb_relance" in local_questionnaire.keys() and local_questionnaire['nb_relance']):
relance_done = mycommon.tryInt(str(local_questionnaire['nb_relance']))
new_relance_date_ISODATE = date_derniere_relance_auto_ISODATE + timedelta(
days=frequence_relance_auto)
date_derniere_relance_auto = "01/12/2099"
if ("date_dernier_relance_auto" in local_questionnaire.keys() and local_questionnaire['date_dernier_relance_auto']):
date_derniere_relance_auto = str(local_questionnaire['date_dernier_relance_auto'])[0:10]
date_derniere_relance_auto_ISODATE = datetime.strptime(str(date_derniere_relance_auto), '%d/%m/%Y')
new_relance_date_ISODATE = date_derniere_relance_auto_ISODATE + timedelta(
days=frequence_relance_auto)
"""print(" ### LA frequence_relance_auto ", frequence_relance_auto)
print(" ### LA dernière relance date de ", date_derniere_relance_auto)
print(" ### LA PROCHAINE RELANCE EST ", new_relance_date_ISODATE)"""
"""print(" ### LA frequence_relance_auto ", frequence_relance_auto)
new_relance_date_no_ISODATE = str(new_relance_date_ISODATE.strftime("%d/%m/%Y"))
# print(" ### LA PROCHAINE RELANCE EST (new_relance_date_no_ISODATE) ", new_relance_date_no_ISODATE)
print(" ### LA dernière relance date de ", date_derniere_relance_auto)
print(" ### LA PROCHAINE RELANCE EST ", new_relance_date_ISODATE)"""
datetime.strptime(str(todays_date), '%d/%m/%Y')
new_relance_date_no_ISODATE = str(new_relance_date_ISODATE.strftime("%d/%m/%Y"))
# print(" ### LA PROCHAINE RELANCE EST (new_relance_date_no_ISODATE) ", new_relance_date_no_ISODATE)
"""print(" ### relance_done = ",relance_done)
print(" ### nb_limite_relance = ", nb_limite_relance)
print(" ### datetime.strptime( str(todays_date), '%d/%m/%Y') = ", datetime.strptime(
str(todays_date), '%d/%m/%Y'))
print(" ### datetime.strptime(str(new_relance_date_no_ISODATE).strip(), '%d/%m/%Y') = ", datetime.strptime(str(new_relance_date_no_ISODATE).strip(),
'%d/%m/%Y'))"""
datetime.strptime(str(todays_date), '%d/%m/%Y')
"""print(" ### relance_done = ",relance_done)
print(" ### nb_limite_relance = ", nb_limite_relance)
print(" ### datetime.strptime( str(todays_date), '%d/%m/%Y') = ", datetime.strptime(
str(todays_date), '%d/%m/%Y'))
print(" ### datetime.strptime(str(new_relance_date_no_ISODATE).strip(), '%d/%m/%Y') = ", datetime.strptime(str(new_relance_date_no_ISODATE).strip(),
'%d/%m/%Y'))"""
if ( relance_done <= nb_limite_relance and datetime.strptime(
str(todays_date), '%d/%m/%Y') >= datetime.strptime(str(new_relance_date_no_ISODATE).strip(),
'%d/%m/%Y')):
"""
On fait le traitement, on envoie le mail
1 - recuperation des data
"""
local_status, my_partner = mycommon.Get_Connected_User_Partner_Data_From_RecID(
str(local_questionnaire['partner_owner_recid']))
if (local_status is not True):
return local_status, my_partner
local_dicton = {}
local_dicton['partner_owner_recid'] = str(local_questionnaire['partner_owner_recid'])
local_dicton['tab_ids'] = str(local_questionnaire['_id'])
#print(" ### local_dicton = ", local_dicton)
local_status, local_retval = survey_mgt.Automatic_Send_Survey_TabIds(local_dicton)
#print(" relance return local_send_remind_status = ", local_status)
if (local_status is True):
print(" RELANCE FAIT ET OK ")
"""
Une fois la relance faite, on met à jour le devis avec les infos suivant :
- liste_relance
if ( relance_done <= nb_limite_relance and datetime.strptime(
str(todays_date), '%d/%m/%Y') >= datetime.strptime(str(new_relance_date_no_ISODATE).strip(),
'%d/%m/%Y')):
"""
On fait le traitement, on envoie le mail
1 - recuperation des data
"""
local_status, my_partner = mycommon.Get_Connected_User_Partner_Data_From_RecID(
str(local_questionnaire['partner_owner_recid']))
if (local_status is not True):
return local_status, my_partner
local_dicton = {}
local_dicton['partner_owner_recid'] = str(local_questionnaire['partner_owner_recid'])
local_dicton['tab_ids'] = str(local_questionnaire['_id'])
#print(" ### local_dicton = ", local_dicton)
local_status, local_retval = survey_mgt.Automatic_Send_Survey_TabIds(local_dicton)
#print(" relance return local_send_remind_status = ", local_status)
if (local_status is True):
print(" RELANCE FAIT ET OK ")
"""
Une fois la relance faite, on met à jour le devis avec les infos suivant :
- liste_relance
"""
frequence_relance_auto_reached = "0"
if ("list_relance" in local_questionnaire.keys() and local_questionnaire['list_relance']):
local_node = {}
local_node['date_relance'] = str(date.today())
local_node['mesg_relance'] = str(local_retval)
local_questionnaire['list_relance'].append(local_node)
else:
local_node = {}
local_node['date_relance'] = str(date.today())
local_questionnaire['list_relance'] = []
local_questionnaire['list_relance'].append(local_node)
local_node['mesg_relance'] = str(local_retval)
nb_relance = str(len(local_questionnaire['list_relance']))
local_data_update = local_questionnaire
id_to_update = str(local_data_update['_id'])
del local_data_update['_id']
local_data_update['nb_relance'] = str(nb_relance)
local_data_update['date_dernier_relance_auto'] = str(todays_date)
result = MYSY_GV.dbname['survey'].find_one_and_update(
{'_id': ObjectId(str(id_to_update)),
'valide': '1',
'locked': '0'},
{"$set": local_data_update},
upsert=False,
return_document=ReturnDocument.AFTER
)
return True, "Relance Questionnaires OK"
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, str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno)
"""
CRON :
Cette fonction permet de faire la relance toutes demandes EMARGEMENT.
"""
def Cron_Emargement_Relance():
try:
print(" Cron : In function = Cron_Emargement_Relance")
todays_date = str(date.today().strftime("%d/%m/%Y"))
todays_date_ISODATE = datetime.strptime(str(todays_date), '%d/%m/%Y')
for relance_setp in MYSY_GV.dbname['base_partner_setup'].find({'valide': '1',
'locked': '0',
'config_name': 'relance_auto',
'config_value': '1',
'related_collection': 'emargement',
'partner_owner_recid': {'$ne': 'default'},
}):
nb_limite_relance = 0
nb_relance_data = MYSY_GV.dbname['base_partner_setup'].find_one({'valide': '1',
'locked': '0',
'config_name': 'nb_relance_auto',
'related_collection': 'emargement',
'partner_owner_recid': str(relance_setp['partner_owner_recid']),
})
print(" ## relance_setp = ", relance_setp)
if("config_value" in nb_relance_data.keys() and nb_relance_data['config_value']):
nb_limite_relance = mycommon.tryInt(str(nb_relance_data['config_value']))
frequence_relance_auto = 0
frequence_relance_data = MYSY_GV.dbname['base_partner_setup'].find_one({'valide': '1',
'locked': '0',
'config_name': 'frequence_relance_auto',
'related_collection': 'emargement',
'partner_owner_recid': str(
relance_setp['partner_owner_recid']),
})
if ("config_value" in frequence_relance_data.keys() and frequence_relance_data['config_value']):
frequence_relance_auto = mycommon.tryInt(str(frequence_relance_data['config_value']))
if ("partner_owner_recid" in relance_setp.keys() and relance_setp['partner_owner_recid']):
local_partner_owner_recid = str(relance_setp['partner_owner_recid'])
# Aller chercher tous les emargements à relancer
devis_qery_match = {'$and': [{'partner_owner_recid': str(local_partner_owner_recid),
'valide': '1',
'locked': '0', 'statut': '1',
'date_dernier_relance_auto': {'$exists': True,}
}
]}
pipe_qry = ([
{'$match': devis_qery_match},
])
print(" ## pipe_qry Cron_Emargement_Relance = ", pipe_qry)
tab_email_sent = []
tab_session_sent = []
tab_emargement_qr_safe_token_sent = []
send_email_relance = "0"
for local_emargement in MYSY_GV.dbname['emargement'].aggregate(pipe_qry):
print("### local_emargement a traiter = ", local_emargement)
relance_done = 0
if ("nb_relance" in local_emargement.keys() and local_emargement['nb_relance']):
relance_done = mycommon.tryInt(str(local_emargement['nb_relance']))
date_derniere_relance_auto = "01/12/2099"
if ("date_dernier_relance_auto" in local_emargement.keys() and local_emargement['date_dernier_relance_auto']):
date_derniere_relance_auto = str(local_emargement['date_dernier_relance_auto'])[0:10]
date_derniere_relance_auto_ISODATE = datetime.strptime(str(date_derniere_relance_auto), '%d/%m/%Y')
new_relance_date_ISODATE = date_derniere_relance_auto_ISODATE + timedelta(days=frequence_relance_auto)
print(" ### LA frequence_relance_auto ", frequence_relance_auto)
print(" ### LA dernière relance date de ", date_derniere_relance_auto)
print(" ### LA PROCHAINE RELANCE EST ", new_relance_date_ISODATE)
new_relance_date_no_ISODATE = str(new_relance_date_ISODATE.strftime("%d/%m/%Y"))
# print(" ### LA PROCHAINE RELANCE EST (new_relance_date_no_ISODATE) ", new_relance_date_no_ISODATE)
datetime.strptime(str(todays_date), '%d/%m/%Y')
print(" ### relance_done = ",relance_done)
print(" ### nb_limite_relance = ", nb_limite_relance)
print(" ### datetime.strptime( str(todays_date), '%d/%m/%Y') = ", datetime.strptime(
str(todays_date), '%d/%m/%Y'))
print(" ### datetime.strptime(str(new_relance_date_no_ISODATE).strip(), '%d/%m/%Y') = ", datetime.strptime(str(new_relance_date_no_ISODATE).strip(),
'%d/%m/%Y'))
if ( relance_done <= nb_limite_relance and datetime.strptime(
str(todays_date), '%d/%m/%Y') >= datetime.strptime(str(new_relance_date_no_ISODATE).strip(),
'%d/%m/%Y')):
"""
On fait le traitement, on envoie le mail
1 - recuperation des data
"""
print(" IL FAUT FAIRE UNE RELANCEEEE ")
"""
Important :
L'idée est d'envoyer 1 et 1 seul par couple : email/session
En effet si il plusieurs séquence, l'apprenant en cliquant sur le mysyurl,
il tombera sur l'affichage de toutes les sequence
"""
if ( "session_id" in local_emargement.keys() and local_emargement['session_id'] in tab_session_sent and
"email" in local_emargement.keys() and local_emargement['email'] in tab_email_sent and
"emargement_qr_safe_token" in local_emargement.keys() and local_emargement['emargement_qr_safe_token'] in tab_emargement_qr_safe_token_sent):
send_email_relance = "0"
else:
send_email_relance = "1"
tab_session_sent.append(local_emargement['session_id'])
tab_email_sent.append(local_emargement['email'])
tab_emargement_qr_safe_token_sent.append(local_emargement['emargement_qr_safe_token'])
local_status, my_partner = mycommon.Get_Connected_User_Partner_Data_From_RecID(
str(local_emargement['partner_owner_recid']))
if (local_status is not True):
return local_status, my_partner
local_dicton = {}
local_dicton['partner_owner_recid'] = str(local_emargement['partner_owner_recid'])
local_dicton['tab_emargement_ids'] = str(local_emargement['_id'])
#print(" ### local_dicton = ", local_dicton)
if( send_email_relance == "1"):
local_status, local_retval = Job_Cron_Common.Cron_Relance_Emargement_By_Email(local_dicton)
else:
print(" ### UNE RELANCE A DEJA ETE ENVOY2 pour ce apprenant et pour cette session")
frequence_relance_auto_reached = "0"
if ("list_relance" in local_questionnaire.keys() and local_questionnaire['list_relance']):
if ("list_relance" in local_emargement.keys() and local_emargement['list_relance']):
local_node = {}
local_node['date_relance'] = str(date.today())
local_node['mesg_relance'] = str(local_retval)
local_questionnaire['list_relance'].append(local_node)
local_emargement['list_relance'].append(local_node)
else:
local_node = {}
local_node['date_relance'] = str(date.today())
local_questionnaire['list_relance'] = []
local_questionnaire['list_relance'].append(local_node)
local_emargement['list_relance'] = []
local_emargement['list_relance'].append(local_node)
local_node['mesg_relance'] = str(local_retval)
nb_relance = str(len(local_questionnaire['list_relance']))
nb_relance = str(len(local_emargement['list_relance']))
local_data_update = local_questionnaire
local_data_update = local_emargement
id_to_update = str(local_data_update['_id'])
@ -2030,7 +2240,7 @@ def Cron_Survey_Questionnaires_Relance():
local_data_update['nb_relance'] = str(nb_relance)
local_data_update['date_dernier_relance_auto'] = str(todays_date)
result = MYSY_GV.dbname['survey'].find_one_and_update(
result = MYSY_GV.dbname['emargement'].find_one_and_update(
{'_id': ObjectId(str(id_to_update)),
'valide': '1',
@ -2042,7 +2252,7 @@ def Cron_Survey_Questionnaires_Relance():
return True, "Relance Questionnaires OK"
return True, "Relance Emargement OK"
except Exception as e:
@ -2051,6 +2261,7 @@ def Cron_Survey_Questionnaires_Relance():
return False, str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno)
"""
Cette fonction permet d'envoyer les emails qui sont dans file d'attente
collection : 'email_queue'
@ -2080,9 +2291,17 @@ def Cron_Send_Mail_Queue_Message_With_Filter(diction):
msg = MIMEMultipart("alternative")
msg['From'] = email_queue_data['from']
msg['Cc'] = email_queue_data['cc']
msg['Bcc'] = 'contact@mysy-training.com'
msg['Subject'] = email_queue_data['subject']
if( "cc" in email_queue_data.keys() and email_queue_data['cc']):
msg['cc'] = email_queue_data['cc']
if ("bcc" in email_queue_data.keys() and email_queue_data['bcc']):
msg['bcc'] = email_queue_data['bcc']
if ("subject" in email_queue_data.keys() and email_queue_data['subject']):
msg['subject'] = email_queue_data['subject']
else:
msg['subject'] = ""
msg['to'] = email_queue_data['to']
# Traitement de l'eventuel fichier joint
tab_files_to_attache_to_mail = []
@ -2116,7 +2335,7 @@ def Cron_Send_Mail_Queue_Message_With_Filter(diction):
val = smtpserver.send_message(msg)
smtpserver.close()
print(" Email envoyé" + str(val))
#print(val)
"""
On met à jour l'email avec le statut d'envoie de l'email
@ -2124,8 +2343,14 @@ def Cron_Send_Mail_Queue_Message_With_Filter(diction):
new_data = diction
new_data['date_update'] = str(datetime.now())
new_data['sent'] = str(datetime.now())
new_data['statut'] = "1"
new_data['sent_message'] = str(val)
error_node = {}
if( len(val.keys()) > 0 ):
new_data['error_message'] = str(val)
new_data['statut'] = "-1"
else:
new_data['error_message'] = ""
new_data['statut'] = "1"
result = MYSY_GV.dbname['mail_queue'].find_one_and_update(
{'_id':ObjectId(str(email_queue_data['_id']))},

View File

@ -12,6 +12,7 @@ from zipfile import ZipFile
import bson
import pymongo
import segno
import xlsxwriter
from pymongo import MongoClient
import json
@ -2910,9 +2911,10 @@ def Cron_Init_Emargement_By_Date_With_Template(diction):
query_key['sequence_start'] = str(session_sequence['sequence_start'])
query_key['sequence_end'] = str(session_sequence['sequence_end'])
session_sequence
new_my_local_data = {}
new_my_local_data['inscription_id'] = str(my_inscription['_id'])
new_my_local_data['session_formation_sequence_id'] = str(session_sequence['_id'])
new_my_local_data['email'] = my_inscription['email']
new_my_local_data['nom'] = my_inscription['nom']
new_my_local_data['prenom'] = my_inscription['prenom']
@ -2964,8 +2966,7 @@ def Cron_Init_Emargement_By_Date_With_Template(diction):
"""
CRON :
Cette fonction prepare et envoi les demandes d'émargement du JOUR qui n'ont pas déjà été envoyées
Important : : On envoie uniquement les demandes d'émargement du jours
Important :On envoie uniquement les demandes d'émargement du jours
"""
def Cron_Send_Emargement_By_Date_By_Email_for_not_sent(Folder, diction):
try:
@ -3047,3 +3048,240 @@ def Cron_Send_Emargement_By_Date_By_Email_for_not_sent(Folder, diction):
return False, " Impossible d'envoyer les demandes d'émargement ", "0"
"""
Cette fonction prends une liste d'emargement et une session
pui créer un QR pour l'emargement
"""
def Cron_Relance_Emargement_By_Email(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['partner_owner_recid', 'tab_emargement_ids']
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 = ['partner_owner_recid', 'tab_emargement_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.Get_Connected_User_Partner_Data_From_RecID(
str(diction['partner_owner_recid']))
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_own_smtp_value
# Verifier que les inscriptions sont valides
my_emargement_ids = ""
if ("tab_emargement_ids" in diction.keys()):
if diction['tab_emargement_ids']:
my_emargement_ids = diction['tab_emargement_ids']
tab_my_emargement_ids = str(my_emargement_ids).split(",")
if (len(tab_my_emargement_ids) <= 0):
mycommon.myprint(
str(inspect.stack()[0][3]) + " Aucune Séquence ")
return False, " Aucun Séquence "
for my_emargement_id in tab_my_emargement_ids:
# Verifier qui la formation n'a pas deja été evaluée
tmp_count = MYSY_GV.dbname['emargement'].count_documents({
'_id': ObjectId(str(my_emargement_id)),
'partner_owner_recid': str(my_partner['recid']),
})
if (tmp_count != 1):
mycommon.myprint(str(inspect.stack()[0][3]) + " L'identifiant de l'émargement " + str(
my_emargement_id) + " est invalide ")
return False, " L'identifiant de l'émargement " + str(my_emargement_id) + " est invalide "
for my_emargement_id in tab_my_emargement_ids:
emargement_data = MYSY_GV.dbname['emargement'].find_one({
'_id': ObjectId(str(my_emargement_id)),
'partner_owner_recid': str(my_partner['recid']),
'statut':'1'
})
"""
Debut de la procedure d'envoie de l'email
"""
convention_dictionnary_data = {}
new_diction = {}
new_diction['token'] = my_partner['token']
new_diction['list_stagiaire_id'] = []
new_diction['list_session_id'] = [ObjectId(str(emargement_data['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'] = str(MYSY_GV.CLIENT_URL_BASE) + "qr_emargement/" + str(emargement_data['session_id']) + "/" + str(
my_partner['recid']) + "/" + str(emargement_data['emargement_qr_safe_token']) + "/"
print(" ### mysyurl = ", str(emargement_dictionnary_data['mysyurl']))
smtpserver = None
if (str(partner_own_smtp_value) == "1"):
smtpserver = smtplib.SMTP(partner_SMTP_COUNT_smtpsrv, partner_SMTP_COUNT_port)
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)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(MYSY_GV.O365_SMTP_COUNT_user, MYSY_GV.O365_SMTP_COUNT_password)
"""
on envoi qu'un seul mail d'emargement par personnes.
1 - On va aller recuperer la liste des personnes concernée (inscription_id)
2 - Apres avoir envoyer les email, on va venir mettre à jour la table emargement id)
"""
cpt_email_envoye = 0
"""
Des qu'on envoie un email on met l'inscription_id dans la collection 'tab_inscription_id_emargement_send'
Avant d'envoyer un email à un inscrit on verifie qu'il n'est pa dans la table : tab_inscription_id_emargement_send
"""
tab_inscription_id_emargement_send = []
if (str(emargement_data['inscription_id']) not in tab_inscription_id_emargement_send):
tab_inscription_id_emargement_send.append(str(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(my_partner['token']), 'inscrit_id': str(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(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'] = 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(str(emargement_data['email']))
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(str(emargement_data['email']))
val = smtpserver.send_message(msg)
print(" Email demande emargement envoyé " + str(val))
smtpserver.close()
print(" NB_email envoyé = ", cpt_email_envoye)
return True, "Les demandes d'émargement ont été correctement envoyées "
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 les demandes d'émargement "

File diff suppressed because one or more lines are too long

View File

@ -68,7 +68,7 @@ def Add_Update_SessionFormation(diction):
'attestation_certif', "distantiel", "presentiel", "prix_session", 'contenu_ftion', 'lms_class_code',
'session_ondemande', 'source', 'session_id', 'session_etape', 'pays', 'formateur_id',
'titre', 'location_type', 'is_bpf', 'site_formation_id', 'price_by', 'mode_animation', 'archive',
'ent_account_automatic', 'lms_account_automatic', 'type_session']
'ent_account_automatic', 'lms_account_automatic', 'type_session', 'entre_scolaire', 'entre_scolaire']
incom_keys = diction.keys()
for val in incom_keys:
@ -312,6 +312,13 @@ def Add_Update_SessionFormation(diction):
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le champ 'location_type' est incorrecte.")
return False, "Le champ 'location_type' est incorrect."
if ("entre_scolaire" in diction.keys()):
mydata['entre_scolaire'] = str(diction['entre_scolaire']).lower()
if (str(diction['entre_scolaire']).lower() not in MYSY_GV.TRAINING_ENTREE_SCOLAIRE):
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le champ 'Entrée scolaire' est incorrecte.")
return False, "Le champ 'Entrée scolaire' est incorrect."
if ("is_bpf" in diction.keys()):
if( str(diction['is_bpf']) not in ['0', '1']):
@ -917,7 +924,7 @@ def GetSessionFormation(diction):
RetObject = []
nb_val = 0
for retval in coll_session.aggregate(myquery):
#print(" ##### retval = " + str(retval))
#print(" ##### retval sess = " + str(retval))
user = {}
user = retval
user['id'] = str(nb_val)
@ -1373,6 +1380,7 @@ d'un partenaire, mais avec une liste reduite de champs
- code_session
- titre
- class_internal_url
- class_id
- date_debut
- date_fin
@ -1445,11 +1453,22 @@ def Get_Partner_Session_Ftion_Reduice_Fields(diction):
for retval in MYSY_GV.dbname['session_formation'].find({ "$and" : [ {'partner_owner_recid':str(my_partner['recid']),
'valide':'1',},filt_scope_class_id, filt_scope_session_id, filt_archive, filt_type_session]},
{'_id':1, 'code_session':1, 'titre':1,
'class_internal_url':1, 'date_debut':1,
'class_internal_url':1, 'date_debut':1, 'class_id':1,
'date_fin':1}):
user = retval
user['id'] = str(val_tmp)
class_id_tmp = ""
if( "class_id" not in user.keys()):
class_data = MYSY_GV.dbname['myclass'].find_one({"internal_url":str(user['class_internal_url']),
'partner_owner_recid':str(my_partner['recid']),}, {'_id':1})
if(class_data ):
class_id_tmp = str(class_data['_id'])
user['class_id'] = str(class_id_tmp)
RetObject.append(mycommon.JSONEncoder().encode(user))
val_tmp = val_tmp + 1
@ -1755,6 +1774,11 @@ def GetAllValideSessionPartner_List_Without_Scope_Action(diction):
else:
val['location_type'] = ""
if ("entre_scolaire" in retVal.keys()):
val['entre_scolaire'] = retVal['entre_scolaire']
else:
val['entre_scolaire'] = ""
if ("is_bpf" in retVal.keys()):
val['is_bpf'] = retVal['is_bpf']
else:
@ -1930,6 +1954,12 @@ def GetAllValideSessionPartner_List(diction):
else:
val['location_type'] = ""
if ("entre_scolaire" in retVal.keys()):
val['entre_scolaire'] = retVal['entre_scolaire']
else:
val['entre_scolaire'] = ""
if ("is_bpf" in retVal.keys()):
val['is_bpf'] = retVal['is_bpf']
else:
@ -2336,6 +2366,11 @@ def GetAllValideSessionPartner_List_filter_like(diction):
else:
val['location_type'] = ""
if ("entre_scolaire" in retVal.keys()):
val['entre_scolaire'] = retVal['entre_scolaire']
else:
val['entre_scolaire'] = ""
if ("is_bpf" in retVal.keys()):
val['is_bpf'] = retVal['is_bpf']
else:
@ -2706,6 +2741,11 @@ def GetAllValideSessionPartner_List_no_filter(diction):
else:
val['location_type'] = ""
if ("entre_scolaire" in retVal.keys()):
val['entre_scolaire'] = retVal['entre_scolaire']
else:
val['entre_scolaire'] = ""
if ("is_bpf" in retVal.keys()):
val['is_bpf'] = retVal['is_bpf']
else:
@ -3016,7 +3056,7 @@ def Add_Update_SessionFormation_mass(file=None, Folder=None, diction=None):
'session_status', 'date_debut_inscription', 'date_fin_inscription', 'attestation', 'formateur',
'code_session', "distanciel", "presentiel", "mode_animation", "prix_session", 'contenu_ftion', 'lms_class_code',
'session_ondemande', 'session_etape', 'formation_code_externe', 'formateur_email', 'titre', 'location_type',
'is_bpf', 'type_session']
'is_bpf', 'type_session', 'entre_scolaire']
# Controle du nombre de lignes dans le fichier.
total_rows = len(df)
@ -3507,7 +3547,7 @@ def Controle_Add_Update_SessionFormation_mass(saved_file=None, Folder=None, dict
'session_status', 'date_debut_inscription', 'date_fin_inscription', 'attestation',
'code_session', "distanciel", "presentiel", "mode_animation", "prix_session", 'contenu_ftion', 'lms_class_code',
'session_ondemande', 'session_etape', 'formation_code_externe','formateur_email', 'titre', 'location_type',
'is_bpf', 'type_session']
'is_bpf', 'type_session', 'entre_scolaire']
# Controle du nombre de lignes dans le fichier.
total_rows = len(df)
@ -3671,6 +3711,15 @@ def Controle_Add_Update_SessionFormation_mass(saved_file=None, Folder=None, dict
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le champ 'location_type' est incorrecte.")
return False, "Le champ 'location_type' est incorrect."
if ("entre_scolaire" in df.keys()):
mydata['entre_scolaire'] = str(df['entre_scolaire'].values[n]).strip().lower()
if (str(df['entre_scolaire'].values[n]).strip().lower() not in MYSY_GV.TRAINING_ENTREE_SCOLAIRE):
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le champ 'entre_scolaire' est incorrecte.")
return False, "Le champ 'entre_scolaire' est incorrect."
if ("is_bpf" in df.keys()):
if (str(df['is_bpf'].values[n]).strip() not in ['0', '1']):
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le champ 'bpf' est incorrect. Les valeurs acceptées sont : '1' ou '0' ")
@ -4070,7 +4119,7 @@ def Add_Update_SessionFormation_mass_for_many_class(file=None, Folder=None, dict
'session_status', 'date_debut_inscription', 'date_fin_inscription', 'attestation',
'code_session', "distanciel", "presentiel", "mode_animation", "prix_session", 'contenu_ftion', 'lms_class_code',
'session_ondemande', 'session_etape', 'formation_code_externe', 'formateur_email', 'titre', 'location_type',
'is_bpf', 'type_session']
'is_bpf', 'type_session', 'entre_scolaire']
# Controle du nombre de lignes dans le fichier.
total_rows = len(df)
@ -4195,6 +4244,13 @@ def Add_Update_SessionFormation_mass_for_many_class(file=None, Folder=None, dict
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le champ 'location_type' est incorrecte.")
return False, "Le champ 'location_type' est incorrect."
if ("entre_scolaire" in df.keys()):
mydata['entre_scolaire'] = str(df['entre_scolaire'].values[n]).strip().lower()
if (str(df['entre_scolaire'].values[n]).strip().lower() not in MYSY_GV.TRAINING_ENTREE_SCOLAIRE):
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le champ 'entre_scolaire' est incorrecte.")
return False, "Le champ 'entre_scolaire' est incorrect."
if ("is_bpf" in df.keys()):
is_bpf = str(df['is_bpf'].values[n]).strip()
is_bpf = str(mycommon.tryInt(is_bpf))
@ -4611,7 +4667,7 @@ def Controle_Add_Update_SessionFormation_mass_for_many_class(saved_file=None, Fo
'session_status', 'date_debut_inscription', 'date_fin_inscription', 'attestation',
'code_session', "distanciel", "presentiel", "mode_animation", "prix_session", 'contenu_ftion', 'lms_class_code',
'session_ondemande', 'session_etape', 'formation_code_externe', 'formateur_email', 'titre', 'location_type',
'is_bpf', 'type_session']
'is_bpf', 'type_session', 'entre_scolaire']
# Controle du nombre de lignes dans le fichier.
total_rows = len(df)
@ -4802,6 +4858,15 @@ def Controle_Add_Update_SessionFormation_mass_for_many_class(saved_file=None, Fo
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le champ 'location_type' est incorrecte. Les valeurs acceptés sont : "+str(MYSY_GV.TRAINING_LOCATION_TYPE))
return False, "Le champ 'location_type' est incorrect. . Les valeurs acceptés sont : "+str(MYSY_GV.TRAINING_LOCATION_TYPE)+ " "
if ("entre_scolaire" in df.keys()):
mydata['entre_scolaire'] = str(df['entre_scolaire'].values[n]).strip().lower()
if (str(df['entre_scolaire'].values[n]).strip().lower() not in MYSY_GV.TRAINING_ENTREE_SCOLAIRE):
mycommon.myprint(str(inspect.stack()[0][3]) + " - Le champ 'entre_scolaire' est incorrecte. Les valeurs acceptés sont : "+str(MYSY_GV.TRAINING_ENTREE_SCOLAIRE))
return False, "Le champ 'entre_scolaire' est incorrect. . Les valeurs acceptés sont : "+str(MYSY_GV.TRAINING_ENTREE_SCOLAIRE)+ " "
if ("is_bpf" in df.keys()):
is_bpf = str(df['is_bpf'].values[n]).strip()
is_bpf = str(mycommon.tryInt(is_bpf))
@ -13256,7 +13321,6 @@ def Invoice_Partner_From_Session_By_Inscription_Id( diction):
"""
27/08/2024 - update pour faire le BPF
on va créer une table de detail qui reprend le detail des inscription
"""
@ -14131,6 +14195,24 @@ def Invoice_Create_Secure_E_Document(diction):
user['valide'] = retval['valide']
user['locked'] = retval['locked']
"""
Si on a une session, on va aller chercher les info de la session
"""
session_date_debut = ""
session_date_fin = ""
if ("order_line_session_id" in retval.keys() and retval['order_line_session_id']):
session_data = MYSY_GV.dbname['session_formation'].find_one(
{'_id': ObjectId(str(retval['order_line_session_id'])),
'partner_owner_recid': str(retval['partner_owner_recid'])},
)
if (session_data and "date_debut" in session_data.keys() and "date_fin" in session_data.keys()):
session_date_debut = str(session_data['date_debut'])
session_date_fin = str(session_data['date_fin'])
user['session_date_debut'] = str(session_date_debut)
user['session_date_fin'] = str(session_date_fin)
if ("order_line_montant_reduction" in retval.keys()):
user['order_line_montant_reduction'] = retval['order_line_montant_reduction']
else:
@ -14339,7 +14421,6 @@ def Invoice_Create_Secure_E_Document(diction):
3]) + " - Aucune ligne de détail pour cette facture ")
return False, " Aucune ligne de détail pour cette facture "
# print(" ### Order_header_lines_data = ", Order_header_lines_data)
contenu_doc_Template = jinja2.Template(str(partner_document_PART_INVOICE_data['contenu_doc']))
@ -14375,6 +14456,8 @@ def Invoice_Create_Secure_E_Document(diction):
convention_dictionnary_data['order_header'] = Order_header_data
convention_dictionnary_data['order_lines'] = Order_header_lines_data
#print(" ### Order_header_lines_data === ", Order_header_lines_data)
# sourceHtml = contenu_doc_Template.render(params=Order_header_data, param_order_lines=Order_header_lines_data, company_data=company_data)
# sourceHtml = contenu_doc_Template.render(params_order_header=Order_header_data, params_order_lines=Order_header_lines_data, params=company_data['params'])
@ -15396,7 +15479,7 @@ def Add_SessionFormation_From_Quotation_Line(diction):
'lms_class_code',
'session_ondemande', 'source', 'session_etape', 'pays', 'formateur_id',
'titre', 'location_type', 'is_bpf', 'site_formation_id', 'price_by',
'quotation_line_id', 'resa_inscrit']
'quotation_line_id', 'resa_inscrit', 'entre_scolaire']
incom_keys = diction.keys()
for val in incom_keys:

View File

@ -4207,9 +4207,6 @@ def Decale_Session_Sequence_X_days(diction):
'partner_owner_recid': str(my_partner['recid'])},
{'$set': new_data})
"""
Après la mise à jour de la sequence,
il faut mettre à jour le planning des ressources associée
@ -4345,7 +4342,6 @@ def Decale_Session_Sequence_X_days(diction):
new_data['update_by'] = str(my_partner['recid'])
ret_val = MYSY_GV.dbname['session_formation'].find_one_and_update(
{'_id': ObjectId(str(local_session_id)), 'valide': '1',
'partner_owner_recid': str(my_partner['recid'])},
@ -4354,7 +4350,18 @@ def Decale_Session_Sequence_X_days(diction):
return_document=ReturnDocument.AFTER
)
"""
Mettre à jour les inscriptions associées à cette session
"""
new_inscription_data = {}
new_inscription_data['date_au'] = str(session_new_start_date.strftime("%d/%m/%Y"))
new_inscription_data['date_du'] = str(session_new_end_date.strftime("%d/%m/%Y"))
new_inscription_data['date_update'] = datetime.now()
new_inscription_data['update_by'] = str(my_partner['recid'])
update = MYSY_GV.dbname['inscription'].update_many({'partner_owner_recid': str(my_partner['recid']),
'session_id': str(local_session_id),},
{'$set': new_inscription_data})
# Logguer l'action de decalage dans l'historique de la session
# pour la collection 'myclass'

View File

@ -2810,7 +2810,7 @@ d'un appernant (bulletin de note)
"""
def Prepare_and_Send_Inscrit_Bulletin_Note_By_PDF(diction):
try:
field_list_obligatoire = ['token', 'tab_inscrit_ids', 'courrier_template_id']
field_list_obligatoire = ['token', 'tab_inscrit_ids']
for val in field_list_obligatoire:
if val not in diction:
@ -2853,6 +2853,25 @@ def Prepare_and_Send_Inscrit_Bulletin_Note_By_PDF(diction):
return False, " L'inscription '" + tmp + "' est invalide "
"""
Aller chercher le modele de courrier 'INSCRIT_BULLETIN_NOTE'
"""
local_diction = {}
local_diction['ref_interne'] = "INSCRIT_BULLETIN_NOTE"
local_diction['type_doc'] = "pdf"
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
if ("contenu_doc" not in courrier_data_retval.keys() or str(courrier_data_retval['contenu_doc']) == ""):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " Le modèle de courrier 'INSCRIT_BULLETIN_NOTE' n'est pas correctement configuré ")
return False, " Le modèle de courrier 'INSCRIT_BULLETIN_NOTE' n'est pas correctement configuré "
# Stokage des nom de fichier à zipper
list_file_name_to_zip = []
for inscrit in tab_inscrit_ids:
@ -2863,7 +2882,7 @@ def Prepare_and_Send_Inscrit_Bulletin_Note_By_PDF(diction):
local_node = {}
local_node['inscription_id'] = str(inscription_data['_id'])
local_node['courrier_template_id'] = str(diction['courrier_template_id'])
local_node['courrier_template_id'] = str(courrier_data_retval['_id'])
local_node['token'] = str(diction['token'])
local_node['session_id'] = str(inscription_data['session_id'])
@ -2929,6 +2948,11 @@ def Create_Bulletin_By_Inscrit_PDF(diction):
return local_status, my_partner
print(" ### QRY = ", {'_id':ObjectId(str(diction['courrier_template_id'])),
'valide':'1',
'locked':'0',
'ref_interne': 'INSCRIT_BULLETIN_NOTE',
'partner_owner_recid':str(my_partner['recid'])})
# 1 - Verifier que le modele de courrier est bien editable par individu
template_courrier_data = MYSY_GV.dbname['courrier_template'].find_one({'_id':ObjectId(str(diction['courrier_template_id'])),
@ -2940,8 +2964,8 @@ def Create_Bulletin_By_Inscrit_PDF(diction):
if (template_courrier_data is None ):
mycommon.myprint(
str(inspect.stack()[0][
3]) + "L'identifiant du modèle de document "+str(diction['courrier_template_id'])+" est invalide")
return False, "L'identifiant du modèle de document "+str(diction['courrier_template_id'])+" est invalide "
3]) + " L'identifiant du modèle de document "+str(diction['courrier_template_id'])+" est invalide")
return False, " L'identifiant du modèle de document "+str(diction['courrier_template_id'])+" est invalide "
if( "edit_by_client" in template_courrier_data.keys() and str(template_courrier_data['edit_by_client']) == "1" ):
mycommon.myprint(

View File

@ -169,7 +169,7 @@ def Add_Update_base_document_automatic_setup(diction):
"""
Recuperation de la liste des documents parametrés pour un partenaire donné
Recuperation de la liste des documents paramétrés pour un partenaire donné
"""
def Get_List_base_document_automatic_setup(diction):
try:

View File

@ -372,7 +372,7 @@ def Get_List_Partner_session_step(diction):
"""
Recuperation des informations d'un point de parametrage donnée
Recuperation des informations d'un point de paramétrage donnée
"""
def Get_Given_Partner_session_step(diction):
try:
@ -416,7 +416,7 @@ def Get_Given_Partner_session_step(diction):
if( str(diction['session_step_name']) not in MYSY_GV.PARTNER_BASE_session_step_name ):
mycommon.myprint(
str(inspect.stack()[0][3]) + " - La valeur '" + str(diction['session_step_name']) + "' n'est pas valide ")
return False, " Point de parametrage "+ str(diction['session_step_name']) + " invalide "
return False, " Point de paramétrage "+ str(diction['session_step_name']) + " invalide "
RetObject = []

View File

@ -13,6 +13,7 @@ from bson import ObjectId
from pymongo import ReturnDocument
from xhtml2pdf import pisa
import email_mgt
import module_editique
import prj_common as mycommon
import GlobalVariable as MYSY_GV
@ -142,16 +143,18 @@ def incription_training_confirmation_mail(diction):
date_fin = diction['date_au']
# JINJA2
# JINJA2 zzzzz
templateLoader = jinja2.FileSystemLoader(searchpath="./")
templateEnv = jinja2.Environment(loader=templateLoader)
TEMPLATE_FILE = "Template/MySy_confirmation_inscription_formation_tpl.html"
template = templateEnv.get_template(TEMPLATE_FILE)
#TEMPLATE_FILE = "Template/MySy_confirmation_inscription_formation_tpl.html"
#template = templateEnv.get_template(TEMPLATE_FILE)
# This data can come from database query
body = {
"params" :{"nom": str(diction['nom']),
"prenom": str(prenom),
"date_debut": str(date_du),
"date_du": str(date_du),
"date_fin": str(date_fin),
"adresse": str(adresse_session),
@ -167,9 +170,9 @@ def incription_training_confirmation_mail(diction):
#print(" ### BODY DATA = ", body)
sourceHtml = template.render(params=body["params"])
#sourceHtml = template.render(params=body["params"])
msg.set_content(sourceHtml, subtype='html')
#msg.set_content(sourceHtml, subtype='html')
"""
Update du 10/09/2023 :
@ -204,14 +207,14 @@ def incription_training_confirmation_mail(diction):
if (partner_document_CONF_INSCRIPTION_data is None):
mycommon.myprint(
str(inspect.stack()[0][
3]) + "-Impossible d'envoyer l'email de la preinscription. Aucun document parametré ")
return False, " Impossible d'envoyer l'email de la preinscription. Aucun document parametré "
3]) + "-Impossible d'envoyer l'email de la preinscription. Aucun document paramétré ")
return False, " Impossible d'envoyer l'email de la preinscription. Aucun document paramétré "
if ("contenu_doc" not in partner_document_CONF_INSCRIPTION_data or len(
str(partner_document_CONF_INSCRIPTION_data['contenu_doc'])) <= 0):
mycommon.myprint(str(inspect.stack()[0][
3]) + " -Impossible d'envoyer l'email de la preinscription. Le parametrage du document est invalide")
return False, " Impossible d'envoyer l'email de la preinscription. Le parametrage du document est invalide "
3]) + " -Impossible d'envoyer l'email de la preinscription. Le paramétrage du document est invalide")
return False, " Impossible d'envoyer l'email de la preinscription. Le paramétrage du document est invalide "
#print(' #### partner_document_CONF_INSCRIPTION_data[contenu_doc]) === ', partner_document_CONF_INSCRIPTION_data['contenu_doc'])
@ -279,6 +282,7 @@ def incription_training_confirmation_mail(diction):
msg['Subject'] = '[MySy Training]: Confirmation inscription formation'
msg['To'] = str(diction['email'])
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(partner_SMTP_COUNT_user, partner_SMTP_COUNT_password)
@ -628,14 +632,14 @@ def incription_training_refused_mail(diction):
if (partner_document_REFUS_INSCRIPTION_data is None):
mycommon.myprint(
str(inspect.stack()[0][
3]) + "-Impossible d'envoyer l'email de la preinscription. Aucun document parametré ")
return False, " Impossible d'envoyer l'email de la preinscription. Aucun document parametré "
3]) + "-Impossible d'envoyer l'email de la preinscription. Aucun document paramétré ")
return False, " Impossible d'envoyer l'email de la preinscription. Aucun document paramétré "
if ("contenu_doc" not in partner_document_REFUS_INSCRIPTION_data or len(
str(partner_document_REFUS_INSCRIPTION_data['contenu_doc'])) <= 0):
mycommon.myprint(str(inspect.stack()[0][
3]) + " -Impossible d'envoyer l'email de la preinscription. Le parametrage du document est invalide")
return False, " Impossible d'envoyer l'email de la preinscription. Le parametrage du document est invalide "
3]) + " -Impossible d'envoyer l'email de la preinscription. Le paramétrage du document est invalide")
return False, " Impossible d'envoyer l'email de la preinscription. Le paramétrage du document est invalide "
REFUS_INSCRIPTION_contenu_doc_Template = jinja2.Template(
str(partner_document_REFUS_INSCRIPTION_data['contenu_doc']))
@ -827,14 +831,14 @@ def incription_training_cancelled_mail(diction):
if (partner_document_ANNULE_INSCRIPTION_data is None):
mycommon.myprint(
str(inspect.stack()[0][
3]) + "-Impossible d'envoyer l'email d'annulation de l'inscription. Aucun document parametré ")
return False, " Impossible d'envoyer l'email d'annulation de l'inscription. Aucun document parametré "
3]) + "-Impossible d'envoyer l'email d'annulation de l'inscription. Aucun document paramétré ")
return False, " Impossible d'envoyer l'email d'annulation de l'inscription. Aucun document paramétré "
if ("contenu_doc" not in partner_document_ANNULE_INSCRIPTION_data or len(
str(partner_document_ANNULE_INSCRIPTION_data['contenu_doc'])) <= 0):
mycommon.myprint(str(inspect.stack()[0][
3]) + " -Impossible d'envoyer l'email d'annulation de l'inscription. Le parametrage du document est invalide")
return False, " Impossible d'envoyer l'email d'annulation de l'inscription. Le parametrage du document est invalide "
3]) + " -Impossible d'envoyer l'email d'annulation de l'inscription. Le paramétrage du document est invalide")
return False, " Impossible d'envoyer l'email d'annulation de l'inscription. Le paramétrage du document est invalide "
ANNULE_INSCRIPTION_contenu_doc_Template = jinja2.Template(
str(partner_document_ANNULE_INSCRIPTION_data['contenu_doc']))
@ -1088,12 +1092,12 @@ def Pre_incription_training_confirmation_mail(diction):
if( partner_document_PRE_INSCRIPTION_data is None):
mycommon.myprint(
str(inspect.stack()[0][3]) + "-Impossible d'envoyer l'email de la preinscription. Aucun document parametré ")
return False, " Impossible d'envoyer l'email de la preinscription. Aucun document parametré "
str(inspect.stack()[0][3]) + "-Impossible d'envoyer l'email de la preinscription. Aucun document paramétré ")
return False, " Impossible d'envoyer l'email de la preinscription. Aucun document paramétré "
if( "contenu_doc" not in partner_document_PRE_INSCRIPTION_data or len(str(partner_document_PRE_INSCRIPTION_data['contenu_doc'])) <= 0 ):
mycommon.myprint( str(inspect.stack()[0][3]) + " -Impossible d'envoyer l'email de la preinscription. Le parametrage du document est invalide")
return False, " Impossible d'envoyer l'email de la preinscription. Le parametrage du document est invalide "
mycommon.myprint( str(inspect.stack()[0][3]) + " -Impossible d'envoyer l'email de la preinscription. Le paramétrage du document est invalide")
return False, " Impossible d'envoyer l'email de la preinscription. Le paramétrage du document est invalide "
PRE_INSCRIPTION_contenu_doc_Template = jinja2.Template(str(partner_document_PRE_INSCRIPTION_data['contenu_doc']))
sourceHtml = PRE_INSCRIPTION_contenu_doc_Template.render(params=body["params"])
@ -2263,10 +2267,15 @@ def LMS_Credential_Sending_mail(diction):
return False, "Le compte LMS n'est pas valide"
"""
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data({'token':str(diction['token'])})
if (local_status is not True):
return local_status, my_partner
tomorrow = datetime.date.today() + datetime.timedelta(days=1)
tomorrow_day = tomorrow.strftime("%A")
print("debut envoi mail de test ")
"""
Verification si c'est une formation en ligne.
@ -2396,6 +2405,32 @@ def LMS_Credential_Sending_mail(diction):
msg['Bcc'] = 'contact@mysy-training.com,' + str(str(diction['course_owner_email']))
msg['Subject'] = sujetHtml
msg['To'] = str(diction['email'])
"""
Gestion mail_queue
"""
mail_queue_local_diction = {}
mail_queue_local_diction['token'] = diction['token']
mail_queue_local_diction['partner_own_smtp_value'] = partner_own_smtp_value
mail_queue_local_diction['partner_SMTP_COUNT_smtpsrv'] = partner_SMTP_COUNT_smtpsrv
mail_queue_local_diction['partner_SMTP_COUNT_port'] = partner_SMTP_COUNT_port
mail_queue_local_diction['inscription_id'] = ""
mail_queue_local_diction['related_collection'] = ""
mail_queue_local_diction['partner_SMTP_COUNT_From_User'] = partner_SMTP_COUNT_From_User
mail_queue_local_diction['tab_email_cc'] = tab_email_cc
mail_queue_local_diction['tab_email_bcc'] = tab_email_bcc
mail_queue_local_diction['tab_files_to_attache_to_mail'] = []
mail_queue_local_diction['email_sujet'] = sujetHtml
mail_queue_local_diction['html_mime'] = html_mime
mail_queue_local_diction['email_to'] = email
mail_queue_local_diction['partner_owner_recid'] = str(my_partner['recid'])
# print(" ### mail_queue_local_diction = ", mail_queue_local_diction)
local_status, local_retval = email_mgt.send_invidual_email(mail_queue_local_diction)
if (local_status is False):
return local_status, local_retval
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(partner_SMTP_COUNT_user, partner_SMTP_COUNT_password)
@ -2521,14 +2556,14 @@ def Employee_Credential_Sending_mail(diction):
if (partner_document_EMPLOYEE_CREDENTIALS_data is None):
mycommon.myprint(
str(inspect.stack()[0][
3]) + "-Impossible d'envoyer l'email de notification des accès. Aucun document parametré ")
return False, " Impossible d'envoyer l'email de notification des accès. Aucun document parametré "
3]) + "-Impossible d'envoyer l'email de notification des accès. Aucun document paramétré ")
return False, " Impossible d'envoyer l'email de notification des accès. Aucun document paramétré "
if ("contenu_doc" not in partner_document_EMPLOYEE_CREDENTIALS_data or len(
str(partner_document_EMPLOYEE_CREDENTIALS_data['contenu_doc'])) <= 0):
mycommon.myprint(str(inspect.stack()[0][
3]) + " -Impossible d'envoyer l'email de notification des accès. Le parametrage du document est invalide")
return False, " Impossible d'envoyer l'email de notification des accès. Le parametrage du document est invalide "
3]) + " -Impossible d'envoyer l'email de notification des accès. Le paramétrage du document est invalide")
return False, " Impossible d'envoyer l'email de notification des accès. Le paramétrage du document est invalide "
EMPLOYEE_CREDENTIALS_contenu_doc_Template = jinja2.Template(
str(partner_document_EMPLOYEE_CREDENTIALS_data['contenu_doc']))
@ -2707,14 +2742,14 @@ def Employee_Acces_LMS_Sending_mail(diction):
if (partner_document_EMPLOYEE_CREDENTIALS_data is None):
mycommon.myprint(
str(inspect.stack()[0][
3]) + "-Impossible d'envoyer l'email de notification des accès. Aucun document parametré ")
return False, " Impossible d'envoyer l'email de notification des accès. Aucun document parametré "
3]) + "-Impossible d'envoyer l'email de notification des accès. Aucun document paramétré ")
return False, " Impossible d'envoyer l'email de notification des accès. Aucun document paramétré "
if ("contenu_doc" not in partner_document_EMPLOYEE_CREDENTIALS_data or len(
str(partner_document_EMPLOYEE_CREDENTIALS_data['contenu_doc'])) <= 0):
mycommon.myprint(str(inspect.stack()[0][
3]) + " -Impossible d'envoyer l'email de notification des accès. Le parametrage du document est invalide")
return False, " Impossible d'envoyer l'email de notification des accès. Le parametrage du document est invalide "
3]) + " -Impossible d'envoyer l'email de notification des accès. Le paramétrage du document est invalide")
return False, " Impossible d'envoyer l'email de notification des accès. Le paramétrage du document est invalide "
EMPLOYEE_CREDENTIALS_contenu_doc_Template = jinja2.Template(
str(partner_document_EMPLOYEE_CREDENTIALS_data['contenu_doc']))

View File

@ -29,6 +29,8 @@ import strype_payement as strype_payement
import ressources_humaines as ressources_humaines
import email_queu.email_queu_mgt as email_queu_mgt
import internal_email_mgt as internal_email_mgt
configuration = sib_api_v3_sdk.Configuration()
configuration.api_key['api-key'] = MYSY_GV.SENDINBLUE_API_KEY
@ -2488,7 +2490,7 @@ def ManualSendInvoiceEmailRIB_CIC_JMJFormation(diction):
body = {
"params": {"order_id": "MTT/2025_N°0012/JMJ FORMATION",
"date_order": ": 14/07/2025",
"periode":"14/08/2025 au 13/09/2025",
"periode":"14/09/2025 au 13/10/2025",
"total_ht": "130",
"tva": "11.05",
"total_ttc": "141,05 ",
@ -2504,9 +2506,9 @@ def ManualSendInvoiceEmailRIB_CIC_JMJFormation(diction):
"montant": "130 €",
"invoice_id": "FACT_20250816",
"invoice_date": "14/08/2025",
"due_date": "14/08/2025",
"invoice_id": "FACT_20250910",
"invoice_date": "14/09/2025",
"due_date": "14/09/2025",
"orign_order": "Contrat MTT/2025_N°0012/JMJ FORMATION",
}
}
@ -2540,7 +2542,7 @@ def ManualSendInvoiceEmailRIB_CIC_JMJFormation(diction):
#print(" ### body 22 = ", body)
sourceHtml = template.render(json_data=body["params"])
orig_file_name = "invoice_FACT_20250816.pdf"
orig_file_name = "invoice_FACT_20250910.pdf"
outputFilename = str(MYSY_GV.INVOICE_DIRECTORY) + str(orig_file_name)
# open output file for writing (truncated binary)
@ -2703,24 +2705,24 @@ def ManualSendInvoiceEmailRIB_CIC_BureauVallee(diction):
body = {
"params": {"order_id": "N/A",
"date_order": ": 12/08/2025",
"periode":"12/08/2025 au 29/08/2025",
"total_ht": "6360,81",
"tva": "1100",
"total_ttc": "7460,81",
"periode":"01/09/2025 au 30/09/2025",
"total_ht": "12 530,18",
"tva": "2 506,04",
"total_ttc": "15 036,22",
"client_name": "BVD Fr (Bureau Vallée)",
"client_address": "25 rue du Gros Caillou",
"client_zip_ville": "78340 Les Clayes-sous-Bois",
"client_pays": "France",
"packs": "Prestation de service ",
"detail_packs": "Accompagnement au deploiement de l'ERP CoQliQo",
"qty": "10 jours",
"unit_price": "550 HT ",
"montant": "5 500",
"detail_packs": "Accompagnement au déploiement de l'ERP CoQliQo",
"qty": "22 jours (-1h)",
"unit_price": "550 ",
"montant": "12 021,43",
"invoice_id": "FACT_20250817",
"invoice_date": "29/08/2025",
"due_date": "15/09/2025",
"invoice_id": "FACT_20250919",
"invoice_date": "30/09/2025",
"due_date": "15/10/2025",
"orign_order": "N/A",
}
}
@ -2754,7 +2756,7 @@ def ManualSendInvoiceEmailRIB_CIC_BureauVallee(diction):
#print(" ### body 22 = ", body)
sourceHtml = template.render(json_data=body["params"])
orig_file_name = "invoice_FACT_20250817.pdf"
orig_file_name = "invoice_FACT_20250919.pdf"
outputFilename = str(MYSY_GV.INVOICE_DIRECTORY) + str(orig_file_name)
# open output file for writing (truncated binary)
@ -3649,7 +3651,7 @@ def Prepare_and_Send_Email_From_Front(tab_files, Folder, diction):
local_diction['partner_own_smtp_value'] = partner_own_smtp_value
local_diction['partner_SMTP_COUNT_smtpsrv'] = partner_SMTP_COUNT_smtpsrv
local_diction['partner_SMTP_COUNT_port'] = partner_SMTP_COUNT_port
local_diction['user_id'] = user_id
local_diction['inscription_id'] = user_id
local_diction['related_collection'] = related_collection
local_diction['partner_SMTP_COUNT_From_User'] = partner_SMTP_COUNT_From_User
local_diction['tab_email_cc'] = tab_email_cc
@ -3657,7 +3659,7 @@ def Prepare_and_Send_Email_From_Front(tab_files, Folder, diction):
local_diction['tab_files_to_attache_to_mail'] = tab_files_to_attache_to_mail
local_diction['email_sujet'] = email_sujet
local_diction['html_mime'] = html_mime
local_diction['email'] = email
local_diction['email_to'] = email
local_diction['partner_owner_recid'] = str(my_partner['recid'])
@ -3781,7 +3783,7 @@ def Prepare_and_Send_Email_From_Front_For_Unknown_Contact(tab_files, Folder, dic
tab_email_cc = str(tab_email_cc).split(",")
for email_cc in tab_email_cc:
if (email_cc):
if (mycommon.isEmailValide(str(email_cc)) is False):
if (mycommon.isEmailValide(str(email_cc.strip())) is False):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'adresse email en CC '" + str(email_cc) + "' est invalide ")
return False, "L'adresse email en CC '" + str(email_cc) + "' est invalide"
@ -3804,7 +3806,7 @@ def Prepare_and_Send_Email_From_Front_For_Unknown_Contact(tab_files, Folder, dic
for email_bcc in tab_email_bcc:
if (email_bcc):
if (mycommon.isEmailValide(str(email_bcc)) is False):
if (mycommon.isEmailValide(str(email_bcc.strip())) is False):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'adresse email en BCC '" + str(email_bcc) + "' est invalide ")
return False, "L'adresse email en BCC '" + str(email_bcc) + "' est invalide"
@ -3826,14 +3828,13 @@ def Prepare_and_Send_Email_From_Front_For_Unknown_Contact(tab_files, Folder, dic
tab_email_dest = str(tab_email_dest).split(",")
for email_dest in tab_email_dest:
if( email_dest ):
if (mycommon.isEmailValide(str(email_dest)) is False):
if (mycommon.isEmailValide(str(email_dest).strip()) is False):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'adresse email '" + str(email_dest) + "' est invalide ")
return False, "L'adresse email '" + str(email_dest) + "' est invalide"
#print(" ### la liste _id des destinataire est ", str(tab_related_collection_id))
if(len(tab_email_dest) > MYSY_GV.EMAIL_MAX_DESTINAIRE ):
@ -3922,7 +3923,7 @@ def Prepare_and_Send_Email_From_Front_For_Unknown_Contact(tab_files, Folder, dic
local_diction['partner_own_smtp_value'] = partner_own_smtp_value
local_diction['partner_SMTP_COUNT_smtpsrv'] = partner_SMTP_COUNT_smtpsrv
local_diction['partner_SMTP_COUNT_port'] = partner_SMTP_COUNT_port
local_diction['user_id'] = ""
local_diction['inscription_id'] = ""
local_diction['related_collection'] = related_collection
local_diction['partner_SMTP_COUNT_From_User'] = partner_SMTP_COUNT_From_User
local_diction['tab_email_cc'] = tab_email_cc
@ -3932,7 +3933,7 @@ def Prepare_and_Send_Email_From_Front_For_Unknown_Contact(tab_files, Folder, dic
local_diction['email_sujet'] = email_sujet
local_diction['html_mime'] = html_mime
local_diction['initial_message'] = sourceHtml
local_diction['email'] = str(local_email_dest)
local_diction['email_to'] = str(local_email_dest)
local_status, local_retval = send_invidual_email (local_diction)
if( local_status is False ):
@ -3951,7 +3952,12 @@ def Prepare_and_Send_Email_From_Front_For_Unknown_Contact(tab_files, Folder, dic
"""
Envoi d'un email email individuel
Envoi d'un email email individuel.
Important :
Cette fonction va faire 2 choses :
1 - Add_Message_To_Mail_Queue : Mettre l'email la file (queu des email)
2 - Add_Message_To_Internal_Mail : Si le destinataire a un compte interne, le système va egalement
mettre l'email dans la table des emails internes
"""
def send_invidual_email(diction):
try:
@ -3987,8 +3993,8 @@ def send_invidual_email(diction):
tab_files_to_attache_to_mail = diction['tab_files_to_attache_to_mail']
email_sujet = diction['email_sujet']
html_mime = diction['html_mime']
email = diction['email']
user_id = diction['user_id']
email_to = diction['email_to']
inscription_id = diction['inscription_id']
related_collection = diction['related_collection']
if( "include_tuteur" in diction.keys() ):
@ -4011,7 +4017,7 @@ def send_invidual_email(diction):
if(related_collection == "inscription" ):
inscription_data = MYSY_GV.dbname['inscription'].find_one({'_id':ObjectId(str(user_id)),
inscription_data = MYSY_GV.dbname['inscription'].find_one({'_id':ObjectId(str(inscription_id)),
'partner_owner_recid':str(partner_owner_recid)},
)
@ -4039,17 +4045,13 @@ def send_invidual_email(diction):
if ("tuteur2_include_com" in inscription_data and inscription_data['tuteur2_include_com'] == "1"):
tab_email_cc.append(inscription_data['tuteur2_email'])
# Recuperation des donnes smtp
(local_stpm_status, local_SMTP_COUNT_smtpsrv, local_own_smtp_value, local_SMTP_COUNT_password,
local_SMTP_COUNT_user, local_SMTP_COUNT_From_User,
local_SMTP_COUNT_port) = mycommon.Get_Partner_SMTP_Param(str(my_partner['recid']))
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(MYSY_GV.O365_SMTP_COUNT_user, MYSY_GV.O365_SMTP_COUNT_password)
cpt_email_envoye = 0
if (local_stpm_status is False):
return local_stpm_status, partner_own_smtp_value
"""
Envoie proprement-dit des emails
@ -4060,84 +4062,179 @@ def send_invidual_email(diction):
tab_email_bcc.append(str(my_partner['email']))
queue_mail_diction = {}
""" 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['from'] = MYSY_GV.O365_SMTP_COUNT_From_User
queue_mail_diction['cc'] = ",".join(tab_email_cc)
queue_mail_diction['bcc'] = ",".join(tab_email_bcc)
queue_mail_diction['subject'] = email_sujet
queue_mail_diction['to'] = str(email)
queue_mail_diction['tab_email_cc'] = tab_email_cc
queue_mail_diction['tab_email_bcc'] = tab_email_bcc
queue_mail_diction['email_sujet'] = email_sujet
queue_mail_diction['email_to'] = str(email_to)
queue_mail_diction['message'] = diction['initial_message']
queue_mail_diction['smtp_account_password'] = local_SMTP_COUNT_password
queue_mail_diction['smtp_account_smtpsrv'] = local_SMTP_COUNT_smtpsrv
queue_mail_diction['smtp_account_user'] = local_SMTP_COUNT_user
queue_mail_diction['smtp_account_From_User'] = local_SMTP_COUNT_From_User
queue_mail_diction['smtp_account_port'] = local_SMTP_COUNT_port
if( "tab_saved_file_full_path" in diction.keys() ):
queue_mail_diction['tab_saved_file_full_path'] = diction['tab_saved_file_full_path']
queue_mail_diction['tab_files_to_attache_to_mail'] = diction['tab_saved_file_full_path']
else:
queue_mail_diction = []
queue_mail_diction['smtp_account_password'] = MYSY_GV.O365_SMTP_COUNT_password
queue_mail_diction['smtp_account_smtpsrv'] = MYSY_GV.O365_SMTP_COUNT_smtpsrv
queue_mail_diction['smtp_account_user'] = MYSY_GV.O365_SMTP_COUNT_user
queue_mail_diction['smtp_account_From_User'] = MYSY_GV.O365_SMTP_COUNT_user
queue_mail_diction['smtp_account_port'] = MYSY_GV.O365_SMTP_COUNT_port
internal_mail_diction = {}
for tmp in queue_mail_diction.keys() :
internal_mail_diction[str(tmp)] = queue_mail_diction[str(tmp)]
queue_and_internal_mail_status, queue_and_internal_mail_status = 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)
return True, " Les emails ont été correctement 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 d'envoyer les emails "
def Individual_Mail_Store_Queu_And_Internal_Mail(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'smtp_account_password', 'smtp_account_smtpsrv', 'smtp_account_user', 'smtp_account_From_User', 'smtp_account_port',
'tab_email_cc', 'tab_email_bcc', 'tab_files_to_attache_to_mail', 'email_sujet', 'html_mime', 'email_to',
'partner_owner_recid', 'message']
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",
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
if ("tab_email_cc" in diction.keys()):
tab_email_cc = diction['tab_email_cc']
else:
tab_email_cc = ""
if ("tab_email_bcc" in diction.keys()):
tab_email_bcc = diction['tab_email_bcc']
else:
tab_email_bcc = ""
"""
IMPORTANT : Cette section sera utilisée une fois que le module de Queu de message est ok
"""
list_cc = ""
for tmp in tab_email_cc:
if (tmp and list_cc):
list_cc = list_cc + ", " + str(tmp)
elif (tmp):
list_cc = str(tmp)
list_ccb = ""
for tmp in tab_email_bcc:
if (tmp and list_ccb):
list_ccb = list_ccb + ", " + str(tmp)
elif (tmp):
list_ccb = str(tmp)
queue_mail_diction = {}
queue_mail_diction['token'] = diction['token']
queue_mail_diction['from'] = diction['smtp_account_From_User']
queue_mail_diction['cc'] = list_cc
queue_mail_diction['bcc'] = str(list_ccb)
queue_mail_diction['subject'] = diction['email_sujet']
queue_mail_diction['to'] = diction['email_to']
queue_mail_diction['message'] = diction['message']
if ("tab_files_to_attache_to_mail" in diction.keys()):
queue_mail_diction['tab_saved_file_full_path'] = diction['tab_files_to_attache_to_mail']
else:
queue_mail_diction = []
queue_mail_diction['smtp_account_password'] = diction['smtp_account_password']
queue_mail_diction['smtp_account_smtpsrv'] = diction['smtp_account_smtpsrv']
queue_mail_diction['smtp_account_user'] = diction['smtp_account_user']
queue_mail_diction['smtp_account_From_User'] = diction['smtp_account_From_User']
queue_mail_diction['smtp_account_port'] = diction['smtp_account_port']
internal_mail_diction = {}
for tmp in queue_mail_diction.keys():
internal_mail_diction[str(tmp)] = queue_mail_diction[str(tmp)]
tab_files = []
queue_mail_status, queue_mail_retval = email_queu_mgt.Add_Message_To_Mail_Queue(tab_files, queue_mail_diction)
if (queue_mail_status is False):
print(" ## WARNING queue_mail_retval = ", queue_mail_retval)
"""
Si l'email du destinataire existe dans l'une des collection :
- partnair_account ou
- user_account
Alors il faudra gerer le email dans la collection 'internal_email'
"""
local_related_collection = ""
local_related_collection_recid = ""
is_destinataire_systeme_user_count = MYSY_GV.dbname['partnair_account'].count_documents({'email': str(diction['email_to']),
'active': '1',
'recid': str(
my_partner[
'recid'])
})
if (is_destinataire_systeme_user_count == 1):
destinataire_systeme_user_data = MYSY_GV.dbname['partnair_account'].find_one({'email': str(diction['email_to']),
'active': '1',
'recid': str(
my_partner[
'recid'])
}, {'_id': 1})
local_related_collection = "partnair_account"
local_related_collection_recid = str(destinataire_systeme_user_data['_id'])
else:
destinataire_systeme_user_data = MYSY_GV.dbname['user_account'].find_one({'email': str(diction['email_to']),
'active': '1',
'partner_owner_recid': str(
my_partner[
'recid'])
}, {'_id': 1})
if (destinataire_systeme_user_data):
local_related_collection = "user_account"
local_related_collection_recid = str(destinataire_systeme_user_data['_id'])
internal_mail_diction['related_collection'] = str(local_related_collection)
internal_mail_diction['related_collection_recid'] = str(local_related_collection_recid)
internal_mail_status, internal_mail_retval = internal_email_mgt.Add_Message_To_Internal_Mail(tab_files,
internal_mail_diction)
if (queue_mail_status is False):
print(" ## WARNING internal_mail_retval = ", internal_mail_retval)
"""
tab_files = []
queue_mail_status, queue_mail_retval = email_queu_mgt.Add_Message_To_Mail_Queue(tab_files, queue_mail_diction)
if( queue_mail_status is False):
print(" ## WARNING queue_mail_retval = ", queue_mail_retval)
if (str(partner_own_smtp_value) == "1"):
msg.attach(html_mime)
msg['From'] = partner_SMTP_COUNT_From_User
msg['Cc'] = ",".join(tab_email_cc)
msg['Bcc'] = ",".join(tab_email_bcc)
msg['Subject'] = email_sujet
msg['to'] = str(email)
# Attacher l'eventuelle pièces jointes
for myfile in tab_files_to_attache_to_mail:
msg.attach(myfile['attached_file'])
val = smtpserver.send_message(msg)
print(" Email a envoyé " + str(email))
cpt_email_envoye = cpt_email_envoye + 1
else:
msg.attach(html_mime)
#msg['From'] = MYSY_GV.O365_SMTP_COUNT_From_User
company_name = ""
my_company_data = MYSY_GV.dbname['partnair_account'].find_one(
{'recid': str(partner_owner_recid), 'is_partner_admin_account': '1', 'active': '1',
'locked': '0'},
{'_id': 1, 'nom': 1})
if (my_company_data and "nom" in my_company_data.keys() and my_company_data['nom']):
company_name = my_company_data['nom']
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['Cc'] = ",".join(tab_email_cc)
msg['Bcc'] = ",".join(tab_email_bcc)
msg['Subject'] = email_sujet
msg['to'] = str(email)
# Attacher l'eventuelle pièces jointes
for myfile in tab_files_to_attache_to_mail:
msg.attach(myfile['attached_file'])
val = smtpserver.send_message(msg)
print(" Email a envoyé " + str(email))
cpt_email_envoye = cpt_email_envoye + 1
smtpserver.close()
return True, " Les emails ont été correctement envoyés"

View File

@ -316,7 +316,6 @@ def Delete_Message_To_Mail_Queue(diction):
return False, " Impossible de supprimer les messages "
"""
Recuperer la liste des message d'un partenaire
"""
@ -386,4 +385,169 @@ def Get_List_Message_To_Mail_Queue(diction):
return False, " Impossible de récupérer la liste des messages "
"""
Récuperation des données d'un email queu
"""
def Get_Given_Mail_Queue(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'mail_queu_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', 'mail_queu_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 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
RetObject = []
val_tmp = 0
#print(" ### data_cle = ", data_cle)
for retval in MYSY_GV.dbname['mail_queue'].find({'_id':ObjectId(str(diction['mail_queu_id'])), 'valide':'1', 'locked':'1'}):
user = retval
user['id'] = str(val_tmp)
val_tmp = val_tmp + 1
RetObject.append(mycommon.JSONEncoder().encode(user))
return True, RetObject
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de récuperer les données du mail "
"""
Cette fonction permet de renvoyer un email
"""
def Resend_List_Mail_Queue(diction):
try:
field_list_obligatoire = ['token', 'tab_mail_queu_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 la liste des arguments ")
return False, " La valeur '" + val + "' n'est pas presente dans la liste des arguments"
tab_mail_queu_id_ObjectId = []
tab_mail_queu_id = []
tab_mail_queu_id_split = str(diction['tab_mail_queu_id']).split(",")
for tmp in tab_mail_queu_id_split:
if( tmp ):
tab_mail_queu_id.append(str(tmp))
tab_mail_queu_id_ObjectId.append(ObjectId(str(tmp)))
if(len(tab_mail_queu_id) > 0 ):
for mail_queu_id in tab_mail_queu_id:
for email_queue_data in MYSY_GV.dbname['mail_queue'].find({'valide':'1', 'locked':'0',
'_id':ObjectId(str(mail_queu_id))}):
msg = MIMEMultipart("alternative")
msg['From'] = email_queue_data['from']
if( "cc" in email_queue_data.keys() and email_queue_data['cc']):
msg['cc'] = email_queue_data['cc']
if ("bcc" in email_queue_data.keys() and email_queue_data['bcc']):
msg['bcc'] = email_queue_data['bcc']
if ("subject" in email_queue_data.keys() and email_queue_data['subject']):
msg['subject'] = email_queue_data['subject']
else:
msg['subject'] = ""
msg['to'] = email_queue_data['to']
# Traitement de l'eventuel fichier joint
tab_files_to_attache_to_mail = []
html_mime = MIMEText(email_queue_data['message'], 'html')
msg.attach(html_mime)
#print(" ### msg = ", str(msg) )
smtpserver = smtplib.SMTP(email_queue_data['smtp_account_smtpsrv'], email_queue_data['smtp_account_port'])
if( "tab_saved_file_full_path" in email_queue_data.keys() ):
for myfile in email_queue_data['tab_saved_file_full_path']:
file_to_attache_to_mail = MIMEBase('application', "octet-stream")
file_to_attache_to_mail.set_payload(open(myfile, "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(myfile)))
new_node = {"attached_file": file_to_attache_to_mail}
tab_files_to_attache_to_mail.append(new_node)
# 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(email_queue_data['smtp_account_user'], email_queue_data['smtp_account_password'])
val = smtpserver.send_message(msg)
smtpserver.close()
#print(val)
"""
On met à jour l'email avec le statut d'envoie de l'email
"""
new_data = diction
new_data['date_update'] = str(datetime.now())
new_data['sent'] = str(datetime.now())
error_node = {}
if( len(val.keys()) > 0 ):
new_data['error_message'] = str(val)
new_data['statut'] = "-1"
else:
new_data['error_message'] = ""
new_data['statut'] = "1"
result = MYSY_GV.dbname['mail_queue'].find_one_and_update(
{'_id':ObjectId(str(email_queue_data['_id']))},
{"$set": new_data},
upsert=False,
return_document=ReturnDocument.AFTER
)
return True, "Email(s) reenvoyé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 renvoyer les emails "

View File

@ -195,6 +195,7 @@ def CreateTableauEmargement(diction):
new_my_local_data['matin'] = False
new_my_local_data['apresmidi'] = False
#print("### emargement insertion de : "+str(new_my_local_data))
local_ret_val = coll_emargement.find_one_and_update(
@ -460,6 +461,7 @@ def CreateTableauEmargement_From_Sequence(diction):
new_my_local_data['apresmidi'] = False
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:
@ -570,31 +572,35 @@ def GetTableauEmargement(diction):
'valide':'1', 'locked':'0',
'partner_owner_recid':str(partner_recid)})
if( is_sequence_valide > 0 ):
user = retval
if( "statut" not in retval.keys() ):
user['statut'] = ""
if( is_sequence_valide > 0 ):
user = retval
if( "statut" not in retval.keys() ):
user['statut'] = ""
if ("date_envoi" not in retval.keys()):
user['date_envoi'] = ""
if ("mode_envoi" not in retval.keys()):
user['mode_envoi'] = ""
if ("date_emargement" not in retval.keys()):
user['date_emargement'] = ""
if ("date_envoi" not in retval.keys()):
user['date_envoi'] = ""
if ("time_in_hour" not in retval.keys()):
delta_time = datetime.strptime(str(user['sequence_end']), '%d/%m/%Y %H:%M') - datetime.strptime(
str(user['sequence_start']),'%d/%m/%Y %H:%M')
if ("date_emargement" not in retval.keys()):
user['date_emargement'] = ""
delta_time_converted_in_hour = round(float(delta_time.total_seconds() / 3600), 2)
user['time_in_hour'] = str(delta_time_converted_in_hour)
if ("time_in_hour" not in retval.keys()):
delta_time = datetime.strptime(str(user['sequence_end']), '%d/%m/%Y %H:%M') - datetime.strptime(
str(user['sequence_start']),'%d/%m/%Y %H:%M')
if ("mysy_manual_signature_img" not in retval.keys()):
user['mysy_manual_signature_img'] = ""
delta_time_converted_in_hour = round(float(delta_time.total_seconds() / 3600), 2)
user['time_in_hour'] = str(delta_time_converted_in_hour)
user['id'] = str(val_tmp)
RetObject.append(mycommon.JSONEncoder().encode(user))
val_tmp = val_tmp + 1
if ("mysy_manual_signature_img" not in retval.keys()):
user['mysy_manual_signature_img'] = ""
user['id'] = str(val_tmp)
RetObject.append(mycommon.JSONEncoder().encode(user))
val_tmp = val_tmp + 1
print(" ### RetObject = ", RetObject)
return True, RetObject
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()

View File

@ -35,6 +35,7 @@ from email.mime.base import MIMEBase
from email import encoders
"""
Important : Seules session avec 'session_status'= '1' (actif sont pris en compte)
Cette fonctions retourne les _id d'un apprenant return : tab_class_id, tab_inscription_id, tab_session_id
exemple :
"message": [
@ -146,7 +147,7 @@ def Get_Apprenant_Tab_Class_Inscrip_Session_Id(diction):
], 'as': 'apprenant_collection'}}
]
print("#### Get_Apprenant_Tab_Class_Inscrip_Session_Id laa 01 : query = ", query)
#print("#### Get_Apprenant_Tab_Class_Inscrip_Session_Id laa 01 : query = ", query)
RetObject = []
cpt = 0
@ -154,16 +155,22 @@ def Get_Apprenant_Tab_Class_Inscrip_Session_Id(diction):
for retVal in MYSY_GV.dbname['inscription'].aggregate(query):
val = {}
local_node = {}
if( "session_id" in retVal.keys() ):
is_active_session_count = MYSY_GV.dbname['session_formation'].count_documents({'_id':ObjectId(str(retVal['session_id'])),
'valide':'1',
'partner_owner_recid':str(retVal['partner_owner_recid']),
'session_status':'1'})
if( is_active_session_count == 1):
local_node = {}
local_node['inscription_id'] = (str(retVal['_id']))
local_node['session_id'] = (str(retVal['session_id']))
local_node['inscription_id'] = (str(retVal['_id']))
local_node['session_id'] = (str(retVal['session_id']))
#print('### retVal = ', retVal)
if ('myclass_collection' in retVal.keys() and len(retVal['myclass_collection']) > 0):
local_node['class_id'] = (str(retVal['myclass_collection'][0]['_id']))
#print('### retVal = ', retVal)
if ('myclass_collection' in retVal.keys() and len(retVal['myclass_collection']) > 0):
local_node['class_id'] = (str(retVal['myclass_collection'][0]['_id']))
RetObject.append(local_node)
RetObject.append(local_node)
return True, RetObject
@ -268,17 +275,19 @@ def Get_Ent_Student_List_Class(diction):
sess_data = MYSY_GV.dbname['session_formation'].find_one({"_id":ObjectId(str(local_data['session_id'])),
'valide':'1',
'session_status':'1',
'partner_owner_recid':str(class_data['partner_owner_recid'])})
user['session_id'] = str(local_data['session_id'])
user['session_code_session'] = str(sess_data['code_session'])
user['session_date_debut'] = str(sess_data['date_debut'])
user['session_date_fin'] = str(sess_data['date_fin'])
if( sess_data ):
user['session_id'] = str(local_data['session_id'])
user['session_code_session'] = str(sess_data['code_session'])
user['session_date_debut'] = str(sess_data['date_debut'])
user['session_date_fin'] = str(sess_data['date_fin'])
user['inscription_id'] = str(local_data['inscription_id'])
user['id'] = str(cpt)
cpt = cpt +1
RetObject.append(mycommon.JSONEncoder().encode(user))
user['inscription_id'] = str(local_data['inscription_id'])
user['id'] = str(cpt)
cpt = cpt +1
RetObject.append(mycommon.JSONEncoder().encode(user))
"""

561
internal_email_mgt.py Normal file
View File

@ -0,0 +1,561 @@
"""
Ce fichier permet le stockage des email interne
"""
import ast
from calendar import monthrange
from zipfile import ZipFile
import bson
import pymongo
import xlsxwriter
from pymongo import MongoClient
import json
from bson import ObjectId
import re
from datetime import datetime, date, timedelta
import Session_Formation
import module_editique
import partner_base_setup
import partner_client
import partner_order
import prj_common as mycommon
import secrets
import inspect
import sys, os
import csv
import pandas as pd
from pymongo import ReturnDocument
import GlobalVariable as MYSY_GV
from math import isnan
import GlobalVariable as MYSY_GV
import ela_index_bdd_classes as eibdd
import email_mgt as email
import jinja2
from flask import send_file
from xhtml2pdf import pisa
from email.message import EmailMessage
from email.mime.text import MIMEText
from email import encoders
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import survey_mgt as survey_mgt
import attached_file_mgt
import Inscription_mgt as Inscription_mgt
"""
Important :
actuellement le login se fait via la collection 'user_account' ou 'partnair_account'
de ce fait, le champ 'related_collection' permettra de connaitre la collection associée et
le champ 'related_collection_recid' permettra de connaitre l'_id
le champs 'is_read' => 0 (pas lu), 1 (lu)
"""
def Add_Message_To_Internal_Mail(tab_files, diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'from', 'cc', 'bcc', 'subject', 'to', 'message', 'tab_saved_file_full_path',
'smtp_account_password', 'smtp_account_smtpsrv', 'smtp_account_user', 'smtp_account_From_User',
'smtp_account_port', 'related_collection', 'related_collection_recid']
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', 'from', 'cc', 'bcc', 'subject', 'to', 'message', 'tab_saved_file_full_path',
'smtp_account_password', 'smtp_account_smtpsrv', 'smtp_account_user',
'smtp_account_From_User', 'smtp_account_port', 'related_collection', 'related_collection_recid']
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
"""
Verifier la validité des related_collection et related_collection_recid
"""
if( "related_collection" in diction.keys() and diction['related_collection'] and
"related_collection_recid" in diction.keys() and diction['related_collection_recid'] ):
login_count = MYSY_GV.dbname[str(diction['related_collection'])].count_documents({'_id':ObjectId(str(diction['related_collection_recid'])),
'partner_owner_recid':str(my_partner['recid'])})
if(login_count != 1 ):
mycommon.myprint("L'utilisateur destinataire de l'email est invalide ")
return False, "L'utilisateur destinataire de l'email est invalide"
# Sauvegarde des fichiers joints depuis le front
if (len(tab_files) > MYSY_GV.EMAIL_MAX_PJ):
mycommon.myprint("Vous ne pouvez pas envoyer plus de " + str(MYSY_GV.EMAIL_MAX_PJ) + " pièces jointes.")
return False, "Vous ne pouvez pas envoyer plus de " + str(MYSY_GV.EMAIL_MAX_PJ) + " pièces jointes. "
tab_saved_file_full_path = []
for file in tab_files:
status, saved_file_full_path = mycommon.Upload_Save_PDF_IMG_File(file, MYSY_GV.TEMPORARY_DIRECTORY_V2)
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)
new_data = diction
del diction['token']
# Initialisation des champs non envoyés à vide
for val in field_list:
if val not in diction.keys():
new_data[str(val)] = ""
new_data['valide'] = "1"
new_data['locked'] = "0"
new_data['statut'] = "0"
new_data['is_read'] = "0"
new_data['attached_files_path'] = tab_saved_file_full_path
new_data['creation_date'] = str(datetime.now())
new_data['creation_by'] = str(my_partner['_id'])
new_data['partner_owner_recid'] = str(my_partner['recid'])
inserted_id = MYSY_GV.dbname['internal_mail'].insert_one(new_data).inserted_id
if (not inserted_id):
mycommon.myprint(
" Impossible d'ajouter le message dans la collection internal_email (2) ")
return False, " Impossible d'ajouter le message dans la collection internal_email (2) "
message_id = ""
return True, str(message_id)
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'ajouter le message dans la collection internal_email "
"""
Mise à jour d'un message, par exemple les status
"""
def Update_Message_To_Internal_Mail(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'from', 'cc', 'bcc', 'subject', 'to', 'message', 'status', 'tab_message_id',
'smtp_account_password', 'smtp_account_smtpsrv', 'smtp_account_user', 'smtp_account_From_User',
'smtp_account_port', 'is_read']
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', 'tab_message_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 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
tab_message_id_split = str(diction['tab_message_id']).split(",")
tab_message_id = []
for tmp in tab_message_id_split:
if( tmp ):
tab_message_id.append(tmp)
for local_message_id in tab_message_id :
"""
Verifier la validité du message
"""
is_massage_valide = MYSY_GV.dbname['internal_mail'].count_documents({'_id':ObjectId(str(local_message_id)),
'valide':'1',
'locked':'0',
'partner_owner_recid':str(my_partner['recid']),
'statut':{'$ne':'1'}})
if( is_massage_valide != 1):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'identifiant du message "+str(local_message_id)+" n'est pas valide")
return False, " L'identifiant du message "+str(local_message_id)+" n'est pas valide "
del diction['token']
del diction['tab_message_id']
for local_message_id in tab_message_id:
local_id = str(local_message_id)
new_data = diction
new_data['date_update'] = str(datetime.now())
new_data['update_by'] = str(my_partner['_id'])
data_cle = {}
data_cle['_id'] = ObjectId(local_id)
data_cle['partner_owner_recid'] = str(my_partner['recid'])
data_cle['statut'] = {'$ne': '1'}
result = MYSY_GV.dbname['internal_mail'].find_one_and_update(
data_cle,
{"$set": new_data},
upsert=False,
return_document=ReturnDocument.AFTER
)
return True, "Le message a été mis à jour"
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 mettre à jour le message "
"""
Supprimer un message donnée
"""
def Delete_Message_To_Internal_Mail(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'tab_message_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'est pas autorisé")
return False, " Les informations fournies sont incorrectes"
"""
Verification des champs obligatoires
"""
field_list_obligatoire = ['token', 'tab_message_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 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
tab_message_id_work = str(diction['tab_message_id']).split(",")
tab_message_id_ObjectId = []
for tmp in tab_message_id_work:
if( tmp ):
tab_message_id_ObjectId.append(ObjectId(str(tmp)))
delete = MYSY_GV.dbname['internal_mail'].delete_many({'_id': {'$in':tab_message_id_ObjectId},
'partner_owner_recid': str(my_partner['recid']),
}, )
return True, str(delete.deleted_count)+" message(s) supprimé(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 supprimer les messages "
"""
Recuperer la liste des message d'un user
"""
def Get_List_User_Internal_Mail(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'related_collection_recid']
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', 'related_collection_recid']
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
"""
Clés de mise à jour
"""
data_cle = {}
data_cle['partner_owner_recid'] = str(my_partner['recid'])
data_cle['valide'] = "1"
data_cle['locked'] = "0"
data_cle['related_collection_recid'] = str(diction['related_collection_recid'])
RetObject = []
val_tmp = 0
for retval in MYSY_GV.dbname['internal_mail'].find(data_cle).sort([("_id", pymongo.DESCENDING), ]):
user = retval
user['id'] = str(val_tmp)
val_tmp = val_tmp + 1
RetObject.append(mycommon.JSONEncoder().encode(user))
return True, RetObject
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de récupérer la liste des messages "
"""
Cette fonction recupere le nombre d'email non lu pour un user
"""
def Get_Nb_User_Internal_Mail_Not_Read(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'related_collection_recid']
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', 'related_collection_recid']
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
"""
Clés de mise à jour
"""
data_cle = {}
data_cle['partner_owner_recid'] = str(my_partner['recid'])
data_cle['valide'] = "1"
data_cle['locked'] = "0"
data_cle['is_read'] = "0"
data_cle['related_collection_recid'] = str(diction['related_collection_recid'])
nb_no_read_internal_mail = MYSY_GV.dbname['internal_mail'].count_documents(data_cle)
return True, str(nb_no_read_internal_mail)
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 le nombre de messages non lu(s)"
"""
Récuperation des données d'un email
"""
def Get_Given_Internal_Mail(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'internal_mail_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', 'internal_mail_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 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
RetObject = []
val_tmp = 0
#print(" ### data_cle = ", data_cle)
for retval in MYSY_GV.dbname['internal_mail'].find({'_id':ObjectId(str(diction['internal_mail_id'])), 'valide':'1', 'locked':'1'}):
user = retval
user['id'] = str(val_tmp)
val_tmp = val_tmp + 1
RetObject.append(mycommon.JSONEncoder().encode(user))
return True, RetObject
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de récuperer les données du mail "
"""
Cette fonction permet de renvoyer un email
"""
def Send_List_Internal_Mail(diction):
try:
field_list_obligatoire = ['token', 'tab_internal_mail_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 la liste des arguments ")
return False, " La valeur '" + val + "' n'est pas presente dans la liste des arguments"
tab_internal_mail_id_ObjectId = []
tab_internal_mail_id = []
tab_internal_mail_id_split = str(diction['tab_internal_mail_id']).split(",")
for tmp in tab_internal_mail_id_split:
if( tmp ):
tab_internal_mail_id.append(str(tmp))
tab_internal_mail_id_ObjectId.append(ObjectId(str(tmp)))
if(len(tab_internal_mail_id) > 0 ):
a=2
return True, "Email(s) reenvoyé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 renvoyer les emails "

File diff suppressed because it is too large Load Diff

481
main.py
View File

@ -3,13 +3,9 @@ import os
from flask import make_response, request, current_app, Flask, jsonify
from functools import update_wrapper
import json
import strype_payement
import wrapper as wp
import ela_user_account as eua
import prj_common as pc
from six import string_types
from datetime import timedelta
import Ela_Spacy as ls
import user_message_mgt as um
@ -24,6 +20,7 @@ import time
from OpenSSL import SSL
from flask import redirect
from flask import Flask, render_template, request, redirect, url_for
from apscheduler.triggers.cron import CronTrigger
import articles_avis as aa
import GlobalVariable as MYSY_GV
import youtubes_analyse as YTA
@ -103,6 +100,7 @@ import reference_pedagogique_mgt as reference_pedagogique_mgt
import ent_student_common as ent_student_common
import groupe_client_mgt as groupe_client_mgt
import email_queu.email_queu_mgt as email_queu_mgt
import internal_email_mgt as internal_email_mgt
import base_document_automatic_setup as base_document_automatic_setup
@ -2320,7 +2318,7 @@ def Update_SessionFormation_Only_Step():
"""
API de mise à jour du parametrage d'automatisation d'envoi des documents
API de mise à jour du paramétrage d'automatisation d'envoi des documents
WARNING : Une session est modifiable tanque la facturation n'a pas demarré. Apres tous est bloqué
"""
@app.route('/myclass/api/Update_SessionFormation_Doc_Automatic_Setup/', methods=['POST','GET'])
@ -2816,7 +2814,7 @@ API d'Envoie de l'email de confirmation de l'inscription
def SendInscriptionConfirmation():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### incription_training_confirmation_mail : payload = ",str(payload))
print(" ### SendInscriptionConfirmation : payload = ",str(payload))
localStatus, message= inscription.SendInscriptionConfirmation(payload)
return jsonify(status=localStatus, message=message )
@ -7320,7 +7318,7 @@ def Get_List_Partner_Basic_Setup():
"""
API de recuperation d'un point de parametrage donnée
API de recuperation d'un point de paramétrage donnée
"""
@app.route('/myclass/api/Get_Given_Partner_Basic_Setup/', methods=['POST','GET'])
@crossdomain(origin='*')
@ -7743,7 +7741,7 @@ def get_Ressource_Info_Data_Satgiaire():
"""
API pour ajouter ou modifier un parametrage : etape des sessions de formation
API pour ajouter ou modifier un paramétrage : etape des sessions de formation
"""
@app.route('/myclass/api/Add_Update_Partner_session_step/', methods=['POST','GET'])
@ -8336,8 +8334,8 @@ 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)
status, retval, retval_total_duration = ressources_humaines_tbd_qries.Get_Humain_Ressource_With_Planning(payload)
return jsonify(status=status, message=retval, retval_total_duration = retval_total_duration)
"""
@ -8752,8 +8750,8 @@ def Get_Humain_Ressource_With_Planning_And_Cost():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Get_Humain_Ressource_With_Planning_And_Cost payload = ",payload)
status, retval = ressources_humaines_tbd_qries.Get_Humain_Ressource_With_Planning_And_Cost(payload)
return jsonify(status=status, message=retval)
status, retval, retval_node_total_duration, retval_node_total_cost = ressources_humaines_tbd_qries.Get_Humain_Ressource_With_Planning_And_Cost(payload)
return jsonify(status=status, message=retval, retval_node_total_duration=retval_node_total_duration, retval_node_total_cost=retval_node_total_cost)
@ -10047,8 +10045,6 @@ def Get_List_Specific_Survey_Internal_Code():
"""
API pour initialiset (suppression et creation ) d'une enquete pour tous
SAUF LES inscrits d'un session.
@ -10122,6 +10118,32 @@ def Export_To_Excel_Survey_with_filter(token, session_id, formulaire_type):
"""
API pour exporter les reponse à un questionnaire données
avec les filter :
- survey_internal_code
"""
@app.route('/myclass/api/Export_To_Excel_Specif_Survey_with_filter_survey_internal_code/<token>/<session_id>/<survey_internal_code>/', methods=['POST','GET'])
@crossdomain(origin='*')
def Export_To_Excel_Specif_Survey_with_filter_survey_internal_code(token, session_id, survey_internal_code):
# 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['survey_internal_code'] = str(survey_internal_code)
print(" ### Export_To_Excel_Survey_with_filter payload = ",payload)
status, retval = survey_mgt.Export_To_Excel_Specif_Survey_with_filter_survey_internal_code(payload)
if(status ):
return retval
else:
return False
"""
API / TBD / QRY : Recuperation des factures sur une periode
@ -10852,6 +10874,21 @@ def Cron_Survey_Questionnaires_Relance():
""""
Test cron qui fait les relance des emargements non repondu (position, eval, etc)
"""
@app.route('/myclass/api/Cron_Emargement_Relance/', methods=['POST','GET'])
@crossdomain(origin='*')
def Cron_Emargement_Relance():
mycommon.myprint(" ### CRONNN Cron_Emargement_Relance : payload = ")
print(" ### CRONNN Cron_Emargement_Relance : payload = ")
status, retval = Job_Cron.Cron_Emargement_Relance()
print(" FIN traitement Cron_Emargement_Relance localStatus = ", status)
return jsonify(status=status, message=retval)
"""
API pour ajouter un type d'evaluation
"""
@ -11835,6 +11872,20 @@ def Delete_List_Survey():
return jsonify(status=status, message=retval)
"""
API pour supprimer une liste d'enquete si elle n'ont pas été envoyé pour les spécific evaluation
statut = 0
"""
@app.route('/myclass/api/Delete_List_Survey_From_survey_internal_code/', methods=['POST','GET'])
@crossdomain(origin='*')
def Delete_List_Survey_From_survey_internal_code():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Delete_List_Survey_From_survey_internal_code payload = ",payload)
status, retval = survey_mgt.Delete_List_Survey_From_survey_internal_code(payload)
return jsonify(status=status, message=retval)
"""
API pour recuperer la l'url d'un survey en fournissant le session_id et l'email de l'inscrit
@ -13079,15 +13130,14 @@ def Get_List_Evaluation_Inscriptio_Note_Classement_With_Filter():
"""
API pour imprimer le bulletin de note d'un inscrit
"""
@app.route('/myclass/api/Prepare_and_Send_Inscrit_Bulletin_Note_By_PDF/<token>/<tab_inscrit_ids>/<courrier_template_id>', methods=['POST','GET'])
@app.route('/myclass/api/Prepare_and_Send_Inscrit_Bulletin_Note_By_PDF/<token>/<tab_inscrit_ids>', methods=['POST','GET'])
@crossdomain(origin='*')
def Prepare_and_Send_Inscrit_Bulletin_Note_By_PDF(token, tab_inscrit_ids, courrier_template_id):
def Prepare_and_Send_Inscrit_Bulletin_Note_By_PDF(token, tab_inscrit_ids):
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
payload = {}
payload['token'] = str(token)
payload['tab_inscrit_ids'] = str(tab_inscrit_ids)
payload['courrier_template_id'] = str(courrier_template_id)
print(" ### Prepare_and_Send_Inscrit_Bulletin_Note_By_PDF : payload = ",str(payload))
@ -13111,6 +13161,20 @@ def Add_Jury():
return jsonify(status=localStatus, message=message )
"""
API pour ajouter un Jury
"""
@app.route('/myclass/api/Add_Conseil_Class/', methods=['POST','GET'])
@crossdomain(origin='*')
def Add_Conseil_Class():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Add_Conseil_Class : payload = ",payload)
localStatus, message= jury_mgt.Add_Conseil_Class(payload)
return jsonify(status=localStatus, message=message )
"""
API pour mettre à jour un Jury
"""
@ -13124,6 +13188,19 @@ def Update_Jury():
return jsonify(status=localStatus, message=message )
"""
API pour mettre à jour un conseil de class
"""
@app.route('/myclass/api/Update_Conseil_Class/', methods=['POST','GET'])
@crossdomain(origin='*')
def Update_Conseil_Class():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Update_Conseil_Class : payload = ",payload)
localStatus, message= jury_mgt.Update_Conseil_Class(payload)
return jsonify(status=localStatus, message=message )
"""
API pour mettre supprimer un Jury
"""
@ -13165,6 +13242,21 @@ def Get_List_Jury():
return jsonify(status=localStatus, message=message )
"""
API pour recuperer la liste des conseils de classe d'un partenaire
IMPORTANT : meme si le jyry et conseil de classe utilise les meme collection,
on differencie les fonctions pour une simplicité d'utilisation
"""
@app.route('/myclass/api/Get_List_Conseil_Classe/', methods=['POST','GET'])
@crossdomain(origin='*')
def Get_List_Conseil_Classe():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Get_List_Conseil_Classe : payload = ",payload)
localStatus, message= jury_mgt.Get_List_Conseil_Classe(payload)
return jsonify(status=localStatus, message=message )
"""
API pour recuperer la liste des Jurys d'un partenaire
avec des filtres sur :
@ -13199,7 +13291,24 @@ def Get_Given_Jury_With_Members():
"""
API pour ajouter / mettre à jour les membres d'un Jury
API pour recuperer les données d'une Jury d'un partenaire,
SANS les membres
"""
@app.route('/myclass/api/Get_Given_Jury_Without_Members/', methods=['POST','GET'])
@crossdomain(origin='*')
def Get_Given_Jury_Without_Members():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Get_Given_Jury_Without_Members : payload = ",payload)
localStatus, message= jury_mgt.Get_Given_Jury_Without_Members(payload)
return jsonify(status=localStatus, message=message )
"""
API pour ajouter / mettre à jour les membres (RH) d'un Jury
"""
@app.route('/myclass/api/Add_Update_Jury_Membres/', methods=['POST','GET'])
@crossdomain(origin='*')
@ -13211,6 +13320,35 @@ def Add_Update_Jury_Membres():
return jsonify(status=localStatus, message=message )
"""
API permet de dire q'une liste de membre d'un conseil de classe ou jury
etait présent
"""
@app.route('/myclass/api/Update_Jury_Membres_Presence/', methods=['POST','GET'])
@crossdomain(origin='*')
def Update_Jury_Membres_Presence():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Update_Jury_Membres_Presence : payload = ",payload)
localStatus, message= jury_mgt.Update_Jury_Membres_Presence(payload)
return jsonify(status=localStatus, message=message )
"""
API pour ajouter / mettre à jour une liste de delegué de classe à un jury comme membre
"""
@app.route('/myclass/api/Add_Update_Jury_Delegue_Membres/', methods=['POST','GET'])
@crossdomain(origin='*')
def Add_Update_Jury_Delegue_Membres():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Add_Update_Jury_Delegue_Membres : payload = ",payload)
localStatus, message= jury_mgt.Add_Update_Jury_Delegue_Membres(payload)
return jsonify(status=localStatus, message=message )
"""
API pour supprimer les membres d'une Jury
"""
@ -13239,6 +13377,22 @@ def Add_Update_Apprenant_To_Jury():
"""
API qui permet d'ajouter ou met à jour des apprenants pour un conseil de classe
"""
@app.route('/myclass/api/Add_Update_Apprenant_To_Conseil_Class/', methods=['POST','GET'])
@crossdomain(origin='*')
def Add_Update_Apprenant_To_Conseil_Class():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Add_Update_Apprenant_To_Conseil_Class : payload = ",payload)
localStatus, message = jury_mgt.Add_Update_Apprenant_To_Conseil_Class(payload)
return jsonify(status=localStatus, message=message)
"""
API qui permet de recuperer les apprenants inscrit à un jury
"""
@ -13254,6 +13408,49 @@ def Get_Given_Jury_Apprenant_With_Filter():
"""
API qui va chercher la liste des inscrits à une session de formation
qui n'appartiennent pas à un jury_apprenant
"""
@app.route('/myclass/api/Get_List_Inscrit_Not_In_jury_apprenant/', methods=['POST','GET'])
@crossdomain(origin='*')
def Get_List_Inscrit_Not_In_jury_apprenant():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Get_List_Inscrit_Not_In_jury_apprenant : payload = ",payload)
localStatus, message= jury_mgt.Get_List_Inscrit_Not_In_jury_apprenant(payload)
return jsonify(status=localStatus, message=message )
"""
API qui va chercher la liste RH (interne ou externe) non membre du conseil de classe
"""
@app.route('/myclass/api/Get_List_RH_Not_In_jury_membre/', methods=['POST','GET'])
@crossdomain(origin='*')
def Get_List_RH_Not_In_jury_membre():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Get_List_RH_Not_In_jury_membre : payload = ",payload)
localStatus, message= jury_mgt.Get_List_RH_Not_In_jury_membre(payload)
return jsonify(status=localStatus, message=message )
"""
API qui va chercher la liste des apprenant qui DELEGUE de classe pour LA PROMOTION
non membre du conseil de classe
"""
@app.route('/myclass/api/Get_List_Delegue_Classe_Not_In_jury_apprenant/', methods=['POST','GET'])
@crossdomain(origin='*')
def Get_List_Delegue_Classe_Not_In_jury_apprenant():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Get_List_Delegue_Classe_Not_In_jury_apprenant : payload = ",payload)
localStatus, message= jury_mgt.Get_List_Delegue_Classe_Not_In_jury_apprenant(payload)
return jsonify(status=localStatus, message=message )
"""
API qui permet de supprimer des inscrits à un jury (membre d'un groupe)
"""
@ -13420,6 +13617,34 @@ def Send_Jury_Membre_Convocation_By_PDF(token, tab_jury_ids, courrier_template_i
"""
API pour generer le proces verbal du conseil de classe en PDF
"""
@app.route('/myclass/api/Send_Conseil_Classe_Proces_Verbal_By_PDF/<token>/<tab_jury_ids>/<courrier_template_id>', methods=['POST','GET'])
@crossdomain(origin='*')
def Send_Conseil_Classe_Proces_Verbal_By_PDF(token, tab_jury_ids, courrier_template_id):
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
payload = {}
payload['token'] = str(token)
if (str(tab_jury_ids) != "-"):
payload['tab_jury_ids'] = str(tab_jury_ids)
if (str(courrier_template_id) != "-"):
payload['courrier_template_id'] = str(courrier_template_id)
print(" ### Send_Conseil_Classe_Proces_Verbal_By_PDF : payload = ",str(payload))
localStatus, response= jury_mgt.Send_Conseil_Classe_Proces_Verbal_By_PDF(payload)
if(localStatus ):
return response
else:
return False
"""
API pour generer les convocation des membres du jury (membre) par email
"""
@ -13471,6 +13696,22 @@ def Add_Update_UE_Jury_Observation():
"""
API permet d'ajouter/mettre à jour une observation d'eleve pendant un conseil
de class
"""
@app.route('/myclass/api/Add_Update_Conseil_Class_Apprenant_Observation/', methods=['POST','GET'])
@crossdomain(origin='*')
def Add_Update_Conseil_Class_Apprenant_Observation():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Add_Update_Conseil_Class_Apprenant_Observation : payload = ",str(payload))
status, retval = jury_mgt.Add_Update_Conseil_Class_Apprenant_Observation( payload)
return jsonify(status=status, message=retval)
"""
API pour ajouter caractéristique financière à un related_collection / related_collection_id
"""
@ -13942,6 +14183,102 @@ def Get_Given_Groupe_Client():
return jsonify(status=status, message=retval)
"""
API pour envoyer un email à un utilisateur du systeme
"""
@app.route('/myclass/api/Add_Message_To_Internal_Mail/', methods=['POST','GET'])
@crossdomain(origin='*')
def Add_Message_To_Internal_Mail():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Add_Message_To_Internal_Mail payload = ",payload)
status, retval = internal_email_mgt.Add_Message_To_Internal_Mail(payload)
return jsonify(status=status, message=retval)
"""
API pour mise à jour d'un email d'un utilisateur du systeme
"""
@app.route('/myclass/api/Update_Message_To_Internal_Mail/', methods=['POST','GET'])
@crossdomain(origin='*')
def Update_Message_To_Internal_Mail():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Update_Message_To_Internal_Mail payload = ",payload)
status, retval = internal_email_mgt.Update_Message_To_Internal_Mail(payload)
return jsonify(status=status, message=retval)
"""
API pour supprimer l'email d'un utilisateur du systeme
"""
@app.route('/myclass/api/Delete_Message_To_Internal_Mail/', methods=['POST','GET'])
@crossdomain(origin='*')
def Delete_Message_To_Internal_Mail():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Delete_Message_To_Internal_Mail payload = ",payload)
status, retval = internal_email_mgt.Delete_Message_To_Internal_Mail(payload)
return jsonify(status=status, message=retval)
"""
API pour recuperer la liste des emails d'un utilisateur du systeme
"""
@app.route('/myclass/api/Get_List_User_Internal_Mail/', methods=['POST','GET'])
@crossdomain(origin='*')
def Get_List_User_Internal_Mail():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Get_List_User_Internal_Mail payload = ",payload)
status, retval = internal_email_mgt.Get_List_User_Internal_Mail(payload)
return jsonify(status=status, message=retval)
"""
API pour recuperer le nombre d'emails non lu pour un user
"""
@app.route('/myclass/api/Get_Nb_User_Internal_Mail_Not_Read/', methods=['POST','GET'])
@crossdomain(origin='*')
def Get_Nb_User_Internal_Mail_Not_Read():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Get_Nb_User_Internal_Mail_Not_Read payload = ",payload)
status, retval = internal_email_mgt.Get_Nb_User_Internal_Mail_Not_Read(payload)
return jsonify(status=status, message=retval)
"""
API pour recuperer les données d'un email d'un utilisateur du systeme
"""
@app.route('/myclass/api/Get_Given_Internal_Mail/', methods=['POST','GET'])
@crossdomain(origin='*')
def Get_Given_Internal_Mail():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Get_Given_Internal_Mail payload = ",payload)
status, retval = internal_email_mgt.Get_Given_Internal_Mail(payload)
return jsonify(status=status, message=retval)
"""
API pour envoyer une liste d'email d'un utilisateur du systeme
"""
@app.route('/myclass/api/Send_List_Internal_Mail/', methods=['POST','GET'])
@crossdomain(origin='*')
def Send_List_Internal_Mail():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Send_List_Internal_Mail payload = ",payload)
status, retval = internal_email_mgt.Send_List_Internal_Mail(payload)
return jsonify(status=status, message=retval)
"""
API pour ajouter un message dans la file d'attente des emails
"""
@ -13996,6 +14333,37 @@ def Get_List_Message_To_Mail_Queue():
return jsonify(status=status, message=retval)
"""
API pour Récuperation des données d'un email queu
"""
@app.route('/myclass/api/Get_Given_Mail_Queue/', methods=['POST','GET'])
@crossdomain(origin='*')
def Get_Given_Mail_Queue():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Get_Given_Mail_Queue payload = ",payload)
status, retval = email_queu_mgt.Get_Given_Mail_Queue(payload)
return jsonify(status=status, message=retval)
"""
API pour renvoyer un email de mail queu
"""
@app.route('/myclass/api/Resend_List_Mail_Queue/', methods=['POST','GET'])
@crossdomain(origin='*')
def Resend_List_Mail_Queue():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Resend_List_Mail_Queue payload = ",payload)
status, retval = email_queu_mgt.Resend_List_Mail_Queue(payload)
return jsonify(status=status, message=retval)
"""
Test reprise facture JMJ
"""
@ -14033,6 +14401,21 @@ if __name__ == '__main__':
mycommon.myprint("++ DBNAME " + str(MYSY_GV.dbname) + " ++")
mycommon.myprint("++ FLASK PORT " + str(MYSY_GV.MYSY_PORT_PROD) + " ++")
mycommon.myprint("++ LMS_BAS_URL " + str(MYSY_GV.LMS_BAS_URL) + " ++")
scheduler = BackgroundScheduler()
scheduler.start()
# Create the job
mysy_trigger = CronTrigger(
year="*", month="*", day="*", hour="18", minute="0", second="0"
)
scheduler.add_job(Flask_Cron_Strip_Get_Customer_Abonnement_Data, trigger=mysy_trigger)
scheduler.add_job(Internal_Global_MySy_Cron_Traitement, trigger=mysy_trigger)
# WARNING IMPORTANT WARNING : Shut down the scheduler when exiting the app
atexit.register(lambda: scheduler.shutdown())
app.run(host='localhost', port=MYSY_GV.MYSY_PORT_PROD, debug=True, threaded=True)
elif (MYSY_GV.MYSY_ENV == "DEV"):
@ -14046,24 +14429,27 @@ if __name__ == '__main__':
"""
WARNING Dasactivé en dev pour pas consommer de ressource pr rien.
"""
"""
"" "
scheduler = BackgroundScheduler()
# Create the job
scheduler.add_job(func=Flask_Cron_Strip_Get_Customer_Abonnement_Data, trigger="interval", minutes=3)
scheduler.add_job(func=Internal_Global_MySy_Cron_Traitement, trigger="interval", minutes=1)
# Cron des email toutes les heures
scheduler.add_job(func=Cron_Send_Mail_Queue_Message_With_Filter, trigger="interval", hours=1)
print(" ### scheduler.print_jobs() = ", scheduler.print_jobs())
# Start the scheduler
scheduler.start()
# Create the job
mysy_trigger = CronTrigger(
year="*", month="*", day="*", hour="20", minute="0", second="0"
)
scheduler.add_job(Flask_Cron_Strip_Get_Customer_Abonnement_Data, trigger=mysy_trigger)
scheduler.add_job(Internal_Global_MySy_Cron_Traitement, trigger=mysy_trigger)
# Cron des email toutes les heures
scheduler.add_job(Cron_Send_Mail_Queue_Message_With_Filter, trigger=mysy_trigger)
# WARNING IMPORTANT WARNING : Shut down the scheduler when exiting the app
atexit.register(lambda: scheduler.shutdown())
"""
app.run(host='localhost', port=MYSY_GV.MYSY_PORT_DEV, debug=True, threaded=True)
# Create the background scheduler
@ -14076,16 +14462,16 @@ if __name__ == '__main__':
mycommon.myprint("++ LMS_BAS_URL " + str(MYSY_GV.LMS_BAS_URL) + " ++")
scheduler = BackgroundScheduler()
# Create the job
scheduler.add_job(func=Flask_Cron_Strip_Get_Customer_Abonnement_Data, trigger="interval", hours=22)
scheduler.add_job(func=Internal_Global_MySy_Cron_Traitement, trigger="interval", hours=22)
# Cron des email toutes les heures
#scheduler.add_job(func=Cron_Send_Mail_Queue_Message_With_Filter, trigger="interval", hours=1)
# Start the scheduler
scheduler.start()
# Create the job
mysy_trigger = CronTrigger(
year="*", month="*", day="*", hour="18", minute="0", second="0"
)
scheduler.add_job(Flask_Cron_Strip_Get_Customer_Abonnement_Data, trigger=mysy_trigger)
scheduler.add_job(Internal_Global_MySy_Cron_Traitement, trigger=mysy_trigger)
# WARNING IMPORTANT WARNING : Shut down the scheduler when exiting the app
atexit.register(lambda: scheduler.shutdown())
@ -14101,18 +14487,19 @@ if __name__ == '__main__':
mycommon.myprint("++ LMS_BAS_URL " + str(MYSY_GV.LMS_BAS_URL) + " ++")
scheduler = BackgroundScheduler()
# Create the job
#scheduler.add_job(func=Flask_Cron_Strip_Get_Customer_Abonnement_Data, trigger="interval", minutes=50)
scheduler.add_job(func=Flask_Cron_Strip_Get_Customer_Abonnement_Data, trigger="interval", hours=22)
scheduler.add_job(func=Internal_Global_MySy_Cron_Traitement, trigger="interval", hours=1)
# Cron des email toutes les heures
#scheduler.add_job(func=Cron_Send_Mail_Queue_Message_With_Filter, trigger="interval", hours=1)
# Start the scheduler
scheduler.start()
# Create the job
mysy_trigger = CronTrigger(
year="*", month="*", day="*", hour="18", minute="0", second="0"
)
scheduler.add_job(Flask_Cron_Strip_Get_Customer_Abonnement_Data, trigger=mysy_trigger)
scheduler.add_job(Internal_Global_MySy_Cron_Traitement, trigger=mysy_trigger)
# Cron des email toutes les heures
scheduler.add_job(Cron_Send_Mail_Queue_Message_With_Filter, trigger=mysy_trigger)
# WARNING IMPORTANT WARNING : Shut down the scheduler when exiting the app
atexit.register(lambda: scheduler.shutdown())

View File

@ -2306,15 +2306,10 @@ def Get_List_Participant_Notes(diction):
user['type_eval_code'] = ""
user['eval_date_heure_debut'] = str(retval['note_evaluation_collection'][0]['eval_date_heure_debut'])
user['eval_date_heure_fin'] = str(retval['note_evaluation_collection'][0]['eval_date_heure_fin'])
user['nom'] = nom_apprenant
user['prenom'] = prenom_apprenant
user['email'] = email_apprenant

View File

@ -14,18 +14,18 @@ ex :
Important : 10/05/2024 :
On ajoute le module concerné à la collection pour pouvoir gerer les parametrage liée à des modules specifique.
On ajoute le module concerné à la collection pour pouvoir gerer les paramétrage liée à des modules specifique.
on aura le champ : "related_collection" pour cela.
par exemple :
- devis (point de parametrage :
- devis (point de paramétrage :
=> relance auto
=> frequence,
etc).
les parametrage generaux auront, le "related_collection" = "" vide ou inexistant
les paramétrage generaux auront, le "related_collection" = "" vide ou inexistant
"""
@ -237,7 +237,7 @@ def Delete_Partner_Basic_Setup(diction):
return False, " Impossible de supprimer le paramétrage "
"""
Recuperation de la liste des parametrage d'un partenaire
Recuperation de la liste des paramétrage d'un partenaire
"""
def Get_List_Partner_Basic_Setup(diction):
try:
@ -290,12 +290,15 @@ def Get_List_Partner_Basic_Setup(diction):
filt_related_collection = {}
filt_related_collection['related_collection'] = {'$in':tab_related_collection}
sort_tab = [("config_name", pymongo.ASCENDING)]
qry = {'partner_owner_recid':str(my_partner['recid']), 'valide':'1', 'locked':'0','related_collection':''}
if(len(tab_related_collection) > 0 ):
qry = {'$and': [{'partner_owner_recid':str(my_partner['recid']), 'valide':'1', 'locked':'0',}, filt_related_collection]}
sort_tab = [("related_collection", pymongo.ASCENDING ), ("config_name", pymongo.ASCENDING)]
print(" ### Get_List_Partner_Basic_Setup QRY = ", qry)
for New_retVal in MYSY_GV.dbname['base_partner_setup'].find(qry ):
for New_retVal in MYSY_GV.dbname['base_partner_setup'].find(qry ).sort(sort_tab):
if( str(New_retVal['config_name']) == "smtp_user_pwd"):
New_retVal['config_value'] = New_retVal['config_value'][:2]+"...."+str(New_retVal['config_value'])[-2:]
@ -313,7 +316,7 @@ def Get_List_Partner_Basic_Setup(diction):
"""
Recuperation des informations d'un point de parametrage donnée
Recuperation des informations d'un point de paramétrage donnée
"""
def Get_Given_Partner_Basic_Setup(diction):
try:
@ -364,7 +367,7 @@ def Get_Given_Partner_Basic_Setup(diction):
if( str(diction['config_name']) not in MYSY_GV.PARTNER_BASE_CONFIG_NAME ):
mycommon.myprint(
str(inspect.stack()[0][3]) + " - La valeur '" + str(diction['config_name']) + "' n'est pas valide ")
return False, " Point de parametrage "+ str(diction['config_name']) + " invalide "
return False, " Point de paramétrage "+ str(diction['config_name']) + " invalide "
RetObject = []

View File

@ -2132,14 +2132,14 @@ def GerneratePDF_Partner_Invoice(diction):
if (partner_document_INVOICE_data is None):
mycommon.myprint(
str(inspect.stack()[0][
3]) + "Aucun document parametré ")
return False, "Aucun document parametré "
3]) + "Aucun document paramétré ")
return False, "Aucun document paramétré "
if ("contenu_doc" not in partner_document_INVOICE_data or len(
str(partner_document_INVOICE_data['contenu_doc'])) <= 0):
mycommon.myprint(str(inspect.stack()[0][
3]) + " - Le parametrage du document est invalide")
return False, " Le parametrage du document est invalide "
3]) + " - Le paramétrage du document est invalide")
return False, " Le paramétrage du document est invalide "
# Recuperation des données du client
if ("order_header_client_id" in Order_header_data.keys()):
@ -2220,6 +2220,22 @@ def GerneratePDF_Partner_Invoice(diction):
else:
user['order_line_type_article'] = ""
"""
Si on a une session, on va aller chercher les info de la session
"""
session_date_debut = ""
session_date_fin = ""
if( "order_line_session_id" in retval.keys() and retval['order_line_session_id']):
session_data = MYSY_GV.dbname['session_formation'].find_one({'_id':ObjectId(str(retval['order_line_session_id'])),
'partner_owner_recid':str(retval['partner_owner_recid'])},
)
if( session_data and "date_debut" in session_data.keys() and "date_fin" in session_data.keys() ):
session_date_debut = str(session_data['date_debut'])
session_date_fin = str(session_data['date_fin'])
user['session_date_debut'] = str(session_date_debut)
user['session_date_fin'] = str(session_date_fin)
if ("order_line_type_apprenant" in retval.keys()):
user['order_line_type_apprenant'] = retval['order_line_type_apprenant']
@ -2584,14 +2600,14 @@ def Send_Partner_Invoice_By_Email(tab_files, Folder, diction):
if (partner_document_INVOICE_data is None):
mycommon.myprint(
str(inspect.stack()[0][
3]) + "Aucun document parametré ")
return False, "Aucun document parametré "
3]) + "Aucun document paramétré ")
return False, "Aucun document paramétré "
if ("contenu_doc" not in partner_document_INVOICE_data or len(
str(partner_document_INVOICE_data['contenu_doc'])) <= 0):
mycommon.myprint(str(inspect.stack()[0][
3]) + " - Le parametrage du document est invalide")
return False, " Le parametrage du document est invalide "
3]) + " - Le paramétrage du document est invalide")
return False, " Le paramétrage du document est invalide "
# Recuperation des données du client

View File

@ -5558,8 +5558,8 @@ def GerneratePDF_Partner_Order(diction):
if ("contenu_doc" not in partner_document_CONF_ORDER_data or len(
str(partner_document_CONF_ORDER_data['contenu_doc'])) <= 0):
mycommon.myprint(str(inspect.stack()[0][
3]) + " - Le parametrage du document est invalide")
return False, " Le parametrage du document est invalide "
3]) + " - Le paramétrage du document est invalide")
return False, " Le paramétrage du document est invalide "
# Recuperation des données du client
if ("order_header_client_id" in Order_header_data.keys()):
@ -6084,8 +6084,8 @@ def Gernerate_Stock_PDF_Partner_Order(diction):
if ("contenu_doc" not in partner_document_CONF_ORDER_data or len(
str(partner_document_CONF_ORDER_data['contenu_doc'])) <= 0):
mycommon.myprint(str(inspect.stack()[0][
3]) + " - Le parametrage du document est invalide")
return False, " Le parametrage du document est invalide "
3]) + " - Le paramétrage du document est invalide")
return False, " Le paramétrage du document est invalide "
# Recuperation des données du client
print(" ### Order_header_data 2888 = ", Order_header_data)
@ -6583,14 +6583,14 @@ def Send_Partner_Order_By_Email(tab_files, Folder, diction):
if (partner_document_CONF_ORDER_data is None):
mycommon.myprint(
str(inspect.stack()[0][
3]) + "Aucun document parametré ")
return False, "Aucun document parametré "
3]) + "Aucun document paramétré ")
return False, "Aucun document paramétré "
if ("contenu_doc" not in partner_document_CONF_ORDER_data or len(
str(partner_document_CONF_ORDER_data['contenu_doc'])) <= 0):
mycommon.myprint(str(inspect.stack()[0][
3]) + " - Le parametrage du document est invalide")
return False, " Le parametrage du document est invalide "
3]) + " - Le paramétrage du document est invalide")
return False, " Le paramétrage du document est invalide "
@ -7511,7 +7511,7 @@ def Convert_Quotation_to_Order(diction):
if (val in New_Order_Line.keys()):
del New_Order_Line[val]
##print(" ### New_Order_Line = ",New_Order_Line)
print(" ### New_Order_Line = ",New_Order_Line)
local_add_line_status, local_add_line_retval = Add_Update_Partner_Order_Line(New_Order_Line)
#print(" Ligne = ", cpt_line)

View File

@ -1206,7 +1206,7 @@ def get_partner_account(diction):
"""
update du 01/05/2024
Pour distinguer si le partenaire est a lié à une formation initiale ou continue
on va aller recuperer les parametrage sur le compte admin du partenaire.
on va aller recuperer les paramétrage sur le compte admin du partenaire.
Volontairement, on ne descend pas ce paramettre sur les utilisateurs associée au partenaire
"""

View File

@ -4589,7 +4589,7 @@ def Get_Dictionnary_data_For_Template(diction):
'prix_session', 'titre', 'location_type', 'is_bpf', 'formateur_id', 'adresse',
'code_postal', 'ville', 'pays', 'date_debut_inscription', 'date_fin_inscription',
'formateur_nom_prenom', 'formateur_email', 'session_formation_titre', 'session_formation_objectif',
'session_formation_description', 'nb_participant']
'session_formation_description', 'nb_participant', 'entre_scolaire']
list_session_data = []
tab_session_id = diction['list_session_id']
@ -5384,7 +5384,8 @@ Mais ca permet d'envoir un systeme pleinement operationnel des l'activation du c
-> Convocation
-> Attestation
-> Devis / Commande
-> Factue
-> Facture,
-> etc
- Un modele de journée de travail
@ -5462,16 +5463,13 @@ def Configure_Partner_Init_Setup_No_Token(diction):
""""
1 - Configuration des documents
"""
liste_document_ref_interne = ['QUALIOPI_AUTOMATIC_DOCUMENT_SENDING', 'LMS_USER_ACCES_NOTIF', 'INTRANET_CLIENT_LOGIN_NOTIF',
'CRM_OPPORTUNITE_CHANGE_NOTIF', 'EVALUATION_CONVOCATION', 'BPF_MODEL',
'EVALUATION_MODEL_PDF', 'EVAL_RESSOURCE_HUMAINE', 'EVAL_AUTRE', 'PART_INVOICE', 'PART_ORDER',
'QUOTATION_REMINDER_LEVEL_1', 'CLASS_INFO_REQUEST', 'PARTICIPANT_LIST_UPDATE',
'QUESTION_POSITIONNEMENT', 'E_DOCUMENT_SIGNATURE_CODE', 'E_DOCUMENT_SIGNED',
'E_DOCUMENT_SIGNATURE_REQUEST', 'ATTESTATION_FORMATION', 'CONVENTION_STAGIAIRE',
'FACTURATION_SESSION', 'EMPLOYEE_CREDENTIALS_FOR_LMS', 'CONVOCATION_STAGIAIRE',
'EMARGEMENT', 'EMPLOYEE_CREDENTIALS', 'TABLEAU EMARGEMENT', 'EMARGEMENT_FORMATION',
'EVAL_FORMATION', 'ANNULE_INSCRIPTION', 'REFUS_INSCRIPTION', 'CONF_INSCRIPTION',
'CONF_PRE_INSCRIPTION', ]
liste_document_ref_interne = ['CONF_PRE_INSCRIPTION', 'CONF_INSCRIPTION', 'REFUS_INSCRIPTION', 'ANNULE_INSCRIPTION', 'EVAL_FORMATION', 'EMARGEMENT_FORMATION', 'TABLEAU EMARGEMENT', 'EMPLOYEE_CREDENTIALS',
'EMARGEMENT', 'CONVOCATION_STAGIAIRE', 'CONVOCATION_STAGIAIRE', 'EMPLOYEE_CREDENTIALS_FOR_LMS', 'CONVENTION_STAGIAIRE', 'CONVENTION_STAGIAIRE', 'CONVENTION_STAGIAIRE',
'CONVENTION_STAGIAIRE', 'ATTESTATION_FORMATION', 'E_DOCUMENT_SIGNATURE_REQUEST', 'E_DOCUMENT_SIGNED', 'E_DOCUMENT_SIGNATURE_CODE', 'QUESTION_POSITIONNEMENT', 'PARTICIPANT_LIST_UPDATE',
'CLASS_INFO_REQUEST', 'QUOTATION_REMINDER_LEVEL_1', 'PART_ORDER', 'PART_ORDER', 'PART_INVOICE', 'PART_INVOICE', 'EVAL_AUTRE', 'EVAL_RESSOURCE_HUMAINE', 'EVALUATION_MODEL_PDF', 'BPF_MODEL',
'EVALUATION_CONVOCATION', 'EVALUATION_CONVOCATION', 'CRM_OPPORTUNITE_CHANGE_NOTIF', 'SURVEY_RESPONSE_NOTIF', 'STUDENT_CREDENTIALS_FOR_ENT', 'CLASS_INFO_REQUEST_WITH_QUOTATION',
'PARTNER_PRE_INSCRIPTION_NOTIF', 'SENDEMAIL_MODELE']
"""
Supprimer les eventuel ancienne information de ce type pour ce partenaire
@ -6083,8 +6081,6 @@ def Get_Partner_SMTP_Param(partner_recid):
partner_SMTP_COUNT_port = ""
partner_own_smtp = MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(partner_recid),
'config_name': 'partner_smtp',
@ -6130,9 +6126,23 @@ def Get_Partner_SMTP_Param(partner_recid):
partner_SMTP_COUNT_smtpsrv = MYSY_GV.O365_SMTP_COUNT_smtpsrv
partner_SMTP_COUNT_password = MYSY_GV.O365_SMTP_COUNT_password
partner_SMTP_COUNT_user = MYSY_GV.O365_SMTP_COUNT_user
partner_SMTP_COUNT_From_User = MYSY_GV.O365_SMTP_COUNT_From_User
partner_SMTP_COUNT_port = MYSY_GV.O365_SMTP_COUNT_port
company_name = ""
my_company_data = MYSY_GV.dbname['partnair_account'].find_one(
{'recid': str(partner_recid), 'is_partner_admin_account': '1', 'active': '1',
'locked': '0'},
{'_id': 1, 'nom': 1})
if (my_company_data and "nom" in my_company_data.keys() and my_company_data['nom']):
company_name = my_company_data['nom']
if (company_name):
partner_SMTP_COUNT_From_User = str(company_name) + " <" + str(MYSY_GV.O365_SMTP_COUNT_From_User) + ">"
else:
partner_SMTP_COUNT_From_User = str(MYSY_GV.O365_SMTP_COUNT_From_User)
return True, 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

View File

@ -1752,7 +1752,7 @@ def Get_List_Specific_Survey_Internal_Code(diction):
RetObject.append(mycommon.JSONEncoder().encode(local_node))
print(" ### RetObject = ", RetObject)
#print(" ### RetObject = ", RetObject)
return True, RetObject
except Exception as e:
@ -2400,7 +2400,7 @@ def Send_Survey_TabIds(diction):
'valide': '1', 'locked': '0', 'partner_recid': str(my_partner['recid'])}, {'_id':1, 'nom':1, 'prenom':1, 'email':1, 'civilite':1})
#print(" ### local_survey_retval = ",local_survey_retval)
print(" ### local_survey_retval = ",local_survey_retval)
courrier_ref_interne = ""
if ( "survey_type" in local_survey_retval.keys() and local_survey_retval['survey_type'] == "pos"):
courrier_ref_interne = "QUESTION_POSITIONNEMENT"
@ -2417,6 +2417,9 @@ def Send_Survey_TabIds(diction):
elif ("survey_type" in local_survey_retval.keys() and local_survey_retval['survey_type'] == "autre_eval"):
courrier_ref_interne = "EVAL_AUTRE"
elif ("survey_type" in local_survey_retval.keys() and local_survey_retval['survey_type'] == "specific_survey"):
courrier_ref_interne = "SPECIFIC_SURVEY"
else :
mycommon.myprint(str(inspect.stack()[0][3]) + " Le type d'enquete est invalide ")
return False, " Le type d'enquete est invalide "
@ -2612,7 +2615,7 @@ def Send_Survey_TabIds(diction):
'$set':{'statut':'1', 'date_update':str(now),
'update_by':str(my_partner['_id']),
'date_envoi':now,
'mode_envoi': "Email",
'mode_envoi': "email",
'date_dernier_relance_auto':str(datetime.now().strftime("%d/%m/%Y"))}
}
)
@ -2634,6 +2637,9 @@ def Send_Survey_TabIds(diction):
elif ("survey_type" in local_survey_retval.keys() and local_survey_retval['survey_type'] == "autre_eval"):
courrier_ref_interne = "EVAL_AUTRE"
elif ("survey_type" in local_survey_retval.keys() and local_survey_retval[ 'survey_type'] == "specific_survey"):
courrier_ref_interne = "SPECIFIC_SURVEY"
else:
mycommon.myprint(str(inspect.stack()[0][3]) + " Le type d'enquete est invalide ")
return False, " Le type d'enquete est invalide "
@ -2845,6 +2851,9 @@ def Automatic_Send_Survey_TabIds(diction):
elif ("survey_type" in local_survey_retval.keys() and local_survey_retval['survey_type'] == "autre_eval"):
courrier_ref_interne = "EVAL_AUTRE"
elif ("survey_type" in local_survey_retval.keys() and local_survey_retval['survey_type'] == "specific_survey"):
courrier_ref_interne = "SPECIFIC_SURVEY"
else :
mycommon.myprint(str(inspect.stack()[0][3]) + " Le type d'enquete est invalide ")
return False, " Le type d'enquete est invalide "
@ -3038,6 +3047,9 @@ def Automatic_Send_Survey_TabIds(diction):
elif ("survey_type" in local_survey_retval.keys() and local_survey_retval['survey_type'] == "autre_eval"):
courrier_ref_interne = "EVAL_AUTRE"
elif ("survey_type" in local_survey_retval.keys() and local_survey_retval['survey_type'] == "specific_survey"):
courrier_ref_interne = "SPECIFIC_SURVEY"
else:
mycommon.myprint(str(inspect.stack()[0][3]) + " Le type d'enquete est invalide ")
return False, " Le type d'enquete est invalide "
@ -3292,7 +3304,8 @@ def Export_To_Excel_Survey_with_filter(diction):
"""
Verification des input acceptés
"""
field_list = ['token', 'session_id', 'formulaire_type' , 'related_collection', 'related_collection_id' ]
field_list = ['token', 'session_id', 'formulaire_type' , 'related_collection',
'related_collection_id', ]
incom_keys = diction.keys()
for val in incom_keys:
@ -3368,7 +3381,8 @@ def Export_To_Excel_Survey_with_filter(diction):
val_tmp = 0
qry = {"partner_owner_recid": str(my_partner['recid']), 'valide': '1', 'locked': '0'}
query_with_filter = {'$and': [qry, filt_session_id, filt_related_collection, filt_related_collection_id]}
query_with_filter = {'$and': [qry, filt_session_id, filt_related_collection, filt_related_collection_id
]}
pipe_qry = ([
{'$match': query_with_filter },
@ -3585,6 +3599,308 @@ def Export_To_Excel_Survey_with_filter(diction):
return False, " Impossible de générer l'export "
"""
Cette fonction pour exporter les resultat d'une enquete dans une fichier excel
avec le cas spécific du survey_internal_code
"""
def Export_To_Excel_Specif_Survey_with_filter_survey_internal_code(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'session_id', 'related_collection',
'related_collection_id', 'survey_internal_code' ]
incom_keys = diction.keys()
for val in incom_keys:
if val not in field_list and val.startswith('my_') is False:
mycommon.myprint(str(
inspect.stack()[0][3]) + " Le champ '" + val + "' n'est pas autorisé")
return False, " Les informations fournies sont incorrectes"
"""
Verification des champs obligatoires
"""
field_list_obligatoire = ['token',]
for val in field_list_obligatoire:
if val not in diction:
mycommon.myprint(
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans 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
filt_session_id = {}
if ("session_id" in diction.keys()):
filt_session_id = {'session_id': str(diction['session_id'])}
filt_related_collection = {}
if ("related_collection" in diction.keys()):
filt_related_collection = {'related_collection': str(diction['related_collection'])}
filt_related_collection_id = {}
if ("related_collection_id" in diction.keys()):
related_collection_id = {'related_collection_id': str(diction['related_collection_id'])}
filt_survey_internal_code = {}
if ("survey_internal_code" in diction.keys()):
filt_survey_internal_code = {'survey_internal_code': str(diction['survey_internal_code'])}
"""
Recuperer les données de la session
"""
my_session_data = MYSY_GV.dbname['session_formation'].find_one({'_id':ObjectId(str(diction['session_id'])),
'valide':'1',
'partner_owner_recid':str(my_partner['recid'])})
if(my_session_data is None):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'identifiant de la session de formation est invalide ")
return False, " L'identifiant de la session de formation est invalide "
"""
Recuperer les données de la formation
"""
my_class_data = MYSY_GV.dbname['myclass'].find_one({'internal_url': str(my_session_data['class_internal_url']),
'valide': '1',
'partner_owner_recid': str(
my_partner['recid'])}, {'title':1})
if (my_class_data is None):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'identifiant de la formation est invalide ")
return False, " L'identifiant de la formation est invalide "
RetObject = []
val_tmp = 0
qry = {"partner_owner_recid": str(my_partner['recid']), 'valide': '1', 'locked': '0'}
query_with_filter = {'$and': [qry, filt_session_id, filt_related_collection, filt_related_collection_id,
filt_survey_internal_code]}
pipe_qry = ([
{'$match': query_with_filter },
{'$project': { 'valide': 0, 'locked': 0, }},
{'$lookup': {
'from': 'formulaire',
"let": {'formulaire_id': "$formulaire_id",
'partner_owner_recid': '$partner_owner_recid'},
'pipeline': [
{'$match':
{'$expr':
{'$and':
[
{'$eq': ["$_id", {'$convert': {
'input': "$$formulaire_id",
'to': "objectId",
'onError': {'error': 'true'},
'onNull': {'isnull': 'true'}
}}]},
{'$eq': ["$valide", "1"]},
{'$eq': ["$partner_owner_recid", '$$partner_owner_recid']}
]
}
}
},
],
'as': 'formulaire'
}
},
{
'$unwind': '$formulaire'
}
])
#print(" ### pipe_qry = ", pipe_qry)
ts = datetime.now().timestamp()
ts = str(ts).replace(".", "").replace(",", "")[-5:]
orig_file_name = "Export_Reponse_" + str(ts) + ".xlsx"
outputFilename = str(MYSY_GV.TEMPORARY_DIRECTORY) + "/" + str(orig_file_name)
tab_exported_fields_header = ["formation", "code_session", "date_debut_session",
"date_fin_session", "email", "nom", "prenom", "date_envoi",
"date_reponse", "question", "reponse", "mode_envoi"]
# Create a workbook and add a worksheet.
workbook = xlsxwriter.Workbook(outputFilename)
worksheet = workbook.add_worksheet()
row = 0
column = 0
"""
Creation de l'entete du fichier excel
"""
for header_item in tab_exported_fields_header:
worksheet.write(row, column, header_item)
column += 1
"""
Creation des data du fichier excel
"""
for Survey_Data in MYSY_GV.dbname['survey'].aggregate(pipe_qry):
column = 0
row = row + 1
# Champ : Titre de la formation
no_html_title = ""
if ("title" in my_class_data.keys()):
no_html_title = my_class_data['title']
worksheet.write(row, column, no_html_title)
column += 1
# Champ : Code session
code_session = ""
if ("code_session" in my_session_data.keys()):
code_session = my_session_data['code_session']
worksheet.write(row, column, code_session)
column += 1
# Champ : Date debut session
date_debut_session = ""
if ("code_session" in my_session_data.keys()):
date_debut_session = my_session_data['date_debut']
worksheet.write(row, column, date_debut_session)
column += 1
# Champ : Date fin session
date_fin_session = ""
if ("date_fin" in my_session_data.keys()):
date_fin_session = my_session_data['date_fin']
worksheet.write(row, column, date_fin_session)
column += 1
# Champ : Email
email = ""
if ("email" in Survey_Data.keys()):
email = Survey_Data['email']
worksheet.write(row, column, email)
column += 1
# Champ : nom
nom = ""
if ("nom" in Survey_Data.keys()):
nom = Survey_Data['nom']
worksheet.write(row, column, nom)
column += 1
# Champ : prenom
prenom = ""
if ("prenom" in Survey_Data.keys()):
prenom = Survey_Data['prenom']
worksheet.write(row, column, prenom)
column += 1
# Champ : date_envoi
date_envoi = ""
if ("date_envoi" in Survey_Data.keys()):
date_envoi = str(Survey_Data['date_envoi'])[0:16]
worksheet.write(row, column, date_envoi)
column += 1
# Champ : date_reponse
date_reponse = ""
if ("date_reponse" in Survey_Data.keys()):
date_reponse = str(Survey_Data['date_reponse'])[0:16]
worksheet.write(row, column, date_reponse)
column += 1
# Gestion des question et reponse
if( "user_response" in Survey_Data.keys() ):
question_num = 1
for user_response in Survey_Data['user_response']:
question = ""
if ("question" in user_response.keys()):
question = str(user_response['question'])
#worksheet.write(0, column, question)
#worksheet.write(row, column, question)
column += 1
#worksheet.write(0, column, "response_"+str(question_num))
worksheet.write(0, column, question)
response = ""
if ("response" in user_response.keys()):
response = str(user_response['response'])
worksheet.write(row, column, response)
column += 1
question_num += 1
else:
#question = "---"
#worksheet.write(row, column, question)
column += 1
response = "---"
worksheet.write(row, column, response)
column += 1
# Champ : date_reponse
mode_envoi = ""
if ("mode_envoi" in Survey_Data.keys()):
mode_envoi = str(Survey_Data['mode_envoi'])
worksheet.write(row, column, mode_envoi)
column += 1
workbook.close()
if os.path.exists(outputFilename):
# print(" ### ok os.path.exists(outputFilename) "+str(outputFilename))
return True, send_file(outputFilename, as_attachment=True)
return False, "Impossible de générer l'export (2) "
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de générer l'export "
"""
Cette fonction pour exporter les resultat d'une enquete dans une fichier excel :
POUR UNE LISTE _ID
@ -4906,6 +5222,83 @@ def Delete_List_Survey(diction):
return False, "Impossible de supprimer les demandes"
"""
Cette fonction supprime un specific_survey (s'il n'a pas de réponse), en se basant
sur le survey_internal_code
"""
def Delete_List_Survey_From_survey_internal_code(diction):
try:
diction = mycommon.strip_dictionary(diction)
'''
# Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
# Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
# Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
# field_list.
'''
field_list = [ 'token', 'survey_internal_code',]
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é, Creation partenaire annulée")
return False, "Toutes les informations fournies ne sont pas valables"
"""
Verification de la liste des champs obligatoires
"""
field_list_obligatoire = [ 'token', 'survey_internal_code']
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, "Toutes les informations necessaires n'ont pas été fournies"
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
if (local_status is not True):
return local_status, my_partner
# Verifier qu'il n'a pas déjà de réponse avec ce survey_internal_code
is_specific_survey_has_response = MYSY_GV.dbname['survey'].count_documents({'survey_internal_code':str(diction['survey_internal_code']),
'valide':'1',
'locked':'0',
'partner_owner_recid':str(my_partner['recid']),
'user_response': {
'$exists': True},
})
if(is_specific_survey_has_response > 0 ):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " Il y a déjà des réponses utilisateur, suppression annulée")
return False, "Il y a déjà des réponses utilisateur, suppression annulée"
delete_row = MYSY_GV.dbname['survey'].delete_many({'survey_internal_code':str(diction['survey_internal_code']),
'valide':'1',
'locked':'0',
'partner_owner_recid':str(my_partner['recid']),
'user_response': {
'$exists': False},
})
return True, str( delete_row.deleted_count) + " demande(s) supprimé(s)"
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, "Impossible de supprimer les demandes"
"""
Cette fonction prends un session_id, une adresse email et
retourne l'url de l'enquete associée, sans token
@ -4945,7 +5338,7 @@ def Get_Survey_Url_From_SessionId_Email_No_Token(diction):
is_inscription_valide = MYSY_GV.dbname['inscription'].count_documents({"session_id": diction['session_id'],
'email':diction['email'],
'valide':'1',
'status':'1'})
'status':{'$in':['0', '1']}})
if( is_inscription_valide != 1):
mycommon.myprint(
@ -4956,7 +5349,7 @@ def Get_Survey_Url_From_SessionId_Email_No_Token(diction):
inscription_data = MYSY_GV.dbname['inscription'].find_one({"session_id": diction['session_id'],
'email': diction['email'],
'valide': '1',
'status': '1'})
'status':{'$in':['0', '1']}})
@ -4985,7 +5378,6 @@ def Get_Survey_Url_From_SessionId_Email_No_Token(diction):
'partner_owner_recid':str(inscription_data['partner_owner_recid']),
'valide':'1',
'locked':'0',
'survey_type':str(diction['survey_type']),
'qr_code_safe_token': str(diction['qr_code_safe_token']),
'statut':'1',})
@ -5127,7 +5519,7 @@ def Create_Evaluation_QR_Code_From_Survey(diction):
data_update['date_update'] = str(datetime.now())
data_update['statut'] = "1"
data_update['date_envoi'] = now
data_update['mode_envoi'] = "QR"
data_update['mode_envoi'] = "qr"
data_update['date_dernier_relance_auto'] = str(datetime.now().strftime("%d/%m/%Y")),
data_update['qr_code_safe_token'] = str(local_QR_Code_safe_token)

View File

@ -2009,8 +2009,10 @@ JMJ reprise factures
"""
def JMJ_Repise_Factures(diction):
try:
saved_file = "./temp_direct/facture_exemple_fichier_v2_dev.csv"
saved_file = ""
#saved_file = "./temp_direct/facture_exemple_fichier_v3_prod.csv"
#saved_file = "./temp_direct/facture_exemple_fichier_v3_rec.csv"
#saved_file = "./temp_direct/facture_exemple_fichier_v3_dev.csv"
#saved_file = "./temp_direct/facture_exemple_fichier_v2_prod.csv"
df = pd.read_csv(saved_file, encoding='utf8', on_bad_lines='skip', sep=';', encoding_errors='ignore',
@ -2022,17 +2024,23 @@ def JMJ_Repise_Factures(diction):
x = range(0, total_rows)
field_list = ['code_client', 'email_client', 'date_echeance', 'date_emission', 'montant_ht',
'montant_ttc', 'num_facture', 'note', 'code_session',
'tax_amount', 'tax_taux', 'annotation', 'facture_initiale', 'type']
'tax_amount', 'tax_taux', 'annotation', 'facture_initiale', 'type',
'email_client_facture']
list_client_ko = []
list_code_session_ko = []
list_client_facture_ko = []
list_code_session_kooo = []
list_client_kooo = []
list_client_facture_kooo = []
for n in x:
client_mail = str(df['email_client'].values[n]).strip()
client_mail_facture = str(df['email_client_facture'].values[n]).strip()
session_formation = str(df['code_session'].values[n]).strip()
if( client_mail != "" and session_formation != ""):
# Verifier si le client existe
is_client_exist = MYSY_GV.dbname['partner_client'].count_documents({"email":client_mail, 'partner_owner_recid':diction['partner_owner_recid']})
@ -2047,6 +2055,21 @@ def JMJ_Repise_Factures(diction):
else:
list_client_kooo.append(str(client_mail))
# Verifier si le client facturer existe
is_client_facture_exist = MYSY_GV.dbname['partner_client'].count_documents(
{"email": client_mail_facture, 'partner_owner_recid': diction['partner_owner_recid']})
if (is_client_facture_exist <= 0):
if (client_mail_facture not in list_client_facture_ko):
list_client_facture_ko.append(str(client_mail_facture))
elif (is_client_facture_exist > 1):
print(" Client email Facturer: " + str(client_mail_facture) + " == ", is_client_facture_exist)
else:
list_client_facture_kooo.append(str(client_mail_facture))
# Verifier si la session existe
is_session_exist = MYSY_GV.dbname['session_formation'].count_documents({"code_session": session_formation, 'partner_owner_recid':diction['partner_owner_recid']})
@ -2065,21 +2088,29 @@ def JMJ_Repise_Factures(diction):
print(" NB client KO = ", len(list_client_ko))
print(" List client KO = ", list_client_ko)
print(" NB client FACTURE KO = ", len(list_client_facture_ko))
print(" List client FACTURE KO = ", list_client_facture_ko)
print(" NB code session KO = ", len(list_code_session_ko))
print(" List code session KO = ", list_code_session_ko)
tab_facture_traite = []
for n in x:
client_mail = str(df['email_client'].values[n]).strip()
client_mail_facture = str(df['email_client_facture'].values[n]).strip()
session_formation = str(df['code_session'].values[n]).strip()
num_facture = str(df['num_facture'].values[n]).strip()
if(client_mail in list_client_kooo and session_formation in list_code_session_kooo ):
if(client_mail in list_client_kooo and session_formation in list_code_session_kooo
and client_mail_facture in list_client_facture_kooo):
node_facture_traiter = {}
node_facture_traiter['num_facture'] = str(num_facture)
node_facture_traiter['session_formation'] = str(session_formation)
node_facture_traiter['client_mail'] = str(client_mail)
node_facture_traiter['client_mail_facture'] = str(client_mail_facture)
tab_facture_traite.append(node_facture_traiter)
print(" ### tab_facture_traite = ", str(tab_facture_traite))
@ -2089,9 +2120,11 @@ def JMJ_Repise_Factures(diction):
cpt_facture_imported = 0
for n in x:
client_mail = str(df['email_client'].values[n]).strip()
client_mail_facture = str(df['email_client_facture'].values[n]).strip()
session_formation = str(df['code_session'].values[n]).strip()
if(client_mail in list_client_kooo and session_formation in list_code_session_kooo ):
if(client_mail in list_client_kooo and session_formation in list_code_session_kooo
and client_mail_facture in list_client_facture_kooo):
date_echeance = str(df['date_echeance'].values[n]).strip()
date_emission = str(df['date_emission'].values[n]).strip()
@ -2110,12 +2143,18 @@ def JMJ_Repise_Factures(diction):
client_data = MYSY_GV.dbname['partner_client'].find_one({"email": client_mail})
session_data = MYSY_GV.dbname['session_formation'].find_one({"code_session": session_formation})
client_facture_data = MYSY_GV.dbname['partner_client'].find_one({"email": client_mail_facture})
class_data = MYSY_GV.dbname['myclass'].find_one({"partner_owner_recid":diction['partner_owner_recid'],
'_id':ObjectId(str(session_data['class_id']))})
inscrit_data = MYSY_GV.dbname['inscription'].find_one({"partner_owner_recid":diction['partner_owner_recid'],
'email':client_mail, 'session_id':str(session_data['_id'])
})
if( client_data and session_data and class_data ):
if( client_data and session_data and class_data and client_facture_data and inscrit_data) :
## Creer les factures de reprise
partner_invoice_header_data = {}
@ -2144,18 +2183,18 @@ def JMJ_Repise_Factures(diction):
partner_invoice_header_data[str(val)] = ""
partner_invoice_header_data['order_header_client_id'] = str(client_data['_id'])
partner_invoice_header_data['order_header_client_id'] = str(client_facture_data['_id'])
partner_invoice_header_data['invoice_date_echeance'] = str(date_echeance)
partner_invoice_header_data['order_header_condition_paiement_code'] = ""
partner_invoice_header_data['order_header_condition_paiement_description'] = ""
partner_invoice_header_data['order_header_ref_interne'] = str(code_session)
partner_invoice_header_data['order_header_email_client'] = str(client_mail)
partner_invoice_header_data['order_header_email_client'] = str(client_mail_facture)
partner_invoice_header_data['order_header_origin'] = "REPRISE"
partner_invoice_header_data['order_header_adr_fact_adresse'] = str(client_data['invoice_adresse'])
partner_invoice_header_data['order_header_adr_fact_ville'] = str(client_data['invoice_ville'])
partner_invoice_header_data['order_header_adr_fact_code_postal'] = str(client_data['invoice_code_postal'])
partner_invoice_header_data['order_header_adr_fact_pays'] = str(client_data['invoice_pays'])
partner_invoice_header_data['order_header_adr_fact_adresse'] = str(client_facture_data['invoice_adresse'])
partner_invoice_header_data['order_header_adr_fact_ville'] = str(client_facture_data['invoice_ville'])
partner_invoice_header_data['order_header_adr_fact_code_postal'] = str(client_facture_data['invoice_code_postal'])
partner_invoice_header_data['order_header_adr_fact_pays'] = str(client_facture_data['invoice_pays'])
order_header_montant_reduction = "0"
partner_invoice_header_data['order_header_montant_reduction'] = "0"
partner_invoice_header_data['total_header_hors_taxe_before_header_reduction'] = str(montant_ht)
@ -2202,7 +2241,7 @@ def JMJ_Repise_Factures(diction):
partner_invoice_line_data['order_line_qty'] = str("1")
partner_invoice_line_data['order_line_prix_unitaire'] = str(montant_ht)
partner_invoice_line_data['order_line_montant_hors_taxes'] = str(montant_ht)
partner_invoice_line_data['order_line_comment'] = "REPRISE"
partner_invoice_line_data['order_line_comment'] = str(inscrit_data['nom']).upper() +" "+str(inscrit_data['prenom']).capitalize()
partner_invoice_line_data['invoice_header_id'] = str(inserted_invoice_id)
partner_invoice_line_data['invoice_line_type'] = "facture"
partner_invoice_line_data['invoice_header_ref_interne'] = partner_invoice_header_data['invoice_header_ref_interne']