Modified "modifier_commande" method to delete lines correctly
This commit is contained in:
parent
cc2b86d533
commit
fc7216fe2f
1 changed files with 115 additions and 143 deletions
|
|
@ -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 où ç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...")
|
||||
champs_modifies = []
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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}")
|
||||
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...")
|
||||
# ============================================
|
||||
# SOUS-ÉTAPE 1 : SUPPRIMER TOUTES LES LIGNES EXISTANTES
|
||||
# ============================================
|
||||
if nb_lignes_initial > 0:
|
||||
logger.info(f" 🗑️ Suppression de {nb_lignes_initial} lignes existantes...")
|
||||
|
||||
ligne_data = nouvelles_lignes[0]
|
||||
# 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()
|
||||
|
||||
try:
|
||||
ligne_p = factory_lignes.List(1)
|
||||
if ligne_p is None:
|
||||
raise ValueError("Aucune ligne existante")
|
||||
# ✅ 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
|
||||
|
||||
ligne = win32com.client.CastTo(ligne_p, "IBODocumentLigne3")
|
||||
ligne.Read()
|
||||
logger.info(" ✅ Toutes les lignes existantes supprimées")
|
||||
|
||||
logger.info(f" Article: {ligne_data['article_code']}")
|
||||
logger.info(f" Quantité: {ligne_data['quantite']}")
|
||||
# ============================================
|
||||
# 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")
|
||||
ligne_obj.Write()
|
||||
logger.info(f" ✅ Ligne {idx} ajoutée")
|
||||
|
||||
# Écrire le document
|
||||
logger.info(" 💾 Write() document après ligne...")
|
||||
doc.Write()
|
||||
logger.info(" ✅ Document écrit")
|
||||
logger.info(f" ✅ {nb_nouvelles} nouvelles lignes ajoutées")
|
||||
|
||||
doc.Read()
|
||||
# Écrire le document
|
||||
logger.info(" 💾 Write() document après remplacement lignes...")
|
||||
doc.Write()
|
||||
logger.info(" ✅ Document écrit")
|
||||
|
||||
# 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")
|
||||
doc.Read()
|
||||
|
||||
champs_modifies.append("lignes")
|
||||
# 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")
|
||||
|
||||
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}")
|
||||
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)
|
||||
|
|
@ -4523,6 +4497,4 @@ class SageConnector:
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue