02/01/26 - 13h

Signed-off-by: Cherif <cbalde@mysy-training.com>
master_Elyos_FI
Cherif 2026-01-02 17:14:07 +00:00
parent 50a262c665
commit fcf5e86710
15 changed files with 7380 additions and 40 deletions

View File

@ -4,13 +4,21 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="13/12/25 - 14h">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="15/12/25 - 13h">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/E_Sign_Document.py" beforeDir="false" afterPath="$PROJECT_DIR$/E_Sign_Document.py" 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$/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$/ela_user_account.py" beforeDir="false" afterPath="$PROJECT_DIR$/ela_user_account.py" 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$/competence.py" beforeDir="false" afterPath="$PROJECT_DIR$/competence.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$/lms_chamilo/mysy_lms.py" beforeDir="false" afterPath="$PROJECT_DIR$/lms_chamilo/mysy_lms.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/survey_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/survey_mgt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/partners.py" beforeDir="false" afterPath="$PROJECT_DIR$/partners.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ressources_humaines.py" beforeDir="false" afterPath="$PROJECT_DIR$/ressources_humaines.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/user_session.py" beforeDir="false" afterPath="$PROJECT_DIR$/user_session.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
@ -454,7 +462,7 @@
<option name="project" value="LOCAL" />
<updated>1747251650255</updated>
</task>
<option name="localTasksCounter" value="520" />
<option name="localTasksCounter" value="521" />
<servers />
</component>
<component name="Vcs.Log.Tabs.Properties">
@ -496,7 +504,6 @@
</option>
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="qsd" />
<MESSAGE value="30/07/2025 -18h" />
<MESSAGE value="10/08/2025 - 10h" />
<MESSAGE value="sss" />
@ -521,6 +528,7 @@
<MESSAGE value="25/11/25 - 21h30dd" />
<MESSAGE value="07/12/25 - 14h" />
<MESSAGE value="13/12/25 - 14h" />
<option name="LAST_COMMIT_MESSAGE" value="13/12/25 - 14h" />
<MESSAGE value="15/12/25 - 13h" />
<option name="LAST_COMMIT_MESSAGE" value="15/12/25 - 13h" />
</component>
</project>

View File

@ -855,8 +855,6 @@ def Create_E_Signature_For_E_Document(file_img=None, Folder=None, diction=None):
return False, " Impossible de signer le document. Email invalide "
encoded_signed_pdf_to_string = base64.b64encode(decrypted_message)
new_data = {}
new_data['signature_digitale'] = msg.digitalsignature
@ -1360,13 +1358,29 @@ def Create_E_Signature_For_E_Document(file_img=None, Folder=None, diction=None):
node_class['related_collection_id'] = str(e_document_data['class_id'])
tab_related_collection.append(node_class)
if ("session_d" in e_document_data.keys() and e_document_data['session_d']):
if ("session_id" in e_document_data.keys() and e_document_data['session_d']):
node_session = {}
node_session['related_collection'] = 'session_formation'
node_session['related_collection_id'] = str(e_document_data['session_d'])
tab_related_collection.append(node_session)
"""
31/12/2025 : Si c'est un contrat d'un employé, on va aller chercher l'_id de l'employé
"""
if( "related_collection" in e_document_data.keys() and e_document_data['related_collection'] == "ressource_humaine_contrat"
and "related_collection_id" in e_document_data.keys() and e_document_data['related_collection_id']):
rh_contrat_data = MYSY_GV.dbname['ressource_humaine_contrat'].find_one({'_id':ObjectId(e_document_data['related_collection_id']),
'partner_owner_recid':e_document_data['partner_owner_recid']})
if( rh_contrat_data and "rh_id" in rh_contrat_data.keys() and rh_contrat_data['rh_id']):
rh_data = MYSY_GV.dbname['ressource_humaine'].find_one({'_id':ObjectId(rh_contrat_data['rh_id']),
'partner_recid':e_document_data['partner_owner_recid']})
if( rh_data and '_id' in rh_data.keys()):
node_rh = {}
node_rh['related_collection'] = 'ressource_humaine'
node_rh['related_collection_id'] = str(rh_data['_id'])
tab_related_collection.append(node_rh)
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, tab_related_collection)

View File

@ -11,3 +11,10 @@ Liste des environnements :
#MYSY_ENV = "REC"
#MYSY_ENV = "DEM"
MYSY_ENV = "DEV"
"""
Pour les partenaires en marque blacnhe
"""
# Le cas Xcelia
#MYSY_ENV = "XCELIA_DEM"

View File

@ -94,6 +94,24 @@ elif (MYSY_ENV == "DEM"):
BLOG_IMG_URL = "https://blogimg.mysy-training.com/"
elif (MYSY_ENV == "XCELIA_DEM"):
CONNECTION_STRING = "mongodb://localhost:27017/cherifdb_xcelia_demo"
client = MongoClient(CONNECTION_STRING)
dbname = client['cherifdb_xcelia_demo']
CLIENT_URL_BASE = 'https://demo.xceliahub.com/'
MYSY_DEBUG_LEVEL = 1
# Domaine pour le catalogue public
MYSY_PUBLIC_CATALOG_DOMAIN = 'xceliacatalogue.com'
"""
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_prod/"
BLOG_IMG_URL = "https://blogimg.xceliahub.com/"
YTUBES_CONNECTION_STRING = "mongodb://localhost:27017/"
YTUBES_client = MongoClient(YTUBES_CONNECTION_STRING)
@ -110,6 +128,12 @@ MYSY_PORT_REC = 5001
MYSY_PORT_DEM = 5003
"""
Pour les partenaire en mode marque page blanche
- XCELIA
"""
MYSY_PORT_XCELIA_DEM = 5053
'''
Cette Variable defini le nombre minimum
@ -235,6 +259,13 @@ if (MYSY_ENV == "DEM"):
MYSY_FTP_LOGIN = "mysysftpuser"
MYSY_FTP_PWD = "JvMysedrBsDMy01!+"
if (MYSY_ENV == "XCELIA_DEM"):
MYSY_FTP_HOST = "51.178.55.224"
MYSY_FTP_LOGIN = "mysyxceliasftpuser"
MYSY_FTP_PWD = "isqsXcesedrBsDMy01!+"
"""
Repertoire de depot des factures
"""
@ -265,6 +296,10 @@ elif (MYSY_ENV == "REC"):
elif (MYSY_ENV == "DEM"):
INVOICE_FTP_LOCAL_STORAGE_DIRECTORY = "/home/mysy_data/mysy_invoices_demo/"
elif (MYSY_ENV == "XCELIA_DEM"):
INVOICE_FTP_LOCAL_STORAGE_DIRECTORY = "/home/mysy_data/mysy_invoices_demo/"
"""
Cette Variable definit le nombre de formation associées à retourner
"""
@ -348,6 +383,12 @@ if (MYSY_ENV == "DEV"):
O365_SMTP_COUNT_port = 587
if (MYSY_ENV == "XCELIA_DEM"):
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
@ -458,6 +499,24 @@ elif (MYSY_ENV == "DEM"):
STRIPE_CONFIG_API_KEY = "sk_test_51LUUfAAbmaEugrFTrWsfcBWZtbBh9r3HCa2sgeyikG808LjSk3bAdFhV6KxgRZ3vFxooa6RE0c5zBkTuOUrKkyjy00BrsIXAPs"
elif (MYSY_ENV == "XCELIA_DEM"):
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"
"""
Limite des zones de texte des formation
- porgramme
@ -509,6 +568,7 @@ if (MYSY_ENV == "PROD"):
MYSY_LMS_BASE_DIRECTORY = "/var/www/html/chamilo_mysy/"
LMS_BAS_URL = "mysy-training.fr/"
"""
elif (MYSY_ENV == "DEV"):
"""
MYSY_MARIADB_USER = "mysy_mariadb_user"
@ -531,7 +591,6 @@ elif (MYSY_ENV == "DEV"):
MYSY_ENV_API = "http://localhost:"+str(MYSY_PORT_DEV)+"/myclass/api/"
elif (MYSY_ENV == "REC"):
MYSY_MARIADB_USER = "mysy_mariadb_user"
MYSY_MARIADB_USER_PASS = "fB5z%M)GG&g!n2c"
@ -555,6 +614,16 @@ elif (MYSY_ENV == "DEM"):
LMS_BAS_URL = "demolmsmysy-hosting.com/"
MYSY_ENV_API = "https://demoapi.mysy-training.com/myclass/api/"
elif (MYSY_ENV == "XCELIA_DEM"):
MYSY_MARIADB_USER = "xcelia_mariadb_user"
MYSY_MARIADB_USER_PASS = "ZedfB5Xcel&g!n2c"
MYSY_MARIADB_HOST = "51.178.55.224"
MYSY_MARIADB_PORT = 3306
MYSY_LMS_BDD = "demo_chamilo"
MYSY_LMS_URL = "https://xceliaedu.com/"
MYSY_LMS_BASE_DIRECTORY = "/var/www/html/chamilo_mysy_demo/"
LMS_BAS_URL = "xceliaedu.com/"
MYSY_ENV_API = "https://demoapi.xceliahub.com/myclass/api/"

File diff suppressed because one or more lines are too long

View File

@ -241,7 +241,7 @@ def Get_Partner_Catalog_Pub_Config(diction):
data_cle['valide'] = "1"
data_cle['locked'] = "0"
#print(" ### data_cle = ", data_cle)
print(" ### data_cle = ", data_cle)
RetObject = []
val_tmp = 0

View File

@ -332,7 +332,7 @@ def Get_Competence_no_filter(diction):
for New_retVal in MYSY_GV.dbname['competence_liste'].find(qry).sort([("_id", pymongo.DESCENDING), ]):
user = New_retVal
print(" ## useruser = ",user)
if( "code" not in user.keys() ):
user["code"] = "--"

View File

@ -77,6 +77,9 @@ def send_user_account_mail_old(message, account_mail):
elif (MYSY_GV.MYSY_ENV == "DEM"):
my_url = "https://demoapi.mysy-training.com/myclass/api/valide_user_account/" + str(message)
elif (MYSY_GV.MYSY_ENV == "XCELIA_DEM"):
my_url = "https://demoapi.xceliahub.com/myclass/api/valide_user_account/" + str(message)
send_smtp_email = sib_api_v3_sdk.SendSmtpEmail(template_id=15, params={"mysyurl": my_url,
"user_name": str(account_mail),
@ -128,6 +131,8 @@ def send_user_thks_mail_old(message, account_mail):
elif (MYSY_GV.MYSY_ENV == "DEM"):
my_url = "https://demoapi.mysy-training.com/myclass/api/valide_user_account/" + str(message)
elif (MYSY_GV.MYSY_ENV == "XCELIA_DEM"):
my_url = "https://demoapi.xceliahub.com/myclass/api/valide_user_account/" + str(message)
send_smtp_email = sib_api_v3_sdk.SendSmtpEmail(template_id=16, params={ "user_name": str(account_mail),},
to=to, bcc=bcc )
@ -163,6 +168,8 @@ def send_partner_account_mail_old(message, account_mail):
elif (MYSY_GV.MYSY_ENV == "DEM"):
my_url = "https://demoapi.mysy-training.com/myclass/api/valide_partnair_account/"+str(message)
elif (MYSY_GV.MYSY_ENV == "XCELIA_DEM"):
my_url = "https://demoapi.xceliahub.com/myclass/api/valide_partnair_account/"+str(message)
print(" mail enoye à toaddrs : "+toaddrs)
@ -1185,7 +1192,9 @@ def send_user_account_mail(message, account_mail):
elif (MYSY_GV.MYSY_ENV == "DEM"):
my_url = "https://demoapi.mysy-training.com/myclass/api/valide_user_account/" + str(message)
elif (MYSY_GV.MYSY_ENV == "XCELIA_DEM"):
my_url = "https://demoapi.xceliahub.com/myclass/api/valide_user_account/" + str(message)
smtpserver = smtplib.SMTP(MYSY_GV.O365_SMTP_COUNT_smtpsrv, MYSY_GV.O365_SMTP_COUNT_port)
@ -1256,6 +1265,9 @@ def send_partner_account_mail(message, account_mail):
elif (MYSY_GV.MYSY_ENV == "DEM"):
my_url = "https://demoapi.mysy-training.com/myclass/api/valide_partnair_account/" + str(message)
elif (MYSY_GV.MYSY_ENV == "XCELIA_DEM"):
my_url = "https://demoapi.xceliahub.com/myclass/api/valide_partnair_account/" + str(message)
smtpserver = smtplib.SMTP(MYSY_GV.O365_SMTP_COUNT_smtpsrv, MYSY_GV.O365_SMTP_COUNT_port)
@ -1423,6 +1435,9 @@ def send_user_thks_mail(message, account_mail):
elif (MYSY_GV.MYSY_ENV == "DEM"):
my_url = "https://demoapi.mysy-training.com/myclass/api/valide_user_account/" + str(message)
elif (MYSY_GV.MYSY_ENV == "XCELIA_DEM"):
my_url = "https://demoapi.xceliahub.com/myclass/api/valide_user_account/" + str(message)
"""
send_smtp_email = sib_api_v3_sdk.SendSmtpEmail(template_id=16, params={ "user_name": str(account_mail),},
to=to, bcc=bcc )
@ -1490,6 +1505,9 @@ def send_user_init_pwd_mail(token, account_mail, type_account):
elif (MYSY_GV.MYSY_ENV == "DEM"):
my_url = "https://demo.mysy-training.com/ResetUserPwd/" + str(token) + "/" + str(type_account)
elif (MYSY_GV.MYSY_ENV == "XCELIA_DEM"):
my_url = "https://demoapi.xceliahub.com/ResetUserPwd/" + str(token) + "/" + str(type_account)
"""send_smtp_email = sib_api_v3_sdk.SendSmtpEmail(template_id=19, params={"mysyurl": my_url,
"user_name": str(account_mail),
}, to=to, bcc=bcc
@ -2156,6 +2174,10 @@ def SendEmargementMail( diction):
elif (MYSY_GV.MYSY_ENV == "DEM"):
myurl = "https://demoapi.mysy-training.com/myclass/api/UserEmargementValidation/" + str(val_emarge['_id']) + "/1"
elif (MYSY_GV.MYSY_ENV == "XCELIA_DEM"):
myurl = "https://demoapi.xceliahub.com/myclass/api/UserEmargementValidation/" + str(val_emarge['_id']) + "/1"
body = {
"params":{"nom": str(val_emarge['nom']),
"prenom": str(val_emarge['prenom']),
@ -2490,7 +2512,7 @@ def ManualSendInvoiceEmailRIB_CIC_JMJFormation(diction):
body = {
"params": {"order_id": "MTT/2025_N°0012/JMJ FORMATION",
"date_order": ": 14/07/2025",
"periode":"13/11/2025 au 14/12/2025",
"periode":"14/12/2025 au 13/01/2026",
"total_ht": "130",
"tva": "11.05",
"total_ttc": "141,05 ",
@ -2506,9 +2528,9 @@ def ManualSendInvoiceEmailRIB_CIC_JMJFormation(diction):
"montant": "130 €",
"invoice_id": "FACT_20251114",
"invoice_date": "16/11/2025",
"due_date": "16/11/2025",
"invoice_id": "FACT_20251215",
"invoice_date": "21/12/2025",
"due_date": "21/12/2025",
"orign_order": "Contrat MTT/2025_N°0012/JMJ FORMATION",
}
}
@ -2542,7 +2564,7 @@ def ManualSendInvoiceEmailRIB_CIC_JMJFormation(diction):
#print(" ### body 22 = ", body)
sourceHtml = template.render(json_data=body["params"])
orig_file_name = "invoice_FACT_20251114.pdf"
orig_file_name = "invoice_FACT_20251215.pdf"
outputFilename = str(MYSY_GV.INVOICE_DIRECTORY) + str(orig_file_name)
# open output file for writing (truncated binary)
@ -2565,6 +2587,114 @@ def ManualSendInvoiceEmailRIB_CIC_JMJFormation(diction):
return False, " impossible d'envoyer la facure"
"""
Creation manuelle d'une facture avec RIB CIC pour Xcelia - perso
"""
def ManualSendInvoiceEmailRIB_CIC_Xcelia(diction):
try:
'''
Verification des données obligatoires
'''
'''
Une fois qu'on a controlé que toutes les clés mise dans l'API sont correcte. etape precedente,
On controle que les champs obligatoires sont presents dans la liste
'''
tomorrow = datetime.date.today() + datetime.timedelta(days=1)
tomorrow_day = tomorrow.strftime("%A")
print("debut envoi mail de test ")
# on rentre les renseignements pris sur le site du fournisseur
#smtpserver = smtplib.SMTP(MYSY_GV.O365_SMTP_COUNT_smtpsrv, MYSY_GV.O365_SMTP_COUNT_port)
# msg = MIMEMultipart("alternative")
#msg = EmailMessage()
# JINJA2
templateLoader = jinja2.FileSystemLoader(searchpath="./")
templateEnv = jinja2.Environment(loader=templateLoader)
TEMPLATE_FILE = "Template/MySy_Invoice_RIB_PortCities_Perso_tpl.html"
template = templateEnv.get_template(TEMPLATE_FILE)
body = {
"params": {"order_id": "N/A",
"date_order": ": 29/10/2025",
"periode":"",
"total_ht": "130",
"tva": "11.05",
"total_ttc": "141,05 ",
"client_name": "XCELIA Consulting",
"client_address": "KOBAYA",
"client_zip_ville": "C/RATOMA",
"client_pays": "CONAKRY-GUINEE",
"packs": "ELYOS - Initialisation de la plateforme de démonstration client ",
"detail_packs": "Mise à disposition dune plateforme standard opérationnelle"
"Location et maintenance du serveur sur 12 mois ",
"qty": "1",
"unit_price": "130 €",
"montant": "130 €",
"invoice_id": "FACT_20251215",
"invoice_date": "21/12/2025",
"due_date": "21/12/2025",
"orign_order": "Contrat MTT/2025_N°0012/JMJ FORMATION",
}
}
#print(" ### body 1 = ", body)
sourceHtml = template.render(params=body["params"])
"""msg.set_content(sourceHtml, subtype='html')
msg['From'] = MYSY_GV.O365_SMTP_COUNT_From_User
msg['Bcc'] = 'contact@mysy-training.com'
msg['Subject'] = "[MySy Training Technology] : Votre facture N° FACT_230500030"
msg['To'] = 'billardman1@gmail.com'
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))
### CREATION DE LA FACTION PDF
templateLoader = jinja2.FileSystemLoader(searchpath="./")
templateEnv = jinja2.Environment(loader=templateLoader)
#TEMPLATE_FILE = "Template/MySy_Invoice_RIB_tpl.html"
TEMPLATE_FILE = "Template/invoice_RIB_PortCities_perso_tpl.html"
template = templateEnv.get_template(TEMPLATE_FILE)
# This data can come from database query
#print(" ### body 22 = ", body)
sourceHtml = template.render(json_data=body["params"])
orig_file_name = "invoice_FACT_20251215.pdf"
outputFilename = str(MYSY_GV.INVOICE_DIRECTORY) + str(orig_file_name)
# open output file for writing (truncated binary)
resultFile = open(outputFilename, "w+b")
# convert HTML to PDF
pisaStatus = pisa.CreatePDF(
src=sourceHtml, # the HTML to convert
dest=resultFile) # file handle to receive result
# close output file
resultFile.close()
return True, " facture envoyée"
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 la facure"
"""
Creation manuelle d'une facture avec RIB CIC pour France Active - perso
@ -2705,24 +2835,24 @@ def ManualSendInvoiceEmailRIB_CIC_BureauVallee(diction):
body = {
"params": {"order_id": "N/A",
"date_order": ": 12/08/2025",
"periode":"01/11/2025 au 30/11/2025",
"total_ht": "8 932,74",
"tva": "1 786,55",
"total_ttc": "10 719,29",
"periode":"01/12/2025 au 19/12/2025",
"total_ht": "7 819,3",
"tva": "1 563,86",
"total_ttc": "9 383,16",
"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 déploiement de l'ERP CoQliQo",
"qty": "15.5 jours",
"qty": "13 jours",
"unit_price": "550 €",
"montant": "8 525 ",
"montant": "7 150",
"invoice_id": "FACT_20251121",
"invoice_date": "30/11/2025",
"due_date": "15/12/2025",
"invoice_id": "FACT_20251222",
"invoice_date": "19/12/2025",
"due_date": "05/01/2026",
"orign_order": "N/A",
}
}
@ -2756,7 +2886,7 @@ def ManualSendInvoiceEmailRIB_CIC_BureauVallee(diction):
#print(" ### body 22 = ", body)
sourceHtml = template.render(json_data=body["params"])
orig_file_name = "invoice_FACT_20251121.pdf"
orig_file_name = "invoice_FACT_20251222.pdf"
outputFilename = str(MYSY_GV.INVOICE_DIRECTORY) + str(orig_file_name)
# open output file for writing (truncated binary)

View File

@ -588,7 +588,7 @@ def Get_Ent_Student_Session_Sequence_List(diction):
"""
Verification des champs obligatoires
"""
field_list_obligatoire = ['token', 'apprenant_id']
field_list_obligatoire = ['token', 'apprenant_id', ]
for val in field_list_obligatoire:
if val not in diction:
mycommon.myprint(

View File

@ -737,7 +737,7 @@ def Get_Nb_User_Internal_Mail_Not_Read(diction):
if (local_status is not True):
return local_status, my_partner
print(" my_partnermy_partner = ", my_partner)
#print(" my_partnermy_partner = ", my_partner)
"""
Clés de mise à jour
@ -756,7 +756,7 @@ def Get_Nb_User_Internal_Mail_Not_Read(diction):
query_qet_email_to_or_cc = [{'$match': {'$and': [data_cle, filt_to_user_or_cc_user]}}, { '$count': "nb_mail_non_lus" }]
print(" ## query_qet_email_to_or_cc = ", query_qet_email_to_or_cc)
#print(" ## query_qet_email_to_or_cc = ", query_qet_email_to_or_cc)
nb_mail_non_lu = "0"
for line in MYSY_GV.dbname['internal_mail'].aggregate(query_qet_email_to_or_cc):

View File

@ -1209,7 +1209,7 @@ def Check_MySy_LMS_Account(diction):
Ce pack necessite un compte LMS
"""
if( mysy_lms_user_id.strip() == ""):
#print(" ### ce partenaire n'as pas de compte LMS, il faut en créer 1 ")
print(" ### ce partenaire n'as pas de compte LMS, il faut en créer 1 ")
new_diction = {}
lastname = ""

70
main.py
View File

@ -377,6 +377,9 @@ def valide_user_account(value):
elif (MYSY_GV.MYSY_ENV == "DEM"):
url = 'https://demo.mysy-training.com/mysy-account-activated/'
elif (MYSY_GV.MYSY_ENV == "XCELIA_DEM"):
url = 'https://demo.xceliahub.com/mysy-account-activated/'
else:
if (MYSY_GV.MYSY_ENV == "PROD"):
url = 'https://www.mysy-training.com/'
@ -390,6 +393,9 @@ def valide_user_account(value):
elif (MYSY_GV.MYSY_ENV == "DEM"):
url = 'https://demo.mysy-training.com/'
elif (MYSY_GV.MYSY_ENV == "XCELIA_DEM"):
url = 'https://demo.xceliahub.com/'
return redirect(url)
@ -878,6 +884,9 @@ def valide_partnair_account(value):
elif (MYSY_GV.MYSY_ENV == "DEM"):
url = 'https://demo.mysy-training.com/PartnerLogin1/'
elif (MYSY_GV.MYSY_ENV == "XCELIA_DEM"):
url = 'https://demo.xceliahub.com/PartnerLogin1/'
else:
if (MYSY_GV.MYSY_ENV == "PROD"):
url = 'https://www.mysy-training.com/'
@ -888,6 +897,9 @@ def valide_partnair_account(value):
elif (MYSY_GV.MYSY_ENV == "DEM"):
url = 'https://demo.mysy-training.com/'
elif (MYSY_GV.MYSY_ENV == "XCELIA_DEM"):
url = 'https://demo.xceliahub.com/'
return redirect(url)
@ -3116,6 +3128,9 @@ def UserEmargementValidation(value, session):
elif (MYSY_GV.MYSY_ENV == "DEM"):
url = 'https://demo.mysy-training.com/Emargement/'
elif (MYSY_GV.MYSY_ENV == "XCELIA_DEM"):
url = 'https://demo.xceliahub.com/Emargement/'
else:
if (MYSY_GV.MYSY_ENV == "PROD"):
url = 'https://www.mysy-training.com/erreur'
@ -3128,6 +3143,9 @@ def UserEmargementValidation(value, session):
elif (MYSY_GV.MYSY_ENV == "DEM"):
url = 'https://demo.mysy-training.com/erreur'
elif (MYSY_GV.MYSY_ENV == "XCELIA_DEM"):
url = 'https://demo.xceliahub.com/erreur'
return redirect(url)
"""
@ -12557,6 +12575,29 @@ def Print_Employee_Given_Contrat(token, rh_id, contract_id):
return False
"""
API qui envoie le contrat d'un employé par email par email avec signature electronique
"""
@app.route('/myclass/api/Send_Employee_Contract_By_Email/', methods=['GET','POST'])
@crossdomain(origin='*')
def Send_Employee_Contract_By_Email():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary(request.form.to_dict())
print(" ### Send_Employee_Contract_By_Email : payload = ", str(payload))
file = []
tab_files = []
if request.method == 'POST':
# Create variable for uploaded file
for tmp in request.files.getlist("File"):
tab_files.append(tmp)
status, retval = ressources_humaines.Send_Employee_Contract_By_Email(tab_files, MYSY_GV.TEMPORARY_DIRECTORY_V2, payload)
return jsonify(status=status, message=retval)
"""
API permet de recuperer les data du partenaire proprietaire d'un sous domaine
"""
@ -14474,7 +14515,7 @@ API pour mise à jour d'un email d'un utilisateur du systeme
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)
print(" ### Update_Message_To_Internal_Mail payload = ")
file = []
if request.method == 'POST':
@ -14978,6 +15019,33 @@ if __name__ == '__main__':
elif (MYSY_GV.MYSY_ENV == "XCELIA_DEM"):
mycommon.myprint(" ++++ ENVIRONNEMENT XCELIA - DEMO ++++")
mycommon.myprint("++ DATABASE " + MYSY_GV.CONNECTION_STRING + " ++")
mycommon.myprint("++ DBNAME " + str(MYSY_GV.dbname) + " ++")
mycommon.myprint("++ FLASK PORT " + str(MYSY_GV.MYSY_PORT_XCELIA_DEM) + " ++")
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)
# 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_XCELIA_DEM, debug=True, threaded=True)

View File

@ -187,6 +187,9 @@ def add_partner_account(diction):
mydata['firstconnexion'] = '1'
mydata['is_partner_admin_account'] = '1'
# 20/12/2025 - Par defaut, on le met en formation initiale pour voir toutes les fonctionalité
mydata['formation_initiale'] = '1'
#print(str(datetime.now()) + " webservice : diction = "+str(mydata))
coll_name = MYSY_GV.dbname['partnair_account']
coll_name_user_account = MYSY_GV.dbname['user_account']
@ -939,9 +942,9 @@ La modification ne s'effectue que si le compte n'est pas verrouillé.
'locked'=0
Important : : Juste apres la validation, le compte de payement est créé dans Stripe
Important : Juste apres la validation, le compte de payement est créé dans Stripe
cette fontion initialise / initialisation des paramettre par defaut de chaque partenaire
cette fonction initialise / initialisation des paramettre par defaut de chaque partenaire
'''
def valide_partnair_account(value):
try:
@ -1005,6 +1008,7 @@ def valide_partnair_account(value):
{'active': "1","date_update":str(now),
'secret_key':str(my_token),
'stripe_account_id':part_stripe_account_id,
'active': "1",
}
},
return_document=ReturnDocument.AFTER

View File

@ -8,6 +8,11 @@ etc
Une ressource humaine a toujours un profil (enseignant, cadre admin) et une fonction.
"""
import smtplib
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import pymongo
from flask import send_file
@ -20,6 +25,7 @@ from datetime import datetime, date
from xhtml2pdf import pisa
import E_Sign_Document
import partners
import prj_common as mycommon
import secrets
@ -4177,7 +4183,8 @@ def Add_Employee_Contrat(diction):
Verification des input acceptés
"""
field_list = ['token', 'rh_id', 'date_debut', 'date_fin', 'type_contrat',
'type_employe', 'cout', 'groupe_prix_achat_id', 'quantite', 'comment', 'periodicite']
'type_employe', 'cout', 'groupe_prix_achat_id', 'quantite', 'comment',
'periodicite', 'class_id', 'session_id']
incom_keys = diction.keys()
for val in incom_keys:
@ -4210,6 +4217,34 @@ def Add_Employee_Contrat(diction):
if (local_status is not True):
return local_status, my_partner
# Verifier la valididé de la formation, si formation
if ("class_id" in diction.keys() and diction['class_id']):
is_valide_class_count = MYSY_GV.dbname['myclass'].count_documents(
{'_id': ObjectId(str(diction['class_id'])),
'valide': '1',
'partner_owner_recid': str(
my_partner['recid'])
})
if (is_valide_class_count != 1):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'identifiant de la formation est invalide ")
return False, " L'identifiant de la formation est invalide "
# Verifier la valididé de la session / promo, si session / promo
if ("session_id" in diction.keys() and diction['session_id']):
is_valide_session_count = MYSY_GV.dbname['session_formation'].count_documents(
{'_id': ObjectId(str(diction['session_id'])),
'valide': '1',
'partner_owner_recid': str(
my_partner['recid'])
})
if (is_valide_session_count != 1):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'identifiant de la session/promo est invalide ")
return False, " L'identifiant de la session/promo est invalide "
# Verifier que la ressource_humaine est valide
is_rh_id_valide = MYSY_GV.dbname['ressource_humaine'].count_documents({'_id':ObjectId(str(diction['rh_id'])),
'valide':'1',
@ -4434,7 +4469,8 @@ def Update_Employee_Contrat(diction):
Verification des input acceptés
"""
field_list = ['token', '_id', 'rh_id', 'date_debut', 'date_fin', 'type_contrat',
'type_employe', 'cout', 'groupe_prix_achat_id', 'quantite', 'comment', 'periodicite']
'type_employe', 'cout', 'groupe_prix_achat_id', 'quantite', 'comment', 'periodicite',
'class_id', 'session_id']
incom_keys = diction.keys()
for val in incom_keys:
@ -4485,6 +4521,32 @@ def Update_Employee_Contrat(diction):
str(inspect.stack()[0][3]) + " L'identifiant du contrat est invalide ")
return False, " L'identifiant du contrat est invalide "
# Verifier la valididé de la formation, si formation
if( "class_id" in diction.keys() and diction['class_id']):
is_valide_class_count = MYSY_GV.dbname['myclass'].count_documents({'_id':ObjectId(str(diction['class_id'])),
'valide':'1',
'partner_owner_recid': str(
my_partner['recid'])
})
if( is_valide_class_count != 1 ):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'identifiant de la formation est invalide ")
return False, " L'identifiant de la formation est invalide "
# Verifier la valididé de la session / promo, si session / promo
if ("session_id" in diction.keys() and diction['session_id']):
is_valide_session_count = MYSY_GV.dbname['session_formation'].count_documents(
{'_id': ObjectId(str(diction['session_id'])),
'valide': '1',
'partner_owner_recid': str(
my_partner['recid'])
})
if (is_valide_session_count != 1):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'identifiant de la session/promo est invalide ")
return False, " L'identifiant de la session/promo est invalide "
# Verifier que la ressource_humaine est valide
@ -4929,6 +4991,40 @@ def Get_List_Employee_Contrat(diction):
for retval in MYSY_GV.dbname['ressource_humaine_contrat'].find({'rh_id':str(diction['rh_id']),
'valide': '1','locked': '0', 'partner_owner_recid': str(my_partner['recid'])}):
user = retval
if( "class_id" not in user.keys()):
user['class_id'] = ""
user['class_title'] = ""
else:
class_title = ""
class_data = MYSY_GV.dbname['myclass'].find_one({'_id':ObjectId(str(user['class_id'])),
'valide':'1',
'partner_owner_recid': str(
my_partner['recid'])
})
if( class_data and "title" in class_data.keys()):
class_title = class_data['title']
user['class_title'] = class_title
if ("session_id" not in user.keys()):
user['session_id'] = ""
user['session_code'] = ""
else:
session_code = ""
session_data = MYSY_GV.dbname['session_formation'].find_one(
{'_id': ObjectId(str(user['session_id'])),
'valide': '1',
'partner_owner_recid': str(
my_partner['recid'])
})
if( session_data and "code_session" in session_data.keys()):
session_code = session_data['code_session']
user['session_code'] = session_code
user['id'] = str(val_tmp)
val_tmp = val_tmp + 1
RetObject.append(mycommon.JSONEncoder().encode(user))
@ -5788,3 +5884,456 @@ def Print_Employee_Given_Contrat(diction):
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 la version PDF du contrat "
"""
Cette fonction permet d'envoyer le contrat d'un employé / vacataire, etc
par email, avec ou sans signature electronique
"""
def Send_Employee_Contract_By_Email(tab_files, Folder, diction):
try:
field_list = ['rh_contrat_id', 'token', 'courrier_template_id', 'request_digital_signature']
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]) + " - La valeur '" + val + "' n'est pas presente dans la liste des arguments ")
return False, "Les informations fournies sont incorrectes"
"""
Verification de la liste des champs obligatoires
"""
field_list_obligatoire = ['rh_contrat_id', 'token', 'courrier_template_id' ]
for val in field_list_obligatoire:
if val not in diction:
mycommon.myprint(
str(inspect.stack()[0][
3]) + " - : La valeur '" + val + "' n'est pas presente dans la liste des arguments ")
return False, " Les informations fournies sont incorrectes "
query_get_data = {}
mytoken = ""
if ("token" in diction.keys()):
if diction['token']:
mytoken = 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
"""
20/03/2024 : Creation du E-Document à signer
On verifier si le partenaire dispose de l'option "signature_digital" dans la collection base_partner_setup
ET SI DEPUIS LE FRONT, L'UTILISATEUR DECIDE DE L'UTILISER
"""
is_partner_digital_signature = ""
if ("request_digital_signature" in diction.keys() and diction['request_digital_signature'] == "1"):
is_signature_digital_count = MYSY_GV.dbname['base_partner_setup'].count_documents(
{'partner_owner_recid': str(my_partner['recid']),
'config_name': 'signature_digital',
'valide': '1',
'locked': '0',
'config_value': '1'})
if (is_signature_digital_count == 1):
is_partner_digital_signature = "1"
# Verification de la validité du contrat
is_contract_Existe_Count = MYSY_GV.dbname['ressource_humaine_contrat'].count_documents(
{'_id': ObjectId(str(diction['rh_contrat_id'])),
'valide': '1', 'locked': '0',
'partner_owner_recid': str(my_partner['recid'])})
if (is_contract_Existe_Count != 1):
mycommon.myprint(
str(inspect.stack()[0][3]) + " L'identifiant du contrat est invalide ")
return False, " L'identifiant du contrat est invalide ",
rh_contract_data = MYSY_GV.dbname['ressource_humaine_contrat'].find_one({'_id': ObjectId(str(diction['rh_contrat_id'])),
'valide': '1', 'locked': '0',
'partner_owner_recid': str(my_partner['recid'])})
# recuperer le modele de document
Contrat_Model_Document_data = MYSY_GV.dbname['courrier_template'].find_one(
{'partner_owner_recid': str(my_partner['recid']),
'valide': '1', 'locked': '0', 'type_doc': 'email', '_id':ObjectId(str(diction['courrier_template_id']))})
if (Contrat_Model_Document_data is None):
mycommon.myprint(
str(inspect.stack()[0][
3]) + " Le modèle de document est invalide ")
return False, " Le modèle de document est invalide"
if ("contenu_doc" not in Contrat_Model_Document_data or len(
str(Contrat_Model_Document_data['contenu_doc'])) <= 0):
mycommon.myprint(str(inspect.stack()[0][
3]) + " Le paramétrage du document est invalide")
return False, " Le paramétrage du document est invalide "
# Recuperation des données de l'employée
employee_data = MYSY_GV.dbname['ressource_humaine'].find_one({'_id':ObjectId(str(rh_contract_data['rh_id'])),
'partner_recid':str(my_partner['recid']),
'valide':'1',
'locked':'0'})
if( employee_data is None):
mycommon.myprint(str(inspect.stack()[0][
3]) + " L'employé associé au contrat est invalide")
return False, " L'employé associé au contrat est invalide "
if( "email" not in employee_data.keys() or str(employee_data['email']).strip() == ""):
mycommon.myprint(str(inspect.stack()[0][
3]) + "L'adresse email de l'employé est invalide")
return False, " L'adresse email de l'employé est invalide "
# 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):
return status, saved_file_full_path
tab_saved_file_full_path.append(saved_file_full_path)
# Traitement de l'eventuel fichier joint
tab_files_to_attache_to_mail = []
for saved_file in tab_saved_file_full_path:
file_to_attache_to_mail = MIMEBase('application', "octet-stream")
file_to_attache_to_mail.set_payload(open(saved_file, "rb").read())
encoders.encode_base64(file_to_attache_to_mail)
file_to_attache_to_mail.add_header('Content-Disposition',
'attachment; filename="{0}"'.format(os.path.basename(saved_file)))
new_node = {"attached_file": file_to_attache_to_mail}
tab_files_to_attache_to_mail.append(new_node)
print(" ## tab_files_to_attache_to_mail 01 = ", tab_files_to_attache_to_mail)
# Creation du dictionnaire d'information à utiliser pour la creation du doc
tab_class = []
if( "class_id" in rh_contract_data.keys() and rh_contract_data['class_id']):
tab_class.append(ObjectId(str(rh_contract_data['class_id'])))
tab_session = []
if ("session_id" in rh_contract_data.keys() and rh_contract_data['session_id']):
tab_session.append(ObjectId(str(rh_contract_data['session_id'])))
convention_dictionnary_data = {}
new_diction = {}
new_diction['token'] = diction['token']
new_diction['list_stagiaire_id'] = []
new_diction['list_session_id'] = tab_session
new_diction['list_class_id'] = tab_class
new_diction['list_client_id'] = []
new_diction['list_apprenant_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']
convention_dictionnary_data = local_retval
convention_dictionnary_data['employee'] = employee_data
convention_dictionnary_data['contrat'] = rh_contract_data
body = {
"params": convention_dictionnary_data,
}
# Verifier s'il s'agit d'un document à envoyer avec une version de pièce jointe.
if ("joint_pdf" in Contrat_Model_Document_data.keys() and str(
Contrat_Model_Document_data['joint_pdf']) == "1"):
# Il s'agit bien d'un envoie avec 'contenu_doc' en pièce jointe PDF
"""
1 - Creation du PDF
"""
contenu_doc_Template = jinja2.Template(str(Contrat_Model_Document_data['contenu_doc']))
sourceHtml = contenu_doc_Template.render(params=body["params"])
todays_date = str(date.today().strftime("%d/%m/%Y"))
ts = datetime.now().timestamp()
ts = str(ts).replace(".", "").replace(",", "")[-5:]
orig_file_name = "Contrat_" + str(employee_data['nom'])+"_"+str(my_partner['recid'])[0:5] + "_" + str(ts) + ".pdf"
outputFilename = str(MYSY_GV.TEMPORARY_DIRECTORY) + "/" + str(orig_file_name)
# open output file for writing (truncated binary)
resultFile = open(outputFilename, "w+b")
# convert HTML to PDF
pisaStatus = pisa.CreatePDF(
src=sourceHtml, # the HTML to convert
dest=resultFile) # file handle to receive result
# close output file
resultFile.close()
# Attachement du fichier joint
file_to_attache_to_mail = MIMEBase('application', "octet-stream")
file_to_attache_to_mail.set_payload(open(outputFilename, "rb").read())
encoders.encode_base64(file_to_attache_to_mail)
file_to_attache_to_mail.add_header('Content-Disposition',
'attachment; filename="{0}"'.format(os.path.basename(outputFilename)))
new_node = {"attached_file": file_to_attache_to_mail}
tab_files_to_attache_to_mail.append(new_node)
contenu_pdf_doc_Template = jinja2.Template(str(Contrat_Model_Document_data['contenu_doc']))
corps_mail_doc_Template = jinja2.Template(str(Contrat_Model_Document_data['corps_mail']))
sujet_doc_Template_subject = jinja2.Template(str(Contrat_Model_Document_data['sujet']))
sourceHtml = corps_mail_doc_Template.render(params=body['params'], )
sujetHtml = sujet_doc_Template_subject.render(params=body['params'], )
contenu_pdf_html = contenu_pdf_doc_Template.render(params=body['params'], )
html_mime = MIMEText(sourceHtml, 'html')
# Creation de l'email à enoyer
msg = MIMEMultipart("alternative")
new_model_courrier_with_code_tag = " <div style='width: 100%'> <div style = 'width: 100%; text-align: center;' >" \
" <img style = 'height:60px; width:60px;' src = '{{ params.mysy_qrcode_securite }}' > <br/>" \
" <nav style = 'font-size: 10px; font-style: italic;' > Sécurisé par MySy Training Technology </nav>" \
" <br/> </div> </div>" + \
str(contenu_pdf_html) + " <div style='width: 100%'> <div style = 'width: 100%; text-align: center;' >" \
" Signature Client <br/> <img style = 'height:100px; width:100px' " \
" src = '{{ params.mysy_manual_signature_img }}' > <br/> " \
" </div> </div>"
todays_date = str(date.today().strftime("%d_%m_%Y"))
ts = datetime.now().timestamp()
ts = str(ts).replace(".", "").replace(",", "")[-2:]
orig_file_name = "Contrat_" + str(employee_data['nom'])+"_"+str(my_partner['recid'])[0:3] + "_" + str(todays_date) + "_" + str(ts) + ".pdf"
outputFilename = str(MYSY_GV.TEMPORARY_DIRECTORY) + "/" + str(orig_file_name)
# open output file for writing (truncated binary)
resultFile = open(outputFilename, "w+b")
# convert HTML to PDF
pisaStatus = pisa.CreatePDF(
src=contenu_pdf_html, # the HTML to convert
dest=resultFile) # file handle to receive result
# close output file
resultFile.close()
else:
mycommon.myprint(str(inspect.stack()[0][
3]) + " Le paramétrage du modèle de courrier ne comporte pas de 'joint_pdf' ")
return False, " Le paramétrage du modèle de courrier ne comporte pas de 'joint_pdf' "
"""
Recuperation des parametre SMTP du partner si le client a decidé d'utiliser son propre smpt
"""
partner_own_smtp_value = "0"
partner_own_smtp = MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(my_partner['recid']),
'config_name': 'partner_smtp',
'valide': '1',
'locked': '0'})
if (partner_own_smtp and "config_value" in partner_own_smtp.keys()):
partner_own_smtp_value = partner_own_smtp['config_value']
if (str(partner_own_smtp_value) == "1"):
partner_SMTP_COUNT_password = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(my_partner['recid']),
'config_name': 'smtp_user_pwd',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_smtpsrv = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(my_partner['recid']),
'config_name': 'smtp_server',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_user = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(my_partner['recid']),
'config_name': 'smtp_user',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_From_User = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(my_partner['recid']),
'config_name': 'smtp_count_from_name',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
partner_SMTP_COUNT_port = str(MYSY_GV.dbname['base_partner_setup'].find_one(
{'partner_owner_recid': str(my_partner['recid']),
'config_name': 'smtp_count_port',
'valide': '1',
'locked': '0'}, {'config_value': 1})['config_value'])
if (str(partner_own_smtp_value) == "1"):
print("debut envoi mail de test ")
# Creation de l'email à enoyer
msg = MIMEMultipart("alternative")
msg.attach(html_mime)
smtpserver = smtplib.SMTP(partner_SMTP_COUNT_smtpsrv, partner_SMTP_COUNT_port)
msg['To'] = employee_data['email']
msg['From'] = partner_SMTP_COUNT_From_User
msg['Bcc'] = 'contact@mysy-training.com'
msg['Subject'] = sujetHtml
# Attacher l'eventuelle pièces jointes
for myfile in tab_files_to_attache_to_mail:
msg.attach(myfile['attached_file'])
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(partner_SMTP_COUNT_user, partner_SMTP_COUNT_password)
val = smtpserver.send_message(msg)
smtpserver.close()
print(" Email envoyé " + str(val))
else:
print("debut envoi mail de test ")
# Creation de l'email à enoyer
msg = MIMEMultipart("alternative")
msg.attach(html_mime)
smtpserver = smtplib.SMTP(MYSY_GV.O365_SMTP_COUNT_smtpsrv, MYSY_GV.O365_SMTP_COUNT_port)
"""
La commande est envoyée à l'adresse email qui se trouve sur la commande, le champ : 'order_header_email_client'.
Si ce champ est vide alors on regarde si il y a un email sur la fiche client.
"""
client_main_mail_tmp = ""
msg['To'] = employee_data['email']
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
# 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(MYSY_GV.O365_SMTP_COUNT_user, MYSY_GV.O365_SMTP_COUNT_password)
val = smtpserver.send_message(msg)
smtpserver.close()
print(" Email envoyé " + str(val))
"""
Gestion de la E-Signature
20/03/2024 : le contrat pdf a été créée.
Si le partenaire a l'option de signature digitale, alors on créé le e-document
"""
if (is_partner_digital_signature == "1"):
tab_class = []
if ("class_id" in rh_contract_data.keys() and rh_contract_data['class_id']):
tab_class.append(ObjectId(str(rh_contract_data['class_id'])))
tab_session = []
if ("session_id" in rh_contract_data.keys() and rh_contract_data['session_id']):
tab_session.append(ObjectId(str(rh_contract_data['session_id'])))
new_diction = {}
new_diction['token'] = diction['token']
new_diction['list_stagiaire_id'] = []
new_diction['list_session_id'] = tab_session
new_diction['list_class_id'] = tab_class
new_diction['list_client_id'] = []
local_status, local_retval = mycommon.Get_Dictionnary_data_For_Template(new_diction)
if (local_status is False):
return local_status, local_retval
convention_dictionnary_data = local_retval
client_data = convention_dictionnary_data['list_client_data']
# print(client_data[0]['list_contact_communication'] )
tab_emails_destinataire = employee_data['email']
new_e_document_diction = {}
new_e_document_diction['token'] = diction['token']
new_e_document_diction['file_name'] = outputFilename
toaddrs = employee_data['email']
new_e_document_diction['email_destinataire'] = str(toaddrs)
new_e_document_diction['source_document'] = new_model_courrier_with_code_tag
new_e_document_diction['type'] = "contrat"
new_e_document_diction['related_collection'] = "ressource_humaine_contrat"
new_e_document_diction['related_collection_id'] = str(rh_contract_data['_id'])
new_e_document_diction['file_cononical_name'] = "Contrat_" + str(employee_data['nom'])+"_"+str(my_partner['recid'])[0:3] + "_" + str(todays_date) + "_" + str(ts)
local_status_e_doc, local_retval_e_doc = E_Sign_Document.Create_E_Document(new_e_document_diction)
if (local_status_e_doc is False):
return local_status_e_doc, local_retval_e_doc
"""
Apres la creation du document electronique, on envoie la demande de validation
Important : on envoie le mail à chaque destinataire
"""
new_send_e_document_diction = {}
new_send_e_document_diction['token'] = diction['token']
new_send_e_document_diction['e_doc_id'] = str(local_retval_e_doc)
new_send_e_document_diction['user_email'] = str(employee_data['email'])
local_status_send_e_doc, local_send_retval_e_doc = E_Sign_Document.Sent_E_Document_Signature_Request(
new_send_e_document_diction)
if (local_status_send_e_doc is False):
return local_status_send_e_doc, local_send_retval_e_doc
# Logguer l'event
now = str(datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
# print(" ####### laaaa diction = ", diction)
history_event_dict = {}
history_event_dict['token'] = mytoken
history_event_dict['related_collection'] = "ressource_humaine"
history_event_dict['related_collection_recid'] = str(employee_data['_id'])
history_event_dict['action_date'] = str(now)
history_event_dict['action_description'] = "Contrat envoyé par email à " + str(employee_data['email'])
local_status, local_retval = mycommon.Collection_Historique.Add_Historique_Event(history_event_dict)
if (local_status is False):
mycommon.myprint(
" WARNING : Impossible de logguer l'historique pour l'évènement : " + str(history_event_dict))
return True, " Le document a été envoyé par email à : '" + str(employee_data['email']) + "' "
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 le contrat par email"

View File

@ -348,7 +348,6 @@ Lorsqu'un user se logue, on recupere son RecId,
puis on enregiste dans table des token :
- le recid,
- le token
'''
def Ent_Student_login(diction):
try:
@ -496,4 +495,4 @@ def Ent_Student_login(diction):
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 se connecter, merci de contacter le support technique", False
return False, "Impossible de se connecter, merci de contacter le support technique", False, False, False