fix: Introduce Sage document type constants and update document transformation and listing endpoints to use correct Sage types.
This commit is contained in:
parent
9d0c26b5d8
commit
9b17149b07
3 changed files with 87 additions and 145 deletions
16
config.py
16
config.py
|
|
@ -1,14 +1,20 @@
|
||||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
|
|
||||||
|
|
||||||
class Settings(BaseSettings):
|
class Settings(BaseSettings):
|
||||||
model_config = SettingsConfigDict(
|
model_config = SettingsConfigDict(
|
||||||
env_file=".env",
|
env_file=".env", env_file_encoding="utf-8", case_sensitive=False, extra="ignore"
|
||||||
env_file_encoding="utf-8",
|
|
||||||
case_sensitive=False,
|
|
||||||
extra="ignore"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
SAGE_TYPE_DEVIS: int = 0
|
||||||
|
SAGE_TYPE_BON_COMMANDE: int = 10
|
||||||
|
SAGE_TYPE_PREPARATION: int = 20
|
||||||
|
SAGE_TYPE_BON_LIVRAISON: int = 30
|
||||||
|
SAGE_TYPE_BON_RETOUR: int = 40
|
||||||
|
SAGE_TYPE_BON_AVOIR: int = 50
|
||||||
|
SAGE_TYPE_FACTURE: int = 60
|
||||||
|
|
||||||
# === SAGE 100c (Windows uniquement) ===
|
# === SAGE 100c (Windows uniquement) ===
|
||||||
chemin_base: str
|
chemin_base: str
|
||||||
utilisateur: str = "Administrateur"
|
utilisateur: str = "Administrateur"
|
||||||
|
|
@ -31,8 +37,10 @@ class Settings(BaseSettings):
|
||||||
# === CORS ===
|
# === CORS ===
|
||||||
cors_origins: List[str] = ["*"]
|
cors_origins: List[str] = ["*"]
|
||||||
|
|
||||||
|
|
||||||
settings = Settings()
|
settings = Settings()
|
||||||
|
|
||||||
|
|
||||||
def validate_settings():
|
def validate_settings():
|
||||||
"""Validation au démarrage"""
|
"""Validation au démarrage"""
|
||||||
if not settings.chemin_base or not settings.mot_de_passe:
|
if not settings.chemin_base or not settings.mot_de_passe:
|
||||||
|
|
|
||||||
113
main.py
113
main.py
|
|
@ -490,33 +490,28 @@ 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_source: str = Query(..., description="Numéro du document source"),
|
||||||
type_source: int = Query(
|
type_source: int = Query(..., description="Type document source"),
|
||||||
...,
|
type_cible: int = Query(..., description="Type document cible"),
|
||||||
ge=0,
|
|
||||||
le=5,
|
|
||||||
description="Type document source (0=Devis, 3=Commande, 5=Facture)",
|
|
||||||
),
|
|
||||||
type_cible: int = Query(..., ge=0, le=5, description="Type document cible"),
|
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
🔧 Transformation de document (devis → commande → facture)
|
🔧 Transformation de document
|
||||||
|
|
||||||
✅ CORRECTION FINALE: Query params au lieu de body JSON
|
✅ CORRECTION : Utilise les VRAIS types Sage Dataven
|
||||||
|
|
||||||
Types de documents:
|
Types valides :
|
||||||
- 0: Devis
|
- 0: Devis
|
||||||
- 1: Bon de livraison
|
- 10: Bon de commande
|
||||||
- 2: Bon de retour
|
- 20: Préparation
|
||||||
- 3: Commande
|
- 30: Bon de livraison
|
||||||
- 4: Préparation
|
- 40: Bon de retour
|
||||||
- 5: Facture
|
- 50: Bon d'avoir
|
||||||
|
- 60: Facture
|
||||||
|
|
||||||
Transformations valides:
|
Transformations autorisées :
|
||||||
- Devis (0) → Commande (3)
|
- Devis (0) → Commande (10)
|
||||||
- Devis (0) → Facture (5)
|
- Commande (10) → Bon livraison (30)
|
||||||
- Commande (3) → Bon livraison (1)
|
- Commande (10) → Facture (60)
|
||||||
- Commande (3) → Facture (5)
|
- Bon livraison (30) → Facture (60)
|
||||||
- Bon livraison (1) → Facture (5)
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
logger.info(
|
logger.info(
|
||||||
|
|
@ -524,13 +519,13 @@ def transformer_document(
|
||||||
f"(type {type_source}) → type {type_cible}"
|
f"(type {type_source}) → type {type_cible}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Validation des transformations autorisées
|
# ✅ Matrice des transformations valides pour VOTRE Sage
|
||||||
transformations_valides = {
|
transformations_valides = {
|
||||||
(0, 3), # Devis → Commande
|
(0, 10), # Devis → Commande
|
||||||
(0, 5), # Devis → Facture
|
(10, 30), # Commande → Bon de livraison
|
||||||
(3, 1), # Commande → Bon de livraison
|
(10, 60), # Commande → Facture
|
||||||
(3, 5), # Commande → Facture
|
(30, 60), # Bon de livraison → Facture
|
||||||
(1, 5), # Bon de livraison → Facture
|
(0, 60), # Devis → Facture (si autorisé)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type_source, type_cible) not in transformations_valides:
|
if (type_source, type_cible) not in transformations_valides:
|
||||||
|
|
@ -557,11 +552,9 @@ def transformer_document(
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
raise
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
# Erreurs métier (document introuvable, déjà transformé, etc.)
|
|
||||||
logger.error(f"❌ Erreur métier transformation: {e}")
|
logger.error(f"❌ Erreur métier transformation: {e}")
|
||||||
raise HTTPException(400, str(e))
|
raise HTTPException(400, str(e))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Erreurs techniques (COM, Sage, etc.)
|
|
||||||
logger.error(f"❌ Erreur technique transformation: {e}", exc_info=True)
|
logger.error(f"❌ Erreur technique transformation: {e}", exc_info=True)
|
||||||
raise HTTPException(500, f"Erreur transformation: {str(e)}")
|
raise HTTPException(500, f"Erreur transformation: {str(e)}")
|
||||||
|
|
||||||
|
|
@ -612,7 +605,7 @@ def contact_read(req: CodeRequest):
|
||||||
def commandes_list(limit: int = 100, statut: Optional[int] = None):
|
def commandes_list(limit: int = 100, statut: Optional[int] = None):
|
||||||
"""
|
"""
|
||||||
📋 Liste toutes les commandes
|
📋 Liste toutes les commandes
|
||||||
✅ CORRECTIONS: Gestion robuste des erreurs + logging détaillé
|
✅ CORRECTION: Filtre sur type 10 (BON_COMMANDE)
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if not sage or not sage.cial:
|
if not sage or not sage.cial:
|
||||||
|
|
@ -622,7 +615,7 @@ def commandes_list(limit: int = 100, statut: Optional[int] = None):
|
||||||
factory = sage.cial.FactoryDocumentVente
|
factory = sage.cial.FactoryDocumentVente
|
||||||
commandes = []
|
commandes = []
|
||||||
index = 1
|
index = 1
|
||||||
max_iterations = limit * 10 # Plus de marge
|
max_iterations = limit * 10
|
||||||
erreurs_consecutives = 0
|
erreurs_consecutives = 0
|
||||||
max_erreurs = 100
|
max_erreurs = 100
|
||||||
|
|
||||||
|
|
@ -636,33 +629,26 @@ def commandes_list(limit: int = 100, statut: Optional[int] = None):
|
||||||
try:
|
try:
|
||||||
persist = factory.List(index)
|
persist = factory.List(index)
|
||||||
if persist is None:
|
if persist is None:
|
||||||
logger.debug(f"Fin de liste à l'index {index}")
|
|
||||||
break
|
break
|
||||||
|
|
||||||
doc = win32com.client.CastTo(persist, "IBODocumentVente3")
|
doc = win32com.client.CastTo(persist, "IBODocumentVente3")
|
||||||
doc.Read()
|
doc.Read()
|
||||||
|
|
||||||
# ✅ CORRECTION 1: Vérifier type de document
|
|
||||||
doc_type = getattr(doc, "DO_Type", -1)
|
doc_type = getattr(doc, "DO_Type", -1)
|
||||||
|
|
||||||
# ⚠️ CRITIQUE: Vérifier que c'est bien une commande (type 3)
|
# ✅ CRITIQUE : Filtrer sur type 10 (BON_COMMANDE)
|
||||||
if doc_type != 3:
|
if doc_type != settings.SAGE_TYPE_BON_COMMANDE:
|
||||||
index += 1
|
index += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
doc_statut = getattr(doc, "DO_Statut", 0)
|
doc_statut = getattr(doc, "DO_Statut", 0)
|
||||||
|
|
||||||
logger.debug(
|
|
||||||
f"Index {index}: Type={doc_type}, Statut={doc_statut}, "
|
|
||||||
f"Numéro={getattr(doc, 'DO_Piece', '?')}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Filtre statut
|
# Filtre statut
|
||||||
if statut is not None and doc_statut != statut:
|
if statut is not None and doc_statut != statut:
|
||||||
index += 1
|
index += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# ✅ CORRECTION 2: Charger client via .Client
|
# Charger client
|
||||||
client_code = ""
|
client_code = ""
|
||||||
client_intitule = ""
|
client_intitule = ""
|
||||||
|
|
||||||
|
|
@ -674,20 +660,8 @@ def commandes_list(limit: int = 100, statut: Optional[int] = None):
|
||||||
client_intitule = getattr(
|
client_intitule = getattr(
|
||||||
client_obj, "CT_Intitule", ""
|
client_obj, "CT_Intitule", ""
|
||||||
).strip()
|
).strip()
|
||||||
logger.debug(f" Client: {client_code} - {client_intitule}")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f" Erreur chargement client: {e}")
|
logger.debug(f"Erreur chargement client: {e}")
|
||||||
# Fallback sur cache si code disponible
|
|
||||||
if not client_code:
|
|
||||||
try:
|
|
||||||
client_code = getattr(doc, "CT_Num", "").strip()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if client_code and not client_intitule:
|
|
||||||
client_cache = sage.lire_client(client_code)
|
|
||||||
if client_cache:
|
|
||||||
client_intitule = client_cache.get("intitule", "")
|
|
||||||
|
|
||||||
commande = {
|
commande = {
|
||||||
"numero": getattr(doc, "DO_Piece", ""),
|
"numero": getattr(doc, "DO_Piece", ""),
|
||||||
|
|
@ -700,27 +674,17 @@ def commandes_list(limit: int = 100, statut: Optional[int] = None):
|
||||||
}
|
}
|
||||||
|
|
||||||
commandes.append(commande)
|
commandes.append(commande)
|
||||||
logger.debug(f" ✅ Commande ajoutée: {commande['numero']}")
|
|
||||||
|
|
||||||
erreurs_consecutives = 0
|
erreurs_consecutives = 0
|
||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
erreurs_consecutives += 1
|
erreurs_consecutives += 1
|
||||||
logger.debug(f"⚠️ Erreur index {index}: {e}")
|
|
||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
if erreurs_consecutives >= max_erreurs:
|
if erreurs_consecutives >= max_erreurs:
|
||||||
logger.warning(
|
|
||||||
f"⚠️ Arrêt après {max_erreurs} erreurs consécutives"
|
|
||||||
)
|
|
||||||
break
|
break
|
||||||
|
|
||||||
nb_avec_client = sum(1 for c in commandes if c["client_intitule"])
|
logger.info(f"✅ {len(commandes)} commandes retournées")
|
||||||
logger.info(
|
|
||||||
f"✅ {len(commandes)} commandes retournées "
|
|
||||||
f"({nb_avec_client} avec client)"
|
|
||||||
)
|
|
||||||
|
|
||||||
return {"success": True, "data": commandes}
|
return {"success": True, "data": commandes}
|
||||||
|
|
||||||
|
|
@ -733,7 +697,10 @@ def commandes_list(limit: int = 100, statut: Optional[int] = None):
|
||||||
|
|
||||||
@app.post("/sage/factures/list", dependencies=[Depends(verify_token)])
|
@app.post("/sage/factures/list", dependencies=[Depends(verify_token)])
|
||||||
def factures_list(limit: int = 100, statut: Optional[int] = None):
|
def factures_list(limit: int = 100, statut: Optional[int] = None):
|
||||||
"""Liste toutes les factures"""
|
"""
|
||||||
|
📋 Liste toutes les factures
|
||||||
|
✅ CORRECTION: Filtre sur type 60 (FACTURE)
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
with sage._com_context(), sage._lock_com:
|
with sage._com_context(), sage._lock_com:
|
||||||
factory = sage.cial.FactoryDocumentVente
|
factory = sage.cial.FactoryDocumentVente
|
||||||
|
|
@ -750,8 +717,8 @@ def factures_list(limit: int = 100, statut: Optional[int] = None):
|
||||||
doc = win32com.client.CastTo(persist, "IBODocumentVente3")
|
doc = win32com.client.CastTo(persist, "IBODocumentVente3")
|
||||||
doc.Read()
|
doc.Read()
|
||||||
|
|
||||||
# Filtrer factures (type 5)
|
# ✅ CRITIQUE: Filtrer factures (type 60)
|
||||||
if getattr(doc, "DO_Type", -1) != 5:
|
if getattr(doc, "DO_Type", -1) != settings.SAGE_TYPE_FACTURE:
|
||||||
index += 1
|
index += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
@ -773,13 +740,6 @@ def factures_list(limit: int = 100, statut: Optional[int] = None):
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Champ libre dernière relance
|
|
||||||
derniere_relance = None
|
|
||||||
try:
|
|
||||||
derniere_relance = getattr(doc, "DO_DerniereRelance", None)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
factures.append(
|
factures.append(
|
||||||
{
|
{
|
||||||
"numero": getattr(doc, "DO_Piece", ""),
|
"numero": getattr(doc, "DO_Piece", ""),
|
||||||
|
|
@ -789,9 +749,6 @@ def factures_list(limit: int = 100, statut: Optional[int] = None):
|
||||||
"total_ht": float(getattr(doc, "DO_TotalHT", 0.0)),
|
"total_ht": float(getattr(doc, "DO_TotalHT", 0.0)),
|
||||||
"total_ttc": float(getattr(doc, "DO_TotalTTC", 0.0)),
|
"total_ttc": float(getattr(doc, "DO_TotalTTC", 0.0)),
|
||||||
"statut": doc_statut,
|
"statut": doc_statut,
|
||||||
"derniere_relance": (
|
|
||||||
str(derniere_relance) if derniere_relance else None
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1027,19 +1027,11 @@ 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 avec la méthode NATIVE de Sage
|
||||||
|
✅ CORRECTION : Utilise les VRAIS types Sage Dataven
|
||||||
CHANGEMENT MAJEUR:
|
|
||||||
- Utilise TransformInto() au lieu de CreateProcess_Document()
|
|
||||||
- Méthode officielle Sage pour les transformations
|
|
||||||
- Gère automatiquement les numéros, statuts, et lignes
|
|
||||||
|
|
||||||
Documentation Sage:
|
|
||||||
IBODocumentVente3.TransformInto(DO_Type: int) -> IBODocumentVente3
|
|
||||||
"""
|
"""
|
||||||
if not self.cial:
|
if not self.cial:
|
||||||
raise RuntimeError("Connexion Sage non etablie")
|
raise RuntimeError("Connexion Sage non etablie")
|
||||||
|
|
||||||
# Convertir en int si enum
|
|
||||||
type_source = int(type_source)
|
type_source = int(type_source)
|
||||||
type_cible = int(type_cible)
|
type_cible = int(type_cible)
|
||||||
|
|
||||||
|
|
@ -1048,24 +1040,28 @@ class SageConnector:
|
||||||
f"(type {type_source}) -> type {type_cible}"
|
f"(type {type_source}) -> type {type_cible}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Validation des types
|
# ✅ Matrice de transformations pour VOTRE installation Sage
|
||||||
types_valides = {0, 1, 2, 3, 4, 5}
|
|
||||||
if type_source not in types_valides or type_cible not in types_valides:
|
|
||||||
raise ValueError(
|
|
||||||
f"Types invalides: source={type_source}, cible={type_cible}. "
|
|
||||||
f"Valeurs valides: {types_valides}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Matrice de transformations Sage 100c
|
|
||||||
transformations_autorisees = {
|
transformations_autorisees = {
|
||||||
(0, 3): "Devis -> Commande",
|
(
|
||||||
(0, 1): "Devis -> Bon de livraison",
|
settings.SAGE_TYPE_DEVIS,
|
||||||
(0, 5): "Devis -> Facture", # Peut être supporté selon config
|
settings.SAGE_TYPE_BON_COMMANDE,
|
||||||
(3, 1): "Commande -> Bon de livraison",
|
): "Devis -> Commande", # 0 → 10
|
||||||
(3, 4): "Commande -> Preparation",
|
(
|
||||||
(3, 5): "Commande -> Facture", # Direct si autorisé
|
settings.SAGE_TYPE_BON_COMMANDE,
|
||||||
(1, 5): "Bon de livraison -> Facture",
|
settings.SAGE_TYPE_BON_LIVRAISON,
|
||||||
(4, 1): "Preparation -> Bon de 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:
|
||||||
|
|
@ -1135,8 +1131,8 @@ class SageConnector:
|
||||||
f"Ce document a deja ete transforme partiellement ou totalement."
|
f"Ce document a deja ete transforme partiellement ou totalement."
|
||||||
)
|
)
|
||||||
|
|
||||||
# Forcer statut "Accepté" si brouillon
|
# Forcer statut "Accepté" si brouillon (uniquement pour devis)
|
||||||
if type_source == 0 and statut_actuel == 0:
|
if type_source == settings.SAGE_TYPE_DEVIS and statut_actuel == 0:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"[TRANSFORM] Devis en brouillon (statut=0), "
|
f"[TRANSFORM] Devis en brouillon (statut=0), "
|
||||||
f"passage a 'Accepte' (statut=2)"
|
f"passage a 'Accepte' (statut=2)"
|
||||||
|
|
@ -1146,7 +1142,6 @@ class SageConnector:
|
||||||
doc_source.Write()
|
doc_source.Write()
|
||||||
logger.info(f"[TRANSFORM] Statut change: 0 -> 2")
|
logger.info(f"[TRANSFORM] Statut change: 0 -> 2")
|
||||||
|
|
||||||
# Re-lire
|
|
||||||
doc_source.Read()
|
doc_source.Read()
|
||||||
nouveau_statut = getattr(doc_source, "DO_Statut", 0)
|
nouveau_statut = getattr(doc_source, "DO_Statut", 0)
|
||||||
if nouveau_statut != 2:
|
if nouveau_statut != 2:
|
||||||
|
|
@ -1162,20 +1157,16 @@ class SageConnector:
|
||||||
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 AttributeError:
|
except:
|
||||||
# BeginTrans n'existe pas sur cette version
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"[TRANSFORM] BeginTrans non disponible, continue sans transaction"
|
"[TRANSFORM] BeginTrans non disponible, continue sans transaction"
|
||||||
)
|
)
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"[TRANSFORM] BeginTrans echoue: {e}")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# ✅✅✅ MÉTHODE NATIVE SAGE: TransformInto() ✅✅✅
|
# ✅✅✅ MÉTHODE NATIVE SAGE: TransformInto() ✅✅✅
|
||||||
logger.info(f"[TRANSFORM] Appel TransformInto({type_cible})...")
|
logger.info(f"[TRANSFORM] Appel TransformInto({type_cible})...")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# La méthode TransformInto() retourne le nouveau document
|
|
||||||
doc_cible = doc_source.TransformInto(type_cible)
|
doc_cible = doc_source.TransformInto(type_cible)
|
||||||
|
|
||||||
if doc_cible is None:
|
if doc_cible is None:
|
||||||
|
|
@ -1186,7 +1177,6 @@ class SageConnector:
|
||||||
|
|
||||||
logger.info("[TRANSFORM] TransformInto() execute avec succes")
|
logger.info("[TRANSFORM] TransformInto() execute avec succes")
|
||||||
|
|
||||||
# Cast vers le bon type
|
|
||||||
try:
|
try:
|
||||||
doc_cible = win32com.client.CastTo(
|
doc_cible = win32com.client.CastTo(
|
||||||
doc_cible, "IBODocumentVente3"
|
doc_cible, "IBODocumentVente3"
|
||||||
|
|
@ -1194,10 +1184,7 @@ class SageConnector:
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Lire le document cible
|
|
||||||
doc_cible.Read()
|
doc_cible.Read()
|
||||||
|
|
||||||
# Récupérer le numéro
|
|
||||||
numero_cible = getattr(doc_cible, "DO_Piece", "")
|
numero_cible = getattr(doc_cible, "DO_Piece", "")
|
||||||
|
|
||||||
if not numero_cible:
|
if not numero_cible:
|
||||||
|
|
@ -1228,40 +1215,30 @@ class SageConnector:
|
||||||
)
|
)
|
||||||
|
|
||||||
except AttributeError as e:
|
except AttributeError as e:
|
||||||
# TransformInto() n'existe pas sur cette version de Sage
|
|
||||||
logger.error(f"[TRANSFORM] TransformInto() non disponible: {e}")
|
logger.error(f"[TRANSFORM] TransformInto() non disponible: {e}")
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"La methode TransformInto() n'est pas disponible sur votre version de Sage 100c. "
|
f"La methode TransformInto() n'est pas disponible. "
|
||||||
f"Vous devez soit: "
|
f"Causes possibles:\n"
|
||||||
f"(1) Mettre a jour Sage, ou "
|
f"1. Le module n'est pas active dans votre licence Sage\n"
|
||||||
f"(2) Activer le module de gestion commerciale pour les commandes, ou "
|
f"2. L'utilisateur n'a pas les droits\n"
|
||||||
f"(3) Utiliser l'interface Sage manuellement pour les transformations."
|
f"3. La transformation {type_source}→{type_cible} n'est pas supportee"
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"[TRANSFORM] TransformInto() echoue: {e}")
|
logger.error(f"[TRANSFORM] TransformInto() echoue: {e}")
|
||||||
|
|
||||||
# Essayer de déterminer la cause
|
|
||||||
if "Valeur invalide" in str(e):
|
if "Valeur invalide" in str(e):
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"Sage refuse la transformation vers le type {type_cible}. "
|
f"Sage refuse la transformation vers le type {type_cible}. "
|
||||||
f"Causes possibles:\n"
|
f"Verifiez:\n"
|
||||||
f"1. Le module 'Commandes' n'est pas active dans votre licence Sage\n"
|
f"1. Que le module est active (Commandes, Factures...)\n"
|
||||||
f"2. L'utilisateur n'a pas les droits sur ce type de document\n"
|
f"2. Les droits utilisateur\n"
|
||||||
f"3. La configuration Sage bloque ce type de transformation\n"
|
f"3. Que le type {type_cible} existe dans votre Sage\n"
|
||||||
f"4. Il manque des parametres obligatoires (depot, tarif, etc.)\n\n"
|
f"4. Les parametres obligatoires (depot, tarif, etc.)"
|
||||||
f"Verifiez dans Sage: Fichier > Autorisations > Gestion Commerciale"
|
|
||||||
)
|
|
||||||
elif "Acces refuse" in str(e) or "Access denied" in str(e):
|
|
||||||
raise RuntimeError(
|
|
||||||
f"Acces refuse pour creer une commande (type {type_cible}). "
|
|
||||||
f"Verifiez les droits utilisateur dans Sage: "
|
|
||||||
f"Fichier > Autorisations > Votre utilisateur"
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"Erreur Sage lors de la transformation: {e}\n"
|
f"Erreur Sage lors de la transformation: {e}"
|
||||||
f"Consultez les logs Sage pour plus de details."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Commit transaction
|
# Commit transaction
|
||||||
|
|
@ -1272,9 +1249,9 @@ class SageConnector:
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# MAJ statut source -> Transformé
|
# MAJ statut source → Transformé
|
||||||
try:
|
try:
|
||||||
doc_source.Read() # Re-lire au cas où
|
doc_source.Read()
|
||||||
doc_source.DO_Statut = 5
|
doc_source.DO_Statut = 5
|
||||||
doc_source.Write()
|
doc_source.Write()
|
||||||
logger.info(
|
logger.info(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue