10/05/2026 - 12h30

Signed-off-by: Cherif <cbalde@mysy-training.com>
master_Elyos_FI
Cherif 2026-05-10 12:33:17 +02:00
parent fa27fdcc3b
commit ed09529c68
6 changed files with 2734 additions and 12 deletions

View File

@ -4,16 +4,13 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="08/05/2026 - 17h">
<change afterPath="$PROJECT_DIR$/Relance_client_facture.py" afterDir="false" />
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="09/05/2025 - 20h30">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" 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$/invoice_paiement_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/invoice_paiement_mgt.py" 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$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/partner_client.py" beforeDir="false" afterPath="$PROJECT_DIR$/partner_client.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/partner_invoice.py" beforeDir="false" afterPath="$PROJECT_DIR$/partner_invoice.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/partners.py" beforeDir="false" afterPath="$PROJECT_DIR$/partners.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/prj_common.py" beforeDir="false" afterPath="$PROJECT_DIR$/prj_common.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -457,7 +454,7 @@
<option name="project" value="LOCAL" />
<updated>1747251650255</updated>
</task>
<option name="localTasksCounter" value="576" />
<option name="localTasksCounter" value="577" />
<servers />
</component>
<component name="Vcs.Log.Tabs.Properties">
@ -499,7 +496,6 @@
</option>
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="20/03/2026 - 9h" />
<MESSAGE value="20/03/2026 - 20h" />
<MESSAGE value="23/03/2026 - 20h" />
<MESSAGE value="25/03/2026 - 20h" />
@ -524,6 +520,7 @@
<MESSAGE value="05/05/2026 - 19h" />
<MESSAGE value="07/05/2026 - 17h" />
<MESSAGE value="08/05/2026 - 17h" />
<option name="LAST_COMMIT_MESSAGE" value="08/05/2026 - 17h" />
<MESSAGE value="09/05/2025 - 20h30" />
<option name="LAST_COMMIT_MESSAGE" value="09/05/2025 - 20h30" />
</component>
</project>

File diff suppressed because one or more lines are too long

View File

@ -357,6 +357,27 @@ def Create_Relance_Client_Facture_Given_Client_PDF(diction):
)
"""
Inserter la relantion dans la collection : 'relance_client_invoice'
"""
new_relance_data = {}
new_relance_data['clien_id'] = diction['client_id']
new_relance_data['tab_invoice'] = tab_invoice_a_relancer
new_relance_data['relance_date'] = str(datetime.now().strftime("%d/%m/%Y %H:%M"))
new_relance_data['relance_level'] = str(new_relance_level)
new_relance_data['relance_by'] = str(my_partner['_id'])
new_relance_data['total_reste_to_paye'] = str(total_reste_to_paye)
new_relance_data['partner_owner_recid'] = str(my_partner['recid'])
new_relance_data['update_date'] = str(datetime.now())
new_relance_data['update_by'] = str(my_partner['_id'])
new_relance_data['valide'] = "1"
new_relance_data['locked'] = "0"
MYSY_GV.dbname['relance_client_invoice'].insert_one(new_relance_data)
"""
# Ajout de l'evenement sur la fiche client
"""
@ -456,7 +477,7 @@ def Create_Relance_Client_Facture_Given_Client_Email(tab_files, Folder, diction)
3]) + " Le modèle de courrier 'RELANCE_FACTURE_CLIENT_LEVEL_1' n'est pas correctement configuré ")
return False, " Le modèle de courrier 'RELANCE_FACTURE_CLIENT_LEVEL_1' n'est pas correctement configuré "
print(" IIIIIIIIIIIIIIIIIII courrier_data_retval[_id] = ", str(courrier_data_retval['_id']))
#print(" IIIIIIIIIIIIIIIIIII courrier_data_retval[_id] = ", str(courrier_data_retval['_id']))
"""
Recuperation du dictionnaire des info
"""
@ -843,6 +864,26 @@ def Create_Relance_Client_Facture_Given_Client_Email(tab_files, Folder, diction)
)
"""
Inserter la relantion dans la collection : 'relance_client_invoice'
"""
new_relance_data = {}
new_relance_data['clien_id'] = diction['client_id']
new_relance_data['tab_invoice'] = tab_invoice_a_relancer
new_relance_data['relance_date'] = str(datetime.now().strftime("%d/%m/%Y %H:%M"))
new_relance_data['relance_level'] = str(new_relance_level)
new_relance_data['relance_by'] = str(my_partner['_id'])
new_relance_data['total_reste_to_paye'] = str(total_reste_to_paye)
new_relance_data['partner_owner_recid'] = str(my_partner['recid'])
new_relance_data['update_date'] = str(datetime.now())
new_relance_data['update_by'] = str(my_partner['_id'])
new_relance_data['valide'] = "1"
new_relance_data['locked'] = "0"
MYSY_GV.dbname['relance_client_invoice'].insert_one(new_relance_data)
"""
# Ajout de l'evenement sur la fiche client
"""
@ -870,3 +911,108 @@ def Create_Relance_Client_Facture_Given_Client_Email(tab_files, Folder, diction)
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, " Impossible d'envoyer la relance client par email"
"""
Recuperer la liste des relances avec un filter
"""
def Get_List_Relance_with_filter(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token', 'client_id', 'invoice_id', 'invoice_ref', 'client_info']
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
"""
Filtre général sur le client (raison_sociale, nom, email, telephone
"""
filt_gle_client = {}
tab_client_id = []
if ("client_info" in diction.keys() and diction['client_info']):
local_myquery_gle = {
"partner_owner_recid": str(my_partner['recid']),
"valide": "1",
"locked": "0",
"$or": [
{'raison_sociale': {'$regex': mycommon.regex_replace_cartere(str(diction['client_info'])),
"$options": "i"}},
{'nom': {'$regex': mycommon.regex_replace_cartere(str(diction['client_info'])),
"$options": "i"}},
{'email': {'$regex': mycommon.regex_replace_cartere(str(diction['client_info'])),
"$options": "i"}},
{'telephone': {'$regex': mycommon.regex_replace_cartere(str(diction['client_info'])),
"$options": "i"}},
]
}
for tmp in MYSY_GV.dbname['partner_client'].find(local_myquery_gle):
tab_client_id.append(str(tmp['_id']))
if ("client_id" in diction.keys() and diction['client_id']):
if (diction['client_id'] not in tab_client_id):
tab_client_id.append(str(diction['client_id']))
filt_gle_client = {'client_id': {'$in': tab_client_id}}
filter_invoice_id = {}
if ("invoice_id" in diction.keys() and diction['invoice_id']):
filter_invoice_id = {'tab_invoice.invoice_id': str(diction['invoice_id'])}
filter_invoice_ref = {}
if ("invoice_ref" in diction.keys() and diction['invoice_ref']):
filter_invoice_ref = {'tab_invoice.invoice_header_ref_interne': str(diction['invoice_ref'])}
qery_match = {'$and': [{"partner_owner_recid": str(my_partner['recid']), 'valide': '1',
'locked': '0'},
filter_invoice_id, filter_invoice_ref, filt_gle_client]}
print(" ### relance list : qery_match = ", qery_match)
RetObject = []
val_tmp = 0
for New_retVal in MYSY_GV.dbname['relance_client_invoice'].find(qery_match).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 relances "

60
main.py
View File

@ -1018,12 +1018,39 @@ Cette API met à jour la clé d'insertion d'un nouvel collaborateur
def update_partner_insert_key():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### payload = ",payload)
print(" ### update_partner_insert_key payload = ",payload)
status, retval = pa.update_partner_insert_key(payload)
return jsonify(status=status, message=retval)
"""
Cette API met à jour les données bancaire d'un partenaire
- Banque / Guichet / Compte / Clé / IBAN / BIC
"""
@app.route('/myclass/api/update_partner_bank_data/', methods=['POST','GET'])
@crossdomain(origin='*')
def update_partner_bank_data():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### update_partner_bank_data = ",payload)
status, retval = pa.update_partner_bank_data(payload)
return jsonify(status=status, message=retval)
"""
Cette API permet de recuperer les données bancaire d'un partenaire
- Banque / Guichet / Compte / Clé / IBAN / BIC
"""
@app.route('/myclass/api/Get_Partner_bank_data/', methods=['POST','GET'])
@crossdomain(origin='*')
def Get_Partner_bank_data():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Get_Partner_bank_data = ",payload)
status, retval = pa.Get_Partner_bank_data(payload)
return jsonify(status=status, message=retval)
'''
Cette fonction recupere les données d'un partenaire
@ -1397,6 +1424,23 @@ def partner_login():
return jsonify(status=status, message=retval)
'''
Cette API gere la deconnexion d'un utilisateur
'''
@app.route('/myclass/api/partner_logout/', methods=['POST','GET'])
@crossdomain(origin='*')
def partner_logout():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### partner_logout payload = ",payload)
print(request.files)
status, retval = pa.partner_logout(payload)
return jsonify(status=status, message=retval)
'''
Cette API récupérer tous les articles PUBLIE (c'est a dire que :
- valide = 1,
@ -17801,6 +17845,20 @@ def Create_Relance_Client_Facture_Given_Client_Email():
return jsonify(status=status, message=retval)
"""
API pour recuperer la liste des relances client sur les factures
"""
@app.route('/myclass/api/Get_List_Relance_with_filter/', methods=['POST','GET'])
@crossdomain(origin='*')
def Get_List_Relance_with_filter():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Get_List_Relance_with_filter payload = ",payload)
status, retval = Relance_client_facture.Get_List_Relance_with_filter(payload)
return jsonify(status=status, message=retval)
if __name__ == '__main__':
print(" debut api")

View File

@ -610,6 +610,182 @@ def update_partner_insert_key(diction):
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, "Impossible de mettre à jour la clé d'insertion "
"""
Cette fonction permet de mettre à jour les données bancaire d'un partenaire
- Banque / Guichet / Compte / Clé / IBAN / BIC
"""
def update_partner_bank_data(diction):
try:
# Dictionnaire des champs utilisables
'''
# Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
# Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
# Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
# field_list.
'''
field_list = ['token', 'code_banque', 'code_guichet', 'compte_bancaire', 'code_cle',
'code_iban', 'code_bic']
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, " Le champ '" + val + "' n'est pas accepté "
'''
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
'''
field_list_obligatoire = ['token', 'code_iban', 'code_bic']
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 "
# Recuperation du recid du partner
mydata = {}
mytoken = ""
if ("token" in diction.keys()):
if diction['token']:
mytoken = diction['token']
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data({'token':mytoken})
if (local_status is not True):
return local_status, my_partner
code_banque=""
if ("code_banque" in diction.keys()):
if diction['code_banque']:
code_banque = diction['code_banque']
mydata['code_banque'] = code_banque
code_guichet = ""
if ("code_guichet" in diction.keys()):
if diction['code_guichet']:
code_guichet = diction['code_guichet']
mydata['code_guichet'] = code_guichet
compte_bancaire = ""
if ("compte_bancaire" in diction.keys()):
if diction['compte_bancaire']:
compte_bancaire = diction['compte_bancaire']
mydata['compte_bancaire'] = compte_bancaire
code_cle = ""
if ("code_cle" in diction.keys()):
if diction['code_cle']:
code_cle = diction['code_cle']
mydata['code_cle'] = code_cle
code_iban = ""
if ("code_iban" in diction.keys()):
if diction['code_iban']:
code_iban = diction['code_iban']
mydata['code_iban'] = code_iban
code_bic = ""
if ("code_bic" in diction.keys()):
if diction['code_bic']:
code_bic = diction['code_bic']
mydata['code_bic'] = code_bic
mydata['update_date'] = str(datetime.now())
mydata['update_by'] = str(my_partner['_id'])
mydata['valide'] = "1"
mydata['locked'] = "0"
#print(mydata)
coll_name = MYSY_GV.dbname['partnair_account_bank']
ret_val = coll_name.find_one_and_update(
{ 'partner_owner_recid':str(my_partner['recid'])},
{"$set": mydata},
upsert=True,
return_document=ReturnDocument.AFTER
)
if (ret_val and ret_val['_id']):
mycommon.myprint(str(inspect.stack()[0][3]) + "Les données bancaires ont bien été mise à jour =" + str(ret_val['_id']))
return True, "Les données bancaires ont bien été mise à jour"
else:
mycommon.myprint(str(inspect.stack()[0][3]) + " - Impossible de mettre à jour la clé d'insertion du partenaire recid= : " )
return False, " Impossible de mettre à jour les données bancaire (2) "
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 mettre à jour les données bancaire "
"""
Cette fonction permet de recuperer les données bancaire d'un partenaire
"""
def Get_Partner_bank_data(diction):
try:
diction = mycommon.strip_dictionary(diction)
"""
Verification des input acceptés
"""
field_list = ['token']
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
RetObject = []
val_tmp = 1
for retval in MYSY_GV.dbname['partnair_account_bank'].find({'partner_owner_recid':str(my_partner['recid'])}):
user = retval
user['id'] = str(val_tmp)
val_tmp = val_tmp + 1
RetObject.append(mycommon.JSONEncoder().encode(user))
return True, RetObject
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de récupérer les données bancaires "
'''
@ -3113,3 +3289,64 @@ def Change_PF_partner_account_Type_Licence_from_id(diction):
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de changer le type de licence de ce compte "
"""
Cette fonction permet de connecter proprement un utilisateur.
En gros, la fonction va mettre à jour la collection : partner_token
en mettant le :
- end_date et
- valide a 0
"""
def partner_logout(diction):
try:
# Dictionnaire des champs utilisables
field_list = ['token', ]
incom_keys = diction.keys()
'''
# Verification que les champs reçus dans l'API sont bien dans la liste des champs autorisés
# Cela evite le cas ou une entité tierce ajouter les valeurs inconnu dans l'API
# Ici on doit mettre tous les champs possible (obligatoire ou non) de la BDD dans la liste
# field_list.
'''
for val in incom_keys:
if str(val).lower() not in str(field_list).lower():
mycommon.myprint(str(inspect.stack()[0][3]) + " Le champ '" + val + "' n'est pas accepté dans cette API")
return False, str(inspect.stack()[0][3]) + " Toutes les informations obligatoires ne sont pas fournies"
'''
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
'''
field_list_obligatoire = ['token', ]
for val in field_list_obligatoire:
if str(val).lower() not in diction:
mycommon.myprint(str(inspect.stack()[0][3]) + " La valeur '" + val + "' n'est pas presente dans la liste des arguments des champs")
return False, str(inspect.stack()[0][3]) + " Toutes les informations obligatoires ne sont pas fournies (2) "
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
if (local_status is not True):
return local_status, my_partner
# A ce niveau le login et passe sont ok.
# il faut donc créer le token et renvoyer le token.
my_token = mycommon.create_token_urlsafe()
# 1 - Vu le login et passe sont valident, alors on va aller desactier un eventuel token qui existerait
local_now = str(datetime.now())
local_result = MYSY_GV.dbname['partner_token'].update_many(
{'valide': '1', 'partner_account_id':str(my_partner['_id'])},
{
"$set": {"valide": '0', 'end_date': str(datetime.now()), 'date_update': str(datetime.now())}
})
return True, "Logout OK"
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 vous déconnecter au système. Merci de contacter votre administrateur "

View File

@ -4619,7 +4619,7 @@ Cette fonction retour un json de ce type :
convention_dictionnary_data =
{
{'connected_user_data':{'email':'toto@.fr', 'contact_nom':'balde'}}
{'company_data':{'num_nda':'1234', 'website':'www.ssds.fr', 'logo':'mylogo', 'cachet':'my_cache'}
{'company_data':{'num_nda':'1234', 'website':'www.ssds.fr', 'logo':'mylogo', 'cachet':'my_cache', 'bank_iban':'xx', ...}
{'class_data':{....}}
{'list_session_data':{....}}
{'list_stagiaire_data':[{...}]}
@ -4744,6 +4744,44 @@ def Get_Dictionnary_data_For_Template(diction):
company_data.update(new_field_cachet)
"""
Recuperer les données bancaire
"""
bank_data_node = {}
for bank_data in MYSY_GV.dbname['partnair_account_bank'].find({'partner_owner_recid': str(my_partner['recid'])}):
if( "code_banque" in bank_data.keys()):
bank_data_node['bank_code_banque'] = bank_data['code_banque']
else:
bank_data_node['bank_code_banque'] = ""
if ("code_guichet" in bank_data.keys()):
bank_data_node['bank_code_guichet'] = bank_data['code_guichet']
else:
bank_data_node['bank_code_guichet'] = ""
if ("compte_bancaire" in bank_data.keys()):
bank_data_node['bank_compte_bancaire'] = bank_data['compte_bancaire']
else:
bank_data_node['bank_compte_bancaire'] = ""
if ("code_cle" in bank_data.keys()):
bank_data_node['bank_code_cle'] = bank_data['code_cle']
else:
bank_data_node['bank_code_cle'] = ""
if ("code_iban" in bank_data.keys()):
bank_data_node['bank_code_iban'] = bank_data['code_iban']
else:
bank_data_node['bank_code_iban'] = ""
if ("code_bic" in bank_data.keys()):
bank_data_node['bank_code_bic'] = bank_data['code_bic']
else:
bank_data_node['bank_code_bic'] = ""
company_data['bank_data'] = bank_data_node
dictionnary_data['company_data'] = company_data
"""