diff --git a/sage_connector.py b/sage_connector.py index 3df2ec3..be452b7 100644 --- a/sage_connector.py +++ b/sage_connector.py @@ -7223,7 +7223,7 @@ class SageConnector: def definir_contact_defaut(self, numero: str, contact_numero: int) -> Dict: """ Définit un contact comme contact par défaut du client - VERSION CORRIGÉE pour Sage 100 + VERSION REFACTORISÉE """ if not self.cial: raise RuntimeError("Connexion Sage non établie") @@ -7231,54 +7231,31 @@ class SageConnector: try: with self._com_context(), self._lock_com: logger.info("=" * 80) - logger.info(f"[DÉFINIR CONTACT PAR DÉFAUT] Client={numero}, Contact={contact_numero}") + logger.info(f"[DEFINIR CONTACT PAR DEFAUT] Client={numero}, Contact={contact_numero}") logger.info("=" * 80) - # Charger le contact - CORRECTION ICI - logger.info("[1] Chargement du contact") - - # Trouver la factory - factory_contact = None - for factory_name in ["FactoryContact", "FactoryContactTiers", "FactoryTypeContacts"]: - try: - if hasattr(self.cial.CptaApplication, factory_name): - factory_contact = getattr(self.cial.CptaApplication, factory_name) - break - except: - continue - - if not factory_contact: - raise RuntimeError("Factory contacts non trouvée") + # Récupérer le nom du contact via SQL + logger.info("[1] Recuperation infos contact") + nom_contact = None + prenom_contact = None try: - # ReadNumero peut accepter 1 ou 2 paramètres - try: - persist_contact = factory_contact.ReadNumero(numero, contact_numero) - except TypeError: - persist_contact = factory_contact.ReadNumero(contact_numero) - - if not persist_contact: - raise ValueError(f"Contact CT_No={contact_numero} non trouvé") - - # Caster - contact = None - for interface in ["IBOContactT3", "IBOContact3", "IBOContactT"]: - try: - contact = win32com.client.CastTo(persist_contact, interface) - break - except: - continue - - if not contact: - contact = persist_contact - - contact.Read() - - nom_contact = getattr(contact, "CT_Nom", "") - prenom_contact = getattr(contact, "CT_Prenom", "") - nom_complet = f"{prenom_contact} {nom_contact}".strip() if prenom_contact else nom_contact - - logger.info(f" ✓ Contact trouvé: {nom_complet}") + with self._get_sql_connection() as conn: + cursor = conn.cursor() + cursor.execute( + "SELECT CT_Nom, CT_Prenom FROM F_CONTACTT WHERE CT_Num = ? AND CT_No = ?", + [numero, contact_numero] + ) + row = cursor.fetchone() + + if not row: + raise ValueError(f"Contact CT_No={contact_numero} non trouve") + + nom_contact = row.CT_Nom.strip() if row.CT_Nom else "" + prenom_contact = row.CT_Prenom.strip() if row.CT_Prenom else "" + + nom_complet = f"{prenom_contact} {nom_contact}".strip() if prenom_contact else nom_contact + logger.info(f" OK Contact trouve: {nom_complet}") except Exception as e: raise ValueError(f"Contact introuvable: {e}") @@ -7290,32 +7267,35 @@ class SageConnector: try: persist_client = factory_client.ReadNumero(numero) if not persist_client: - raise ValueError(f"Client {numero} non trouvé") + raise ValueError(f"Client {numero} non trouve") client = win32com.client.CastTo(persist_client, "IBOClient3") client.Read() - logger.info(f" ✓ Client chargé: {client.CT_Intitule}") + logger.info(f" OK Client charge: {client.CT_Intitule}") except Exception as e: raise ValueError(f"Client introuvable: {e}") # Définir le contact par défaut - logger.info("[3] Définition du contact par défaut") + logger.info("[3] Definition du contact par defaut") ancien_contact = getattr(client, "CT_Contact", "") client.CT_Contact = nom_complet - logger.info(f" CT_Contact: '{ancien_contact}' → '{nom_complet}'") + logger.info(f" CT_Contact: '{ancien_contact}' -> '{nom_complet}'") - # Essayer CT_NoContact si disponible - if self._try_set_attribute(client, "CT_NoContact", contact_numero): - logger.info(f" CT_NoContact = {contact_numero}") + if hasattr(client, 'CT_NoContact'): + try: + client.CT_NoContact = contact_numero + logger.info(f" CT_NoContact = {contact_numero}") + except: + pass # Enregistrement - logger.info("[4] WRITE") + logger.info("[4] Enregistrement") try: client.Write() client.Read() - logger.info(" ✓ Client mis à jour") + logger.info(" OK Client mis a jour") except Exception as e: error_detail = str(e) try: @@ -7324,10 +7304,10 @@ class SageConnector: error_detail = f"{sage_error.Description} (Code: {sage_error.Number})" except: pass - raise RuntimeError(f"Échec mise à jour: {error_detail}") + raise RuntimeError(f"Echec mise a jour: {error_detail}") logger.info("=" * 80) - logger.info(f"[SUCCÈS] Contact par défaut: {nom_complet}") + logger.info(f"[SUCCES] Contact par defaut: {nom_complet}") logger.info("=" * 80) return { @@ -7345,8 +7325,8 @@ class SageConnector: except Exception as e: logger.error(f"[ERREUR] {e}", exc_info=True) raise RuntimeError(f"Erreur technique: {e}") - + def lister_contacts(self, numero: str) -> List[Dict]: """ Liste tous les contacts d'un client @@ -7453,6 +7433,7 @@ class SageConnector: def supprimer_contact(self, numero: str, contact_numero: int) -> Dict: """ Supprime un contact via COM + VERSION REFACTORISÉE """ if not self.cial: raise RuntimeError("Connexion Sage non établie") @@ -7463,27 +7444,53 @@ class SageConnector: logger.info(f"[SUPPRESSION CONTACT] CT_No={contact_numero}") logger.info("=" * 80) - # Lire le contact - factory_contact = self.cial.CptaApplication.FactoryContactT + # Récupérer le nom du contact via SQL + logger.info("[1] Recuperation infos contact") + nom_contact = None + prenom_contact = None try: - persist = factory_contact.ReadNumero(numero, contact_numero) - if not persist: - raise ValueError(f"Contact CT_No={contact_numero} non trouvé") + with self._get_sql_connection() as conn: + cursor = conn.cursor() + cursor.execute( + "SELECT CT_Nom, CT_Prenom FROM F_CONTACTT WHERE CT_Num = ? AND CT_No = ?", + [numero, contact_numero] + ) + row = cursor.fetchone() + + if not row: + raise ValueError(f"Contact CT_No={contact_numero} non trouve") + + nom_contact = row.CT_Nom.strip() if row.CT_Nom else "" + prenom_contact = row.CT_Prenom.strip() if row.CT_Prenom else "" + + logger.info(f" OK Contact trouve: {prenom_contact} {nom_contact}") + + except Exception as e: + raise ValueError(f"Contact introuvable: {e}") + + # Charger le contact via FactoryDossierContact + logger.info("[2] Chargement du contact") + factory_dossier = self.cial.CptaApplication.FactoryDossierContact + + try: + persist = factory_dossier.ReadNomPrenom(nom_contact, prenom_contact) - contact = win32com.client.CastTo(persist, "IBOContactT3") + if not persist: + raise ValueError(f"Contact non trouvable via ReadNomPrenom") + + contact = win32com.client.CastTo(persist, "IBOTiersContact3") contact.Read() - nom_contact = contact.CT_Nom - logger.info(f" ✓ Contact trouvé: {nom_contact}") + logger.info(f" OK Contact charge: {contact.Nom}") except Exception as e: raise ValueError(f"Contact introuvable: {e}") # Supprimer - logger.info("[SUPPRESSION]") + logger.info("[3] Suppression") try: contact.Remove() - logger.info(" ✓ Remove() réussi") + logger.info(" OK Remove() reussi") except Exception as e: error_detail = str(e) try: @@ -7492,17 +7499,18 @@ class SageConnector: error_detail = f"{sage_error.Description} (Code: {sage_error.Number})" except: pass - logger.error(f" ✗ Erreur Remove: {error_detail}") - raise RuntimeError(f"Échec suppression contact: {error_detail}") + logger.error(f" ERROR Remove: {error_detail}") + raise RuntimeError(f"Echec suppression contact: {error_detail}") logger.info("=" * 80) - logger.info(f"[SUCCÈS] Contact supprimé: {nom_contact}") + logger.info(f"[SUCCES] Contact supprime: {prenom_contact} {nom_contact}") logger.info("=" * 80) return { "numero": numero, "contact_numero": contact_numero, "nom": nom_contact, + "prenom": prenom_contact, "supprime": True, "date_suppression": datetime.now().isoformat() }