Modified "modifier_commande" method to delete lines correctly

This commit is contained in:
Fanilo-Nantenaina 2025-12-08 08:42:03 +03:00
parent cc2b86d533
commit fc7216fe2f

View file

@ -4122,27 +4122,24 @@ class SageConnector:
def modifier_commande(self, numero: str, commande_data: Dict) -> Dict:
"""
Modification commande - VERSION ULTRA-DIAGNOSTIQUE
Modification commande - VERSION SIMPLIFIÉE
🔬 OBJECTIF: Identifier EXACTEMENT ça plante et pourquoi
Stratégies testées dans l'ordre :
1. Diagnostic complet de l'état du document
2. Comparaison avec un document qui fonctionne (BC00068)
3. Approche minimaliste (modifier 1 seul champ à la fois)
4. Approche progressive (ajouter champs un par un)
🔧 STRATÉGIE REMPLACEMENT LIGNES:
- Si nouvelles lignes fournies Supprime TOUTES les anciennes puis ajoute les nouvelles
- Utilise .Remove() pour la suppression
- Simple, robuste, prévisible
"""
if not self.cial:
raise RuntimeError("Connexion Sage non établie")
try:
with self._com_context(), self._lock_com:
logger.info(f"🔬 === DIAGNOSTIC MODIFICATION COMMANDE {numero} ===")
logger.info(f"🔬 === MODIFICATION COMMANDE {numero} ===")
# ========================================
# PHASE 0 : DIAGNOSTIC COMPLET INITIAL
# ÉTAPE 1 : CHARGER LE DOCUMENT
# ========================================
logger.info("📊 PHASE 0: Diagnostic état initial...")
logger.info("📂 Chargement document...")
factory = self.cial.FactoryDocumentVente
persist = None
@ -4164,20 +4161,14 @@ class SageConnector:
doc = win32com.client.CastTo(persist, "IBODocumentVente3")
doc.Read()
# Diagnostic complet de l'état initial
diag_initial = {
"DO_Piece": getattr(doc, "DO_Piece", ""),
"DO_Type": getattr(doc, "DO_Type", -1),
"DO_Statut": getattr(doc, "DO_Statut", -1),
"DO_Date": str(getattr(doc, "DO_Date", "")),
"DO_Ref": getattr(doc, "DO_Ref", ""),
"DO_TotalHT": float(getattr(doc, "DO_TotalHT", 0.0)),
"DO_TotalTTC": float(getattr(doc, "DO_TotalTTC", 0.0)),
}
statut_actuel = getattr(doc, "DO_Statut", 0)
type_reel = getattr(doc, "DO_Type", -1)
logger.info(f" 📋 État initial: {diag_initial}")
logger.info(f" 📊 Type={type_reel}, Statut={statut_actuel}")
# Charger le client INITIAL
# ========================================
# ÉTAPE 2 : VÉRIFIER CLIENT INITIAL
# ========================================
client_code_initial = ""
try:
client_obj = getattr(doc, "Client", None)
@ -4213,56 +4204,25 @@ class SageConnector:
logger.warning(f" ⚠️ Erreur comptage lignes: {e}")
# ========================================
# PHASE 1 : COMPARAISON AVEC BC00068 (qui fonctionne)
# ÉTAPE 3 : DÉTERMINER LES MODIFICATIONS
# ========================================
if numero != "BC00068":
logger.info("🔍 PHASE 1: Comparaison avec BC00068...")
try:
persist_ref = None
for type_test in [10, 3, settings.SAGE_TYPE_BON_COMMANDE]:
try:
persist_ref = factory.ReadPiece(type_test, "BC00068")
if persist_ref:
break
except:
continue
if persist_ref:
doc_ref = win32com.client.CastTo(persist_ref, "IBODocumentVente3")
doc_ref.Read()
# Comparer tous les champs critiques
champs_a_comparer = [
"DO_Type", "DO_Statut", "DO_Domaine", "DO_Souche",
"DO_Transfere", "DO_Valide", "DO_Cloture"
]
differences = {}
for champ in champs_a_comparer:
val_doc = getattr(doc, champ, None)
val_ref = getattr(doc_ref, champ, None)
if val_doc != val_ref:
differences[champ] = {
"doc_actuel": str(val_doc),
"bc00068": str(val_ref)
}
if differences:
logger.warning(f" ⚠️ DIFFÉRENCES avec BC00068:")
for champ, vals in differences.items():
logger.warning(f" {champ}: {vals['doc_actuel']} != {vals['bc00068']}")
else:
logger.info(f" ✅ Aucune différence critique avec BC00068")
except Exception as e:
logger.warning(f" ⚠️ Impossible de comparer avec BC00068: {e}")
champs_modifies = []
modif_date = "date_commande" in commande_data
modif_statut = "statut" in commande_data
modif_ref = "reference" in commande_data
modif_lignes = "lignes" in commande_data and commande_data["lignes"] is not None
logger.info(f"📋 Modifications demandées:")
logger.info(f" Date: {modif_date}")
logger.info(f" Statut: {modif_statut}")
logger.info(f" Référence: {modif_ref}")
logger.info(f" Lignes: {modif_lignes}")
# ========================================
# PHASE 2 : TEST WRITE() BASIQUE (SANS AUCUNE MODIFICATION)
# ÉTAPE 4 : TEST WRITE() BASIQUE
# ========================================
logger.info("🧪 PHASE 2: Test Write() basique (sans modification)...")
logger.info("🧪 Test Write() basique (sans modification)...")
try:
doc.Write()
@ -4287,27 +4247,10 @@ class SageConnector:
raise ValueError(f"Document verrouillé, impossible de modifier: {e}")
# ========================================
# PHASE 3 : STRATÉGIE SELON LES MODIFICATIONS DEMANDÉES
# ========================================
champs_modifies = []
# Détecter ce qui doit être modifié
modif_date = "date_commande" in commande_data
modif_statut = "statut" in commande_data
modif_ref = "reference" in commande_data
modif_lignes = "lignes" in commande_data and commande_data["lignes"] is not None
logger.info(f"📋 Modifications demandées:")
logger.info(f" Date: {modif_date}")
logger.info(f" Statut: {modif_statut}")
logger.info(f" Référence: {modif_ref}")
logger.info(f" Lignes: {modif_lignes}")
# ========================================
# STRATÉGIE A : MODIFICATIONS SIMPLES (pas de lignes)
# ÉTAPE 5 : MODIFICATIONS SIMPLES (pas de lignes)
# ========================================
if not modif_lignes and (modif_date or modif_statut or modif_ref):
logger.info("🎯 STRATÉGIE A: Modifications simples (sans lignes)...")
logger.info("🎯 Modifications simples (sans lignes)...")
if modif_date:
logger.info(" 📅 Modification date...")
@ -4372,15 +4315,15 @@ class SageConnector:
raise ValueError(f"Sage refuse: {error_msg}")
# ========================================
# STRATÉGIE B : MODIFICATION LIGNES (approche minimaliste)
# ÉTAPE 6 : REMPLACEMENT COMPLET DES LIGNES
# ========================================
elif modif_lignes:
logger.info("🎯 STRATÉGIE B: Modification lignes (approche minimaliste)...")
logger.info("🎯 REMPLACEMENT COMPLET DES LIGNES...")
nouvelles_lignes = commande_data["lignes"]
nb_nouvelles = len(nouvelles_lignes)
logger.info(f" 📊 {nb_lignes_initial} lignes existantes → {nb_nouvelles} nouvelles")
logger.info(f" 📊 {nb_lignes_initial} lignes existantes → {nb_nouvelles} nouvelles lignes")
try:
factory_lignes = doc.FactoryDocumentLigne
@ -4389,21 +4332,36 @@ class SageConnector:
factory_article = self.cial.FactoryArticle
# APPROCHE MINIMALISTE: Tester avec UNE SEULE ligne d'abord
logger.info(" 🧪 TEST: Modification de la ligne 1 uniquement...")
ligne_data = nouvelles_lignes[0]
try:
ligne_p = factory_lignes.List(1)
if ligne_p is None:
raise ValueError("Aucune ligne existante")
# ============================================
# SOUS-ÉTAPE 1 : SUPPRIMER TOUTES LES LIGNES EXISTANTES
# ============================================
if nb_lignes_initial > 0:
logger.info(f" 🗑️ Suppression de {nb_lignes_initial} lignes existantes...")
ligne = win32com.client.CastTo(ligne_p, "IBODocumentLigne3")
ligne.Read()
# Supprimer depuis la fin pour éviter les problèmes d'index
for idx in range(nb_lignes_initial, 0, -1):
try:
ligne_p = factory_lignes.List(idx)
if ligne_p:
ligne = win32com.client.CastTo(ligne_p, "IBODocumentLigne3")
ligne.Read()
# ✅ Utiliser .Remove() comme indiqué
ligne.Remove()
logger.debug(f" ✅ Ligne {idx} supprimée")
except Exception as e:
logger.warning(f" ⚠️ Impossible de supprimer ligne {idx}: {e}")
# Continuer même si une suppression échoue
logger.info(f" Article: {ligne_data['article_code']}")
logger.info(f" Quantité: {ligne_data['quantite']}")
logger.info(" ✅ Toutes les lignes existantes supprimées")
# ============================================
# SOUS-ÉTAPE 2 : AJOUTER LES NOUVELLES LIGNES
# ============================================
logger.info(f" Ajout de {nb_nouvelles} nouvelles lignes...")
for idx, ligne_data in enumerate(nouvelles_lignes, 1):
logger.info(f" --- Ligne {idx}/{nb_nouvelles}: {ligne_data['article_code']} ---")
# Charger l'article
persist_article = factory_article.ReadReference(ligne_data["article_code"])
@ -4413,50 +4371,66 @@ class SageConnector:
article_obj = win32com.client.CastTo(persist_article, "IBOArticle3")
article_obj.Read()
# MÉTHODE ULTRA-MINIMALISTE : Juste changer la quantité
logger.info(" 🔧 Modification quantité uniquement...")
# Créer nouvelle ligne
ligne_persist = factory_lignes.Create()
try:
ligne_obj = win32com.client.CastTo(ligne_persist, "IBODocumentLigne3")
except:
ligne_obj = win32com.client.CastTo(ligne_persist, "IBODocumentVenteLigne3")
quantite = float(ligne_data["quantite"])
ligne.DL_Qte = quantite
# Associer article
try:
ligne_obj.SetDefaultArticleReference(ligne_data["article_code"], quantite)
except:
try:
ligne_obj.SetDefaultArticle(article_obj, quantite)
except:
ligne_obj.DL_Design = ligne_data.get("designation", "")
ligne_obj.DL_Qte = quantite
# Prix
if ligne_data.get("prix_unitaire_ht"):
ligne_obj.DL_PrixUnitaire = float(ligne_data["prix_unitaire_ht"])
# Remise
if ligne_data.get("remise_pourcentage", 0) > 0:
try:
ligne_obj.DL_Remise01REM_Valeur = float(ligne_data["remise_pourcentage"])
ligne_obj.DL_Remise01REM_Type = 0
except:
pass
# Écrire la ligne
logger.info(" 💾 Write() ligne...")
ligne.Write()
logger.info(" ✅ Ligne 1 modifiée")
# Écrire le document
logger.info(" 💾 Write() document après ligne...")
doc.Write()
logger.info(" ✅ Document écrit")
doc.Read()
# Vérifier client
client_obj = getattr(doc, "Client", None)
if client_obj:
client_obj.Read()
client_apres = getattr(client_obj, "CT_Num", "")
logger.info(f" 👤 Client après modif: {client_apres}")
else:
logger.error(" ❌ Client NULL après modif")
champs_modifies.append("lignes")
ligne_obj.Write()
logger.info(f" ✅ Ligne {idx} ajoutée")
except Exception as e:
error_msg = str(e)
try:
sage_error = self.cial.CptaApplication.LastError
if sage_error:
error_msg = f"{sage_error.Description} (Code: {sage_error.Number})"
except:
pass
logger.error(f" ❌ Modification ligne échoue: {error_msg}")
raise ValueError(f"Sage refuse modification ligne: {error_msg}")
logger.info(f"{nb_nouvelles} nouvelles lignes ajoutées")
# Écrire le document
logger.info(" 💾 Write() document après remplacement lignes...")
doc.Write()
logger.info(" ✅ Document écrit")
doc.Read()
# Vérifier client
client_obj = getattr(doc, "Client", None)
if client_obj:
client_obj.Read()
client_apres = getattr(client_obj, "CT_Num", "")
logger.info(f" 👤 Client après remplacement: {client_apres}")
else:
logger.error(" ❌ Client NULL après remplacement")
champs_modifies.append("lignes")
# ========================================
# PHASE FINALE : RELECTURE ET RETOUR
# ÉTAPE 7 : RELECTURE ET RETOUR
# ========================================
logger.info("📊 PHASE FINALE: Relecture...")
logger.info("📊 Relecture finale...")
import time
time.sleep(1)
@ -4522,7 +4496,5 @@ class SageConnector: