Added commercial on tiers retrieving method

This commit is contained in:
fanilo 2026-01-05 08:40:05 +01:00
parent ea344b2669
commit 6a346876aa
5 changed files with 281 additions and 625 deletions

View file

@ -76,7 +76,7 @@ from utils.documents.devis.devis_check import (
) )
from utils.tiers.contacts.contacts import ( from utils.tiers.contacts.contacts import (
_get_contacts_client, _get_contacts,
_chercher_contact_en_base, _chercher_contact_en_base,
_lire_contact_depuis_base, _lire_contact_depuis_base,
) )
@ -199,220 +199,54 @@ class SageConnector:
pass pass
def lister_tous_fournisseurs(self, filtre=""): def lister_tous_fournisseurs(self, filtre=""):
"""Liste tous les fournisseurs avec leur commercial"""
try: try:
with self._get_sql_connection() as conn: with self._get_sql_connection() as conn:
cursor = conn.cursor() cursor = conn.cursor()
query = """ query = _build_tiers_select_query()
SELECT query += """
-- IDENTIFICATION (9) FROM F_COMPTET t
CT_Num, CT_Intitule, CT_Type, CT_Qualite, LEFT JOIN F_COLLABORATEUR c ON t.CO_No = c.CO_No
CT_Classement, CT_Raccourci, CT_Siret, CT_Identifiant, WHERE t.CT_Type = 1
CT_Ape,
-- ADRESSE (7)
CT_Contact, CT_Adresse, CT_Complement,
CT_CodePostal, CT_Ville, CT_CodeRegion, CT_Pays,
-- TELECOM (6)
CT_Telephone, CT_Telecopie, CT_EMail, CT_Site,
CT_Facebook, CT_LinkedIn,
-- TAUX (4)
CT_Taux01, CT_Taux02, CT_Taux03, CT_Taux04,
-- STATISTIQUES (10)
CT_Statistique01, CT_Statistique02, CT_Statistique03,
CT_Statistique04, CT_Statistique05, CT_Statistique06,
CT_Statistique07, CT_Statistique08, CT_Statistique09,
CT_Statistique10,
-- COMMERCIAL (4)
CT_Encours, CT_Assurance, CT_Langue, CO_No,
-- FACTURATION (11)
CT_Lettrage, CT_Sommeil, CT_Facture, CT_Prospect,
CT_BLFact, CT_Saut, CT_ValidEch, CT_ControlEnc,
CT_NotRappel, CT_NotPenal, CT_BonAPayer,
-- LOGISTIQUE (4)
CT_PrioriteLivr, CT_LivrPartielle,
CT_DelaiTransport, CT_DelaiAppro,
-- COMMENTAIRE (1)
CT_Commentaire,
-- ANALYTIQUE (1)
CA_Num,
-- ORGANISATION / SURVEILLANCE (10)
MR_No, CT_Surveillance, CT_Coface,
CT_SvFormeJuri, CT_SvEffectif, CT_SvRegul,
CT_SvCotation, CT_SvObjetMaj, CT_SvCA, CT_SvResultat,
-- COMPTE GENERAL ET CATEGORIES (3)
CG_NumPrinc, N_CatTarif, N_CatCompta
FROM F_COMPTET
WHERE CT_Type = 1
""" """
params = [] params = []
if filtre: if filtre:
query += " AND (CT_Num LIKE ? OR CT_Intitule LIKE ?)" query += " AND (t.CT_Num LIKE ? OR t.CT_Intitule LIKE ?)"
params.extend([f"%{filtre}%", f"%{filtre}%"]) params.extend([f"%{filtre}%", f"%{filtre}%"])
query += " ORDER BY CT_Intitule" query += " ORDER BY t.CT_Intitule"
cursor.execute(query, params) cursor.execute(query, params)
rows = cursor.fetchall() rows = cursor.fetchall()
fournisseurs = [] fournisseurs = []
for row in rows: for row in rows:
fournisseur = { fournisseur = _row_to_tiers_dict(row)
"numero": _safe_strip(row.CT_Num), fournisseur["contacts"] = _get_contacts(row.CT_Num, conn)
"intitule": _safe_strip(row.CT_Intitule),
"type_tiers": row.CT_Type,
"qualite": _safe_strip(row.CT_Qualite),
"classement": _safe_strip(row.CT_Classement),
"raccourci": _safe_strip(row.CT_Raccourci),
"siret": _safe_strip(row.CT_Siret),
"tva_intra": _safe_strip(row.CT_Identifiant),
"code_naf": _safe_strip(row.CT_Ape),
"contact": _safe_strip(row.CT_Contact),
"adresse": _safe_strip(row.CT_Adresse),
"complement": _safe_strip(row.CT_Complement),
"code_postal": _safe_strip(row.CT_CodePostal),
"ville": _safe_strip(row.CT_Ville),
"region": _safe_strip(row.CT_CodeRegion),
"pays": _safe_strip(row.CT_Pays),
"telephone": _safe_strip(row.CT_Telephone),
"telecopie": _safe_strip(row.CT_Telecopie),
"email": _safe_strip(row.CT_EMail),
"site_web": _safe_strip(row.CT_Site),
"facebook": _safe_strip(row.CT_Facebook),
"linkedin": _safe_strip(row.CT_LinkedIn),
"taux01": row.CT_Taux01,
"taux02": row.CT_Taux02,
"taux03": row.CT_Taux03,
"taux04": row.CT_Taux04,
"statistique01": _safe_strip(row.CT_Statistique01),
"statistique02": _safe_strip(row.CT_Statistique02),
"statistique03": _safe_strip(row.CT_Statistique03),
"statistique04": _safe_strip(row.CT_Statistique04),
"statistique05": _safe_strip(row.CT_Statistique05),
"statistique06": _safe_strip(row.CT_Statistique06),
"statistique07": _safe_strip(row.CT_Statistique07),
"statistique08": _safe_strip(row.CT_Statistique08),
"statistique09": _safe_strip(row.CT_Statistique09),
"statistique10": _safe_strip(row.CT_Statistique10),
"encours_autorise": row.CT_Encours,
"assurance_credit": row.CT_Assurance,
"langue": row.CT_Langue,
"commercial_code": row.CO_No,
"lettrage_auto": (row.CT_Lettrage == 1),
"est_actif": (row.CT_Sommeil == 0),
"type_facture": row.CT_Facture,
"est_prospect": (row.CT_Prospect == 1),
"bl_en_facture": row.CT_BLFact,
"saut_page": row.CT_Saut,
"validation_echeance": row.CT_ValidEch,
"controle_encours": row.CT_ControlEnc,
"exclure_relance": (row.CT_NotRappel == 1),
"exclure_penalites": (row.CT_NotPenal == 1),
"bon_a_payer": row.CT_BonAPayer,
"priorite_livraison": row.CT_PrioriteLivr,
"livraison_partielle": row.CT_LivrPartielle,
"delai_transport": row.CT_DelaiTransport,
"delai_appro": row.CT_DelaiAppro,
"commentaire": _safe_strip(row.CT_Commentaire),
"section_analytique": _safe_strip(row.CA_Num),
"mode_reglement_code": row.MR_No,
"surveillance_active": (row.CT_Surveillance == 1),
"coface": _safe_strip(row.CT_Coface),
"forme_juridique": _safe_strip(row.CT_SvFormeJuri),
"effectif": _safe_strip(row.CT_SvEffectif),
"sv_regularite": _safe_strip(row.CT_SvRegul),
"sv_cotation": _safe_strip(row.CT_SvCotation),
"sv_objet_maj": _safe_strip(row.CT_SvObjetMaj),
"sv_chiffre_affaires": row.CT_SvCA,
"sv_resultat": row.CT_SvResultat,
"compte_general": _safe_strip(row.CG_NumPrinc),
"categorie_tarif": row.N_CatTarif,
"categorie_compta": row.N_CatCompta,
}
fournisseur["contacts"] = _get_contacts_client(row.CT_Num, conn)
fournisseurs.append(fournisseur) fournisseurs.append(fournisseur)
logger.info( logger.info(
f" SQL: {len(fournisseurs)} fournisseurs avec {len(fournisseur)} champs" f"✓ SQL: {len(fournisseurs)} fournisseurs avec {len(fournisseur)} champs"
) )
return fournisseurs return fournisseurs
except Exception as e: except Exception as e:
logger.error(f" Erreur SQL fournisseurs: {e}") logger.error(f"✗ Erreur SQL fournisseurs: {e}")
raise RuntimeError(f"Erreur lecture fournisseurs: {str(e)}") raise RuntimeError(f"Erreur lecture fournisseurs: {str(e)}")
def lire_fournisseur(self, code_fournisseur): def lire_fournisseur(self, code_fournisseur):
"""Lit un fournisseur avec son commercial"""
try: try:
with self._get_sql_connection() as conn: with self._get_sql_connection() as conn:
cursor = conn.cursor() cursor = conn.cursor()
query = """ query = _build_tiers_select_query()
SELECT query += """
-- IDENTIFICATION (9) FROM F_COMPTET t
CT_Num, CT_Intitule, CT_Type, CT_Qualite, LEFT JOIN F_COLLABORATEUR c ON t.CO_No = c.CO_No
CT_Classement, CT_Raccourci, CT_Siret, CT_Identifiant, WHERE t.CT_Num = ? AND t.CT_Type = 1
CT_Ape,
-- ADRESSE (7)
CT_Contact, CT_Adresse, CT_Complement,
CT_CodePostal, CT_Ville, CT_CodeRegion, CT_Pays,
-- TELECOM (6)
CT_Telephone, CT_Telecopie, CT_EMail, CT_Site,
CT_Facebook, CT_LinkedIn,
-- TAUX (4)
CT_Taux01, CT_Taux02, CT_Taux03, CT_Taux04,
-- STATISTIQUES (10)
CT_Statistique01, CT_Statistique02, CT_Statistique03,
CT_Statistique04, CT_Statistique05, CT_Statistique06,
CT_Statistique07, CT_Statistique08, CT_Statistique09,
CT_Statistique10,
-- COMMERCIAL (4)
CT_Encours, CT_Assurance, CT_Langue, CO_No,
-- FACTURATION (11)
CT_Lettrage, CT_Sommeil, CT_Facture, CT_Prospect,
CT_BLFact, CT_Saut, CT_ValidEch, CT_ControlEnc,
CT_NotRappel, CT_NotPenal, CT_BonAPayer,
-- LOGISTIQUE (4)
CT_PrioriteLivr, CT_LivrPartielle,
CT_DelaiTransport, CT_DelaiAppro,
-- COMMENTAIRE (1)
CT_Commentaire,
-- ANALYTIQUE (1)
CA_Num,
-- ORGANISATION / SURVEILLANCE (10)
MR_No, CT_Surveillance, CT_Coface,
CT_SvFormeJuri, CT_SvEffectif, CT_SvRegul,
CT_SvCotation, CT_SvObjetMaj, CT_SvCA, CT_SvResultat,
-- COMPTE GENERAL ET CATEGORIES (3)
CG_NumPrinc, N_CatTarif, N_CatCompta
FROM F_COMPTET
WHERE CT_Num = ? AND CT_Type = 1
""" """
cursor.execute(query, (code_fournisseur.upper(),)) cursor.execute(query, (code_fournisseur.upper(),))
@ -421,88 +255,16 @@ class SageConnector:
if not row: if not row:
return None return None
fournisseur = { fournisseur = _row_to_tiers_dict(row)
"numero": _safe_strip(row.CT_Num), fournisseur["contacts"] = _get_contacts(row.CT_Num, conn)
"intitule": _safe_strip(row.CT_Intitule),
"type_tiers": row.CT_Type,
"qualite": _safe_strip(row.CT_Qualite),
"classement": _safe_strip(row.CT_Classement),
"raccourci": _safe_strip(row.CT_Raccourci),
"siret": _safe_strip(row.CT_Siret),
"tva_intra": _safe_strip(row.CT_Identifiant),
"code_naf": _safe_strip(row.CT_Ape),
"contact": _safe_strip(row.CT_Contact),
"adresse": _safe_strip(row.CT_Adresse),
"complement": _safe_strip(row.CT_Complement),
"code_postal": _safe_strip(row.CT_CodePostal),
"ville": _safe_strip(row.CT_Ville),
"region": _safe_strip(row.CT_CodeRegion),
"pays": _safe_strip(row.CT_Pays),
"telephone": _safe_strip(row.CT_Telephone),
"telecopie": _safe_strip(row.CT_Telecopie),
"email": _safe_strip(row.CT_EMail),
"site_web": _safe_strip(row.CT_Site),
"facebook": _safe_strip(row.CT_Facebook),
"linkedin": _safe_strip(row.CT_LinkedIn),
"taux01": row.CT_Taux01,
"taux02": row.CT_Taux02,
"taux03": row.CT_Taux03,
"taux04": row.CT_Taux04,
"statistique01": _safe_strip(row.CT_Statistique01),
"statistique02": _safe_strip(row.CT_Statistique02),
"statistique03": _safe_strip(row.CT_Statistique03),
"statistique04": _safe_strip(row.CT_Statistique04),
"statistique05": _safe_strip(row.CT_Statistique05),
"statistique06": _safe_strip(row.CT_Statistique06),
"statistique07": _safe_strip(row.CT_Statistique07),
"statistique08": _safe_strip(row.CT_Statistique08),
"statistique09": _safe_strip(row.CT_Statistique09),
"statistique10": _safe_strip(row.CT_Statistique10),
"encours_autorise": row.CT_Encours,
"assurance_credit": row.CT_Assurance,
"langue": row.CT_Langue,
"commercial_code": row.CO_No,
"lettrage_auto": (row.CT_Lettrage == 1),
"est_actif": (row.CT_Sommeil == 0),
"type_facture": row.CT_Facture,
"est_prospect": (row.CT_Prospect == 1),
"bl_en_facture": row.CT_BLFact,
"saut_page": row.CT_Saut,
"validation_echeance": row.CT_ValidEch,
"controle_encours": row.CT_ControlEnc,
"exclure_relance": (row.CT_NotRappel == 1),
"exclure_penalites": (row.CT_NotPenal == 1),
"bon_a_payer": row.CT_BonAPayer,
"priorite_livraison": row.CT_PrioriteLivr,
"livraison_partielle": row.CT_LivrPartielle,
"delai_transport": row.CT_DelaiTransport,
"delai_appro": row.CT_DelaiAppro,
"commentaire": _safe_strip(row.CT_Commentaire),
"section_analytique": _safe_strip(row.CA_Num),
"mode_reglement_code": row.MR_No,
"surveillance_active": (row.CT_Surveillance == 1),
"coface": _safe_strip(row.CT_Coface),
"forme_juridique": _safe_strip(row.CT_SvFormeJuri),
"effectif": _safe_strip(row.CT_SvEffectif),
"sv_regularite": _safe_strip(row.CT_SvRegul),
"sv_cotation": _safe_strip(row.CT_SvCotation),
"sv_objet_maj": _safe_strip(row.CT_SvObjetMaj),
"sv_chiffre_affaires": row.CT_SvCA,
"sv_resultat": row.CT_SvResultat,
"compte_general": _safe_strip(row.CG_NumPrinc),
"categorie_tarif": row.N_CatTarif,
"categorie_compta": row.N_CatCompta,
}
fournisseur["contacts"] = _get_contacts_client(row.CT_Num, conn)
logger.info( logger.info(
f" SQL: Fournisseur {code_fournisseur} avec {len(fournisseur)} champs" f"✓ SQL: Fournisseur {code_fournisseur} avec {len(fournisseur)} champs"
) )
return fournisseur return fournisseur
except Exception as e: except Exception as e:
logger.error(f" Erreur SQL fournisseur {code_fournisseur}: {e}") logger.error(f"✗ Erreur SQL fournisseur {code_fournisseur}: {e}")
return None return None
def creer_fournisseur(self, fournisseur_data: Dict) -> Dict: def creer_fournisseur(self, fournisseur_data: Dict) -> Dict:
@ -951,226 +713,52 @@ class SageConnector:
raise RuntimeError(f"Erreur technique Sage: {error_message}") raise RuntimeError(f"Erreur technique Sage: {error_message}")
def lister_tous_clients(self, filtre=""): def lister_tous_clients(self, filtre=""):
""" """Liste tous les clients avec leur commercial"""
Liste tous les clients avec TOUS les champs gérés par creer_client
Symétrie complète GET/POST
"""
try: try:
with self._get_sql_connection() as conn: with self._get_sql_connection() as conn:
cursor = conn.cursor() cursor = conn.cursor()
query = """ query = _build_tiers_select_query()
SELECT query += """
-- IDENTIFICATION (8) FROM F_COMPTET t
CT_Num, CT_Intitule, CT_Type, CT_Qualite, LEFT JOIN F_COLLABORATEUR c ON t.CO_No = c.CO_No
CT_Classement, CT_Raccourci, CT_Siret, CT_Identifiant, WHERE t.CT_Type = 0
CT_Ape,
-- ADRESSE (7)
CT_Contact, CT_Adresse, CT_Complement,
CT_CodePostal, CT_Ville, CT_CodeRegion, CT_Pays,
-- TELECOM (7)
CT_Telephone, CT_Telecopie, CT_EMail, CT_Site,
CT_Facebook, CT_LinkedIn,
-- TAUX (4)
CT_Taux01, CT_Taux02, CT_Taux03, CT_Taux04,
-- STATISTIQUES (10)
CT_Statistique01, CT_Statistique02, CT_Statistique03,
CT_Statistique04, CT_Statistique05, CT_Statistique06,
CT_Statistique07, CT_Statistique08, CT_Statistique09,
CT_Statistique10,
-- COMMERCIAL (4)
CT_Encours, CT_Assurance, CT_Langue, CO_No,
-- FACTURATION (11)
CT_Lettrage, CT_Sommeil, CT_Facture, CT_Prospect,
CT_BLFact, CT_Saut, CT_ValidEch, CT_ControlEnc,
CT_NotRappel, CT_NotPenal, CT_BonAPayer,
-- LOGISTIQUE (4)
CT_PrioriteLivr, CT_LivrPartielle,
CT_DelaiTransport, CT_DelaiAppro,
-- COMMENTAIRE (1)
CT_Commentaire,
-- ANALYTIQUE (1)
CA_Num,
-- ORGANISATION / SURVEILLANCE (10)
MR_No, CT_Surveillance, CT_Coface,
CT_SvFormeJuri, CT_SvEffectif, CT_SvRegul,
CT_SvCotation, CT_SvObjetMaj, CT_SvCA, CT_SvResultat,
-- COMPTE GENERAL ET CATEGORIES (3)
CG_NumPrinc, N_CatTarif, N_CatCompta
FROM F_COMPTET
WHERE CT_Type = 0
""" """
params = [] params = []
if filtre: if filtre:
query += " AND (CT_Num LIKE ? OR CT_Intitule LIKE ?)" query += " AND (t.CT_Num LIKE ? OR t.CT_Intitule LIKE ?)"
params.extend([f"%{filtre}%", f"%{filtre}%"]) params.extend([f"%{filtre}%", f"%{filtre}%"])
query += " ORDER BY CT_Intitule" query += " ORDER BY t.CT_Intitule"
cursor.execute(query, params) cursor.execute(query, params)
rows = cursor.fetchall() rows = cursor.fetchall()
clients = [] clients = []
for row in rows: for row in rows:
client = { client = _row_to_tiers_dict(row)
"numero": _safe_strip(row.CT_Num), client["contacts"] = _get_contacts(row.CT_Num, conn)
"intitule": _safe_strip(row.CT_Intitule),
"type_tiers": row.CT_Type,
"qualite": _safe_strip(row.CT_Qualite),
"classement": _safe_strip(row.CT_Classement),
"raccourci": _safe_strip(row.CT_Raccourci),
"siret": _safe_strip(row.CT_Siret),
"tva_intra": _safe_strip(row.CT_Identifiant),
"code_naf": _safe_strip(row.CT_Ape),
"contact": _safe_strip(row.CT_Contact),
"adresse": _safe_strip(row.CT_Adresse),
"complement": _safe_strip(row.CT_Complement),
"code_postal": _safe_strip(row.CT_CodePostal),
"ville": _safe_strip(row.CT_Ville),
"region": _safe_strip(row.CT_CodeRegion),
"pays": _safe_strip(row.CT_Pays),
"telephone": _safe_strip(row.CT_Telephone),
"telecopie": _safe_strip(row.CT_Telecopie),
"email": _safe_strip(row.CT_EMail),
"site_web": _safe_strip(row.CT_Site),
"facebook": _safe_strip(row.CT_Facebook),
"linkedin": _safe_strip(row.CT_LinkedIn),
"taux01": row.CT_Taux01,
"taux02": row.CT_Taux02,
"taux03": row.CT_Taux03,
"taux04": row.CT_Taux04,
"statistique01": _safe_strip(row.CT_Statistique01),
"statistique02": _safe_strip(row.CT_Statistique02),
"statistique03": _safe_strip(row.CT_Statistique03),
"statistique04": _safe_strip(row.CT_Statistique04),
"statistique05": _safe_strip(row.CT_Statistique05),
"statistique06": _safe_strip(row.CT_Statistique06),
"statistique07": _safe_strip(row.CT_Statistique07),
"statistique08": _safe_strip(row.CT_Statistique08),
"statistique09": _safe_strip(row.CT_Statistique09),
"statistique10": _safe_strip(row.CT_Statistique10),
"encours_autorise": row.CT_Encours,
"assurance_credit": row.CT_Assurance,
"langue": row.CT_Langue,
"commercial_code": row.CO_No,
"lettrage_auto": (row.CT_Lettrage == 1),
"est_actif": (row.CT_Sommeil == 0),
"type_facture": row.CT_Facture,
"est_prospect": (row.CT_Prospect == 1),
"bl_en_facture": row.CT_BLFact,
"saut_page": row.CT_Saut,
"validation_echeance": row.CT_ValidEch,
"controle_encours": row.CT_ControlEnc,
"exclure_relance": (row.CT_NotRappel == 1),
"exclure_penalites": (row.CT_NotPenal == 1),
"bon_a_payer": row.CT_BonAPayer,
"priorite_livraison": row.CT_PrioriteLivr,
"livraison_partielle": row.CT_LivrPartielle,
"delai_transport": row.CT_DelaiTransport,
"delai_appro": row.CT_DelaiAppro,
"commentaire": _safe_strip(row.CT_Commentaire),
"section_analytique": _safe_strip(row.CA_Num),
"mode_reglement_code": row.MR_No,
"surveillance_active": (row.CT_Surveillance == 1),
"coface": _safe_strip(row.CT_Coface),
"forme_juridique": _safe_strip(row.CT_SvFormeJuri),
"effectif": _safe_strip(row.CT_SvEffectif),
"sv_regularite": _safe_strip(row.CT_SvRegul),
"sv_cotation": _safe_strip(row.CT_SvCotation),
"sv_objet_maj": _safe_strip(row.CT_SvObjetMaj),
"sv_chiffre_affaires": row.CT_SvCA,
"sv_resultat": row.CT_SvResultat,
"compte_general": _safe_strip(row.CG_NumPrinc),
"categorie_tarif": row.N_CatTarif,
"categorie_compta": row.N_CatCompta,
}
client["contacts"] = _get_contacts_client(row.CT_Num, conn)
clients.append(client) clients.append(client)
logger.info(f" SQL: {len(clients)} clients avec {len(client)} champs") logger.info(f"✓ SQL: {len(clients)} clients avec {len(client)} champs")
return clients return clients
except Exception as e: except Exception as e:
logger.error(f" Erreur SQL clients: {e}") logger.error(f"✗ Erreur SQL clients: {e}")
raise RuntimeError(f"Erreur lecture clients: {str(e)}") raise RuntimeError(f"Erreur lecture clients: {str(e)}")
def lire_client(self, code_client): def lire_client(self, code_client):
""" """Lit un client avec son commercial"""
Lit un client avec TOUS les champs (identique à lister_tous_clients)
Symétrie complète GET/POST
"""
try: try:
with self._get_sql_connection() as conn: with self._get_sql_connection() as conn:
cursor = conn.cursor() cursor = conn.cursor()
query = """ query = _build_tiers_select_query()
SELECT query += """
-- IDENTIFICATION (8) FROM F_COMPTET t
CT_Num, CT_Intitule, CT_Type, CT_Qualite, LEFT JOIN F_COLLABORATEUR c ON t.CO_No = c.CO_No
CT_Classement, CT_Raccourci, CT_Siret, CT_Identifiant, WHERE t.CT_Num = ? AND t.CT_Type = 0
CT_Ape,
-- ADRESSE (7)
CT_Contact, CT_Adresse, CT_Complement,
CT_CodePostal, CT_Ville, CT_CodeRegion, CT_Pays,
-- TELECOM (7)
CT_Telephone, CT_Telecopie, CT_EMail, CT_Site,
CT_Facebook, CT_LinkedIn,
-- TAUX (4)
CT_Taux01, CT_Taux02, CT_Taux03, CT_Taux04,
-- STATISTIQUES (10)
CT_Statistique01, CT_Statistique02, CT_Statistique03,
CT_Statistique04, CT_Statistique05, CT_Statistique06,
CT_Statistique07, CT_Statistique08, CT_Statistique09,
CT_Statistique10,
-- COMMERCIAL (4)
CT_Encours, CT_Assurance, CT_Langue, CO_No,
-- FACTURATION (11)
CT_Lettrage, CT_Sommeil, CT_Facture, CT_Prospect,
CT_BLFact, CT_Saut, CT_ValidEch, CT_ControlEnc,
CT_NotRappel, CT_NotPenal, CT_BonAPayer,
-- LOGISTIQUE (4)
CT_PrioriteLivr, CT_LivrPartielle,
CT_DelaiTransport, CT_DelaiAppro,
-- COMMENTAIRE (1)
CT_Commentaire,
-- ANALYTIQUE (1)
CA_Num,
-- ORGANISATION / SURVEILLANCE (10)
MR_No, CT_Surveillance, CT_Coface,
CT_SvFormeJuri, CT_SvEffectif, CT_SvRegul,
CT_SvCotation, CT_SvObjetMaj, CT_SvCA, CT_SvResultat,
-- COMPTE GENERAL ET CATEGORIES (3)
CG_NumPrinc, N_CatTarif, N_CatCompta
FROM F_COMPTET
WHERE CT_Num = ? AND CT_Type = 0
""" """
cursor.execute(query, (code_client.upper(),)) cursor.execute(query, (code_client.upper(),))
@ -1179,86 +767,14 @@ class SageConnector:
if not row: if not row:
return None return None
client = { client = _row_to_tiers_dict(row)
"numero": _safe_strip(row.CT_Num), client["contacts"] = _get_contacts(row.CT_Num, conn)
"intitule": _safe_strip(row.CT_Intitule),
"type_tiers": row.CT_Type,
"qualite": _safe_strip(row.CT_Qualite),
"classement": _safe_strip(row.CT_Classement),
"raccourci": _safe_strip(row.CT_Raccourci),
"siret": _safe_strip(row.CT_Siret),
"tva_intra": _safe_strip(row.CT_Identifiant),
"code_naf": _safe_strip(row.CT_Ape),
"contact": _safe_strip(row.CT_Contact),
"adresse": _safe_strip(row.CT_Adresse),
"complement": _safe_strip(row.CT_Complement),
"code_postal": _safe_strip(row.CT_CodePostal),
"ville": _safe_strip(row.CT_Ville),
"region": _safe_strip(row.CT_CodeRegion),
"pays": _safe_strip(row.CT_Pays),
"telephone": _safe_strip(row.CT_Telephone),
"telecopie": _safe_strip(row.CT_Telecopie),
"email": _safe_strip(row.CT_EMail),
"site_web": _safe_strip(row.CT_Site),
"facebook": _safe_strip(row.CT_Facebook),
"linkedin": _safe_strip(row.CT_LinkedIn),
"taux01": row.CT_Taux01,
"taux02": row.CT_Taux02,
"taux03": row.CT_Taux03,
"taux04": row.CT_Taux04,
"statistique01": _safe_strip(row.CT_Statistique01),
"statistique02": _safe_strip(row.CT_Statistique02),
"statistique03": _safe_strip(row.CT_Statistique03),
"statistique04": _safe_strip(row.CT_Statistique04),
"statistique05": _safe_strip(row.CT_Statistique05),
"statistique06": _safe_strip(row.CT_Statistique06),
"statistique07": _safe_strip(row.CT_Statistique07),
"statistique08": _safe_strip(row.CT_Statistique08),
"statistique09": _safe_strip(row.CT_Statistique09),
"statistique10": _safe_strip(row.CT_Statistique10),
"encours_autorise": row.CT_Encours,
"assurance_credit": row.CT_Assurance,
"langue": row.CT_Langue,
"commercial_code": row.CO_No,
"lettrage_auto": (row.CT_Lettrage == 1),
"est_actif": (row.CT_Sommeil == 0),
"type_facture": row.CT_Facture,
"est_prospect": (row.CT_Prospect == 1),
"bl_en_facture": row.CT_BLFact,
"saut_page": row.CT_Saut,
"validation_echeance": row.CT_ValidEch,
"controle_encours": row.CT_ControlEnc,
"exclure_relance": (row.CT_NotRappel == 1),
"exclure_penalites": (row.CT_NotPenal == 1),
"bon_a_payer": row.CT_BonAPayer,
"priorite_livraison": row.CT_PrioriteLivr,
"livraison_partielle": row.CT_LivrPartielle,
"delai_transport": row.CT_DelaiTransport,
"delai_appro": row.CT_DelaiAppro,
"commentaire": _safe_strip(row.CT_Commentaire),
"section_analytique": _safe_strip(row.CA_Num),
"mode_reglement_code": row.MR_No,
"surveillance_active": (row.CT_Surveillance == 1),
"coface": _safe_strip(row.CT_Coface),
"forme_juridique": _safe_strip(row.CT_SvFormeJuri),
"effectif": _safe_strip(row.CT_SvEffectif),
"sv_regularite": _safe_strip(row.CT_SvRegul),
"sv_cotation": _safe_strip(row.CT_SvCotation),
"sv_objet_maj": _safe_strip(row.CT_SvObjetMaj),
"sv_chiffre_affaires": row.CT_SvCA,
"sv_resultat": row.CT_SvResultat,
"compte_general": _safe_strip(row.CG_NumPrinc),
"categorie_tarif": row.N_CatTarif,
"categorie_compta": row.N_CatCompta,
}
client["contacts"] = _get_contacts_client(row.CT_Num, conn) logger.info(f"✓ SQL: Client {code_client} avec {len(client)} champs")
logger.info(f" SQL: Client {code_client} avec {len(client)} champs")
return client return client
except Exception as e: except Exception as e:
logger.error(f" Erreur SQL client {code_client}: {e}") logger.error(f"✗ Erreur SQL client {code_client}: {e}")
return None return None
def lister_tous_articles(self, filtre=""): def lister_tous_articles(self, filtre=""):
@ -3101,19 +2617,51 @@ class SageConnector:
logger.info(f" CLIENT: {numero_client}") logger.info(f" CLIENT: {numero_client}")
logger.info(f" CONTACT: {prenom} {nom}") logger.info(f" CONTACT: {prenom} {nom}")
logger.info(f"[1] Chargement du client: {numero_client}") logger.info(f"[1] Chargement du tiers: {numero_client}")
factory_client = self.cial.CptaApplication.FactoryClient factory_client = self.cial.CptaApplication.FactoryClient
factory_fournisseur = self.cial.CptaApplication.FactoryFournisseur
persist_tiers = None
type_tiers = None
# Tentative 1 : Client
try: try:
persist_client = factory_client.ReadNumero(numero_client) logger.info(" Recherche dans Clients...")
if not persist_client: persist_tiers = factory_client.ReadNumero(numero_client)
raise ValueError(f"Client {numero_client} non trouve") if persist_tiers:
type_tiers = "Client"
client_obj = win32com.client.CastTo(persist_client, "IBOClient3") logger.info(" ✓ Trouvé comme Client")
client_obj.Read()
logger.info(" OK Client charge")
except Exception as e: except Exception as e:
raise ValueError(f"Client {numero_client} introuvable: {e}") logger.debug(f" Pas trouvé comme Client: {e}")
# Tentative 2 : Fournisseur (si pas trouvé comme client)
if not persist_tiers:
try:
logger.info(" Recherche dans Fournisseurs...")
persist_tiers = factory_fournisseur.ReadNumero(numero_client)
if persist_tiers:
type_tiers = "Fournisseur"
logger.info(" ✓ Trouvé comme Fournisseur")
except Exception as e:
logger.debug(" Pas trouvé comme Fournisseur: {e}")
# Vérification finale
if not persist_tiers:
raise ValueError(
f"Le tiers '{numero_client}' est introuvable dans Sage 100c. "
f"Vérifiez que le code est exact et que le tiers existe "
f"(Client ou Fournisseur)."
)
# Cast et lecture
try:
client_obj = win32com.client.CastTo(persist_tiers, "IBOClient3")
client_obj.Read()
logger.info(f" OK {type_tiers} chargé")
except Exception as e:
raise ValueError(
f"Erreur lors du chargement du {type_tiers} '{numero_client}': {e}"
)
logger.info("[2] Creation via FactoryTiersContact") logger.info("[2] Creation via FactoryTiersContact")
if not hasattr(client_obj, "FactoryTiersContact"): if not hasattr(client_obj, "FactoryTiersContact"):
@ -3541,19 +3089,51 @@ class SageConnector:
logger.info(f"[MODIFICATION CONTACT] CT_No={contact_numero}") logger.info(f"[MODIFICATION CONTACT] CT_No={contact_numero}")
logger.info("=" * 80) logger.info("=" * 80)
logger.info("[1] Chargement du client") logger.info("[1] Chargement du tiers")
factory_client = self.cial.CptaApplication.FactoryClient factory_client = self.cial.CptaApplication.FactoryClient
factory_fournisseur = self.cial.CptaApplication.FactoryFournisseur
persist_tiers = None
type_tiers = None
# Tentative 1 : Client
try: try:
persist_client = factory_client.ReadNumero(numero) logger.info(" Recherche dans Clients...")
if not persist_client: persist_tiers = factory_client.ReadNumero(numero)
raise ValueError(f"Client {numero} non trouve") if persist_tiers:
type_tiers = "Client"
client_obj = win32com.client.CastTo(persist_client, "IBOClient3") logger.info(" ✓ Trouvé comme Client")
client_obj.Read()
logger.info(f" OK Client charge: {client_obj.CT_Intitule}")
except Exception as e: except Exception as e:
raise ValueError(f"Client {numero} introuvable: {e}") logger.debug(f" Pas trouvé comme Client: {e}")
# Tentative 2 : Fournisseur (si pas trouvé comme client)
if not persist_tiers:
try:
logger.info(" Recherche dans Fournisseurs...")
persist_tiers = factory_fournisseur.ReadNumero(numero)
if persist_tiers:
type_tiers = "Fournisseur"
logger.info(" ✓ Trouvé comme Fournisseur")
except Exception as e:
logger.debug(f" Pas trouvé comme Fournisseur: {e}")
# Vérification finale
if not persist_tiers:
raise ValueError(
f"Le tiers '{numero}' est introuvable dans Sage 100c. "
f"Vérifiez que le code est exact et que le tiers existe "
f"(Client ou Fournisseur)."
)
# Cast et lecture
try:
client_obj = win32com.client.CastTo(persist_tiers, "IBOClient3")
client_obj.Read()
logger.info(f" OK {type_tiers} chargé: {client_obj.CT_Intitule}")
except Exception as e:
raise ValueError(
f"Erreur lors du chargement du {type_tiers} '{numero}': {e}"
)
logger.info("[2] Chargement du contact") logger.info("[2] Chargement du contact")
@ -4127,7 +3707,7 @@ class SageConnector:
def lister_contacts(self, numero: str) -> List[Dict]: def lister_contacts(self, numero: str) -> List[Dict]:
try: try:
with self._get_sql_connection() as conn: with self._get_sql_connection() as conn:
return _get_contacts_client(numero, conn) return _get_contacts(numero, conn)
except Exception as e: except Exception as e:
logger.error(f"Erreur liste contacts: {e}") logger.error(f"Erreur liste contacts: {e}")
raise RuntimeError(f"Erreur lecture contacts: {str(e)}") raise RuntimeError(f"Erreur lecture contacts: {str(e)}")
@ -11271,28 +10851,33 @@ class SageConnector:
def lister_tous_tiers( def lister_tous_tiers(
self, type_tiers: Optional[str] = None, filtre: str = "" self, type_tiers: Optional[str] = None, filtre: str = ""
) -> List[Dict]: ) -> List[Dict]:
"""Liste tous les tiers avec jointure sur le collaborateur/commercial"""
try: try:
with self._get_sql_connection() as conn: with self._get_sql_connection() as conn:
cursor = conn.cursor() cursor = conn.cursor()
query = _build_tiers_select_query() query = _build_tiers_select_query()
query += " FROM F_COMPTET WHERE 1=1" query += """
FROM F_COMPTET t
LEFT JOIN F_COLLABORATEUR c ON t.CO_No = c.CO_No
WHERE 1=1
"""
params = [] params = []
if type_tiers and type_tiers != "all": if type_tiers and type_tiers != "all":
if type_tiers == "prospect": if type_tiers == "prospect":
query += " AND CT_Type = 0 AND CT_Prospect = 1" query += " AND t.CT_Type = 0 AND t.CT_Prospect = 1"
elif type_tiers == "client": elif type_tiers == "client":
query += " AND CT_Type = 0 AND CT_Prospect = 0" query += " AND t.CT_Type = 0 AND t.CT_Prospect = 0"
elif type_tiers == "fournisseur": elif type_tiers == "fournisseur":
query += " AND CT_Type = 1" query += " AND t.CT_Type = 1"
if filtre: if filtre:
query += " AND (CT_Num LIKE ? OR CT_Intitule LIKE ?)" query += " AND (t.CT_Num LIKE ? OR t.CT_Intitule LIKE ?)"
params.extend([f"%{filtre}%", f"%{filtre}%"]) params.extend([f"%{filtre}%", f"%{filtre}%"])
query += " ORDER BY CT_Intitule" query += " ORDER BY t.CT_Intitule"
cursor.execute(query, params) cursor.execute(query, params)
rows = cursor.fetchall() rows = cursor.fetchall()
@ -11300,26 +10885,30 @@ class SageConnector:
tiers_list = [] tiers_list = []
for row in rows: for row in rows:
tiers = _row_to_tiers_dict(row) tiers = _row_to_tiers_dict(row)
tiers["contacts"] = _get_contacts_client(row.CT_Num, conn) tiers["contacts"] = _get_contacts(row.CT_Num, conn)
tiers_list.append(tiers) tiers_list.append(tiers)
logger.info( logger.info(
f" SQL: {len(tiers_list)} tiers retournés (type={type_tiers}, filtre={filtre})" f" SQL: {len(tiers_list)} tiers retournés (type={type_tiers}, filtre={filtre})"
) )
return tiers_list return tiers_list
except Exception as e: except Exception as e:
logger.error(f" Erreur SQL tiers: {e}") logger.error(f" Erreur SQL tiers: {e}")
raise RuntimeError(f"Erreur lecture tiers: {str(e)}") raise RuntimeError(f"Erreur lecture tiers: {str(e)}")
def lire_tiers(self, code: str) -> Optional[Dict]: def lire_tiers(self, code: str) -> Optional[Dict]:
"""Lit un tiers (client/fournisseur/prospect) par code""" """Lit un tiers (client/fournisseur/prospect) par code avec son commercial"""
try: try:
with self._get_sql_connection() as conn: with self._get_sql_connection() as conn:
cursor = conn.cursor() cursor = conn.cursor()
query = _build_tiers_select_query() query = _build_tiers_select_query()
query += " FROM F_COMPTET WHERE CT_Num = ?" query += """
FROM F_COMPTET t
LEFT JOIN F_COLLABORATEUR c ON t.CO_No = c.CO_No
WHERE t.CT_Num = ?
"""
cursor.execute(query, (code.upper(),)) cursor.execute(query, (code.upper(),))
row = cursor.fetchone() row = cursor.fetchone()
@ -11328,11 +10917,11 @@ class SageConnector:
return None return None
tiers = _row_to_tiers_dict(row) tiers = _row_to_tiers_dict(row)
tiers["contacts"] = _get_contacts_client(row.CT_Num, conn) tiers["contacts"] = _get_contacts(row.CT_Num, conn)
logger.info(f" SQL: Tiers {code} lu avec succès") logger.info(f" SQL: Tiers {code} lu avec succès")
return tiers return tiers
except Exception as e: except Exception as e:
logger.error(f" Erreur SQL tiers {code}: {e}") logger.error(f" Erreur SQL tiers {code}: {e}")
return None return None

View file

@ -423,9 +423,6 @@ def _lister_documents_avec_lignes_sql(
for idx, entete in enumerate(entetes): for idx, entete in enumerate(entetes):
numero = _safe_strip(entete.DO_Piece) numero = _safe_strip(entete.DO_Piece)
logger.info(
f"[SQL LIST] [{idx + 1}/{len(entetes)}] Traitement {numero}..."
)
try: try:
prefixes_vente = { prefixes_vente = {
@ -785,9 +782,6 @@ def _lister_documents_avec_lignes_sql(
documents.append(doc) documents.append(doc)
stats["succes"] += 1 stats["succes"] += 1
logger.info(
f"[SQL LIST] {numero} : AJOUTÉ à la liste (total: {len(documents)})"
)
except Exception as e: except Exception as e:
logger.error( logger.error(
@ -796,20 +790,6 @@ def _lister_documents_avec_lignes_sql(
) )
continue continue
logger.info("[SQL LIST] ═══════════════════════════")
logger.info("[SQL LIST] STATISTIQUES FINALES:")
logger.info(f"[SQL LIST] Total SQL: {stats['total']}")
logger.info(f"[SQL LIST] Exclus préfixe: {stats['exclus_prefixe']}")
logger.info(f"[SQL LIST] Erreur construction: {stats['erreur_construction']}")
logger.info(f"[SQL LIST] Erreur lignes: {stats['erreur_lignes']}")
logger.info(
f"[SQL LIST] Erreur transformations: {stats['erreur_transformations']}"
)
logger.info(f"[SQL LIST] Erreur liaisons: {stats['erreur_liaisons']}")
logger.info(f"[SQL LIST] SUCCÈS: {stats['succes']}")
logger.info(f"[SQL LIST] Documents retournés: {len(documents)}")
logger.info("[SQL LIST] ═══════════════════════════")
return documents return documents
except Exception as e: except Exception as e:

View file

@ -1,4 +1,4 @@
from typing import Dict from typing import Dict, Optional
import logging import logging
from utils.functions.functions import _safe_strip from utils.functions.functions import _safe_strip
@ -78,9 +78,55 @@ def _row_to_contact_dict(row) -> Dict:
} }
def _row_to_tiers_dict(row) -> Dict: def _row_to_collaborateur_dict(row) -> Optional[dict]:
"""Convertit une ligne SQL en dictionnaire tiers (factorisation DRY)""" """Convertit une ligne SQL en dictionnaire collaborateur"""
# Vérifier si le collaborateur existe
if not hasattr(row, "Collab_CO_No") or row.Collab_CO_No is None:
return None
return { return {
"numero": row.Collab_CO_No,
"nom": _safe_strip(row.Collab_CO_Nom),
"prenom": _safe_strip(row.Collab_CO_Prenom),
"fonction": _safe_strip(row.Collab_CO_Fonction),
"adresse": _safe_strip(row.Collab_CO_Adresse),
"complement": _safe_strip(row.Collab_CO_Complement),
"code_postal": _safe_strip(row.Collab_CO_CodePostal),
"ville": _safe_strip(row.Collab_CO_Ville),
"region": _safe_strip(row.Collab_CO_CodeRegion),
"pays": _safe_strip(row.Collab_CO_Pays),
"service": _safe_strip(row.Collab_CO_Service),
"est_vendeur": (row.Collab_CO_Vendeur == 1)
if row.Collab_CO_Vendeur is not None
else None,
"est_caissier": (row.Collab_CO_Caissier == 1)
if row.Collab_CO_Caissier is not None
else None,
"est_acheteur": (row.Collab_CO_Acheteur == 1)
if row.Collab_CO_Acheteur is not None
else None,
"telephone": _safe_strip(row.Collab_CO_Telephone),
"telecopie": _safe_strip(row.Collab_CO_Telecopie),
"email": _safe_strip(row.Collab_CO_EMail),
"tel_portable": _safe_strip(row.Collab_CO_TelPortable),
"matricule": _safe_strip(row.Collab_CO_Matricule),
"facebook": _safe_strip(row.Collab_CO_Facebook),
"linkedin": _safe_strip(row.Collab_CO_LinkedIn),
"skype": _safe_strip(row.Collab_CO_Skype),
"est_actif": (row.Collab_CO_Sommeil == 0)
if row.Collab_CO_Sommeil is not None
else None,
"est_chef_ventes": (row.Collab_CO_ChefVentes == 1)
if row.Collab_CO_ChefVentes is not None
else None,
"chef_ventes_numero": row.Collab_CO_NoChefVentes,
}
def _row_to_tiers_dict(row) -> dict:
"""Convertit une ligne SQL en dictionnaire tiers"""
tiers = {
# IDENTIFICATION
"numero": _safe_strip(row.CT_Num), "numero": _safe_strip(row.CT_Num),
"intitule": _safe_strip(row.CT_Intitule), "intitule": _safe_strip(row.CT_Intitule),
"type_tiers": row.CT_Type, "type_tiers": row.CT_Type,
@ -90,6 +136,7 @@ def _row_to_tiers_dict(row) -> Dict:
"siret": _safe_strip(row.CT_Siret), "siret": _safe_strip(row.CT_Siret),
"tva_intra": _safe_strip(row.CT_Identifiant), "tva_intra": _safe_strip(row.CT_Identifiant),
"code_naf": _safe_strip(row.CT_Ape), "code_naf": _safe_strip(row.CT_Ape),
# ADRESSE
"contact": _safe_strip(row.CT_Contact), "contact": _safe_strip(row.CT_Contact),
"adresse": _safe_strip(row.CT_Adresse), "adresse": _safe_strip(row.CT_Adresse),
"complement": _safe_strip(row.CT_Complement), "complement": _safe_strip(row.CT_Complement),
@ -97,16 +144,19 @@ def _row_to_tiers_dict(row) -> Dict:
"ville": _safe_strip(row.CT_Ville), "ville": _safe_strip(row.CT_Ville),
"region": _safe_strip(row.CT_CodeRegion), "region": _safe_strip(row.CT_CodeRegion),
"pays": _safe_strip(row.CT_Pays), "pays": _safe_strip(row.CT_Pays),
# TELECOM
"telephone": _safe_strip(row.CT_Telephone), "telephone": _safe_strip(row.CT_Telephone),
"telecopie": _safe_strip(row.CT_Telecopie), "telecopie": _safe_strip(row.CT_Telecopie),
"email": _safe_strip(row.CT_EMail), "email": _safe_strip(row.CT_EMail),
"site_web": _safe_strip(row.CT_Site), "site_web": _safe_strip(row.CT_Site),
"facebook": _safe_strip(row.CT_Facebook), "facebook": _safe_strip(row.CT_Facebook),
"linkedin": _safe_strip(row.CT_LinkedIn), "linkedin": _safe_strip(row.CT_LinkedIn),
# TAUX
"taux01": row.CT_Taux01, "taux01": row.CT_Taux01,
"taux02": row.CT_Taux02, "taux02": row.CT_Taux02,
"taux03": row.CT_Taux03, "taux03": row.CT_Taux03,
"taux04": row.CT_Taux04, "taux04": row.CT_Taux04,
# STATISTIQUES
"statistique01": _safe_strip(row.CT_Statistique01), "statistique01": _safe_strip(row.CT_Statistique01),
"statistique02": _safe_strip(row.CT_Statistique02), "statistique02": _safe_strip(row.CT_Statistique02),
"statistique03": _safe_strip(row.CT_Statistique03), "statistique03": _safe_strip(row.CT_Statistique03),
@ -117,10 +167,13 @@ def _row_to_tiers_dict(row) -> Dict:
"statistique08": _safe_strip(row.CT_Statistique08), "statistique08": _safe_strip(row.CT_Statistique08),
"statistique09": _safe_strip(row.CT_Statistique09), "statistique09": _safe_strip(row.CT_Statistique09),
"statistique10": _safe_strip(row.CT_Statistique10), "statistique10": _safe_strip(row.CT_Statistique10),
# COMMERCIAL
"encours_autorise": row.CT_Encours, "encours_autorise": row.CT_Encours,
"assurance_credit": row.CT_Assurance, "assurance_credit": row.CT_Assurance,
"langue": row.CT_Langue, "langue": row.CT_Langue,
"commercial_code": row.CO_No, "commercial_code": row.CO_No,
"commercial": _row_to_collaborateur_dict(row),
# FACTURATION
"lettrage_auto": (row.CT_Lettrage == 1), "lettrage_auto": (row.CT_Lettrage == 1),
"est_actif": (row.CT_Sommeil == 0), "est_actif": (row.CT_Sommeil == 0),
"type_facture": row.CT_Facture, "type_facture": row.CT_Facture,
@ -132,12 +185,16 @@ def _row_to_tiers_dict(row) -> Dict:
"exclure_relance": (row.CT_NotRappel == 1), "exclure_relance": (row.CT_NotRappel == 1),
"exclure_penalites": (row.CT_NotPenal == 1), "exclure_penalites": (row.CT_NotPenal == 1),
"bon_a_payer": row.CT_BonAPayer, "bon_a_payer": row.CT_BonAPayer,
# LOGISTIQUE
"priorite_livraison": row.CT_PrioriteLivr, "priorite_livraison": row.CT_PrioriteLivr,
"livraison_partielle": row.CT_LivrPartielle, "livraison_partielle": row.CT_LivrPartielle,
"delai_transport": row.CT_DelaiTransport, "delai_transport": row.CT_DelaiTransport,
"delai_appro": row.CT_DelaiAppro, "delai_appro": row.CT_DelaiAppro,
# COMMENTAIRE
"commentaire": _safe_strip(row.CT_Commentaire), "commentaire": _safe_strip(row.CT_Commentaire),
# ANALYTIQUE
"section_analytique": _safe_strip(row.CA_Num), "section_analytique": _safe_strip(row.CA_Num),
# ORGANISATION / SURVEILLANCE
"mode_reglement_code": row.MR_No, "mode_reglement_code": row.MR_No,
"surveillance_active": (row.CT_Surveillance == 1), "surveillance_active": (row.CT_Surveillance == 1),
"coface": _safe_strip(row.CT_Coface), "coface": _safe_strip(row.CT_Coface),
@ -148,11 +205,14 @@ def _row_to_tiers_dict(row) -> Dict:
"sv_objet_maj": _safe_strip(row.CT_SvObjetMaj), "sv_objet_maj": _safe_strip(row.CT_SvObjetMaj),
"sv_chiffre_affaires": row.CT_SvCA, "sv_chiffre_affaires": row.CT_SvCA,
"sv_resultat": row.CT_SvResultat, "sv_resultat": row.CT_SvResultat,
# COMPTE GENERAL ET CATEGORIES
"compte_general": _safe_strip(row.CG_NumPrinc), "compte_general": _safe_strip(row.CG_NumPrinc),
"categorie_tarif": row.N_CatTarif, "categorie_tarif": row.N_CatTarif,
"categorie_compta": row.N_CatCompta, "categorie_compta": row.N_CatCompta,
} }
return tiers
__all__ = [ __all__ = [
"_contact_to_dict", "_contact_to_dict",

View file

@ -5,7 +5,7 @@ from utils.functions.functions import _safe_strip
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def _get_contacts_client(numero: str, conn) -> list: def _get_contacts(numero: str, conn) -> list:
try: try:
cursor = conn.cursor() cursor = conn.cursor()
@ -162,7 +162,7 @@ def _lire_contact_depuis_base(
__all__ = [ __all__ = [
"_get_contacts_client", "_get_contacts",
"_chercher_contact_en_base", "_chercher_contact_en_base",
"_lire_contact_depuis_base" "_lire_contact_depuis_base"
] ]

View file

@ -1,54 +1,81 @@
def _build_tiers_select_query() -> str: def _build_tiers_select_query():
"""Construit la requête SELECT pour les tiers (factorisation)""" """Construit la partie SELECT de la requête avec tous les champs tiers + collaborateur"""
return """ return """
SELECT SELECT
-- IDENTIFICATION (9) -- IDENTIFICATION TIERS (9)
CT_Num, CT_Intitule, CT_Type, CT_Qualite, t.CT_Num, t.CT_Intitule, t.CT_Type, t.CT_Qualite,
CT_Classement, CT_Raccourci, CT_Siret, CT_Identifiant, t.CT_Classement, t.CT_Raccourci, t.CT_Siret, t.CT_Identifiant,
CT_Ape, t.CT_Ape,
-- ADRESSE (7) -- ADRESSE TIERS (7)
CT_Contact, CT_Adresse, CT_Complement, t.CT_Contact, t.CT_Adresse, t.CT_Complement,
CT_CodePostal, CT_Ville, CT_CodeRegion, CT_Pays, t.CT_CodePostal, t.CT_Ville, t.CT_CodeRegion, t.CT_Pays,
-- TELECOM (6) -- TELECOM TIERS (6)
CT_Telephone, CT_Telecopie, CT_EMail, CT_Site, t.CT_Telephone, t.CT_Telecopie, t.CT_EMail, t.CT_Site,
CT_Facebook, CT_LinkedIn, t.CT_Facebook, t.CT_LinkedIn,
-- TAUX (4) -- TAUX TIERS (4)
CT_Taux01, CT_Taux02, CT_Taux03, CT_Taux04, t.CT_Taux01, t.CT_Taux02, t.CT_Taux03, t.CT_Taux04,
-- STATISTIQUES (10) -- STATISTIQUES TIERS (10)
CT_Statistique01, CT_Statistique02, CT_Statistique03, t.CT_Statistique01, t.CT_Statistique02, t.CT_Statistique03,
CT_Statistique04, CT_Statistique05, CT_Statistique06, t.CT_Statistique04, t.CT_Statistique05, t.CT_Statistique06,
CT_Statistique07, CT_Statistique08, CT_Statistique09, t.CT_Statistique07, t.CT_Statistique08, t.CT_Statistique09,
CT_Statistique10, t.CT_Statistique10,
-- COMMERCIAL (4) -- COMMERCIAL TIERS (4)
CT_Encours, CT_Assurance, CT_Langue, CO_No, t.CT_Encours, t.CT_Assurance, t.CT_Langue, t.CO_No,
-- FACTURATION (11) -- FACTURATION TIERS (11)
CT_Lettrage, CT_Sommeil, CT_Facture, CT_Prospect, t.CT_Lettrage, t.CT_Sommeil, t.CT_Facture, t.CT_Prospect,
CT_BLFact, CT_Saut, CT_ValidEch, CT_ControlEnc, t.CT_BLFact, t.CT_Saut, t.CT_ValidEch, t.CT_ControlEnc,
CT_NotRappel, CT_NotPenal, CT_BonAPayer, t.CT_NotRappel, t.CT_NotPenal, t.CT_BonAPayer,
-- LOGISTIQUE (4) -- LOGISTIQUE TIERS (4)
CT_PrioriteLivr, CT_LivrPartielle, t.CT_PrioriteLivr, t.CT_LivrPartielle,
CT_DelaiTransport, CT_DelaiAppro, t.CT_DelaiTransport, t.CT_DelaiAppro,
-- COMMENTAIRE (1) -- COMMENTAIRE TIERS (1)
CT_Commentaire, t.CT_Commentaire,
-- ANALYTIQUE (1) -- ANALYTIQUE TIERS (1)
CA_Num, t.CA_Num,
-- ORGANISATION / SURVEILLANCE (10) -- ORGANISATION / SURVEILLANCE TIERS (10)
MR_No, CT_Surveillance, CT_Coface, t.MR_No, t.CT_Surveillance, t.CT_Coface,
CT_SvFormeJuri, CT_SvEffectif, CT_SvRegul, t.CT_SvFormeJuri, t.CT_SvEffectif, t.CT_SvRegul,
CT_SvCotation, CT_SvObjetMaj, CT_SvCA, CT_SvResultat, t.CT_SvCotation, t.CT_SvObjetMaj, t.CT_SvCA, t.CT_SvResultat,
-- COMPTE GENERAL ET CATEGORIES (3) -- COMPTE GENERAL ET CATEGORIES TIERS (3)
CG_NumPrinc, N_CatTarif, N_CatCompta t.CG_NumPrinc, t.N_CatTarif, t.N_CatCompta,
-- COLLABORATEUR (23 champs)
c.CO_No AS Collab_CO_No,
c.CO_Nom AS Collab_CO_Nom,
c.CO_Prenom AS Collab_CO_Prenom,
c.CO_Fonction AS Collab_CO_Fonction,
c.CO_Adresse AS Collab_CO_Adresse,
c.CO_Complement AS Collab_CO_Complement,
c.CO_CodePostal AS Collab_CO_CodePostal,
c.CO_Ville AS Collab_CO_Ville,
c.CO_CodeRegion AS Collab_CO_CodeRegion,
c.CO_Pays AS Collab_CO_Pays,
c.CO_Service AS Collab_CO_Service,
c.CO_Vendeur AS Collab_CO_Vendeur,
c.CO_Caissier AS Collab_CO_Caissier,
c.CO_Acheteur AS Collab_CO_Acheteur,
c.CO_Telephone AS Collab_CO_Telephone,
c.CO_Telecopie AS Collab_CO_Telecopie,
c.CO_EMail AS Collab_CO_EMail,
c.CO_TelPortable AS Collab_CO_TelPortable,
c.CO_Matricule AS Collab_CO_Matricule,
c.CO_Facebook AS Collab_CO_Facebook,
c.CO_LinkedIn AS Collab_CO_LinkedIn,
c.CO_Skype AS Collab_CO_Skype,
c.CO_Sommeil AS Collab_CO_Sommeil,
c.CO_ChefVentes AS Collab_CO_ChefVentes,
c.CO_NoChefVentes AS Collab_CO_NoChefVentes
""" """