fix(sage_connector): enforce mandatory casting after Create() in client creation

This commit is contained in:
Fanilo-Nantenaina 2025-12-05 22:37:51 +03:00
parent 49fdc8425b
commit c48a3f033a

View file

@ -2377,45 +2377,36 @@ class SageConnector:
def creer_client(self, client_data: Dict) -> Dict: def creer_client(self, client_data: Dict) -> Dict:
""" """
Crée un nouveau client dans Sage 100c via l'API COM, Crée un nouveau client dans Sage 100c via l'API COM.
en utilisant Create() pour obtenir l'objet Tiers. CORRECTION : Cast obligatoire après Create()
""" """
if not self.cial: if not self.cial:
raise RuntimeError("Connexion Sage non établie") raise RuntimeError("Connexion Sage non établie")
try: try:
with self._com_context(), self._lock_com: with self._com_context(), self._lock_com:
# 1. Accès à la Factory Client (CptaApplication si Tiers) # 1. Accès à la Factory Client
factory_client = self.cial.CptaApplication.FactoryClient factory_client = self.cial.CptaApplication.FactoryClient
# ✅ Utiliser Create() qui retourne directement l'objet utilisable # ✅ Create() retourne IBIPersistObject (générique)
client = factory_client.Create() persist = factory_client.Create()
if not client: if not persist:
raise RuntimeError("Factory.Create() a retourné None") raise RuntimeError("Factory.Create() a retourné None")
logger.debug(f"📦 Objet créé, type: {type(client)}") logger.debug(f"📦 Objet IBIPersistObject créé : {type(persist)}")
# ✅ PAS DE CAST - L'objet retourné par Create() est déjà typé correctement # ✅ CAST OBLIGATOIRE vers IBOClient3 pour accéder aux propriétés métier
# Tester l'accès aux propriétés pour vérifier que l'objet est valide
try: try:
test_intitule = getattr(client, "CT_Intitule", None) client = win32com.client.CastTo(persist, "IBOClient3")
logger.debug(f"✅ Objet valide, CT_Intitule accessible: {test_intitule}") logger.debug(f"✅ Cast réussi vers IBOClient3")
except AttributeError as e: except Exception as e:
logger.error(f"❌ Objet invalide: {e}") raise RuntimeError(f"Impossible de caster vers IBOClient3: {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)
# 2. Remplissage des Champs OBLIGATOIRES
logger.info(f"📝 Création client: {client_data['intitule']}") logger.info(f"📝 Création client: {client_data['intitule']}")
# CT_Intitule - OBLIGATOIRE (définir en premier) # CT_Intitule - OBLIGATOIRE
try: try:
client.CT_Intitule = client_data["intitule"] client.CT_Intitule = client_data["intitule"]
logger.debug(f"✅ CT_Intitule défini: {client_data['intitule']}") logger.debug(f"✅ CT_Intitule défini: {client_data['intitule']}")
@ -2433,7 +2424,6 @@ class SageConnector:
num_prop = client_data.get("num", "") num_prop = client_data.get("num", "")
if num_prop: if num_prop:
try: try:
# S'assurer que le numéro est en majuscule (conforme Alpha Majuscule)
client.CT_Num = num_prop.upper() client.CT_Num = num_prop.upper()
logger.debug(f"✅ CT_Num défini: {num_prop.upper()}") logger.debug(f"✅ CT_Num défini: {num_prop.upper()}")
except Exception as e: except Exception as e:
@ -2564,5 +2554,4 @@ class SageConnector:
except: except:
pass pass
# Le connecteur lève maintenant un RuntimeError clair
raise RuntimeError(f"Erreur technique Sage: {error_message}") raise RuntimeError(f"Erreur technique Sage: {error_message}")