21/06/26 - 22h

Signed-off-by: Cherif <cbalde@mysy-training.com>
master_Elyos_FI
Cherif 2026-06-21 22:26:00 +02:00
parent d5700dc6d7
commit 7e6b1a73b9
18 changed files with 13071 additions and 84 deletions

View File

@ -4,10 +4,25 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="08/06/2026 - 21h">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="14/06/2026 - 12h">
<change afterPath="$PROJECT_DIR$/Bulletin_Note_mgt.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/tools_cherif/send_sms_ovh.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Env_Data.py" beforeDir="false" afterPath="$PROJECT_DIR$/Env_Data.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/GlobalVariable.py" beforeDir="false" afterPath="$PROJECT_DIR$/GlobalVariable.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Inscription_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/Inscription_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Log/log_file.log" beforeDir="false" afterPath="$PROJECT_DIR$/Log/log_file.log" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Relance_client_facture.py" beforeDir="false" afterPath="$PROJECT_DIR$/Relance_client_facture.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Session_Formation.py" beforeDir="false" afterPath="$PROJECT_DIR$/Session_Formation.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/attached_file_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/attached_file_mgt.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$/class_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/class_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$/ent_student_common.py" beforeDir="false" afterPath="$PROJECT_DIR$/ent_student_common.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/internal_email_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/internal_email_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/prj_common.py" beforeDir="false" afterPath="$PROJECT_DIR$/prj_common.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ressources_humaines.py" beforeDir="false" afterPath="$PROJECT_DIR$/ressources_humaines.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/session_admission_fi.py" beforeDir="false" afterPath="$PROJECT_DIR$/session_admission_fi.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -53,14 +68,14 @@
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;git-widget-placeholder&quot;: &quot;master__Elyos__FI&quot;,
&quot;ignore.virus.scanning.warn.message&quot;: &quot;true&quot;,
&quot;last_opened_file_path&quot;: &quot;C:/Users/Cherif/Documents/myclass.com/Siteweb/Elyos_Ftion_Initiale/Ela_back/Back_Office_FI&quot;,
&quot;last_opened_file_path&quot;: &quot;C:/Users/Cherif/Documents/myclass.com/Siteweb/Elyos_Ftion_Initiale/Ela_back/Back_Office_FI/tools_cherif&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.lookFeel&quot;
}
}</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\Cherif\Documents\myclass.com\Siteweb\Elyos_Ftion_Initiale\Ela_back\Back_Office_FI" />
<recent name="C:\Users\Cherif\Documents\myclass.com\Siteweb\Elyos_Ftion_Initiale\Ela_back\Back_Office_FI\tools_cherif" />
<recent name="C:\Users\Cherif\Documents\myclass.com\Siteweb\Elyos_Ftion_Initiale\Ela_back\Back_Office_FI" />
<recent name="C:\Users\billa\Documents\myclass.com\Siteweb\Production\Ela_back\Back_Office\tools_cherif" />
<recent name="C:\Users\billa\Documents\myclass.com\Siteweb\Production\Ela_back\Back_Office" />
</key>
@ -451,7 +466,7 @@
<option name="project" value="LOCAL" />
<updated>1747251650255</updated>
</task>
<option name="localTasksCounter" value="598" />
<option name="localTasksCounter" value="599" />
<servers />
</component>
<component name="Vcs.Log.Tabs.Properties">
@ -493,7 +508,6 @@
</option>
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="05/05/2026 - 19h" />
<MESSAGE value="07/05/2026 - 17h" />
<MESSAGE value="08/05/2026 - 17h" />
<MESSAGE value="09/05/2025 - 20h30" />
@ -518,6 +532,7 @@
<MESSAGE value="01/06/2026 - 22h00" />
<MESSAGE value="06/06/2026 - 21h" />
<MESSAGE value="08/06/2026 - 21h" />
<option name="LAST_COMMIT_MESSAGE" value="08/06/2026 - 21h" />
<MESSAGE value="14/06/2026 - 12h" />
<option name="LAST_COMMIT_MESSAGE" value="14/06/2026 - 12h" />
</component>
</project>

428
Bulletin_Note_mgt.py Normal file
View File

@ -0,0 +1,428 @@
"""
Ce document permet de gerer les bulletin de note créer
- Recuperation liste bulletin note
- publication / Depublication ENT
Un bulletin de note est definit par
- inscription_id,
- class_id,
- session_id,
- tab_semestre,
- diplome_id
"""
import bson
import pymongo
from pymongo import MongoClient
import json
from bson import ObjectId
import re
from datetime import datetime
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
"""
Recuperer la liste de bulletin de note d'un inscrit
"""
def Get_Bulletin_Note_Inscrit(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'inscription_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', 'inscription_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
qry = {"partner_owner_recid":str(my_partner['recid']), 'valide':'1', 'locked':'0',
'object_owner_collection':'inscription',
'object_owner_id':str(diction['inscription_id']),
'type_document':'bulletin'}
for New_retVal in MYSY_GV.dbname['download_files'].find(qry).sort([("_id", pymongo.DESCENDING), ]):
user = New_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 compétences "
"""
Recuperer la liste de bulletin de note d'un partenaire avec des filter sur :
- session_id
- class_id
- diplome_id
- inscrit_id
"""
def Get_Partner_Bulletin_Note_With_Filter(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'inscription_id', 'session_id', 'class_id', 'diplome_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', ]
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_class_id = {}
if ("class_id" in diction.keys()):
filt_class_id = {'class_id': str(diction['class_id'])}
filt_diplome_id = {}
if ("diplome_id" in diction.keys()):
filt_diplome_id = {'diplome_id': str(diction['diplome_id'])}
filt_inscription_id = {}
if ("inscription_id" in diction.keys()):
filt_inscription_id = {'inscription_id': str(diction['inscription_id'])}
RetObject = []
val_tmp = 0
qry = {"partner_owner_recid":str(my_partner['recid']), 'valide':'1', 'locked':'0',
'object_owner_collection':'inscription',
'object_owner_id':str(diction['inscription_id']),
'type_document':'bulletin'}
query_with_filter = {'$and': [qry, filt_session_id, filt_class_id, filt_diplome_id, filt_inscription_id]}
for New_retVal in MYSY_GV.dbname['download_files'].find(query_with_filter).sort([("_id", pymongo.DESCENDING), ]):
user = New_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 bulletins de notes "
"""
Publier une liste de bulletin de note
"""
def Publish_Tab_Bulletin_Note(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'tab_download_files_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 = ['token', 'tab_download_files_ids']
for val in field_list_obligatoire:
if val not in diction:
mycommon.myprint(
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans la liste des arguments ")
return False, " Les informations fournies sont incorrectes"
"""
Verification de l'identité et autorisation de l'entité qui
appelle cette API
"""
token = ""
if ("token" in diction.keys()):
if diction['token']:
token = diction['token']
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
if (local_status is not True):
return local_status, my_partner
tab_download_files_ids_work = str(diction['tab_download_files_ids']).split(",")
tab_download_files_ids = []
tab_download_files_ids_ObjectId = []
for tmp in tab_download_files_ids_work:
if( tmp ):
tab_download_files_ids.append(tmp)
tab_download_files_ids_ObjectId.append(tmp)
update_data = {}
update_data['update_date'] = str(datetime.now())
update_data['update_by'] = str(my_partner['_id'])
update_data['publish'] = "1"
update_data['publish_date'] = str(datetime.now())
result = MYSY_GV.dbname['download_files'].update_many(
{'_id':{'$in':tab_download_files_ids_ObjectId},
'partner_owner_recid':str(my_partner['recid'])},
update_data
)
return True, " Les bulletins ont été publié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 publier les bulletins de notes "
"""
Dépublier une liste de bulletin de note
"""
def Unpublish_Tab_Bulletin_Note(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'tab_download_files_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 = ['token', 'tab_download_files_ids']
for val in field_list_obligatoire:
if val not in diction:
mycommon.myprint(
str(inspect.stack()[0][
3]) + " - La valeur '" + val + "' n'est pas presente dans la liste des arguments ")
return False, " Les informations fournies sont incorrectes"
"""
Verification de l'identité et autorisation de l'entité qui
appelle cette API
"""
token = ""
if ("token" in diction.keys()):
if diction['token']:
token = diction['token']
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
if (local_status is not True):
return local_status, my_partner
tab_download_files_ids_work = str(diction['tab_download_files_ids']).split(",")
tab_download_files_ids = []
tab_download_files_ids_ObjectId = []
for tmp in tab_download_files_ids_work:
if (tmp):
tab_download_files_ids.append(tmp)
tab_download_files_ids_ObjectId.append(tmp)
update_data = {}
update_data['update_date'] = str(datetime.now())
update_data['update_by'] = str(my_partner['_id'])
update_data['publish'] = "0"
update_data['unpublish_date'] = str(datetime.now())
result = MYSY_GV.dbname['download_files'].update_many(
{'_id': {'$in': tab_download_files_ids_ObjectId},
'partner_owner_recid': str(my_partner['recid'])},
update_data
)
return True, " Les bulletins ont été dépublié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 dépublier les bulletins de notes "
"""
Supprimer une liste de bulletin de note
"""
def Delete_Tab_Bulletin_Note(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'tab_download_files_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 = ['token', 'tab_download_files_ids']
for val in field_list_obligatoire:
if val not in diction:
mycommon.myprint(
str(inspect.stack()[0][
3]) + " - La valeur '" + val + "' n'est pas presente dans la liste des arguments ")
return False, " Les informations fournies sont incorrectes"
"""
Verification de l'identité et autorisation de l'entité qui
appelle cette API
"""
token = ""
if ("token" in diction.keys()):
if diction['token']:
token = diction['token']
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
if (local_status is not True):
return local_status, my_partner
tab_download_files_ids_work = str(diction['tab_download_files_ids']).split(",")
tab_download_files_ids = []
tab_download_files_ids_ObjectId = []
for tmp in tab_download_files_ids_work:
if (tmp):
tab_download_files_ids.append(tmp)
tab_download_files_ids_ObjectId.append(tmp)
update_data = {}
update_data['update_date'] = str(datetime.now())
update_data['update_by'] = str(my_partner['_id'])
update_data['publish'] = "0"
update_data['unpublish_date'] = str(datetime.now())
result = MYSY_GV.dbname['download_files'].delete_many(
{'_id': {'$in': tab_download_files_ids_ObjectId},
'partner_owner_recid': str(my_partner['recid'])}
)
return True, " Les bulletins ont été 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 bulletins de notes "

View File

@ -4,12 +4,14 @@ Liste des environnements :
- Developpement (DEV)
- Recette (REC)
- Demonstration (DEM)
- Formation (FORMATION)
- Production (PROD)
"""
#MYSY_ENV = "PROD"
#MYSY_ENV = "REC"
#MYSY_ENV = "DEM"
#MYSY_ENV = "FORMATION"
MYSY_ENV = "DEV"

View File

@ -93,6 +93,23 @@ elif (MYSY_ENV == "DEM"):
BLOG_FTP_IMG_REPOSITORY = "/var/www/html/blog_imgs/blog_img_prod/"
BLOG_IMG_URL = "https://blogimg.mysy-training.com/"
elif (MYSY_ENV == "FORMATION"):
CONNECTION_STRING = "mongodb://localhost:27017/cherifdb_formation"
client = MongoClient(CONNECTION_STRING)
dbname = client['cherifdb_formation_fi']
CLIENT_URL_BASE = 'https://formation.mysy-training.com/'
MYSY_DEBUG_LEVEL = 1
# Domaine pour le catalogue public
MYSY_PUBLIC_CATALOG_DOMAIN = 'demomysy-hosting.online'
"""
REPERTOIRE FTP DES IMAGES DU BLOG
Volontairement on met tous les environnements dans le meme repertoire. C'est un choix
"""
BLOG_FTP_IMG_REPOSITORY = "/var/www/html/blog_imgs/blog_img_formation/"
BLOG_IMG_URL = "https://blogformationimg.mysy-training.com/"
elif (MYSY_ENV == "XCELIA_DEM"):
CONNECTION_STRING = "mongodb://localhost:27017/cherifdb_xcelia_demo"
@ -126,6 +143,7 @@ MYSY_PORT_PROD = 5000
MYSY_PORT_DEV = 5001
MYSY_PORT_REC = 5001
MYSY_PORT_DEM = 5003
MYSY_PORT_FORMATION = 5004
"""
@ -295,6 +313,9 @@ elif (MYSY_ENV == "DEV"):
elif (MYSY_ENV == "REC"):
INVOICE_FTP_LOCAL_STORAGE_DIRECTORY = "/home/mysy_data/mysy_invoices_rec/"
elif (MYSY_ENV == "FORMATION"):
INVOICE_FTP_LOCAL_STORAGE_DIRECTORY = "/home/mysy_data/mysy_invoices_rec/"
elif (MYSY_ENV == "DEM"):
INVOICE_FTP_LOCAL_STORAGE_DIRECTORY = "/home/mysy_data/mysy_invoices_demo/"
@ -336,6 +357,15 @@ if (MYSY_ENV == "REC"):
O365_SMTP_COUNT_From_User = "support@mysy-training.com"
O365_SMTP_COUNT_port = 587
if (MYSY_ENV == "FORMATION"):
O365_SMTP_COUNT_password = 'Xad47198'
O365_SMTP_COUNT_smtpsrv = "smtp.office365.com"
O365_SMTP_COUNT_user = "support@mysy-training.com"
O365_SMTP_COUNT_From_User = "support@mysy-training.com"
O365_SMTP_COUNT_port = 587
if (MYSY_ENV == "DEM"):
O365_SMTP_COUNT_password = 'Xad47198'
O365_SMTP_COUNT_smtpsrv = "smtp.office365.com"
@ -487,6 +517,22 @@ elif (MYSY_ENV == "REC"):
STRIPE_STANDARD_PRICE_ID_100_OFF = "price_1NEpbrAbmaEugrFTgLABbIOF"
STRIPE_TEST_PRICE_ID = "price_1MT3FLAbmaEugrFTDgw7MVgb"
STRIPE_CONFIG_KEY_PUB = "pk_test_51LUUfAAbmaEugrFTI25uZBD3IFjbtaL6jUfRV83diDf7nco8worna4NGKhMHbPP71WCwT5EHFRdDNatxPrJWwgZ300kgH5EO4p"
STRIPE_CONFIG_API_KEY = "sk_test_51LUUfAAbmaEugrFTrWsfcBWZtbBh9r3HCa2sgeyikG808LjSk3bAdFhV6KxgRZ3vFxooa6RE0c5zBkTuOUrKkyjy00BrsIXAPs"
elif (MYSY_ENV == "FORMATION"):
STRIPE_GOLD_PRICE_ID = "price_1MT3FmAbmaEugrFTZ5vyJRcZ"
STRIPE_GOLD_PRICE_ID_50_OFF = "price_1NEpALAbmaEugrFTCDhlJyo3"
STRIPE_GOLD_PRICE_ID_95_OFF = "price_1NFyUEAbmaEugrFT5sRXixeZ"
STRIPE_GOLD_PRICE_ID_100_OFF = "price_1NEpeJAbmaEugrFTXT5OFciX"
STRIPE_STANDARD_PRICE_ID = "price_1MT3FLAbmaEugrFTDgw7MVgb"
STRIPE_STANDARD_PRICE_ID_50_OFF = "price_1NEpCOAbmaEugrFTcBnOf89X"
STRIPE_STANDARD_PRICE_ID_95_OFF = "price_1NFySwAbmaEugrFTxrQHhFN9"
STRIPE_STANDARD_PRICE_ID_100_OFF = "price_1NEpbrAbmaEugrFTgLABbIOF"
STRIPE_TEST_PRICE_ID = "price_1MT3FLAbmaEugrFTDgw7MVgb"
STRIPE_CONFIG_KEY_PUB = "pk_test_51LUUfAAbmaEugrFTI25uZBD3IFjbtaL6jUfRV83diDf7nco8worna4NGKhMHbPP71WCwT5EHFRdDNatxPrJWwgZ300kgH5EO4p"
STRIPE_CONFIG_API_KEY = "sk_test_51LUUfAAbmaEugrFTrWsfcBWZtbBh9r3HCa2sgeyikG808LjSk3bAdFhV6KxgRZ3vFxooa6RE0c5zBkTuOUrKkyjy00BrsIXAPs"
@ -532,9 +578,9 @@ Limite des zones de texte des formation
- objectif
- description
"""
CLASS_ZONE_PROGRAM_LIMIT = 1200
CLASS_ZONE_DESCRIP_LIMIT = 1200
CLASS_ZONE_OBJECTIF_LIMIT = 1200
CLASS_ZONE_PROGRAM_LIMIT = 5000
CLASS_ZONE_DESCRIP_LIMIT = 5000
CLASS_ZONE_OBJECTIF_LIMIT = 5000
"""
@ -611,6 +657,18 @@ elif (MYSY_ENV == "REC"):
LMS_BAS_URL = "mysy-hosting.com/"
MYSY_ENV_API = "https://devapimysy.mysy-training.com/myclass/api/"
elif (MYSY_ENV == "FORMATION"):
MYSY_MARIADB_USER = "mysy_mariadb_user"
MYSY_MARIADB_USER_PASS = "fB5z%M)GG&g!n2c"
MYSY_MARIADB_HOST = "51.77.211.142"
MYSY_MARIADB_PORT = 3306
MYSY_LMS_BDD = "mysy_db_chamilo_formation"
MYSY_LMS_URL = "https://formationlms.mysy-training.com/"
MYSY_LMS_BASE_DIRECTORY = "/var/www/html/chamilo_mysy_formation/"
LMS_BAS_URL = "mysy-hosting.com/"
MYSY_ENV_API = "https://formationapimysy.mysy-training.com/myclass/api/"
elif (MYSY_ENV == "DEM"):
MYSY_MARIADB_USER = "mysy_mariadb_user"
MYSY_MARIADB_USER_PASS = "fB5z%M)GG&g!n2c"
@ -1228,4 +1286,11 @@ STAGE_TYPE_EVAL = ['eval_tuteur_entreprise', 'eval_tuteur_ecole']
Gestion Ressource humaine : Type RH
type_rh = 1 ==> Autre RH (ex : parent d'eleves, etc)
"""
"""
## Application name : EYSY02
OVH_ENDPOINT="ovh-eu"
OVH_APPLICATION_KEY="16ef9f92d1580d15"
OVH_APPLICATION_SECRET="ec7e66e0f27f5494038c14fcb11d105a"
OVH_CONSUMER_KEY="0268191866b32cce8ea012136ce94ddd"
OVH_SMS_SERVICE_NAME="sms-bc2043990-1"
OVH_SMS_SENDER="EYSY"

View File

@ -15813,8 +15813,17 @@ def Get_Statgiaire_Communication_Contact(diction):
for retval in MYSY_GV.dbname['ressource_humaine'].find({'partner_recid': my_partner['recid'],
'tab_inscription_id.inscription_id':str(diction['_id']), 'tab_inscription_id.include_com':'1'} ):
'tab_inscription_id': {
'$elemMatch': {
'inscription_id': str(diction['_id']),
'include_com': "1",
}
}
}
):
node_rh_tuteur = {}
node_rh_tuteur['_id'] = str(retval['_id'])
@ -15924,6 +15933,9 @@ def Get_Statgiaire_Communication_Contact(diction):
"""
Fonction permet d'exporter des inscription dans un fichier excel
"""
@ -19767,6 +19779,8 @@ def Get_Inscrit_List_Tuteurs(diction):
tuteur_label = "Tuteur scolaire"
elif (str(insc_tutore_data['role']) == "3"):
tuteur_label = "Autre"
elif (str(insc_tutore_data['role']) == "4"):
tuteur_label = "Tuteur pédagogique"
node_rh_tuteur['tuteur_role_label'] = tuteur_label

File diff suppressed because one or more lines are too long

View File

@ -5055,7 +5055,7 @@ def Add_Update_SessionFormation_mass_for_many_class(file=None, Folder=None, dict
clean_dict = {k: mydata[k] for k in mydata if (str(mydata[k]) != "nan")}
print("#### Add_Update_SessionFormation_mass_for_many_class : clean_dict ", clean_dict)
#print("#### Add_Update_SessionFormation_mass_for_many_class : clean_dict ", clean_dict)
status, retval = Add_Update_SessionFormation(clean_dict)
if (status is False):

View File

@ -301,7 +301,7 @@ def Internal_Usage_Store_User_Downloaded_File(Folder=None, diction=None, tab_rel
"""
field_list = ['token', 'file_business_object', 'file_name', 'status','object_owner_collection', 'object_owner_id',
'file_name_to_store', 'type_document', 'metadata_field', 'tab_key_word', 'related_collection_ue',
'related_collection_session', 'related_collection_class', 'is_secure_file']
'related_collection_session', 'related_collection_class', 'is_secure_file',]
incom_keys = diction.keys()
for val in incom_keys:
if val not in field_list and val.startswith('my_') is False:
@ -1434,7 +1434,7 @@ def Get_List_object_owner_collection_Stored_Files_With_Filter(diction):
field_list = ['token', 'filter_object_owner_collection', 'filter_object_owner_id',
'filter_file_business_object', 'date_create_start_date', 'date_create_end_date', 'filter_type_document',
'filter_nom_client', 'filter_formation_external_code', 'filter_session_code',
'filter_class_external_code', 'filter_nom_prenom_mail_inscrit']
'filter_class_external_code', 'filter_nom_prenom_mail_inscrit', 'expiration_start_date', 'expiration_end_date']
incom_keys = diction.keys()
for val in incom_keys:
@ -1566,18 +1566,39 @@ def Get_List_object_owner_collection_Stored_Files_With_Filter(diction):
return False, " Le filtre : 'date de fin' n'est pas au format jj/mm/aaaa."
"""
Gestion date expiration document
"""
filt_expiration_start_date = ""
if ("expiration_start_date" in diction.keys() and diction['expiration_start_date']):
filt_expiration_start_date = str(diction['expiration_start_date'])[0:10]
local_status = mycommon.CheckisDate(filt_expiration_start_date)
if (local_status is False):
mycommon.myprint(str(
inspect.stack()[0][3]) + " Le filtre : 'date expiration Du' n'est pas au format jj/mm/aaaa.")
return False, " Le filtre : 'date expiration Du' n'est pas au format jj/mm/aaaa."
filt_expiration_end_date = ""
if ("expiration_end_date" in diction.keys() and diction['expiration_end_date']):
filt_expiration_end_date = str(diction['expiration_end_date'])[0:10]
local_status = mycommon.CheckisDate(filt_expiration_end_date)
if (local_status is False):
mycommon.myprint(str(
inspect.stack()[0][3]) + " Le filtre : 'date expiration Au' n'est pas au format jj/mm/aaaa.")
return False, " Le filtre : 'date expiration Au' n'est pas au format jj/mm/aaaa."
# Controle de cohérence des dates
if ("date_create_start_date" in diction.keys() and "date_create_end_date" in diction.keys() and
datetime.strptime(str(diction['date_create_start_date'])[0:10], '%d/%m/%Y') > datetime.strptime(
str(diction['date_create_end_date'])[0:10], '%d/%m/%Y')):
if ("expiration_start_date" in diction.keys() and "expiration_end_date" in diction.keys() and
datetime.strptime(str(diction['expiration_start_date'])[0:10], '%d/%m/%Y') > datetime.strptime(
str(diction['expiration_end_date'])[0:10], '%d/%m/%Y')):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " Filtre de recherche : La date debut " + str(
diction['date_create_start_date'])[0:10] +
" est postérieure à la date de fin " + str(diction['date_create_end_date'])[0:10])
3]) + " Filtre de recherche : La date expiration debut " + str(
diction['expiration_start_date'])[0:10] +
" est postérieure à la date de fin " + str(diction['expiration_end_date'])[0:10])
return False, " Filtre de recherche : La date debut de début " + str(diction['date_create_start_date'])[0:10] + \
" est postérieure à la date de fin " + str(diction['date_create_end_date'])[0:10] + " "
return False, " Filtre de recherche : La date debut de début " + str(diction['expiration_start_date'])[0:10] + \
" est postérieure à la date de fin " + str(diction['expiration_end_date'])[0:10] + " "
"""
@ -1696,6 +1717,34 @@ def Get_List_object_owner_collection_Stored_Files_With_Filter(diction):
}
}
"""
Construction filtre sur les dates d'expiration
"""
filt_expiration_start_date_ISODATE = None
filt_expiration_end_date_ISODATE = None
if (filt_expiration_start_date):
filt_expiration_start_date_ISODATE = datetime.strptime(str(filt_expiration_start_date), '%d/%m/%Y')
if (filt_expiration_end_date):
filt_expiration_end_date_ISODATE = datetime.strptime(str(filt_expiration_end_date), '%d/%m/%Y')
filt_date_expiration = {}
if (filt_expiration_start_date_ISODATE and filt_expiration_end_date_ISODATE):
filt_date_expiration = {'mysy_download_files_date_expiration': {'$gte': filt_expiration_start_date_ISODATE,
'$lte': filt_expiration_end_date_ISODATE}
}
elif (filt_expiration_start_date_ISODATE):
filt_date_expiration = {'mysy_download_files_date_expiration': {'$gte': filt_expiration_start_date_ISODATE,
}
}
elif (filt_expiration_end_date_ISODATE):
filt_date_expiration = {'mysy_download_files_date_expiration': {'$lte': filt_expiration_end_date_ISODATE,
}
}
filt_securised_doc = {}
user_has_acces_to_secure_doc = MYSY_GV.dbname['user_access_right'].count_documents(
{'module_name': 'file_secure', 'user_id': str(my_partner['ressource_humaine_id']),
@ -1706,20 +1755,44 @@ def Get_List_object_owner_collection_Stored_Files_With_Filter(diction):
filt_securised_doc = {'is_secure_file':{'$ne':'1'}}
my_query = {'$and': [ filt_object_owner_collection, filt_filter_object_owner_id, filt_date_creation,
my_query = {'$and': [ filt_object_owner_collection, filt_filter_object_owner_id, filt_date_creation, filt_date_expiration,
filt_type_document, filt_session_code,filt_partner_client_nom, filt_file_business_object,
filt_class_external_code, filt_nom_prenom_mail_inscrit, filt_securised_doc, {'partner_owner_recid': str(my_partner['recid']),
'valide':'1'}]}
new_query = ([ {"$addFields": {
"mysy_download_files_date_creation": {
'$dateFromString': {
'dateString': {"$substr": ["$creation_date", 0, 10]},
"format": "%Y-%m-%d"
}
}
}
},
new_query = ([
{
"$addFields": {
"mysy_download_files_date_creation": {
"$dateFromString": {
"dateString": {
"$substrBytes": [
{"$ifNull": ["$creation_date", ""]},
0,
10
]
},
"format": "%Y-%m-%d",
"onError": None,
"onNull": None
}
},
"mysy_download_files_date_expiration": {
"$dateFromString": {
"dateString": {
"$substrBytes": [
{"$ifNull": ["$file_date_expiration", ""]},
0,
10
]
},
"format": "%d/%m/%Y",
"onError": None,
"onNull": None
}
}
}
},
{'$match': my_query
},
{
@ -1905,6 +1978,22 @@ def Get_List_object_owner_collection_Stored_Files_With_Filter(diction):
ret_file['tab_related_collection'] = tab_related_collection
local_file_date_expiration = "01/01/2099"
if ("file_date_expiration" in retval.keys()):
local_file_date_expiration = retval['file_date_expiration']
ret_file['file_date_expiration'] = local_file_date_expiration
local_status = mycommon.CheckisDate(local_file_date_expiration)
file_expired = ''
if (local_status is True):
mytoday = datetime.today().strftime("%d/%m/%Y")
if (datetime.strptime(str(local_file_date_expiration)[0:10], '%d/%m/%Y') < datetime.strptime(
str(mytoday).strip(), '%d/%m/%Y')):
file_expired = "1"
ret_file['file_expired'] = str(file_expired)
RetObject.append(mycommon.JSONEncoder().encode(ret_file))
nb_val = nb_val + 1

View File

@ -44,6 +44,7 @@ from datetime import datetime, date
from xhtml2pdf import pisa
import Inscription_mgt
import attached_file_mgt
import module_editique
import prj_common as mycommon
import secrets
@ -3256,8 +3257,6 @@ def Prepare_and_Send_Inscrit_Bulletin_Note_By_PDF(diction):
local_node['diplome_id'] = str(diction['diplome_id'])
print(" #### Traitemnt de local_diction rrr = ", local_node)
#local_status, local_full_file_name = Create_Bulletin_By_Inscrit_PDF(local_node)
"""
New version
@ -3270,15 +3269,16 @@ def Prepare_and_Send_Inscrit_Bulletin_Note_By_PDF(diction):
list_file_name_to_zip.append(str(local_full_file_name))
# Create a ZipFile Object
todays_date = str(date.today().strftime("%d/%m/%Y"))
ts = datetime.now().timestamp()
ts = str(ts).replace(".", "").replace(",", "")[-3:]
zip_file_name = str(MYSY_GV.TEMPORARY_DIRECTORY_V2)+"List_Bulletin_Notes_"+str(ts)+".zip"
zip_file_name = str(MYSY_GV.upload_folder)+"List_Bulletin_Notes_"+str(ts)+".zip"
with ZipFile(zip_file_name, 'w') as zip_object:
for pdf_files in list_file_name_to_zip :
#print(" ### fichier a zipper = ", pdf_files)
print(" ### fichier a zipper = ", pdf_files)
zip_object.write(str(pdf_files))
@ -3620,11 +3620,7 @@ def Create_Bulletin_By_Inscrit_PDF_V2_Work_Collection(diction):
if( tmp ):
tab_semestre.append(str(tmp).strip())
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(
@ -3858,7 +3854,7 @@ def Create_Bulletin_By_Inscrit_PDF_V2_Work_Collection(diction):
orig_file_name = "Bulletin_Note_" + str(statgiaire_data['nom'] + '_' + statgiaire_data['prenom']) + "_" + str(
ts) + ".pdf"
outputFilename = str(MYSY_GV.TEMPORARY_DIRECTORY) + "/" + str(orig_file_name)
outputFilename = str(MYSY_GV.upload_folder) + str(orig_file_name)
# open output file for writing (truncated binary)
resultFile = open(outputFilename, "w+b")
@ -3917,7 +3913,50 @@ def Create_Bulletin_By_Inscrit_PDF_V2_Work_Collection(diction):
canvas.save()
return True, outputFilename
new_file = {}
new_file['token'] = diction['token']
type_document = "Bulletin"
new_file['file_business_object'] = str(orig_file_name)
new_file['file_name'] = str(orig_file_name)
new_file['status'] = "1"
new_file['type_document'] = str(type_document)
new_file['object_owner_collection'] = "inscription"
new_file['object_owner_id'] = str(diction['inscription_id'])
new_file['file_name_to_store'] = outputFilename
tab_related_collection = []
if( "session_id" in diction.keys() and diction['session_id']):
local_node = {}
local_node['related_collection'] = "session_formation"
local_node['related_collection_id'] = str(diction['session_id'])
tab_related_collection.append(local_node)
if ("class_id" in diction.keys() and diction['class_id']):
local_node = {}
local_node['related_collection'] = "myclass"
local_node['related_collection_id'] = str(diction['class_id'])
tab_related_collection.append(local_node)
if ("diplome_id" in diction.keys() and diction['diplome_id']):
local_node = {}
local_node['related_collection'] = "diplome"
local_node['related_collection_id'] = str(diction['diplome_id'])
tab_related_collection.append(local_node)
local_status, local_retval = attached_file_mgt.Internal_Usage_Store_User_Downloaded_File(
MYSY_GV.upload_folder, new_file, tab_related_collection)
if (local_status is False):
print(" ## WARNINGGG Impossible de stocker le fichier d'attestation")
return True, local_retval
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()

View File

@ -517,15 +517,17 @@ def add_class(diction):
# Eviter les formations avec 0 heures/jours..
duration = 1
if ("duration" in diction.keys()):
if diction['duration']:
duration = float(str(diction['duration']))
mydata['duration'] = duration
duration_operationnelle = 1
if ("duration" in diction.keys()):
if diction['duration']:
duration = mycommon.tryFloat(str(diction['duration']))
duration_operationnelle = mycommon.tryFloat(str(diction['duration']))
mydata['duration'] = duration
if ("duration_operationnelle" in diction.keys()):
if diction['duration_operationnelle']:
duration_operationnelle = float(str(diction['duration_operationnelle']))
duration_operationnelle = mycommon.tryFloat(str(diction['duration_operationnelle']))
mydata['duration_operationnelle'] = duration_operationnelle
@ -5290,7 +5292,8 @@ def add_class_mass(file=None, Folder=None, diction=None):
'objectif', 'programme', 'prerequis', 'formateur', 'note', 'cpf', 'certif',
'class_inscription_url', 'pourqui', 'support', 'img_banner_detail_class', 'formateur_email',
'methode_pedagogique', 'condition_handicape', 'suivi_eval', 'version', 'categorie', 'recyclage_delai',
'recyclage_periodicite' 'recyclage_alert', 'contenu_attestation']
'recyclage_periodicite' 'recyclage_alert', 'contenu_attestation',
'published_catalog_prive', 'is_ftion_initiale', 'inscription_direct', 'duration_operationnelle']
total_rows = len(df)
@ -5392,6 +5395,27 @@ def add_class_mass(file=None, Folder=None, diction=None):
mydata['version'] = version
published_catalog_prive = "0"
if ("published_catalog_prive" in df.keys()):
if (str(df['published_catalog_prive'].values[n])):
published_catalog_prive = str(df['published_catalog_prive'].values[n]).strip()
mydata['published_catalog_prive'] = published_catalog_prive
is_ftion_initiale = "0"
if ("is_ftion_initiale" in df.keys()):
if (str(df['is_ftion_initiale'].values[n])):
is_ftion_initiale = str(df['is_ftion_initiale'].values[n]).strip()
mydata['is_ftion_initiale'] = is_ftion_initiale
inscription_direct = "0"
if ("inscription_direct" in df.keys()):
if (str(df['inscription_direct'].values[n])):
inscription_direct = str(df['inscription_direct'].values[n]).strip()
mydata['inscription_direct'] = inscription_direct
categorie_id = ""
if ("categorie" in df.keys()):
@ -5840,7 +5864,8 @@ def Controle_add_class_mass(saved_file=None, Folder=None, diction=None):
'objectif', 'programme', 'prerequis', 'formateur', 'note', 'cpf', 'certif',
'class_inscription_url', 'pourqui', 'support', 'img_banner_detail_class', 'formateur_email' ,'methode_pedagogique',
'condition_handicape', 'suivi_eval', 'version', 'categorie', 'recyclage_delai',
'recyclage_periodicite', 'recyclage_alert', 'contenu_attestation']
'recyclage_periodicite', 'recyclage_alert', 'contenu_attestation',
'published_catalog_prive', 'is_ftion_initiale', 'inscription_direct', 'duration_operationnelle']
total_rows = len(df)
@ -6244,6 +6269,24 @@ def Controle_add_class_mass(saved_file=None, Folder=None, diction=None):
else:
mydata['duration_unit'] = "jour"
if ("published_catalog_prive" in df.keys()):
if (str(df['published_catalog_prive'].values[n]).strip() not in ['', '1', '0']):
mycommon.myprint(
str(inspect.stack()[0][3]) + " : le champ 'published_catalog_prive' contient une valeur erronées."
" Les valeurs acceptées sont ['', '1', '0'] ")
return False, " : le champ 'published_catalog_prive' contient une valeur erronées." \
" Les valeurs acceptées sont ['', '1', '0'] "
if ("is_ftion_initiale" in df.keys()):
if (str(df['is_ftion_initiale'].values[n]).strip() not in [ '1', '0']):
mycommon.myprint(
str(inspect.stack()[0][3]) + " : le champ 'is_ftion_initiale' contient une valeur erronées."
" Les valeurs acceptées sont [ '1', '0'] " )
return False, " : le champ 'published_catalog_prive' contient une valeur erronées." \
" Les valeurs acceptées sont ['1', '0'] "
'''
Verification de l'image
'''

View File

@ -6,6 +6,8 @@ from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email import encoders
import Inscription_mgt
import Inscription_mgt as inscription
import partner_client
import locale
@ -30,6 +32,8 @@ import ressources_humaines as ressources_humaines
import email_queu.email_queu_mgt as email_queu_mgt
import internal_email_mgt as internal_email_mgt
import email_mgt
configuration = sib_api_v3_sdk.Configuration()
configuration.api_key['api-key'] = MYSY_GV.SENDINBLUE_API_KEY
@ -3960,7 +3964,10 @@ def Prepare_and_Send_Email_From_Front(tab_files, Folder, diction):
sourceHtml = contenu_doc_Template.render(params=body["params"])
html_mime = MIMEText(sourceHtml, 'html')
#html_mime = MIMEText(sourceHtml, 'html')
tab_email_bcc.append(str(my_partner['email']))
@ -3976,7 +3983,7 @@ def Prepare_and_Send_Email_From_Front(tab_files, Folder, diction):
local_diction['tab_email_bcc'] = tab_email_bcc
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['html_mime'] = sourceHtml
local_diction['email_to'] = email
local_diction['partner_owner_recid'] = str(my_partner['recid'])
@ -3991,7 +3998,7 @@ def Prepare_and_Send_Email_From_Front(tab_files, Folder, diction):
else:
local_diction['include_tuteur'] = "0"
#print(" ### local_diction = ", local_diction)
print(" ### local_diction send_invidual_email= ", local_diction)
local_status, local_retval = send_invidual_email (local_diction)
if( local_status is False ):
return local_status, local_retval
@ -4330,6 +4337,7 @@ def send_invidual_email(diction):
# Recuperer les données tuteurs
if(related_collection == "inscription" ):
inscription_data = MYSY_GV.dbname['inscription'].find_one({'_id':ObjectId(str(inscription_id)),
@ -4353,13 +4361,27 @@ def send_invidual_email(diction):
if( include_tuteur == "1"):
if( "tuteur1_include_com" in inscription_data and inscription_data['tuteur1_include_com'] == "1"):
tab_email_cc.append(inscription_data['tuteur1_email'])
if( include_tuteur == "1" and inscription_id):
local_dict = {'token': str(my_token), '_id': str(diction['inscription_id'])}
if ("tuteur2_include_com" in inscription_data and inscription_data['tuteur2_include_com'] == "1"):
tab_email_cc.append(inscription_data['tuteur2_email'])
local_status, tab_apprenant_contact = Inscription_mgt.Get_Statgiaire_Communication_Contact(local_dict)
if (local_status is False):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " WARNING : Impossible de récuperer les adresse email des tuteurs de communication de l'inscrit "+str(inscription_id))
for tmp in tab_apprenant_contact:
if ("email" in tmp.keys()):
if( str(tmp['email']) not in tab_email_cc and str(tmp['email']) != email_to):
tab_email_cc.append((tmp['email']))
tab_email_cc_clean = []
for tmp in tab_email_cc:
if(len(str(tmp).strip()) > 2 ):
tab_email_cc_clean.append(str(tmp).strip())
tab_email_cc = tab_email_cc_clean
"""
@ -4406,6 +4428,31 @@ def send_invidual_email(diction):
if( queue_and_internal_mail_status is False):
print(" ## WARNING queue_mail_retval = ", queue_and_internal_mail_status)
"""
20/06/2026 - on envoie la notification par email / sms à la personne concernée, et au personnes en copie
"""
if (queue_mail_diction and 'email_to' in queue_mail_diction.keys() and queue_mail_diction['email_to']):
local_diction = {}
local_diction['token'] = str(my_token)
local_diction['list_email_dest'] = queue_mail_diction['email_to']
notif_status, notif_retval = email_mgt.Internal_Email_Send_Notification_to_external_email(local_diction)
if (notif_status is False):
mycommon.myprint(
" WARNING : Impossible d'envoyer l'email de notification -Internal_Email_Send_Notification_to_external_email- ")
if (queue_mail_diction and len(tab_email_cc) > 0 ):
for email_cc in tab_email_cc :
local_diction = {}
local_diction['token'] = str(my_token)
local_diction['list_email_dest'] = str(email_cc)
notif_status, notif_retval = email_mgt.Internal_Email_Send_Notification_to_external_email(local_diction)
if (notif_status is False):
mycommon.myprint(
" WARNING : Impossible d'envoyer l'email de notification -Internal_Email_Send_Notification_to_external_email- ")
return True, " Les emails ont été correctement envoyés"
@ -4480,6 +4527,7 @@ def Individual_Mail_Store_Queu_And_Internal_Mail(diction):
elif (tmp):
list_ccb = str(tmp)
queue_mail_diction = {}
queue_mail_diction['token'] = diction['token']
queue_mail_diction['from'] = diction['smtp_account_From_User']
@ -4690,6 +4738,188 @@ def Internal_Email_Send_Notification_to_external_email(diction):
"""
Envoie proprement-dit des emails
"""
for local_email_dest in tab_email_dest:
# Creation de l'email à enoyer
msg = MIMEMultipart("alternative")
dictionnary_data['url_connexion'] = str(MYSY_GV.CLIENT_URL_BASE)+"signin/"
node = {}
node['nom'] = ""
node['prenom'] = ""
body = {
"params": dictionnary_data
}
# Creation de l'email à enoyer
msg = MIMEMultipart("alternative")
contenu_doc_Template = jinja2.Template(str(courrier_data_retval['contenu_doc']))
sourceHtml = contenu_doc_Template.render(params=body["params"])
html_mime = MIMEText(sourceHtml, 'html')
sujet_doc_Template = jinja2.Template(str(courrier_data_retval['sujet']))
sujetHtml = sujet_doc_Template.render(params=body["params"])
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")
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(local_email_dest)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(MYSY_GV.O365_SMTP_COUNT_user, MYSY_GV.O365_SMTP_COUNT_password)
val = smtpserver.send_message(msg)
smtpserver.close()
print(" Email envoyé " + str(val))
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 "
"""
Cette fonction fait une notif sur un email envoyé depuis l'ENT
"""
def From_ENT_Internal_Email_Send_Notification_to_external_email(diction):
try:
diction = mycommon.strip_dictionary(diction)
field_list = ['token', 'list_email_dest',]
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, "Toutes les informations fournies ne sont pas valables"
field_list_obligatoire = ['token', 'list_email_dest', ]
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"
my_token = ""
if ("token" in diction.keys()):
if diction['token']:
my_token = diction['token']
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
if (local_status is not True):
return local_status, my_partner
"""
Verifier la validité des emails de destinataire.
Si et SEULEMENT SI "related_collection" != "no_contact"
"""
tab_related_collection_id = []
tab_email_dest = ""
if ("list_email_dest" in diction.keys()):
if diction['list_email_dest']:
tab_email_dest = diction['list_email_dest']
tab_email_dest = str(tab_email_dest).split(",")
for email_dest in tab_email_dest:
if( email_dest ):
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 ):
mycommon.myprint("Vous ne pouvez pas envoyer plus de "+str(MYSY_GV.EMAIL_MAX_DESTINAIRE)+" emails à la fois.")
return False, "Vous ne pouvez pas envoyer plus de "+str(MYSY_GV.EMAIL_MAX_DESTINAIRE)+" emails à la fois."
# Creation du dictionnaire d'information à utiliser pour la creation du doc
convention_dictionnary_data = {}
new_diction = {}
new_diction['token'] = my_partner['token']
new_diction['list_stagiaire_id'] = []
new_diction['list_session_id'] = []
new_diction['list_class_id'] = []
new_diction['list_client_id'] = []
new_diction['from_ent'] = "1"
local_status, local_retval = mycommon.Get_Dictionnary_data_For_Template(new_diction)
if (local_status is False):
return local_status, local_retval
company_name = ""
if ("company_data" in local_retval.keys() and "societe_nom" in local_retval['company_data'].keys()):
company_name = local_retval['company_data']['societe_nom']
dictionnary_data = local_retval
"""
Recuperer le modèle de document
"""
local_diction = {}
local_diction['ref_interne'] = "NOTIF_EMAIL_ELYOS"
local_diction['type_doc'] = "email"
local_diction['partner_owner_recid'] = str(my_partner['partner_owner_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 'NOTIF_EMAIL_ELYOS' n'est pas correctement configuré ")
return False, " Le modèle de courrier 'NOTIF_EMAIL_ELYOS' n'est pas correctement configuré "
# 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['partner_owner_recid'])
if (local_stpm_status is False):
return local_stpm_status, partner_SMTP_COUNT_smtpsrv
smtpserver = None
if (str(partner_own_smtp_value) == "1"):
smtpserver = smtplib.SMTP(partner_SMTP_COUNT_smtpsrv, partner_SMTP_COUNT_port)
else:
smtpserver = smtplib.SMTP(MYSY_GV.O365_SMTP_COUNT_smtpsrv, MYSY_GV.O365_SMTP_COUNT_port)
"""
Envoie proprement-dit des emails
"""

View File

@ -950,8 +950,8 @@ def Get_Ent_Student_Inscrit_List_EU(diction):
return local_status, my_partner
"""
Verifier la validité de l'apprenant
"""
Verifier la validité de l'apprenant
"""
is_apprenant_valide_count = MYSY_GV.dbname['apprenant'].count_documents(
{'_id': ObjectId(str(diction['apprenant_id'])),
'valide': '1',
@ -1490,7 +1490,7 @@ def Get_Ent_Student_Participant_Notes(diction):
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.mymycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, "Impossible de récupérer les notes de l'apprenant"
@ -2032,7 +2032,7 @@ def Get_Ent_Student_List_object_owner_collection_Stored_Files(diction):
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.mymycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, False
"""
@ -2150,7 +2150,7 @@ def Get_Ent_Student_Stored_Downloaded_File(diction):
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.mymycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, False
@ -2560,7 +2560,7 @@ def Get_Ent_Student_update_user_account(diction):
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.mymycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, "Impossible de mettre à jour le compte utilisateur"
@ -2674,7 +2674,7 @@ def Get_Ent_Student_change_user_pwd(diction):
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.mymycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, "Impossible de mettre à jour le mot de passe"
@ -2793,7 +2793,7 @@ def Get_Ent_Student_Stored_Downloaded_File(diction):
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.mymycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, False
@ -2895,8 +2895,8 @@ def Get_Ent_Student_Absence(diction):
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
Verification des input acceptés
"""
field_list = ['token', 'apprenant_id', 'session_id', 'inscription_id']
@ -3111,7 +3111,7 @@ def Get_Ent_Student_total_Heure_Absence(diction):
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.mymycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de récupérer le total des heures d'absences "
"""
@ -3684,3 +3684,102 @@ def Absence_Refuse_Motif_From_Mail_No_Token(diction):
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de mettre à jour l'absence "
"""
Recuperation des emails d'un étudiant sur l'espace ENT
"""
def Get_ENT_Given_Internal_Mail(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'apprenant_id', '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'est pas autorisé ")
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
liste_user_id_read = []
RetObject = []
val_tmp = 0
print(" ### data_cle = ", {'_id':ObjectId(str(diction['internal_mail_id'])), 'valide':'1', 'locked':'0'})
for retval in MYSY_GV.dbname['internal_mail'].find({'_id':ObjectId(str(diction['internal_mail_id'])), 'valide':'1', 'locked':'0'}):
user = retval
user['id'] = str(val_tmp)
val_tmp = val_tmp + 1
if( "liste_user_id_read" in retval.keys() ):
for user_id in retval['liste_user_id_read']:
liste_user_id_read.append(str(user_id))
"""
Recuperer les eventuels _id des fichiers joints stocké dans la collection : 'download_files'
"""
tab_saved_file_id = []
for download_files_data in MYSY_GV.dbname['download_files'].find({'type_document':'email', 'object_owner_collection':'internal_mail',
'object_owner_id':str(retval['_id'])},
{'_id':1, 'file_business_object':1, 'file_name':1},):
local_node = {}
local_node['download_files_id'] = str(download_files_data['_id'])
local_node['download_files_file_business_object'] = str(download_files_data['file_business_object'])
local_node['download_files_file_name'] = str(download_files_data['file_name'])
tab_saved_file_id.append(local_node)
user['tab_saved_file_id'] = tab_saved_file_id
RetObject.append(mycommon.JSONEncoder().encode(user))
"""
Mettre à jour pour dire que le mail est lu par ce user connecté
"""
current_user_id = str(my_partner['_id'])
if( current_user_id not in liste_user_id_read ):
liste_user_id_read.append(str(current_user_id))
updata_data = {}
updata_data['liste_user_id_read'] = liste_user_id_read
MYSY_GV.dbname['internal_mail'].find_one_and_update(
{'_id':ObjectId(str(diction['internal_mail_id'])), 'valide':'1', 'locked':'0'},
{'$set': updata_data})
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 "

View File

@ -13,7 +13,7 @@ import json
from bson import ObjectId
import re
from datetime import datetime, date, timedelta
from email.utils import parseaddr
import Session_Formation
import email_mgt
import module_editique
@ -407,17 +407,22 @@ def Update_Message_To_Internal_Mail(tab_files, Folder, diction):
return_document=ReturnDocument.AFTER
)
print(" check notif update result = ", result)
"""
Si l'insertion de l'email fonctionne, alors on envoie une notification a la personnes
vers sa boite email externe"""
if( result and 'to' in result.keys() and result['to']):
local_diction = {}
local_diction['token'] = str(my_token)
local_diction['list_email_dest'] = result['to']
if( result and 'to' in new_data.keys() and new_data['to']):
name, email = parseaddr(new_data['to'])
if ( email ):
local_diction = {}
local_diction['token'] = str(my_token)
local_diction['list_email_dest'] = email
notif_status, notif_retval = email_mgt.Internal_Email_Send_Notification_to_external_email(local_diction)
if( notif_status is False):
mycommon.myprint(" WARNING : Impossible d'envoyer l'email de notification -Internal_Email_Send_Notification_to_external_email- ")
print(" local_diction = ", local_diction)
notif_status, notif_retval = email_mgt.Internal_Email_Send_Notification_to_external_email(local_diction)
if( notif_status is False):
mycommon.myprint(" WARNING : Impossible d'envoyer l'email de notification -Internal_Email_Send_Notification_to_external_email- ")
"""
@ -469,6 +474,242 @@ def Update_Message_To_Internal_Mail(tab_files, Folder, diction):
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, "Impossible de mettre à jour le message "
"""
Mise à jour d'un message, par exemple les status, depuis l'ENT
"""
def From_ENT_Update_Message_To_Internal_Mail(tab_files, Folder, 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', 'to', 'subject']
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']
if( diction['to'] == ""):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " Aucun destinataire n'est précisé ")
return False, " Aucun destinataire n'est précisé"
if (diction['subject'] == ""):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " Aucun sujet n'est précisé ")
return False, " Aucun sujet n'est précisé"
if( len(diction['subject']) > 300 ):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " Le sujet ne doit pas faire plus de 300 caractères ")
return False, " Le sujet ne doit pas faire plus de 300 caractères "
# Sauvegarde des fichiers joints depuis le front
tab_saved_file_full_path = []
for file in tab_files:
status, saved_file_full_path = mycommon.Upload_Save_PDF_IMG_File(file, Folder)
if (status is False):
mycommon.myprint("Impossible de récupérer correctement le fichier à importer")
return False, "Impossible de récupérer correctement le fichier à importer"
if (saved_file_full_path):
new_file = {}
new_file['token'] = diction['token']
type_document = "email"
new_file['file_business_object'] = str(file.filename)
new_file['file_name'] = str(file.filename)
new_file['status'] = "1"
new_file['type_document'] = str(type_document)
new_file['object_owner_collection'] = "internal_mail"
new_file['object_owner_id'] = str(diction['tab_message_id'])
new_file['file_name_to_store'] = saved_file_full_path
# print(" ### new_file new_file = ", new_file)
local_status, local_retval = attached_file_mgt.Internal_Usage_Store_User_Downloaded_File(
MYSY_GV.upload_folder, new_file)
if (local_status is False):
print(" ## WARINNGGG Impossible de stocker le fichier de Convocation ")
tab_saved_file_full_path.append(local_retval)
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)
local_partner_owner_recid = ""
if ("type_user_collection" in my_partner.keys() and my_partner['type_user_collection'] == "user_account"):
local_partner_owner_recid = str(my_partner['partner_owner_recid'])
else:
local_partner_owner_recid = str(my_partner['recid'])
# 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(local_partner_owner_recid))
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(local_partner_owner_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 "
my_token = diction['token']
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['from'] = str(my_partner['email'])
new_data['sent'] = str(datetime.now())
new_data['update_date'] = str(datetime.now())
new_data['update_by'] = str(my_partner['_id'])
data_cle = {}
data_cle['_id'] = ObjectId(local_id)
if ("type_user_collection" in my_partner.keys() and my_partner['type_user_collection'] == "user_account"):
data_cle['partner_owner_recid'] = str(my_partner['partner_owner_recid'])
else:
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
)
print(" check notif update result = ", result)
"""
Si l'insertion de l'email fonctionne, alors on envoie une notification a la personnes
vers sa boite email externe"""
if( result and 'to' in new_data.keys() and new_data['to']):
name, email = parseaddr(new_data['to'])
if ( email ):
local_diction = {}
local_diction['token'] = str(my_token)
local_diction['list_email_dest'] = email
print(" local_diction = ", local_diction)
notif_status, notif_retval = email_mgt.From_ENT_Internal_Email_Send_Notification_to_external_email(local_diction)
if( notif_status is False):
mycommon.myprint(" WARNING : Impossible d'envoyer l'email de notification -Internal_Email_Send_Notification_to_external_email- ")
"""
Une fois l'email mis dans la table interne, on va aller le mettre dans le queu d'envoie
pour qu'un DOUBLE DU MAIL soit aussi envoyé directement
Important : On le fait pour chaque mail destinataire
"""
if (local_stpm_status is True and local_SMTP_COUNT_smtpsrv and local_own_smtp_value):
tmp_mail_to = str(diction['to']).replace(";", ",")
tab_tmp_mail_to = tmp_mail_to.split(",")
for mail_to in tab_tmp_mail_to:
if( tmp ):
queue_mail_diction = {}
queue_mail_diction['token'] = str(my_token)
queue_mail_diction['from'] = local_SMTP_COUNT_From_User
queue_mail_diction['cc'] = []
queue_mail_diction['bcc'] = []
if( diction['subject']):
queue_mail_diction['subject'] = diction['subject']
else:
queue_mail_diction['subject'] = "[MySy Training] Vous avez un nouveau message"
queue_mail_diction['to'] = str(mail_to)
queue_mail_diction['message'] = diction['message']
queue_mail_diction['tab_saved_file_full_path'] = tab_saved_file_full_path
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
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)
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
"""

143
main.py
View File

@ -40,6 +40,8 @@ import opco as opco
import Attestation_Certificat as Att_Cert
import tools_cherif.tools_cherif as tools_cherif
import tools_cherif.send_sms_ovh as send_sms_ovh
import tools_cherif.check_domain_certif_v2 as check_domain_certif_v2
import business_prices as business_prices
@ -121,6 +123,7 @@ import Categorie_apprenant as Categorie_apprenant
import Type_groupe_inscrit_mgt as Type_groupe_inscrit_mgt
import Relance_client_facture as Relance_client_facture
import Diplome_mgt as Diplome_mgt
import Bulletin_Note_mgt as Bulletin_Note_mgt
import base_document_automatic_setup as base_document_automatic_setup
@ -15524,6 +15527,18 @@ def Absence_Refuse_Motif_From_Mail_No_Token():
status, retval = ent_student_common.Absence_Refuse_Motif_From_Mail_No_Token( payload)
return jsonify(status=status, message=retval)
"""
API pour écupter une email depuis l'ENT
"""
@app.route('/myclass/api/Get_ENT_Given_Internal_Mail/', methods=['POST','GET'])
@crossdomain(origin='*')
def Get_ENT_Given_Internal_Mail():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Get_ENT_Given_Internal_Mail : payload = ",str(payload))
status, retval = ent_student_common.Get_ENT_Given_Internal_Mail( payload)
return jsonify(status=status, message=retval)
"""
@ -15812,6 +15827,31 @@ def Update_Message_To_Internal_Mail():
"""
API pour mise à jour d'un email d'un utilisateur du systeme depuis l'ENT
"""
@app.route('/myclass/api/From_ENT_Update_Message_To_Internal_Mail/', methods=['POST','GET'])
@crossdomain(origin='*')
def From_ENT_Update_Message_To_Internal_Mail():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### From_ENT_Update_Message_To_Internal_Mail payload = ")
file = []
if request.method == 'POST':
# Create variable for uploaded file
tab_files = []
for tmp in request.files.getlist("File"):
tab_files.append(tmp)
status, retval = internal_email_mgt.From_ENT_Update_Message_To_Internal_Mail(tab_files, MYSY_GV.TEMPORARY_DIRECTORY_V2, payload)
return jsonify(status=status, message=retval)
"""
API pour supprimer l'email d'un utilisateur du systeme
"""
@ -16212,7 +16252,17 @@ def Correcte_Type_session_For_Old_Session():
return jsonify(status=localStatus, message=message )
"""
API pour pour envoyer des sms avec OVH
"""
@app.route('/myclass/api/EYSY_Send_OVH_SMS/', methods=['POST','GET'])
@crossdomain(origin='*')
def EYSY_Send_OVH_SMS():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### EYSY_Send_OVH_SMS : payload = ",payload)
localStatus, message= send_sms_ovh.Send_OVH_SMS()
return jsonify(status=localStatus, message=message )
"""
@ -18318,8 +18368,72 @@ def Run_BC_Compensation_Rules_01():
return jsonify(status=localStatus, message=message )
"""
API pour récuperer la liste des bulletins de notes d'un partenaire avec des filtres
"""
@app.route('/myclass/api/Get_Partner_Bulletin_Note_With_Filter', methods=['POST','GET'])
@crossdomain(origin='*')
def Get_Partner_Bulletin_Note_With_Filter():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary(request.form.to_dict())
print(" ### Get_Partner_Bulletin_Note_With_Filter : payload = ",payload)
localStatus, message= Bulletin_Note_mgt.Get_Partner_Bulletin_Note_With_Filter(payload)
return jsonify(status=localStatus, message=message )
"""
API pour récuperer la liste des bulletins de notes d'un inscrit
"""
@app.route('/myclass/api/Get_Bulletin_Note_Inscrit', methods=['POST','GET'])
@crossdomain(origin='*')
def Get_Bulletin_Note_Inscrit():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary(request.form.to_dict())
print(" ### Get_Bulletin_Note_Inscrit : payload = ",payload)
localStatus, message= Bulletin_Note_mgt.Get_Bulletin_Note_Inscrit(payload)
return jsonify(status=localStatus, message=message )
"""
API pour Publier une liste de bulletin de note
"""
@app.route('/myclass/api/Publish_Tab_Bulletin_Note', methods=['POST','GET'])
@crossdomain(origin='*')
def Publish_Tab_Bulletin_Note():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary(request.form.to_dict())
print(" ### Publish_Tab_Bulletin_Note : payload = ",payload)
localStatus, message= Bulletin_Note_mgt.Publish_Tab_Bulletin_Note(payload)
return jsonify(status=localStatus, message=message )
"""
API pour Dépublier une liste de bulletin de note
"""
@app.route('/myclass/api/Unpublish_Tab_Bulletin_Note', methods=['POST','GET'])
@crossdomain(origin='*')
def Unpublish_Tab_Bulletin_Note():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary(request.form.to_dict())
print(" ### Unpublish_Tab_Bulletin_Note : payload = ",payload)
localStatus, message= Bulletin_Note_mgt.Unpublish_Tab_Bulletin_Note(payload)
return jsonify(status=localStatus, message=message )
"""
API pour Supprimer une liste de bulletin de note
"""
@app.route('/myclass/api/Delete_Tab_Bulletin_Note', methods=['POST','GET'])
@crossdomain(origin='*')
def Delete_Tab_Bulletin_Note():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary(request.form.to_dict())
print(" ### Delete_Tab_Bulletin_Note : payload = ",payload)
localStatus, message= Bulletin_Note_mgt.Delete_Tab_Bulletin_Note(payload)
return jsonify(status=localStatus, message=message )
@ -18412,6 +18526,33 @@ if __name__ == '__main__':
app.run(host='localhost', port=MYSY_GV.MYSY_PORT_REC, debug=True, threaded=True)
elif (MYSY_GV.MYSY_ENV == "FORMATION"):
mycommon.myprint(" ++++ ENVIRONNEMENT FORMATION ++++")
mycommon.myprint("++ DATABASE " + MYSY_GV.CONNECTION_STRING + " ++")
mycommon.myprint("++ DBNAME " + str(MYSY_GV.dbname) + " ++")
mycommon.myprint("++ FLASK PORT " + str(MYSY_GV.MYSY_PORT_FORMATION) + " ++")
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_FORMATION, debug=True, threaded=True)
elif (MYSY_GV.MYSY_ENV == "DEM"):
mycommon.myprint(" ++++ ENVIRONNEMENT DEMONSTRATION ++++")
mycommon.myprint("++ DATABASE " + MYSY_GV.CONNECTION_STRING + " ++")

View File

@ -4636,7 +4636,7 @@ def Get_Dictionnary_data_For_Template(diction):
Verification des input acceptés
"""
field_list = ['token', 'list_stagiaire_id', 'list_session_id', 'list_class_id', 'list_client_id',
'list_apprenant_id', 'list_sequence_session_id', 'list_jury_soutenance_id', 'list_candidat_admission_id']
'list_apprenant_id', 'list_sequence_session_id', 'list_jury_soutenance_id', 'list_candidat_admission_id', 'from_ent']
incom_keys = diction.keys()
for val in incom_keys:
@ -4665,10 +4665,17 @@ def Get_Dictionnary_data_For_Template(diction):
if diction['token']:
token = diction['token']
my_partner = {}
local_status, my_partner = Check_Connexion_And_Return_Partner_Data(diction)
if (local_status is not True):
return local_status, my_partner
if("from_ent" in diction.keys() and diction['from_ent'] == "1" and "partner_owner_recid" in my_partner.keys() and "recid" not in my_partner.keys() ):
my_partner['recid'] = str(my_partner['partner_owner_recid'])
dictionnary_data = {}
connected_user_data = {}

View File

@ -7949,7 +7949,7 @@ def Create_RH_And_Add_List_Insc_Tutore(diction):
if( is_existe_rh_by_email > 0 ):
mycommon.myprint(
str(inspect.stack()[0][
3]) + "Cette adresse e-mail est déjà associée à une personne enregistrée. Veuillez en saisir une autre ou vérifier la fiche existante.")
3]) + " Cette adresse e-mail est déjà associée à une personne enregistrée. Veuillez en saisir une autre ou vérifier la fiche existante.")
return False, " Cette adresse e-mail est déjà associée à une personne enregistrée. Veuillez en saisir une autre ou vérifier la fiche existante.",

View File

@ -842,7 +842,7 @@ def Add_Stagiaire_To_Admission_Session(diction):
'type_apprenant', 'civilite', 'date_naissance', 'memo', 'comment',
"num_secu", "is_rgpd", "situation_famille", "piece_identite_type", "piece_identite_num",
"type_mobilite", "telephone_bis", "nationalite", "is_handicap", "is_handicap", "is_droit_image",
'naissance_lieu', 'naissance_departement', 'naissance_pays', 'session_etape', 'ine'
'naissance_lieu', 'naissance_departement', 'naissance_pays', 'session_etape', 'ine', 'nom_fille'
]
incom_keys = diction.keys()
@ -1297,7 +1297,8 @@ def Update_Stagiaire_To_Admission_Session(diction):
'type_apprenant', 'civilite', 'date_naissance', 'memo', 'comment',
"num_secu", "is_rgpd", "situation_famille", "piece_identite_type", "piece_identite_num",
"type_mobilite", "telephone_bis", "nationalite", "is_handicap", "is_droit_image",
'naissance_lieu', 'naissance_departement', 'naissance_pays', 'session_etape', 'rang', 'ine'
'naissance_lieu', 'naissance_departement', 'naissance_pays', 'session_etape', 'rang', 'ine',
'nom_fille'
]
incom_keys = diction.keys()
@ -1753,6 +1754,8 @@ def Get_List_Stagiaire_Admission_Session(diction):
if ("civilite" not in retval.keys() or retval['civilite'] == ""):
retval['civilite'] = "neutre"
if ("nom_fille" not in retval.keys() ):
retval['nom_fille'] = ""
age = relativedelta( date.today(), datetime.strptime(str(retval['date_naissance']), '%d/%m/%Y') )
retval['age'] = str(age.years)
@ -1863,6 +1866,9 @@ def Get_Given_Stagiaire_Admission_Session(diction):
if ("civilite" not in retval.keys() or retval['civilite'] == ""):
retval['civilite'] = "neutre"
if ("nom_fille" not in retval.keys() ):
retval['nom_fille'] = ""
age = relativedelta(date.today(), datetime.strptime(str(retval['date_naissance']), '%d/%m/%Y'))
retval['age'] = str(age.years)

View File

@ -0,0 +1,99 @@
import os
import ovh
from dotenv import load_dotenv
import GlobalVariable as MYSY_GV
import sys
import inspect
load_dotenv()
def send_sms(phone_number: str, message: str):
try:
"""
Envoie un SMS via l'API OVHcloud.
phone_number : numéro au format international, ex: +33612345678
message : contenu du SMS
"""
client = ovh.Client(
endpoint="ovh-eu",
application_key="16ef9f92d1580d15",
application_secret="ec7e66e0f27f5494038c14fcb11d105a",
consumer_key="0268191866b32cce8ea012136ce94ddd",
)
service_name = MYSY_GV.OVH_SMS_SERVICE_NAME
sender = MYSY_GV.OVH_SMS_SENDER
print('## get/SMS ')
print(client.get("/sms"))
response = client.post(
f"/sms/{service_name}/jobs",
charset="UTF-8",
coding="7bit",
message=message,
noStopClause=False,
priority="high",
receivers=[phone_number],
sender=sender,
senderForResponse=False,
validityPeriod=2880
)
return response
except ovh.exceptions.APIError as e:
print("Erreur OVH :", e)
if "This call has not been granted" in str(e):
print("""
La Consumer Key n'a pas les droits nécessaires.
Ajoute les droits suivants lors de la génération du token :
GET /sms
GET /sms/*
POST /sms/*/jobs
""")
return False, " Impossible d'envoyer les sms 0222"
def list_sms_services():
"""
Liste les services SMS disponibles sur le compte OVHcloud.
Utile pour retrouver OVH_SMS_SERVICE_NAME.
"""
client = ovh.Client(
endpoint="ovh-eu",
application_key="16ef9f92d1580d15",
application_secret="ec7e66e0f27f5494038c14fcb11d105a",
consumer_key="0268191866b32cce8ea012136ce94ddd",
)
return client.get("/sms")
def Send_OVH_SMS():
try:
list_sms_services()
print(" DEBUT ENVOI SMSSSS ")
result = send_sms(
phone_number="+33629378286",
message="Bonjour, ceci est un SMS de test envoyé depuis MySy / Elyos."
)
print("SMS envoyé avec succès :")
print(result)
return True, "SMS envoyé avec succès "
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
print(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, " Impossible d'envoyer les sms"