refactor(sage_connector): improve client creation with better error handling and logging
This commit is contained in:
parent
914ea61243
commit
49fdc8425b
1 changed files with 114 additions and 45 deletions
|
|
@ -2388,85 +2388,154 @@ class SageConnector:
|
|||
# 1. Accès à la Factory Client (CptaApplication si Tiers)
|
||||
factory_client = self.cial.CptaApplication.FactoryClient
|
||||
|
||||
# ✅ CORRECTION CRITIQUE: Utiliser Create() au lieu de CreateNew()
|
||||
persist_client = factory_client.Create()
|
||||
# ✅ Utiliser Create() qui retourne directement l'objet utilisable
|
||||
client = factory_client.Create()
|
||||
|
||||
if not persist_client:
|
||||
if not client:
|
||||
raise RuntimeError("Factory.Create() a retourné None")
|
||||
|
||||
# Cast en IBOClient3 pour accéder aux propriétés
|
||||
client = win32com.client.CastTo(persist_client, "IBOClient3")
|
||||
logger.debug(f"📦 Objet créé, type: {type(client)}")
|
||||
|
||||
# ✅ PAS DE CAST - L'objet retourné par Create() est déjà typé correctement
|
||||
# Tester l'accès aux propriétés pour vérifier que l'objet est valide
|
||||
try:
|
||||
test_intitule = getattr(client, "CT_Intitule", None)
|
||||
logger.debug(f"✅ Objet valide, CT_Intitule accessible: {test_intitule}")
|
||||
except AttributeError as e:
|
||||
logger.error(f"❌ Objet invalide: {e}")
|
||||
# Si ça échoue, essayer le cast en dernier recours
|
||||
logger.warning("Tentative de cast en IBOClient3...")
|
||||
try:
|
||||
client = win32com.client.CastTo(client, "IBOClient3")
|
||||
logger.debug("✅ Cast réussi")
|
||||
except Exception as cast_err:
|
||||
raise RuntimeError(f"Impossible d'accéder aux propriétés du client. Objet type: {type(client)}, erreur: {e}")
|
||||
|
||||
# 2. Remplissage des Champs OBLIGATOIRES (Conformes F_COMPTET)
|
||||
|
||||
logger.info(f"📝 Création client: {client_data['intitule']}")
|
||||
|
||||
# CT_Intitule - OBLIGATOIRE (définir en premier)
|
||||
try:
|
||||
client.CT_Intitule = client_data["intitule"]
|
||||
logger.debug(f"✅ CT_Intitule défini: {client_data['intitule']}")
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"Impossible de définir CT_Intitule: {e}")
|
||||
|
||||
# CT_Type - OBLIGATOIRE
|
||||
try:
|
||||
client.CT_Type = 0 # 0 = Client
|
||||
logger.debug("✅ CT_Type = 0 (Client)")
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"Impossible de définir CT_Type: {e}")
|
||||
|
||||
# CT_Num (Numéro de compte) - Optionnel si auto-numérotation
|
||||
num_prop = client_data.get("num", "")
|
||||
if num_prop:
|
||||
# S'assurer que le numéro est en majuscule (conforme Alpha Majuscule)
|
||||
client.CT_Num = num_prop.upper()
|
||||
try:
|
||||
# S'assurer que le numéro est en majuscule (conforme Alpha Majuscule)
|
||||
client.CT_Num = num_prop.upper()
|
||||
logger.debug(f"✅ CT_Num défini: {num_prop.upper()}")
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ Impossible de définir CT_Num: {e}")
|
||||
|
||||
# CT_Intitule - OBLIGATOIRE
|
||||
client.CT_Intitule = client_data["intitule"]
|
||||
client.CT_Type = 0 # 0 = Client
|
||||
# ✅ Compte comptable général
|
||||
try:
|
||||
if client_data.get("compte_collectif"):
|
||||
client.CT_CompteG = client_data["compte_collectif"]
|
||||
logger.debug(f"✅ CT_CompteG: {client_data['compte_collectif']}")
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ Impossible de définir CT_CompteG: {e}")
|
||||
|
||||
# ✅ CORRECTION : Utiliser CT_CompteG (mappé à CG_NumPrinc)
|
||||
if client_data.get("compte_collectif"):
|
||||
client.CT_CompteG = client_data["compte_collectif"]
|
||||
|
||||
# Initialisation des champs obligatoires (N_...)
|
||||
client.N_CatTarif = 1
|
||||
client.N_CatCompta = 1
|
||||
client.N_Period = 1
|
||||
client.N_Expedition = 1
|
||||
client.N_Condition = 1
|
||||
client.N_Risque = 1
|
||||
# Initialisation des champs catégoriels (si disponibles)
|
||||
try:
|
||||
client.N_CatTarif = 1
|
||||
client.N_CatCompta = 1
|
||||
client.N_Period = 1
|
||||
client.N_Expedition = 1
|
||||
client.N_Condition = 1
|
||||
client.N_Risque = 1
|
||||
logger.debug("✅ Catégories initialisées")
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ Catégories non disponibles: {e}")
|
||||
|
||||
# CT_NumPayeur doit être défini - Si pas de num, sera auto-généré
|
||||
# CT_NumPayeur - Géré après Write() si auto-numérotation
|
||||
if num_prop:
|
||||
client.CT_NumPayeur = num_prop.upper()
|
||||
try:
|
||||
client.CT_NumPayeur = num_prop.upper()
|
||||
logger.debug(f"✅ CT_NumPayeur: {num_prop.upper()}")
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ Impossible de définir CT_NumPayeur: {e}")
|
||||
|
||||
# 3. CHAMPS OPTIONNELS
|
||||
|
||||
# --- Adresse principale (Accès via sous-objet Adresse) ---
|
||||
try:
|
||||
if client_data.get("adresse"):
|
||||
client.Adresse.Adresse = client_data["adresse"]
|
||||
if client_data.get("code_postal"):
|
||||
client.Adresse.CodePostal = client_data["code_postal"]
|
||||
if client_data.get("ville"):
|
||||
client.Adresse.Ville = client_data["ville"]
|
||||
if client_data.get("pays"):
|
||||
client.Adresse.Pays = client_data["pays"]
|
||||
adresse_obj = getattr(client, "Adresse", None)
|
||||
if adresse_obj:
|
||||
if client_data.get("adresse"):
|
||||
adresse_obj.Adresse = client_data["adresse"]
|
||||
if client_data.get("code_postal"):
|
||||
adresse_obj.CodePostal = client_data["code_postal"]
|
||||
if client_data.get("ville"):
|
||||
adresse_obj.Ville = client_data["ville"]
|
||||
if client_data.get("pays"):
|
||||
adresse_obj.Pays = client_data["pays"]
|
||||
logger.debug("✅ Adresse définie")
|
||||
except Exception as e:
|
||||
logger.warning(f"Impossible de définir l'adresse: {e}")
|
||||
logger.warning(f"⚠️ Impossible de définir l'adresse: {e}")
|
||||
|
||||
# --- Contact / Télécom (Accès via sous-objet Telecom) ---
|
||||
try:
|
||||
if client_data.get("telephone"):
|
||||
client.Telecom.Telephone = client_data["telephone"]
|
||||
if client_data.get("email"):
|
||||
client.Telecom.EMail = client_data["email"]
|
||||
telecom_obj = getattr(client, "Telecom", None)
|
||||
if telecom_obj:
|
||||
if client_data.get("telephone"):
|
||||
telecom_obj.Telephone = client_data["telephone"]
|
||||
if client_data.get("email"):
|
||||
telecom_obj.EMail = client_data["email"]
|
||||
logger.debug("✅ Télécom défini")
|
||||
except Exception as e:
|
||||
logger.warning(f"Impossible de définir les télécoms: {e}")
|
||||
logger.warning(f"⚠️ Impossible de définir les télécoms: {e}")
|
||||
|
||||
# --- Identifiants ---
|
||||
if client_data.get("siret"):
|
||||
client.CT_Siret = client_data["siret"]
|
||||
if client_data.get("tva_intra"):
|
||||
client.CT_Identifiant = client_data["tva_intra"]
|
||||
try:
|
||||
if client_data.get("siret"):
|
||||
client.CT_Siret = client_data["siret"]
|
||||
logger.debug(f"✅ SIRET: {client_data['siret']}")
|
||||
if client_data.get("tva_intra"):
|
||||
client.CT_Identifiant = client_data["tva_intra"]
|
||||
logger.debug(f"✅ TVA: {client_data['tva_intra']}")
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ Impossible de définir les identifiants: {e}")
|
||||
|
||||
# 4. Écriture en base
|
||||
client.Write()
|
||||
logger.info("💾 Écriture du client dans Sage...")
|
||||
try:
|
||||
client.Write()
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"Échec Write(): {e}")
|
||||
|
||||
# ✅ IMPORTANT: Relire pour récupérer le numéro auto-généré
|
||||
client.Read()
|
||||
try:
|
||||
client.Read()
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ Impossible de relire après Write(): {e}")
|
||||
|
||||
num_final = client.CT_Num
|
||||
num_final = getattr(client, "CT_Num", "")
|
||||
|
||||
if not num_final:
|
||||
raise RuntimeError("CT_Num vide après Write() - création échouée")
|
||||
|
||||
logger.info(f"✅ Client créé: {num_final} - {client.CT_Intitule}")
|
||||
# Si CT_NumPayeur était vide, le définir maintenant avec le numéro auto-généré
|
||||
if not num_prop:
|
||||
try:
|
||||
client.CT_NumPayeur = num_final
|
||||
client.Write()
|
||||
logger.debug(f"✅ CT_NumPayeur auto-défini: {num_final}")
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ Impossible de définir CT_NumPayeur après création: {e}")
|
||||
|
||||
logger.info(f"✅ Client créé avec succès: {num_final} - {client.CT_Intitule}")
|
||||
|
||||
# ✅ Forcer le refresh du cache pour que le nouveau client soit visible
|
||||
self._refresh_cache_clients()
|
||||
|
|
|
|||
Loading…
Reference in a new issue