modifier_contact successful
This commit is contained in:
parent
3e617d070a
commit
7f64a2a548
1 changed files with 164 additions and 130 deletions
|
|
@ -6962,7 +6962,7 @@ class SageConnector:
|
|||
def modifier_contact(self, numero: str, contact_numero: int, updates: Dict) -> Dict:
|
||||
"""
|
||||
Modifie un contact existant via COM
|
||||
VERSION CORRIGÉE pour Sage 100
|
||||
VERSION REFACTORISÉE - Utilise FactoryTiersContact
|
||||
"""
|
||||
if not self.cial:
|
||||
raise RuntimeError("Connexion Sage non établie")
|
||||
|
|
@ -6973,135 +6973,192 @@ class SageConnector:
|
|||
logger.info(f"[MODIFICATION CONTACT] CT_No={contact_numero}")
|
||||
logger.info("=" * 80)
|
||||
|
||||
# Lire le contact existant - CORRECTION ICI
|
||||
logger.info("[1] Lecture contact existant")
|
||||
|
||||
# Trouver la factory
|
||||
factory_contact = None
|
||||
factory_names = [
|
||||
"FactoryContact",
|
||||
"FactoryContactTiers",
|
||||
"FactoryTypeContacts",
|
||||
]
|
||||
|
||||
for factory_name in factory_names:
|
||||
# Charger le client
|
||||
logger.info("[1] Chargement du client")
|
||||
factory_client = self.cial.CptaApplication.FactoryClient
|
||||
try:
|
||||
if hasattr(self.cial.CptaApplication, factory_name):
|
||||
factory_contact = getattr(self.cial.CptaApplication, factory_name)
|
||||
break
|
||||
except:
|
||||
continue
|
||||
persist_client = factory_client.ReadNumero(numero)
|
||||
if not persist_client:
|
||||
raise ValueError(f"Client {numero} non trouve")
|
||||
|
||||
if not factory_contact:
|
||||
raise RuntimeError("Aucune factory de contacts trouvée")
|
||||
client_obj = win32com.client.CastTo(persist_client, "IBOClient3")
|
||||
client_obj.Read()
|
||||
logger.info(f" OK Client charge")
|
||||
except Exception as e:
|
||||
raise ValueError(f"Client {numero} introuvable: {e}")
|
||||
|
||||
# Charger le contact via FactoryTiersContact
|
||||
logger.info("[2] Chargement du contact")
|
||||
|
||||
if not hasattr(client_obj, 'FactoryTiersContact'):
|
||||
raise RuntimeError("FactoryTiersContact non trouvee sur le client")
|
||||
|
||||
factory_contact = client_obj.FactoryTiersContact
|
||||
|
||||
try:
|
||||
# ReadNumero peut accepter 1 ou 2 paramètres selon la version
|
||||
# Chercher le contact par son CT_No
|
||||
# Il faut lister et trouver celui avec le bon CT_No
|
||||
# ou utiliser une autre méthode de lecture
|
||||
|
||||
# STRATÉGIE : Lister tous les contacts et trouver le bon
|
||||
contacts_collection = None
|
||||
all_contacts = []
|
||||
|
||||
# Essayer de lister via SQL d'abord (plus fiable)
|
||||
try:
|
||||
persist = factory_contact.ReadNumero(numero, contact_numero)
|
||||
except TypeError:
|
||||
# Si 2 paramètres ne fonctionnent pas, essayer avec CT_No seulement
|
||||
persist = factory_contact.ReadNumero(contact_numero)
|
||||
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_recherche = row.CT_Nom.strip() if row.CT_Nom else ""
|
||||
prenom_recherche = row.CT_Prenom.strip() if row.CT_Prenom else ""
|
||||
|
||||
logger.info(f" Contact trouve en SQL: {prenom_recherche} {nom_recherche}")
|
||||
|
||||
except Exception as e:
|
||||
raise ValueError(f"Contact introuvable: {e}")
|
||||
|
||||
# Charger via ReadNomPrenom
|
||||
factory_dossier = self.cial.CptaApplication.FactoryDossierContact
|
||||
persist = factory_dossier.ReadNomPrenom(nom_recherche, prenom_recherche)
|
||||
|
||||
if not persist:
|
||||
raise ValueError(f"Contact CT_No={contact_numero} non trouvé pour client {numero}")
|
||||
|
||||
# Essayer de caster
|
||||
contact = None
|
||||
for interface_name in ["IBOContactT3", "IBOContact3", "IBOContactT"]:
|
||||
try:
|
||||
contact = win32com.client.CastTo(persist, interface_name)
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
if not contact:
|
||||
contact = persist
|
||||
raise ValueError(f"Contact non trouvable via ReadNomPrenom")
|
||||
|
||||
contact = win32com.client.CastTo(persist, "IBOTiersContact3")
|
||||
contact.Read()
|
||||
logger.info(f" ✓ Contact chargé: {getattr(contact, 'CT_Nom', '?')}")
|
||||
logger.info(f" OK Contact charge: {contact.Nom}")
|
||||
|
||||
except Exception as e:
|
||||
raise ValueError(f"Contact introuvable: {e}")
|
||||
|
||||
# Appliquer les modifications
|
||||
logger.info("[2] Application des modifications")
|
||||
logger.info("[3] Application des modifications")
|
||||
modifications_appliquees = []
|
||||
|
||||
# Identité
|
||||
if "civilite" in updates:
|
||||
civilite_map = {"M.": 0, "Mme": 1, "Mlle": 2, "Société": 3}
|
||||
civilite_map = {"M.": 0, "Mme": 1, "Mlle": 2, "Societe": 3}
|
||||
civilite_code = civilite_map.get(updates["civilite"])
|
||||
if civilite_code is not None:
|
||||
self._try_set_attribute(contact, "CT_Civilite", civilite_code)
|
||||
logger.info(f" CT_Civilite = {civilite_code}")
|
||||
try:
|
||||
contact.Civilite = civilite_code
|
||||
logger.info(f" Civilite = {civilite_code}")
|
||||
modifications_appliquees.append("civilite")
|
||||
except:
|
||||
pass
|
||||
|
||||
if "nom" in updates:
|
||||
nom = self._clean_str(updates["nom"], 35)
|
||||
if nom:
|
||||
self._try_set_attribute(contact, "CT_Nom", nom)
|
||||
logger.info(f" CT_Nom = {nom}")
|
||||
try:
|
||||
contact.Nom = nom
|
||||
logger.info(f" Nom = {nom}")
|
||||
modifications_appliquees.append("nom")
|
||||
except:
|
||||
pass
|
||||
|
||||
if "prenom" in updates:
|
||||
prenom = self._clean_str(updates["prenom"], 35)
|
||||
self._try_set_attribute(contact, "CT_Prenom", prenom)
|
||||
logger.info(f" CT_Prenom = {prenom}")
|
||||
try:
|
||||
contact.Prenom = prenom
|
||||
logger.info(f" Prenom = {prenom}")
|
||||
modifications_appliquees.append("prenom")
|
||||
except:
|
||||
pass
|
||||
|
||||
if "fonction" in updates:
|
||||
fonction = self._clean_str(updates["fonction"], 35)
|
||||
self._try_set_attribute(contact, "CT_Fonction", fonction)
|
||||
logger.info(f" CT_Fonction = {fonction}")
|
||||
try:
|
||||
contact.Fonction = fonction
|
||||
logger.info(f" Fonction = {fonction}")
|
||||
modifications_appliquees.append("fonction")
|
||||
except:
|
||||
pass
|
||||
|
||||
# Service
|
||||
if "service_code" in updates:
|
||||
service = self._safe_int(updates["service_code"])
|
||||
if service is not None:
|
||||
self._try_set_attribute(contact, "N_Service", service)
|
||||
logger.info(f" N_Service = {service}")
|
||||
if service is not None and hasattr(contact, 'ServiceContact'):
|
||||
try:
|
||||
contact.ServiceContact = service
|
||||
logger.info(f" ServiceContact = {service}")
|
||||
modifications_appliquees.append("service_code")
|
||||
|
||||
# Coordonnées
|
||||
coord_fields = {
|
||||
"telephone": ("CT_Telephone", 21),
|
||||
"portable": ("CT_TelPortable", 21),
|
||||
"telecopie": ("CT_Telecopie", 21),
|
||||
"email": ("CT_EMail", 69),
|
||||
}
|
||||
|
||||
for key, (attr, max_len) in coord_fields.items():
|
||||
if key in updates:
|
||||
value = self._clean_str(updates[key], max_len)
|
||||
self._try_set_attribute(contact, attr, value)
|
||||
logger.info(f" {attr} = {value}")
|
||||
modifications_appliquees.append(key)
|
||||
|
||||
# Réseaux sociaux
|
||||
social_fields = {
|
||||
"facebook": ("CT_Facebook", 69),
|
||||
"linkedin": ("CT_LinkedIn", 69),
|
||||
"skype": ("CT_Skype", 69),
|
||||
}
|
||||
|
||||
for key, (attr, max_len) in social_fields.items():
|
||||
if key in updates:
|
||||
value = self._clean_str(updates[key], max_len)
|
||||
self._try_set_attribute(contact, attr, value)
|
||||
logger.info(f" {attr} = {value}")
|
||||
modifications_appliquees.append(key)
|
||||
|
||||
# Enregistrement du contact
|
||||
logger.info("[3] WRITE CONTACT")
|
||||
try:
|
||||
contact.Write()
|
||||
try:
|
||||
contact.Read()
|
||||
except:
|
||||
pass
|
||||
logger.info(" ✓ Write() réussi")
|
||||
|
||||
# Coordonnées via Telecom
|
||||
if hasattr(contact, 'Telecom'):
|
||||
try:
|
||||
telecom = contact.Telecom
|
||||
|
||||
if "telephone" in updates:
|
||||
telephone = self._clean_str(updates["telephone"], 21)
|
||||
if self._try_set_attribute(telecom, "Telephone", telephone):
|
||||
logger.info(f" Telephone = {telephone}")
|
||||
modifications_appliquees.append("telephone")
|
||||
|
||||
if "portable" in updates:
|
||||
portable = self._clean_str(updates["portable"], 21)
|
||||
if self._try_set_attribute(telecom, "Portable", portable):
|
||||
logger.info(f" Portable = {portable}")
|
||||
modifications_appliquees.append("portable")
|
||||
|
||||
if "email" in updates:
|
||||
email = self._clean_str(updates["email"], 69)
|
||||
if self._try_set_attribute(telecom, "EMail", email):
|
||||
logger.info(f" EMail = {email}")
|
||||
modifications_appliquees.append("email")
|
||||
|
||||
if "telecopie" in updates:
|
||||
fax = self._clean_str(updates["telecopie"], 21)
|
||||
if self._try_set_attribute(telecom, "Telecopie", fax):
|
||||
logger.info(f" Telecopie = {fax}")
|
||||
modifications_appliquees.append("telecopie")
|
||||
except:
|
||||
pass
|
||||
|
||||
# Réseaux sociaux
|
||||
if "facebook" in updates:
|
||||
facebook = self._clean_str(updates["facebook"], 69)
|
||||
try:
|
||||
contact.Facebook = facebook
|
||||
logger.info(f" Facebook = {facebook}")
|
||||
modifications_appliquees.append("facebook")
|
||||
except:
|
||||
pass
|
||||
|
||||
if "linkedin" in updates:
|
||||
linkedin = self._clean_str(updates["linkedin"], 69)
|
||||
try:
|
||||
contact.LinkedIn = linkedin
|
||||
logger.info(f" LinkedIn = {linkedin}")
|
||||
modifications_appliquees.append("linkedin")
|
||||
except:
|
||||
pass
|
||||
|
||||
if "skype" in updates:
|
||||
skype = self._clean_str(updates["skype"], 69)
|
||||
try:
|
||||
contact.Skype = skype
|
||||
logger.info(f" Skype = {skype}")
|
||||
modifications_appliquees.append("skype")
|
||||
except:
|
||||
pass
|
||||
|
||||
# Enregistrement du contact
|
||||
logger.info("[4] Enregistrement")
|
||||
try:
|
||||
contact.Write()
|
||||
contact.Read()
|
||||
logger.info(" OK Write() reussi")
|
||||
except Exception as e:
|
||||
error_detail = str(e)
|
||||
try:
|
||||
|
|
@ -7110,67 +7167,44 @@ class SageConnector:
|
|||
error_detail = f"{sage_error.Description} (Code: {sage_error.Number})"
|
||||
except:
|
||||
pass
|
||||
logger.error(f" ✗ Erreur Write: {error_detail}")
|
||||
raise RuntimeError(f"Échec modification contact: {error_detail}")
|
||||
logger.error(f" ERROR Write: {error_detail}")
|
||||
raise RuntimeError(f"Echec modification contact: {error_detail}")
|
||||
|
||||
logger.info(f" Modifications appliquées: {', '.join(modifications_appliquees)}")
|
||||
logger.info(f" Modifications appliquees: {', '.join(modifications_appliquees)}")
|
||||
|
||||
# Gestion du contact par défaut
|
||||
est_defaut_demande = updates.get("est_defaut")
|
||||
est_actuellement_defaut = False
|
||||
|
||||
if est_defaut_demande is not None and est_defaut_demande:
|
||||
logger.info("[4] Gestion contact par défaut")
|
||||
logger.info("[5] Gestion contact par defaut")
|
||||
try:
|
||||
# Construire le nom complet
|
||||
nom_final = getattr(contact, "CT_Nom", "")
|
||||
prenom_final = getattr(contact, "CT_Prenom", "")
|
||||
nom_complet = f"{prenom_final} {nom_final}".strip() if prenom_final else nom_final
|
||||
nom_complet = f"{contact.Prenom} {contact.Nom}".strip() if contact.Prenom else contact.Nom
|
||||
|
||||
# Charger le client
|
||||
factory_client = self.cial.CptaApplication.FactoryClient
|
||||
persist_client = factory_client.ReadNumero(numero)
|
||||
client_obj = win32com.client.CastTo(persist_client, "IBOClient3")
|
||||
client_obj.Read()
|
||||
|
||||
# Mettre à jour CT_Contact
|
||||
ancien_contact = getattr(client_obj, "CT_Contact", "")
|
||||
client_obj.CT_Contact = nom_complet
|
||||
logger.info(f" CT_Contact: '{ancien_contact}' → '{nom_complet}'")
|
||||
logger.info(f" CT_Contact = '{nom_complet}'")
|
||||
|
||||
# Essayer CT_NoContact si disponible
|
||||
if self._try_set_attribute(client_obj, "CT_NoContact", contact_numero):
|
||||
logger.info(f" CT_NoContact = {contact_numero}")
|
||||
|
||||
# Enregistrer le client
|
||||
client_obj.Write()
|
||||
client_obj.Read()
|
||||
logger.info(" ✓ Contact défini comme par défaut")
|
||||
est_actuellement_defaut = True
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f" ⚠ Échec définition par défaut: {e}")
|
||||
else:
|
||||
# Vérifier si c'est déjà le contact par défaut
|
||||
if hasattr(client_obj, 'CT_NoContact'):
|
||||
try:
|
||||
factory_client = self.cial.CptaApplication.FactoryClient
|
||||
persist_client = factory_client.ReadNumero(numero)
|
||||
client_obj = win32com.client.CastTo(persist_client, "IBOClient3")
|
||||
client_obj.Read()
|
||||
|
||||
ct_contact = getattr(client_obj, "CT_Contact", "")
|
||||
nom_final = getattr(contact, "CT_Nom", "")
|
||||
prenom_final = getattr(contact, "CT_Prenom", "")
|
||||
nom_complet = f"{prenom_final} {nom_final}".strip() if prenom_final else nom_final
|
||||
|
||||
est_actuellement_defaut = (ct_contact == nom_complet)
|
||||
client_obj.CT_NoContact = contact_numero
|
||||
logger.info(f" CT_NoContact = {contact_numero}")
|
||||
except:
|
||||
pass
|
||||
|
||||
client_obj.Write()
|
||||
client_obj.Read()
|
||||
logger.info(" OK Contact par defaut defini")
|
||||
est_actuellement_defaut = True
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f" WARN Echec: {e}")
|
||||
|
||||
logger.info("=" * 80)
|
||||
logger.info(f"[SUCCÈS] Contact modifié: CT_No={contact_numero}")
|
||||
if est_actuellement_defaut:
|
||||
logger.info(f" Contact par défaut")
|
||||
logger.info(f"[SUCCES] Contact modifie: CT_No={contact_numero}")
|
||||
logger.info("=" * 80)
|
||||
|
||||
contact_dict = self._contact_to_dict(contact)
|
||||
|
|
|
|||
Loading…
Reference in a new issue