settling invoice check

This commit is contained in:
fanilo 2026-01-15 08:14:32 +01:00
parent b6416487c0
commit ff8c35fcfa
2 changed files with 485 additions and 261 deletions

View file

@ -3696,10 +3696,107 @@ class SageConnector:
raise ValueError(f"Client {code} introuvable") raise ValueError(f"Client {code} introuvable")
client = win32com.client.CastTo(persist, "IBOClient3") client = win32com.client.CastTo(persist, "IBOClient3")
# ============================================================
# DEBUG TEMPORAIRE : Lister les méthodes disponibles
# ============================================================
methodes_client = [m for m in dir(client) if not m.startswith("_")]
logger.info(
f" [DEBUG] Méthodes disponibles sur client: {methodes_client}"
)
# Chercher spécifiquement les méthodes de verrouillage
lock_methods = [
m
for m in methodes_client
if "lock" in m.lower()
or "read" in m.lower()
or "write" in m.lower()
]
logger.info(f" [DEBUG] Méthodes lock/read/write: {lock_methods}")
# ============================================================
# VERROUILLAGE : Tenter plusieurs approches
# ============================================================
import time
max_retries = 3
retry_delay = 1.0
locked = False
lock_method_used = None
for attempt in range(max_retries):
try:
# Approche 1: ReadLock (méthode préférée)
if hasattr(client, "ReadLock"):
client.ReadLock()
locked = True
lock_method_used = "ReadLock"
logger.info(f" Verrouillage via ReadLock() [OK]")
break
# Approche 2: Lock
elif hasattr(client, "Lock"):
client.Lock()
locked = True
lock_method_used = "Lock"
logger.info(f" Verrouillage via Lock() [OK]")
break
# Approche 3: LockRecord
elif hasattr(client, "LockRecord"):
client.LockRecord()
locked = True
lock_method_used = "LockRecord"
logger.info(f" Verrouillage via LockRecord() [OK]")
break
# Approche 4: Read avec paramètre mode écriture
else:
try:
client.Read(1) # 1 = mode écriture
lock_method_used = "Read(1)"
logger.info(f" Verrouillage via Read(1) [OK]")
except TypeError:
client.Read() client.Read()
lock_method_used = "Read()"
logger.info(
f" Read() simple (pas de verrouillage explicite)"
)
break
logger.info(f" Client chargé: {getattr(client, 'CT_Intitule', '')}") except Exception as lock_err:
err_str = str(lock_err)
is_lock_error = (
"en cours d'utilisation" in err_str
or "-2512" in err_str
or "locked" in err_str.lower()
)
if is_lock_error:
if attempt < max_retries - 1:
logger.warning(
f" Tentative {attempt + 1}/{max_retries} - "
f"Client verrouillé, attente {retry_delay}s..."
)
time.sleep(retry_delay)
retry_delay *= 2 # Backoff exponentiel
else:
raise RuntimeError(
f"Client {code} verrouillé après {max_retries} tentatives. "
"Vérifiez qu'il n'est pas ouvert dans Sage ou par un autre processus."
)
else:
# Autre erreur, propager
raise
logger.info(
f" Client chargé: {getattr(client, 'CT_Intitule', '')} (via {lock_method_used})"
)
# ============================================================
# ETAPE 2: IDENTIFICATION
# ============================================================
logger.info("[ETAPE 2] IDENTIFICATION") logger.info("[ETAPE 2] IDENTIFICATION")
if "intitule" in client_data: if "intitule" in client_data:
@ -3757,6 +3854,9 @@ class SageConnector:
): ):
champs_modifies.append("code_naf") champs_modifies.append("code_naf")
# ============================================================
# ETAPE 3: ADRESSE
# ============================================================
adresse_keys = [ adresse_keys = [
"contact", "contact",
"adresse", "adresse",
@ -3830,6 +3930,9 @@ class SageConnector:
except Exception as e: except Exception as e:
logger.error(f" Adresse erreur: {e}") logger.error(f" Adresse erreur: {e}")
# ============================================================
# ETAPE 4: TELECOM
# ============================================================
telecom_keys = [ telecom_keys = [
"telephone", "telephone",
"telecopie", "telecopie",
@ -3890,6 +3993,9 @@ class SageConnector:
except Exception as e: except Exception as e:
logger.error(f" Telecom erreur: {e}") logger.error(f" Telecom erreur: {e}")
# ============================================================
# ETAPE 5: COMPTE GENERAL
# ============================================================
if "compte_general" in client_data: if "compte_general" in client_data:
logger.info("[ETAPE 5] COMPTE GENERAL") logger.info("[ETAPE 5] COMPTE GENERAL")
@ -3916,6 +4022,9 @@ class SageConnector:
except Exception as e: except Exception as e:
logger.warning(f" CompteGPrinc erreur: {e}") logger.warning(f" CompteGPrinc erreur: {e}")
# ============================================================
# ETAPE 6: CATEGORIES
# ============================================================
if ( if (
"categorie_tarifaire" in client_data "categorie_tarifaire" in client_data
or "categorie_comptable" in client_data or "categorie_comptable" in client_data
@ -3960,6 +4069,9 @@ class SageConnector:
except Exception as e: except Exception as e:
logger.warning(f" CatCompta erreur: {e}") logger.warning(f" CatCompta erreur: {e}")
# ============================================================
# ETAPE 7: TAUX
# ============================================================
taux_modifies = False taux_modifies = False
for i in range(1, 5): for i in range(1, 5):
key = f"taux{i:02d}" key = f"taux{i:02d}"
@ -3972,6 +4084,9 @@ class SageConnector:
if try_set_attribute(client, f"CT_Taux{i:02d}", val): if try_set_attribute(client, f"CT_Taux{i:02d}", val):
champs_modifies.append(key) champs_modifies.append(key)
# ============================================================
# ETAPE 8: STATISTIQUES
# ============================================================
stat_modifies = False stat_modifies = False
stat01 = client_data.get("statistique01") or client_data.get("secteur") stat01 = client_data.get("statistique01") or client_data.get("secteur")
@ -3999,6 +4114,9 @@ class SageConnector:
): ):
champs_modifies.append(key) champs_modifies.append(key)
# ============================================================
# ETAPE 9: COMMERCIAL
# ============================================================
commercial_keys = [ commercial_keys = [
"encours_autorise", "encours_autorise",
"assurance_credit", "assurance_credit",
@ -4050,6 +4168,9 @@ class SageConnector:
except Exception as e: except Exception as e:
logger.warning(f" Collaborateur erreur: {e}") logger.warning(f" Collaborateur erreur: {e}")
# ============================================================
# ETAPE 10: FACTURATION
# ============================================================
facturation_keys = [ facturation_keys = [
"lettrage_auto", "lettrage_auto",
"est_actif", "est_actif",
@ -4112,6 +4233,9 @@ class SageConnector:
): ):
champs_modifies.append(key) champs_modifies.append(key)
# ============================================================
# ETAPE 11: LOGISTIQUE
# ============================================================
logistique_keys = [ logistique_keys = [
"priorite_livraison", "priorite_livraison",
"livraison_partielle", "livraison_partielle",
@ -4136,6 +4260,9 @@ class SageConnector:
): ):
champs_modifies.append(key) champs_modifies.append(key)
# ============================================================
# ETAPE 12: COMMENTAIRE
# ============================================================
if "commentaire" in client_data: if "commentaire" in client_data:
logger.info("[ETAPE 12] COMMENTAIRE") logger.info("[ETAPE 12] COMMENTAIRE")
if try_set_attribute( if try_set_attribute(
@ -4145,6 +4272,9 @@ class SageConnector:
): ):
champs_modifies.append("commentaire") champs_modifies.append("commentaire")
# ============================================================
# ETAPE 13: ANALYTIQUE
# ============================================================
if "section_analytique" in client_data: if "section_analytique" in client_data:
logger.info("[ETAPE 13] ANALYTIQUE") logger.info("[ETAPE 13] ANALYTIQUE")
if try_set_attribute( if try_set_attribute(
@ -4154,6 +4284,9 @@ class SageConnector:
): ):
champs_modifies.append("section_analytique") champs_modifies.append("section_analytique")
# ============================================================
# ETAPE 14: ORGANISATION & SURVEILLANCE
# ============================================================
organisation_keys = [ organisation_keys = [
"mode_reglement_code", "mode_reglement_code",
"surveillance_active", "surveillance_active",
@ -4261,8 +4394,20 @@ class SageConnector:
): ):
champs_modifies.append("sv_resultat") champs_modifies.append("sv_resultat")
# ============================================================
# VERIFICATION AVANT WRITE
# ============================================================
if not champs_modifies: if not champs_modifies:
logger.warning("Aucun champ à modifier") logger.warning("Aucun champ à modifier")
# Déverrouiller si nécessaire
if locked:
try:
if hasattr(client, "ReadUnlock"):
client.ReadUnlock()
elif hasattr(client, "Unlock"):
client.Unlock()
except Exception:
pass
return _extraire_client(client) return _extraire_client(client)
logger.info("=" * 80) logger.info("=" * 80)
@ -4271,9 +4416,11 @@ class SageConnector:
logger.info(f" {i}. {champ}") logger.info(f" {i}. {champ}")
logger.info("=" * 80) logger.info("=" * 80)
# ============================================================
# WRITE AVEC GESTION DU DEVERROUILLAGE
# ============================================================
try: try:
client.Write() client.Write()
client.Read()
logger.info("[OK] Write réussi") logger.info("[OK] Write réussi")
except Exception as e: except Exception as e:
error_detail = str(e) error_detail = str(e)
@ -4288,6 +4435,24 @@ class SageConnector:
logger.error(f"[ERREUR] {error_detail}") logger.error(f"[ERREUR] {error_detail}")
raise RuntimeError(f"Echec Write(): {error_detail}") raise RuntimeError(f"Echec Write(): {error_detail}")
finally:
# Toujours déverrouiller après Write (succès ou échec)
if locked:
try:
if hasattr(client, "ReadUnlock"):
client.ReadUnlock()
logger.debug(" ReadUnlock() [OK]")
elif hasattr(client, "Unlock"):
client.Unlock()
logger.debug(" Unlock() [OK]")
elif hasattr(client, "UnlockRecord"):
client.UnlockRecord()
logger.debug(" UnlockRecord() [OK]")
except Exception as unlock_err:
logger.warning(f" Déverrouillage ignoré: {unlock_err}")
# Relire après Write pour retourner les données à jour
client.Read()
logger.info("=" * 80) logger.info("=" * 80)
logger.info( logger.info(

View file

@ -135,14 +135,6 @@ def regler_facture(
if not echeance: if not echeance:
raise ValueError(f"Facture {numero_facture} sans échéance") raise ValueError(f"Facture {numero_facture} sans échéance")
transaction_active = False
try:
self.cial.CptaApplication.BeginTrans()
transaction_active = True
except Exception:
pass
try:
numero_reglement = _executer_reglement_com( numero_reglement = _executer_reglement_com(
self, self,
doc, doc,
@ -157,13 +149,7 @@ def regler_facture(
numero_facture, numero_facture,
) )
if transaction_active: time.sleep(0.3)
try:
self.cial.CptaApplication.CommitTrans()
except Exception:
pass
time.sleep(0.5)
doc.Read() doc.Read()
nouveau_montant_regle = float(getattr(doc, "DO_MontantRegle", 0.0)) nouveau_montant_regle = float(getattr(doc, "DO_MontantRegle", 0.0))
@ -190,13 +176,6 @@ def regler_facture(
"facture_soldee": nouveau_solde < 0.01, "facture_soldee": nouveau_solde < 0.01,
"client_code": client_code, "client_code": client_code,
} }
except Exception:
if transaction_active:
try:
self.cial.CptaApplication.RollbackTrans()
except Exception:
pass
raise
except ValueError: except ValueError:
raise raise
except Exception as e: except Exception as e:
@ -241,225 +220,262 @@ def _executer_reglement_com(
): ):
erreurs = [] erreurs = []
# Approche 1: CreateProcess_ReglerEcheances - Créer règlement puis l'assigner # APPROCHE PRINCIPALE: Créer règlement complet, l'écrire, puis l'assigner au process
try: try:
logger.info( logger.info("Création du règlement via FactoryDocumentReglement...")
"Tentative via CreateProcess_ReglerEcheances avec règlement créé..."
)
process = self.cial.CreateProcess_ReglerEcheances()
if process: # 1. Créer le règlement
# D'abord créer un règlement via FactoryDocumentReglement
factory_reg = self.cial.FactoryDocumentReglement factory_reg = self.cial.FactoryDocumentReglement
reg = factory_reg.Create() reg = factory_reg.Create()
reg = win32com.client.CastTo(reg, "IBODocumentReglement") reg = win32com.client.CastTo(reg, "IBODocumentReglement")
logger.info(" Règlement créé et casté vers IBODocumentReglement")
# Configurer le règlement # 2. Configurer le Journal (objet)
try: try:
journal_factory = self.cial.CptaApplication.FactoryJournal journal_factory = self.cial.CptaApplication.FactoryJournal
journal_persist = journal_factory.ReadNumero(code_journal) journal_persist = journal_factory.ReadNumero(code_journal)
if journal_persist: if journal_persist:
reg.Journal = journal_persist reg.Journal = journal_persist
logger.info(f" Journal: {code_journal}") logger.info(f" Journal défini: {code_journal}")
except Exception as e: except Exception as e:
logger.warning(f" Journal: {e}") logger.warning(f" Journal: {e}")
# 3. Configurer le TiersPayeur (objet client)
try: try:
factory_client = self.cial.CptaApplication.FactoryClient factory_client = self.cial.CptaApplication.FactoryClient
if client_code: if client_code:
client_persist = factory_client.ReadNumero(client_code) client_persist = factory_client.ReadNumero(client_code)
if client_persist: if client_persist:
reg.TiersPayeur = client_persist reg.TiersPayeur = client_persist
logger.info(f" TiersPayeur: {client_code}") logger.info(f" TiersPayeur défini: {client_code}")
except Exception as e: except Exception as e:
logger.warning(f" TiersPayeur: {e}") logger.warning(f" TiersPayeur: {e}")
# 4. Configurer les champs simples
try: try:
reg.RG_Date = pywintypes.Time(date_reglement) reg.RG_Date = pywintypes.Time(date_reglement)
except Exception: logger.info(f" RG_Date: {date_reglement}")
pass except Exception as e:
logger.warning(f" RG_Date: {e}")
try: try:
reg.RG_Montant = montant reg.RG_Montant = montant
except Exception: logger.info(f" RG_Montant: {montant}")
pass except Exception as e:
logger.warning(f" RG_Montant: {e}")
# 5. Mode de règlement via l'objet Reglement
try:
# Lire le mode de règlement depuis la base
mode_factory = getattr(
self.cial.CptaApplication, "FactoryModeReglement", None
)
if mode_factory:
mode_obj = mode_factory.ReadNumero(mode_reglement)
if mode_obj:
reg.Reglement = mode_obj
logger.info(f" Mode règlement défini: {mode_reglement}")
except Exception as e:
logger.debug(f" Mode règlement via factory: {e}")
if reference: if reference:
try: try:
reg.RG_Reference = reference reg.RG_Reference = reference
except Exception: except Exception:
pass pass
if libelle: if libelle:
try: try:
reg.RG_Libelle = libelle reg.RG_Libelle = libelle
except Exception: except Exception:
pass pass
try: try:
reg.RG_Impute = 1 reg.RG_Impute = 1 # Imputé
except Exception: except Exception:
pass pass
# Assigner le règlement au process
try: try:
process.Reglement = reg reg.RG_Compta = 0 # Non comptabilisé
logger.info(" Règlement assigné au process") except Exception:
pass
# 6. ÉCRIRE le règlement
reg.Write()
numero = getattr(reg, "RG_Piece", None)
logger.info(f" Règlement écrit avec numéro: {numero}")
# 7. Créer le lien règlement-échéance via la factory DU RÈGLEMENT
try:
logger.info(" Création du lien règlement-échéance...")
factory_reg_ech = getattr(reg, "FactoryDocumentReglementEcheance", None)
if factory_reg_ech:
reg_ech = factory_reg_ech.Create()
# Cast vers IBODocumentReglementEcheance
for iface in [
"IBODocumentReglementEcheance3",
"IBODocumentReglementEcheance",
]:
try:
reg_ech = win32com.client.CastTo(reg_ech, iface)
logger.info(f" Cast vers {iface} réussi")
break
except Exception:
continue
# Définir l'échéance - le Reglement est déjà lié via la factory
try:
reg_ech.Echeance = echeance
logger.info(" Echeance définie")
except Exception as e: except Exception as e:
logger.warning(f" Assignation règlement: {e}") logger.warning(f" Echeance: {e}")
# Ajouter l'échéance avec montant # Définir le montant
try: try:
process.AddDocumentEcheanceMontant(echeance, montant) reg_ech.RC_Montant = montant
logger.info(" Échéance ajoutée avec montant") logger.info(f" RC_Montant: {montant}")
except Exception as e1: except Exception as e:
logger.debug(f" AddDocumentEcheanceMontant: {e1}") logger.warning(f" RC_Montant: {e}")
# Écrire le lien
try: try:
process.AddDocumentEcheance(echeance) reg_ech.SetDefault()
logger.info(" Échéance ajoutée")
except Exception as e2:
raise RuntimeError(f"AddEcheance: {e2}")
can_process = getattr(process, "CanProcess", True)
logger.info(f" CanProcess: {can_process}")
if can_process:
process.Process()
logger.info(" Process() réussi")
numero = None
try:
result = getattr(process, "ReglementResult", None)
if result:
result.Read()
numero = getattr(result, "RG_Piece", "")
except Exception: except Exception:
pass pass
reg_ech.Write()
logger.info(" Lien règlement-échéance écrit!")
return str(numero) if numero else None return str(numero) if numero else None
except Exception as e: except Exception as e:
erreurs.append(f"CreateProcess avec règlement: {e}") erreurs.append(f"Lien échéance: {e}")
logger.warning(f"CreateProcess avec règlement échoué: {e}") logger.warning(f" Erreur création lien: {e}")
# Approche 2: Configurer le Reglement du process directement (toutes propriétés) # Si le lien a échoué, essayer via le process
logger.info(" Tentative via CreateProcess_ReglerEcheances...")
try: try:
logger.info("Tentative via configuration complète Process.Reglement...")
process = self.cial.CreateProcess_ReglerEcheances() process = self.cial.CreateProcess_ReglerEcheances()
if process: # Assigner le règlement déjà écrit
reglement = getattr(process, "Reglement", None) process.Reglement = reg
if reglement: logger.info(" Règlement assigné au process")
# Lister TOUS les attributs
reg_attrs = [a for a in dir(reglement) if not a.startswith("_")]
logger.info(f" Attributs Reglement: {reg_attrs}")
# Configurer TOUT
_set_safe(
reglement, ["RG_Date", "Date"], pywintypes.Time(date_reglement)
)
_set_safe(reglement, ["RG_Montant", "Montant"], montant)
_set_safe(reglement, ["JO_Num", "Journal", "CodeJournal"], code_journal)
_set_safe(
reglement,
["CT_NumPayeur", "CT_Num", "Tiers", "Client"],
client_code,
)
_set_safe(
reglement,
["N_Reglement", "ModeReglement", "RG_ModeReglement"],
mode_reglement,
)
_set_safe(reglement, ["RG_Type", "Type"], 0) # 0 = Client
_set_safe(reglement, ["RG_Impute", "Impute"], 1)
_set_safe(reglement, ["RG_Compta", "Compta"], 0)
if reference:
_set_safe(reglement, ["RG_Reference", "Reference"], reference)
if libelle:
_set_safe(reglement, ["RG_Libelle", "Libelle"], libelle)
# Essayer SetDefault
try:
reglement.SetDefault()
logger.info(" SetDefault() appelé")
except Exception:
pass
logger.info(" Reglement configuré")
# Ajouter l'échéance # Ajouter l'échéance
try: try:
process.AddDocumentEcheanceMontant(echeance, montant) process.AddDocumentEcheanceMontant(echeance, montant)
logger.info(" Échéance ajoutée") logger.info(" Échéance ajoutée avec montant")
except Exception as e1: except Exception:
try:
process.AddDocumentEcheance(echeance) process.AddDocumentEcheance(echeance)
logger.info(" Échéance ajoutée (sans montant)") logger.info(" Échéance ajoutée")
except Exception as e2:
raise RuntimeError(f"AddEcheance: {e2}")
can_process = getattr(process, "CanProcess", True) can_process = getattr(process, "CanProcess", True)
logger.info(f" CanProcess: {can_process}") logger.info(f" CanProcess: {can_process}")
# Vérifier les erreurs du process
try:
errors = getattr(process, "Errors", None)
if errors:
err_count = getattr(errors, "Count", 0)
for i in range(1, err_count + 1):
err = errors.Item(i)
logger.warning(f" Erreur process [{i}]: {err}")
except Exception:
pass
if can_process: if can_process:
process.Process() process.Process()
logger.info(" Process() réussi") logger.info(" Process() réussi!")
return str(numero) if numero else None
numero = None else:
# Vérifier les erreurs
try: try:
result = getattr(process, "ReglementResult", None) errors = process.Errors
if result: if errors:
result.Read() for i in range(1, errors.Count + 1):
numero = getattr(result, "RG_Piece", "") logger.warning(f" Erreur [{i}]: {errors.Item(i)}")
except Exception: except Exception:
pass pass
return str(numero) if numero else None except Exception as e:
else: erreurs.append(f"Process: {e}")
logger.warning(" CanProcess = False!") logger.warning(f" Process échoué: {e}")
except Exception as e: except Exception as e:
erreurs.append(f"Config complète: {e}") erreurs.append(f"FactoryDocumentReglement: {e}")
logger.warning(f"Config complète échouée: {e}") logger.error(f"FactoryDocumentReglement échoué: {e}")
# Approche 3: Utiliser SetDefaultReglement sur le document # APPROCHE ALTERNATIVE: Via le mode règlement de l'échéance
try: try:
logger.info("Tentative via doc.SetDefaultReglement...") logger.info("Tentative via modification directe de l'échéance...")
if hasattr(doc, "SetDefaultReglement"): # L'échéance a un attribut Reglement qui est le mode de règlement
doc.SetDefaultReglement() mode_obj = getattr(echeance, "Reglement", None)
logger.info(" SetDefaultReglement() appelé") if mode_obj:
attrs = [a for a in dir(mode_obj) if not a.startswith("_")]
logger.info(f" Attributs Reglement échéance: {attrs[:15]}...")
# Configurer via le règlement par défaut # Vérifier si l'échéance a FactoryDocumentReglementEcheance
reg = getattr(doc, "Reglement", None) factory_reg_ech = getattr(echeance, "FactoryDocumentReglementEcheance", None)
if reg: if factory_reg_ech:
attrs = [a for a in dir(reg) if not a.startswith("_")] logger.info(" FactoryDocumentReglementEcheance trouvée sur échéance")
logger.info(f" Attributs doc.Reglement: {attrs[:15]}...")
except Exception as e: # Créer le lien depuis l'échéance
erreurs.append(f"SetDefaultReglement: {e}") reg_ech = factory_reg_ech.Create()
logger.warning(f"SetDefaultReglement: {e}")
raise RuntimeError(f"Aucune méthode n'a fonctionné. Erreurs: {'; '.join(erreurs)}") for iface in [
"IBODocumentReglementEcheance3",
"IBODocumentReglementEcheance",
def _set_safe(obj, attrs, value): ]:
for attr in attrs:
try: try:
setattr(obj, attr, value) reg_ech = win32com.client.CastTo(reg_ech, iface)
logger.debug(f" {attr} = {value}") logger.info(f" Cast vers {iface}")
return True break
except Exception: except Exception:
continue continue
return False
# Ici, l'échéance devrait déjà être liée
# Il faut définir le règlement
try:
# Créer un nouveau règlement pour ce lien
factory_reg = self.cial.FactoryDocumentReglement
new_reg = factory_reg.Create()
new_reg = win32com.client.CastTo(new_reg, "IBODocumentReglement")
# Configurer minimalement
journal_factory = self.cial.CptaApplication.FactoryJournal
journal_persist = journal_factory.ReadNumero(code_journal)
if journal_persist:
new_reg.Journal = journal_persist
factory_client = self.cial.CptaApplication.FactoryClient
if client_code:
client_persist = factory_client.ReadNumero(client_code)
if client_persist:
new_reg.TiersPayeur = client_persist
new_reg.RG_Date = pywintypes.Time(date_reglement)
new_reg.RG_Montant = montant
new_reg.RG_Impute = 1
# Écrire le règlement
new_reg.Write()
logger.info(
f" Nouveau règlement créé: {getattr(new_reg, 'RG_Piece', None)}"
)
# Assigner au lien - ici on doit peut-être utiliser un autre attribut
# Puisque reg_ech.Reglement n'est pas settable, essayons via SetDefault
try:
reg_ech.SetDefault()
except Exception:
pass
reg_ech.RC_Montant = montant
reg_ech.Write()
logger.info(" Lien créé depuis échéance!")
return str(getattr(new_reg, "RG_Piece", None))
except Exception as e:
logger.warning(f" Erreur: {e}")
except Exception as e:
erreurs.append(f"Via échéance: {e}")
logger.warning(f"Via échéance échoué: {e}")
raise RuntimeError(f"Aucune méthode n'a fonctionné. Erreurs: {'; '.join(erreurs)}")
def introspecter_reglement(self): def introspecter_reglement(self):
@ -468,28 +484,7 @@ def introspecter_reglement(self):
result = {} result = {}
try: try:
with self._com_context(), self._lock_com: with self._com_context(), self._lock_com:
# Process et son Reglement # IBODocumentReglement et sa factory de liens
try:
process = self.cial.CreateProcess_ReglerEcheances()
result["Process"] = [a for a in dir(process) if not a.startswith("_")]
reglement = getattr(process, "Reglement", None)
if reglement:
result["Process_Reglement"] = [
a for a in dir(reglement) if not a.startswith("_")
]
# Essayer de lire les valeurs par défaut
for attr in ["RG_Type", "RG_Impute", "JO_Num", "CT_NumPayeur"]:
try:
val = getattr(reglement, attr, "N/A")
result[f"Reglement_{attr}"] = str(val)
except Exception:
pass
except Exception as e:
result["error_process"] = str(e)
# IBODocumentReglement
try: try:
factory = self.cial.FactoryDocumentReglement factory = self.cial.FactoryDocumentReglement
reg = factory.Create() reg = factory.Create()
@ -497,10 +492,38 @@ def introspecter_reglement(self):
result["IBODocumentReglement"] = [ result["IBODocumentReglement"] = [
a for a in dir(reg) if not a.startswith("_") a for a in dir(reg) if not a.startswith("_")
] ]
# FactoryDocumentReglementEcheance depuis le règlement
factory_lien = getattr(reg, "FactoryDocumentReglementEcheance", None)
if factory_lien:
lien = factory_lien.Create()
result["ReglementEcheance_base"] = [
a for a in dir(lien) if not a.startswith("_")
]
for iface in [
"IBODocumentReglementEcheance3",
"IBODocumentReglementEcheance",
]:
try:
lien_cast = win32com.client.CastTo(lien, iface)
result[f"ReglementEcheance_{iface}"] = [
a for a in dir(lien_cast) if not a.startswith("_")
]
except Exception as e:
result[f"cast_{iface}_error"] = str(e)
except Exception as e: except Exception as e:
result["error_reglement"] = str(e) result["error_reglement"] = str(e)
# Échéance # Process
try:
process = self.cial.CreateProcess_ReglerEcheances()
result["Process"] = [a for a in dir(process) if not a.startswith("_")]
except Exception as e:
result["error_process"] = str(e)
# Échéance et ses attributs
try: try:
factory_doc = self.cial.FactoryDocumentVente factory_doc = self.cial.FactoryDocumentVente
doc_list = factory_doc.List doc_list = factory_doc.List
@ -528,10 +551,46 @@ def introspecter_reglement(self):
if not a.startswith("_") if not a.startswith("_")
] ]
# Mode règlement de l'échéance # FactoryDocumentReglementEcheance depuis l'échéance
factory_lien_ech = getattr(
ech,
"FactoryDocumentReglementEcheance",
None,
)
if factory_lien_ech:
lien_ech = factory_lien_ech.Create()
result[
"EcheanceReglementEcheance_base"
] = [
a
for a in dir(lien_ech)
if not a.startswith("_")
]
for iface in [
"IBODocumentReglementEcheance3",
"IBODocumentReglementEcheance",
]:
try:
lien_ech_cast = (
win32com.client.CastTo(
lien_ech, iface
)
)
result[
f"EcheanceReglementEcheance_{iface}"
] = [
a
for a in dir(lien_ech_cast)
if not a.startswith("_")
]
except Exception:
pass
# Reglement de l'échéance (mode)
mode = getattr(ech, "Reglement", None) mode = getattr(ech, "Reglement", None)
if mode: if mode:
result["Echeance_Reglement"] = [ result["Echeance_Reglement_mode"] = [
a a
for a in dir(mode) for a in dir(mode)
if not a.startswith("_") if not a.startswith("_")