refactor: Replace native Sage TransformInto() with manual document transformation logic, including source data extraction and simplified transformation rules.
This commit is contained in:
parent
6c1de3583c
commit
6733f506eb
1 changed files with 294 additions and 152 deletions
|
|
@ -1027,8 +1027,10 @@ class SageConnector:
|
||||||
|
|
||||||
def transformer_document(self, numero_source, type_source, type_cible):
|
def transformer_document(self, numero_source, type_source, type_cible):
|
||||||
"""
|
"""
|
||||||
Transformation de document avec la méthode NATIVE de Sage
|
🔧 Transformation de document - MÉTHODE MANUELLE
|
||||||
✅ CORRECTION : Utilise les VRAIS types Sage Dataven
|
|
||||||
|
⚠️ TransformInto() n'est pas disponible sur cette installation Sage
|
||||||
|
→ On crée manuellement le document cible en copiant les données
|
||||||
"""
|
"""
|
||||||
if not self.cial:
|
if not self.cial:
|
||||||
raise RuntimeError("Connexion Sage non etablie")
|
raise RuntimeError("Connexion Sage non etablie")
|
||||||
|
|
@ -1037,58 +1039,36 @@ class SageConnector:
|
||||||
type_cible = int(type_cible)
|
type_cible = int(type_cible)
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"[TRANSFORM] Demande: {numero_source} "
|
f"[TRANSFORM] Demande MANUELLE: {numero_source} "
|
||||||
f"(type {type_source}) -> type {type_cible}"
|
f"(type {type_source}) -> type {type_cible}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# ✅ Matrice de transformations pour VOTRE installation Sage
|
# ✅ Matrice de transformations
|
||||||
transformations_autorisees = {
|
transformations_autorisees = {
|
||||||
(
|
(0, 10): "Devis -> Commande",
|
||||||
settings.SAGE_TYPE_DEVIS,
|
(10, 30): "Commande -> Bon de livraison",
|
||||||
settings.SAGE_TYPE_BON_COMMANDE,
|
(10, 60): "Commande -> Facture",
|
||||||
): "Devis -> Commande", # 0 → 10
|
(30, 60): "Bon de livraison -> Facture",
|
||||||
(
|
(0, 60): "Devis -> Facture",
|
||||||
settings.SAGE_TYPE_BON_COMMANDE,
|
|
||||||
settings.SAGE_TYPE_BON_LIVRAISON,
|
|
||||||
): "Commande -> Bon de livraison", # 10 → 30
|
|
||||||
(
|
|
||||||
settings.SAGE_TYPE_BON_COMMANDE,
|
|
||||||
settings.SAGE_TYPE_FACTURE,
|
|
||||||
): "Commande -> Facture", # 10 → 60
|
|
||||||
(
|
|
||||||
settings.SAGE_TYPE_BON_LIVRAISON,
|
|
||||||
settings.SAGE_TYPE_FACTURE,
|
|
||||||
): "Bon de livraison -> Facture", # 30 → 60
|
|
||||||
(
|
|
||||||
settings.SAGE_TYPE_DEVIS,
|
|
||||||
settings.SAGE_TYPE_FACTURE,
|
|
||||||
): "Devis -> Facture", # 0 → 60 (si autorisé)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type_source, type_cible) not in transformations_autorisees:
|
if (type_source, type_cible) not in transformations_autorisees:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Transformation non autorisee par Sage: "
|
f"Transformation non autorisee: {type_source} -> {type_cible}"
|
||||||
f"{type_source} -> {type_cible}. "
|
|
||||||
f"Valides: "
|
|
||||||
+ ", ".join(
|
|
||||||
f"{k[0]}->{k[1]}" for k in transformations_autorisees.keys()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with self._com_context(), self._lock_com:
|
with self._com_context(), self._lock_com:
|
||||||
# ===== LECTURE SOURCE =====
|
# ========================================
|
||||||
|
# ÉTAPE 1 : LIRE LE DOCUMENT SOURCE
|
||||||
|
# ========================================
|
||||||
factory = self.cial.FactoryDocumentVente
|
factory = self.cial.FactoryDocumentVente
|
||||||
persist_source = factory.ReadPiece(type_source, numero_source)
|
persist_source = factory.ReadPiece(type_source, numero_source)
|
||||||
|
|
||||||
if not persist_source:
|
if not persist_source:
|
||||||
logger.warning(
|
|
||||||
f"[TRANSFORM] ReadPiece failed, searching in List()..."
|
|
||||||
)
|
|
||||||
persist_source = self._find_document_in_list(
|
persist_source = self._find_document_in_list(
|
||||||
numero_source, type_source
|
numero_source, type_source
|
||||||
)
|
)
|
||||||
|
|
||||||
if not persist_source:
|
if not persist_source:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Document {numero_source} (type {type_source}) introuvable"
|
f"Document {numero_source} (type {type_source}) introuvable"
|
||||||
|
|
@ -1097,152 +1077,316 @@ class SageConnector:
|
||||||
doc_source = win32com.client.CastTo(persist_source, "IBODocumentVente3")
|
doc_source = win32com.client.CastTo(persist_source, "IBODocumentVente3")
|
||||||
doc_source.Read()
|
doc_source.Read()
|
||||||
|
|
||||||
# VÉRIFICATIONS STATUT
|
# Vérifications statut
|
||||||
statut_actuel = getattr(doc_source, "DO_Statut", 0)
|
statut_actuel = getattr(doc_source, "DO_Statut", 0)
|
||||||
type_reel = getattr(doc_source, "DO_Type", -1)
|
type_reel = getattr(doc_source, "DO_Type", -1)
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"[TRANSFORM] Document source: type={type_reel}, "
|
f"[TRANSFORM] Source: type={type_reel}, statut={statut_actuel}"
|
||||||
f"statut={statut_actuel}, numero={numero_source}"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Vérifier cohérence type
|
|
||||||
if type_reel != type_source:
|
if type_reel != type_source:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Incoherence: document {numero_source} est de type {type_reel}, "
|
f"Incoherence: document est de type {type_reel}, pas {type_source}"
|
||||||
f"pas de type {type_source}"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# RÈGLES DE STATUT
|
|
||||||
if statut_actuel == 5:
|
if statut_actuel == 5:
|
||||||
raise ValueError(
|
raise ValueError("Document deja transforme (statut=5)")
|
||||||
f"Document {numero_source} deja transforme (statut=5). "
|
|
||||||
f"Impossible de le transformer a nouveau."
|
|
||||||
)
|
|
||||||
|
|
||||||
if statut_actuel == 6:
|
if statut_actuel == 6:
|
||||||
raise ValueError(
|
raise ValueError("Document annule (statut=6)")
|
||||||
f"Document {numero_source} annule (statut=6). "
|
|
||||||
f"Impossible de le transformer."
|
|
||||||
)
|
|
||||||
|
|
||||||
if statut_actuel in [3, 4]:
|
if statut_actuel in [3, 4]:
|
||||||
|
raise ValueError(f"Document deja realise (statut={statut_actuel})")
|
||||||
|
|
||||||
|
# Forcer statut "Accepté" si devis brouillon
|
||||||
|
if type_source == 0 and statut_actuel == 0:
|
||||||
|
logger.info("[TRANSFORM] Passage devis a statut Accepte (2)")
|
||||||
|
doc_source.DO_Statut = 2
|
||||||
|
doc_source.Write()
|
||||||
|
doc_source.Read()
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# ÉTAPE 2 : EXTRAIRE LES DONNÉES SOURCE
|
||||||
|
# ========================================
|
||||||
|
logger.info("[TRANSFORM] Extraction donnees source...")
|
||||||
|
|
||||||
|
# Client
|
||||||
|
client_code = ""
|
||||||
|
client_obj = None
|
||||||
|
try:
|
||||||
|
client_obj = getattr(doc_source, "Client", None)
|
||||||
|
if client_obj:
|
||||||
|
client_obj.Read()
|
||||||
|
client_code = getattr(client_obj, "CT_Num", "").strip()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Erreur lecture client: {e}")
|
||||||
|
raise ValueError(f"Impossible de lire le client du document source")
|
||||||
|
|
||||||
|
if not client_code:
|
||||||
|
raise ValueError("Client introuvable dans document source")
|
||||||
|
|
||||||
|
logger.info(f"[TRANSFORM] Client: {client_code}")
|
||||||
|
|
||||||
|
# Date
|
||||||
|
date_source = getattr(doc_source, "DO_Date", None)
|
||||||
|
|
||||||
|
# Lignes
|
||||||
|
lignes_source = []
|
||||||
|
try:
|
||||||
|
factory_lignes_source = getattr(
|
||||||
|
doc_source, "FactoryDocumentLigne", None
|
||||||
|
)
|
||||||
|
if not factory_lignes_source:
|
||||||
|
factory_lignes_source = getattr(
|
||||||
|
doc_source, "FactoryDocumentVenteLigne", None
|
||||||
|
)
|
||||||
|
|
||||||
|
if factory_lignes_source:
|
||||||
|
index = 1
|
||||||
|
while index <= 1000:
|
||||||
|
try:
|
||||||
|
ligne_p = factory_lignes_source.List(index)
|
||||||
|
if ligne_p is None:
|
||||||
|
break
|
||||||
|
|
||||||
|
ligne = win32com.client.CastTo(
|
||||||
|
ligne_p, "IBODocumentLigne3"
|
||||||
|
)
|
||||||
|
ligne.Read()
|
||||||
|
|
||||||
|
# Récupérer référence article
|
||||||
|
article_ref = ""
|
||||||
|
try:
|
||||||
|
article_ref = getattr(ligne, "AR_Ref", "").strip()
|
||||||
|
if not article_ref:
|
||||||
|
article_obj = getattr(ligne, "Article", None)
|
||||||
|
if article_obj:
|
||||||
|
article_obj.Read()
|
||||||
|
article_ref = getattr(
|
||||||
|
article_obj, "AR_Ref", ""
|
||||||
|
).strip()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
lignes_source.append(
|
||||||
|
{
|
||||||
|
"article_ref": article_ref,
|
||||||
|
"designation": getattr(ligne, "DL_Design", ""),
|
||||||
|
"quantite": float(
|
||||||
|
getattr(ligne, "DL_Qte", 0.0)
|
||||||
|
),
|
||||||
|
"prix_unitaire": float(
|
||||||
|
getattr(ligne, "DL_PrixUnitaire", 0.0)
|
||||||
|
),
|
||||||
|
"remise": float(
|
||||||
|
getattr(ligne, "DL_Remise01REM_Valeur", 0.0)
|
||||||
|
),
|
||||||
|
"type_remise": int(
|
||||||
|
getattr(ligne, "DL_Remise01REM_Type", 0)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
index += 1
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(f"Erreur ligne {index}: {e}")
|
||||||
|
break
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Erreur extraction lignes: {e}")
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Document {numero_source} deja realise (statut={statut_actuel}). "
|
"Impossible d'extraire les lignes du document source"
|
||||||
f"Ce document a deja ete transforme partiellement ou totalement."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Forcer statut "Accepté" si brouillon (uniquement pour devis)
|
nb_lignes = len(lignes_source)
|
||||||
if type_source == settings.SAGE_TYPE_DEVIS and statut_actuel == 0:
|
logger.info(f"[TRANSFORM] {nb_lignes} lignes extraites")
|
||||||
logger.warning(
|
|
||||||
f"[TRANSFORM] Devis en brouillon (statut=0), "
|
|
||||||
f"passage a 'Accepte' (statut=2)"
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
doc_source.DO_Statut = 2
|
|
||||||
doc_source.Write()
|
|
||||||
logger.info(f"[TRANSFORM] Statut change: 0 -> 2")
|
|
||||||
|
|
||||||
doc_source.Read()
|
if nb_lignes == 0:
|
||||||
nouveau_statut = getattr(doc_source, "DO_Statut", 0)
|
raise ValueError("Document source vide (aucune ligne)")
|
||||||
if nouveau_statut != 2:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"Echec changement statut: toujours a {nouveau_statut}"
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
raise RuntimeError(f"Impossible de changer le statut: {e}")
|
|
||||||
|
|
||||||
# ===== TRANSACTION =====
|
# ========================================
|
||||||
|
# ÉTAPE 3 : TRANSACTION
|
||||||
|
# ========================================
|
||||||
transaction_active = False
|
transaction_active = False
|
||||||
try:
|
try:
|
||||||
self.cial.CptaApplication.BeginTrans()
|
self.cial.CptaApplication.BeginTrans()
|
||||||
transaction_active = True
|
transaction_active = True
|
||||||
logger.debug("[TRANSFORM] Transaction demarree")
|
logger.debug("[TRANSFORM] Transaction demarree")
|
||||||
except:
|
except:
|
||||||
logger.debug(
|
logger.debug("[TRANSFORM] BeginTrans non disponible")
|
||||||
"[TRANSFORM] BeginTrans non disponible, continue sans transaction"
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# ✅✅✅ MÉTHODE NATIVE SAGE: TransformInto() ✅✅✅
|
# ========================================
|
||||||
logger.info(f"[TRANSFORM] Appel TransformInto({type_cible})...")
|
# ÉTAPE 4 : CRÉER LE DOCUMENT CIBLE
|
||||||
|
# ========================================
|
||||||
|
logger.info(f"[TRANSFORM] Creation document type {type_cible}...")
|
||||||
|
|
||||||
|
process = self.cial.CreateProcess_Document(type_cible)
|
||||||
|
if not process:
|
||||||
|
raise RuntimeError(
|
||||||
|
f"CreateProcess_Document({type_cible}) a retourne None"
|
||||||
|
)
|
||||||
|
|
||||||
|
doc_cible = process.Document
|
||||||
|
try:
|
||||||
|
doc_cible = win32com.client.CastTo(
|
||||||
|
doc_cible, "IBODocumentVente3"
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
logger.info("[TRANSFORM] Document cible cree")
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# ÉTAPE 5 : DÉFINIR LA DATE
|
||||||
|
# ========================================
|
||||||
|
import pywintypes
|
||||||
|
|
||||||
|
if date_source:
|
||||||
|
try:
|
||||||
|
doc_cible.DO_Date = date_source
|
||||||
|
logger.info(f"[TRANSFORM] Date copiee: {date_source}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Impossible de copier date: {e}")
|
||||||
|
doc_cible.DO_Date = pywintypes.Time(datetime.now())
|
||||||
|
else:
|
||||||
|
doc_cible.DO_Date = pywintypes.Time(datetime.now())
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# ÉTAPE 6 : ASSOCIER LE CLIENT
|
||||||
|
# ========================================
|
||||||
|
logger.info(f"[TRANSFORM] Association client {client_code}...")
|
||||||
|
|
||||||
|
factory_client = self.cial.CptaApplication.FactoryClient
|
||||||
|
persist_client = factory_client.ReadNumero(client_code)
|
||||||
|
|
||||||
|
if not persist_client:
|
||||||
|
raise ValueError(f"Client {client_code} introuvable")
|
||||||
|
|
||||||
|
client_obj_cible = self._cast_client(persist_client)
|
||||||
|
if not client_obj_cible:
|
||||||
|
raise ValueError(f"Impossible de charger client {client_code}")
|
||||||
|
|
||||||
|
doc_cible.SetDefaultClient(client_obj_cible)
|
||||||
|
doc_cible.Write()
|
||||||
|
|
||||||
|
logger.info(f"[TRANSFORM] Client {client_code} associe")
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# ÉTAPE 7 : COPIER LES LIGNES
|
||||||
|
# ========================================
|
||||||
|
logger.info(f"[TRANSFORM] Copie de {nb_lignes} lignes...")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
doc_cible = doc_source.TransformInto(type_cible)
|
factory_lignes_cible = doc_cible.FactoryDocumentLigne
|
||||||
|
except:
|
||||||
|
factory_lignes_cible = doc_cible.FactoryDocumentVenteLigne
|
||||||
|
|
||||||
if doc_cible is None:
|
factory_article = self.cial.FactoryArticle
|
||||||
raise RuntimeError(
|
|
||||||
"TransformInto() a retourne None. "
|
for idx, ligne_data in enumerate(lignes_source, 1):
|
||||||
"Verifiez la configuration Sage et les autorisations."
|
logger.debug(f"[TRANSFORM] Ligne {idx}/{nb_lignes}")
|
||||||
|
|
||||||
|
# Charger article
|
||||||
|
article_ref = ligne_data["article_ref"]
|
||||||
|
if not article_ref:
|
||||||
|
logger.warning(
|
||||||
|
f"Ligne {idx}: pas de reference article, skip"
|
||||||
)
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
logger.info("[TRANSFORM] TransformInto() execute avec succes")
|
persist_article = factory_article.ReadReference(article_ref)
|
||||||
|
if not persist_article:
|
||||||
|
logger.warning(
|
||||||
|
f"Ligne {idx}: article {article_ref} introuvable, skip"
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
article_obj = win32com.client.CastTo(
|
||||||
|
persist_article, "IBOArticle3"
|
||||||
|
)
|
||||||
|
article_obj.Read()
|
||||||
|
|
||||||
|
# Créer ligne
|
||||||
|
ligne_persist = factory_lignes_cible.Create()
|
||||||
try:
|
try:
|
||||||
doc_cible = win32com.client.CastTo(
|
ligne_obj = win32com.client.CastTo(
|
||||||
doc_cible, "IBODocumentVente3"
|
ligne_persist, "IBODocumentLigne3"
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
pass
|
ligne_obj = win32com.client.CastTo(
|
||||||
|
ligne_persist, "IBODocumentVenteLigne3"
|
||||||
|
)
|
||||||
|
|
||||||
doc_cible.Read()
|
# Associer article avec quantité
|
||||||
|
quantite = ligne_data["quantite"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
ligne_obj.SetDefaultArticleReference(article_ref, quantite)
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
ligne_obj.SetDefaultArticle(article_obj, quantite)
|
||||||
|
except:
|
||||||
|
# Fallback manuel
|
||||||
|
ligne_obj.DL_Design = ligne_data["designation"]
|
||||||
|
ligne_obj.DL_Qte = quantite
|
||||||
|
|
||||||
|
# Définir prix
|
||||||
|
prix = ligne_data["prix_unitaire"]
|
||||||
|
if prix > 0:
|
||||||
|
ligne_obj.DL_PrixUnitaire = float(prix)
|
||||||
|
|
||||||
|
# Copier remise
|
||||||
|
remise = ligne_data["remise"]
|
||||||
|
if remise > 0:
|
||||||
|
try:
|
||||||
|
ligne_obj.DL_Remise01REM_Valeur = float(remise)
|
||||||
|
ligne_obj.DL_Remise01REM_Type = ligne_data[
|
||||||
|
"type_remise"
|
||||||
|
]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Écrire ligne
|
||||||
|
ligne_obj.Write()
|
||||||
|
|
||||||
|
logger.info(f"[TRANSFORM] {nb_lignes} lignes copiees")
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# ÉTAPE 8 : VALIDER LE DOCUMENT
|
||||||
|
# ========================================
|
||||||
|
logger.info("[TRANSFORM] Validation document cible...")
|
||||||
|
|
||||||
|
doc_cible.Write()
|
||||||
|
process.Process()
|
||||||
|
|
||||||
|
logger.info("[TRANSFORM] Document cible valide")
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# ÉTAPE 9 : RÉCUPÉRER LE NUMÉRO
|
||||||
|
# ========================================
|
||||||
|
numero_cible = None
|
||||||
|
try:
|
||||||
|
doc_result = process.DocumentResult
|
||||||
|
if doc_result:
|
||||||
|
doc_result = win32com.client.CastTo(
|
||||||
|
doc_result, "IBODocumentVente3"
|
||||||
|
)
|
||||||
|
doc_result.Read()
|
||||||
|
numero_cible = getattr(doc_result, "DO_Piece", "")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not numero_cible:
|
||||||
numero_cible = getattr(doc_cible, "DO_Piece", "")
|
numero_cible = getattr(doc_cible, "DO_Piece", "")
|
||||||
|
|
||||||
if not numero_cible:
|
if not numero_cible:
|
||||||
raise RuntimeError(
|
raise RuntimeError("Numero document cible vide")
|
||||||
"Numero document cible vide apres transformation"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Compter les lignes
|
logger.info(f"[TRANSFORM] Document cible cree: {numero_cible}")
|
||||||
try:
|
|
||||||
factory_lignes = doc_cible.FactoryDocumentLigne
|
|
||||||
except:
|
|
||||||
factory_lignes = doc_cible.FactoryDocumentVenteLigne
|
|
||||||
|
|
||||||
nb_lignes = 0
|
# ========================================
|
||||||
index = 1
|
# ÉTAPE 10 : COMMIT & MAJ STATUT SOURCE
|
||||||
while index <= 1000:
|
# ========================================
|
||||||
try:
|
|
||||||
ligne_p = factory_lignes.List(index)
|
|
||||||
if ligne_p is None:
|
|
||||||
break
|
|
||||||
nb_lignes += 1
|
|
||||||
index += 1
|
|
||||||
except:
|
|
||||||
break
|
|
||||||
|
|
||||||
logger.info(
|
|
||||||
f"[TRANSFORM] Document cible cree: {numero_cible} avec {nb_lignes} lignes"
|
|
||||||
)
|
|
||||||
|
|
||||||
except AttributeError as e:
|
|
||||||
logger.error(f"[TRANSFORM] TransformInto() non disponible: {e}")
|
|
||||||
raise RuntimeError(
|
|
||||||
f"La methode TransformInto() n'est pas disponible. "
|
|
||||||
f"Causes possibles:\n"
|
|
||||||
f"1. Le module n'est pas active dans votre licence Sage\n"
|
|
||||||
f"2. L'utilisateur n'a pas les droits\n"
|
|
||||||
f"3. La transformation {type_source}→{type_cible} n'est pas supportee"
|
|
||||||
)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"[TRANSFORM] TransformInto() echoue: {e}")
|
|
||||||
|
|
||||||
if "Valeur invalide" in str(e):
|
|
||||||
raise RuntimeError(
|
|
||||||
f"Sage refuse la transformation vers le type {type_cible}. "
|
|
||||||
f"Verifiez:\n"
|
|
||||||
f"1. Que le module est active (Commandes, Factures...)\n"
|
|
||||||
f"2. Les droits utilisateur\n"
|
|
||||||
f"3. Que le type {type_cible} existe dans votre Sage\n"
|
|
||||||
f"4. Les parametres obligatoires (depot, tarif, etc.)"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"Erreur Sage lors de la transformation: {e}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Commit transaction
|
|
||||||
if transaction_active:
|
if transaction_active:
|
||||||
try:
|
try:
|
||||||
self.cial.CptaApplication.CommitTrans()
|
self.cial.CptaApplication.CommitTrans()
|
||||||
|
|
@ -1250,22 +1394,20 @@ class SageConnector:
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# MAJ statut source → Transformé
|
# Attente indexation
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# Marquer source comme "Transformé"
|
||||||
try:
|
try:
|
||||||
doc_source.Read()
|
doc_source.Read()
|
||||||
doc_source.DO_Statut = 5
|
doc_source.DO_Statut = 5
|
||||||
doc_source.Write()
|
doc_source.Write()
|
||||||
logger.info(
|
logger.info("[TRANSFORM] Statut source -> 5 (TRANSFORME)")
|
||||||
f"[TRANSFORM] Statut source mis a jour: -> 5 (TRANSFORME)"
|
|
||||||
)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(
|
logger.warning(f"Impossible MAJ statut source: {e}")
|
||||||
f"[TRANSFORM] Impossible de MAJ statut source: {e}"
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"[TRANSFORM] SUCCES: "
|
f"[TRANSFORM] ✅ SUCCES: {numero_source} ({type_source}) -> "
|
||||||
f"{numero_source} ({type_source}) -> "
|
|
||||||
f"{numero_cible} ({type_cible}) - {nb_lignes} lignes"
|
f"{numero_cible} ({type_cible}) - {nb_lignes} lignes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -1280,13 +1422,13 @@ class SageConnector:
|
||||||
if transaction_active:
|
if transaction_active:
|
||||||
try:
|
try:
|
||||||
self.cial.CptaApplication.RollbackTrans()
|
self.cial.CptaApplication.RollbackTrans()
|
||||||
logger.error("[TRANSFORM] Transaction annulee")
|
logger.error("[TRANSFORM] Transaction annulee (rollback)")
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
raise
|
raise
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"[TRANSFORM] Erreur: {e}", exc_info=True)
|
logger.error(f"[TRANSFORM] ❌ ERREUR: {e}", exc_info=True)
|
||||||
raise RuntimeError(f"Echec transformation: {str(e)}")
|
raise RuntimeError(f"Echec transformation: {str(e)}")
|
||||||
|
|
||||||
def _find_document_in_list(self, numero, type_doc):
|
def _find_document_in_list(self, numero, type_doc):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue