Diagnostic transformation selective error

This commit is contained in:
Fanilo-Nantenaina 2025-11-28 22:30:06 +03:00
parent e6c2ab6670
commit de0053b98b

287
main.py
View file

@ -489,74 +489,255 @@ def lire_document(numero: str, type_doc: int):
@app.post("/sage/documents/transform", dependencies=[Depends(verify_token)]) @app.post("/sage/documents/transform", dependencies=[Depends(verify_token)])
def transformer_document( def transformer_document(
numero_source: str = Query(..., description="Numéro du document source"), numero: str, type_source: int = Query(...), type_cible: int = Query(...)
type_source: int = Query(..., description="Type document source"),
type_cible: int = Query(..., description="Type document cible"),
): ):
""" """
🔧 Transformation de document 🔍 DIAGNOSTIC AVANCÉ: Analyse pourquoi une transformation échoue
CORRECTION : Utilise les VRAIS types Sage Dataven Vérifie:
- Statut du document source
Types valides : - Statuts autorisés
- 0: Devis - Lignes du document
- 10: Bon de commande - Client associé
- 20: Préparation - Champs obligatoires manquants
- 30: Bon de livraison
- 40: Bon de retour
- 50: Bon d'avoir
- 60: Facture
Transformations autorisées :
- Devis (0) Commande (10)
- Commande (10) Bon livraison (30)
- Commande (10) Facture (60)
- Bon livraison (30) Facture (60)
""" """
try: try:
logger.info( if not sage or not sage.cial:
f"🔄 Transformation demandée: {numero_source} " raise HTTPException(503, "Service Sage indisponible")
f"(type {type_source}) → type {type_cible}"
)
# ✅ Matrice des transformations valides pour VOTRE Sage with sage._com_context(), sage._lock_com:
transformations_valides = { factory = sage.cial.FactoryDocumentVente
(0, 10), # Devis → Commande
(10, 30), # Commande → Bon de livraison
(10, 60), # Commande → Facture
(30, 60), # Bon de livraison → Facture
(0, 60), # Devis → Facture (si autorisé)
}
if (type_source, type_cible) not in transformations_valides: # Lire le document source
logger.error( persist = factory.ReadPiece(type_source, numero)
f"❌ Transformation non autorisée: {type_source}{type_cible}"
) if not persist:
raise HTTPException( persist = sage._find_document_in_list(numero, type_source)
400,
f"Transformation non autorisée: type {type_source} → type {type_cible}. " if not persist:
f"Transformations valides: {transformations_valides}", raise HTTPException(
404, f"Document {numero} (type {type_source}) introuvable"
)
doc = win32com.client.CastTo(persist, "IBODocumentVente3")
doc.Read()
diagnostic = {
"numero": numero,
"type_source": type_source,
"type_cible": type_cible,
"problemes_detectes": [],
"avertissements": [],
"suggestions": [],
}
# 1. Vérifier le statut
statut_actuel = getattr(doc, "DO_Statut", -1)
diagnostic["statut_actuel"] = statut_actuel
if statut_actuel == 5:
diagnostic["problemes_detectes"].append(
{
"severite": "BLOQUANT",
"champ": "DO_Statut",
"valeur": 5,
"message": "Document déjà transformé (statut=5)",
}
)
elif statut_actuel == 6:
diagnostic["problemes_detectes"].append(
{
"severite": "BLOQUANT",
"champ": "DO_Statut",
"valeur": 6,
"message": "Document annulé (statut=6)",
}
)
elif statut_actuel in [3, 4]:
diagnostic["avertissements"].append(
{
"severite": "ATTENTION",
"champ": "DO_Statut",
"valeur": statut_actuel,
"message": f"Document déjà réalisé (statut={statut_actuel}). "
f"Un document cible existe peut-être déjà.",
}
)
elif statut_actuel == 0:
diagnostic["suggestions"].append(
"Le document est en 'Brouillon' (statut=0). "
"Le système le passera automatiquement à 'Accepté' (statut=2) avant transformation."
)
# 2. Vérifier le client
client_code = ""
try:
client_obj = getattr(doc, "Client", None)
if client_obj:
client_obj.Read()
client_code = getattr(client_obj, "CT_Num", "").strip()
except:
pass
if not client_code:
diagnostic["problemes_detectes"].append(
{
"severite": "BLOQUANT",
"champ": "CT_Num",
"valeur": None,
"message": "Aucun client associé au document",
}
)
else:
diagnostic["client_code"] = client_code
# 3. Vérifier les lignes
try:
factory_lignes = getattr(doc, "FactoryDocumentLigne", None) or getattr(
doc, "FactoryDocumentVenteLigne", None
)
nb_lignes = 0
lignes_problemes = []
if factory_lignes:
index = 1
while index <= 100:
try:
ligne_p = factory_lignes.List(index)
if ligne_p is None:
break
ligne = win32com.client.CastTo(ligne_p, "IBODocumentLigne3")
ligne.Read()
nb_lignes += 1
# Vérifier 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
if not article_ref:
lignes_problemes.append(
{
"ligne": index,
"probleme": "Aucune référence article",
}
)
# Vérifier prix
prix = float(getattr(ligne, "DL_PrixUnitaire", 0.0))
if prix == 0:
lignes_problemes.append(
{"ligne": index, "probleme": "Prix unitaire = 0"}
)
index += 1
except:
break
diagnostic["nb_lignes"] = nb_lignes
if nb_lignes == 0:
diagnostic["problemes_detectes"].append(
{
"severite": "BLOQUANT",
"champ": "Lignes",
"valeur": 0,
"message": "Document vide (aucune ligne)",
}
)
if lignes_problemes:
diagnostic["avertissements"].append(
{
"severite": "ATTENTION",
"champ": "Lignes",
"message": f"{len(lignes_problemes)} ligne(s) avec des problèmes",
"details": lignes_problemes,
}
)
except Exception as e:
diagnostic["avertissements"].append(
{
"severite": "ERREUR",
"champ": "Lignes",
"message": f"Impossible de lire les lignes: {e}",
}
)
# 4. Vérifier les totaux
total_ht = float(getattr(doc, "DO_TotalHT", 0.0))
total_ttc = float(getattr(doc, "DO_TotalTTC", 0.0))
diagnostic["totaux"] = {"total_ht": total_ht, "total_ttc": total_ttc}
if total_ht == 0 and total_ttc == 0:
diagnostic["avertissements"].append(
{
"severite": "ATTENTION",
"champ": "Totaux",
"message": "Tous les totaux sont à 0",
}
)
# 5. Vérifier si la transformation est autorisée
transformations_valides = {(0, 10), (10, 30), (10, 60), (30, 60), (0, 60)}
if (type_source, type_cible) not in transformations_valides:
diagnostic["problemes_detectes"].append(
{
"severite": "BLOQUANT",
"champ": "Transformation",
"message": f"Transformation {type_source}{type_cible} non autorisée. "
f"Transformations valides: {transformations_valides}",
}
)
# Résumé
nb_bloquants = sum(
1
for p in diagnostic["problemes_detectes"]
if p.get("severite") == "BLOQUANT"
) )
nb_avertissements = len(diagnostic["avertissements"])
# Appel au connecteur Sage diagnostic["resume"] = {
resultat = sage.transformer_document(numero_source, type_source, type_cible) "peut_transformer": nb_bloquants == 0,
"nb_problemes_bloquants": nb_bloquants,
"nb_avertissements": nb_avertissements,
}
logger.info( if nb_bloquants == 0:
f"✅ Transformation réussie: {numero_source}" diagnostic["suggestions"].append(
f"{resultat.get('document_cible', '?')} " "✅ Aucun problème bloquant détecté. La transformation devrait fonctionner."
f"({resultat.get('nb_lignes', 0)} lignes)" )
) else:
diagnostic["suggestions"].append(
f"{nb_bloquants} problème(s) bloquant(s) doivent être résolus avant la transformation."
)
return {"success": True, "data": resultat} return {"success": True, "diagnostic": diagnostic}
except HTTPException: except HTTPException:
raise raise
except ValueError as e:
logger.error(f"❌ Erreur métier transformation: {e}")
raise HTTPException(400, str(e))
except Exception as e: except Exception as e:
logger.error(f"❌ Erreur technique transformation: {e}", exc_info=True) logger.error(f"[DIAG] Erreur diagnostic transformation: {e}", exc_info=True)
raise HTTPException(500, f"Erreur transformation: {str(e)}") raise HTTPException(500, str(e))
@app.post("/sage/documents/champ-libre", dependencies=[Depends(verify_token)]) @app.post("/sage/documents/champ-libre", dependencies=[Depends(verify_token)])