feat: add optional inclusion of line items to the devis list endpoint.
This commit is contained in:
parent
4da650e361
commit
efa4edcae0
1 changed files with 85 additions and 7 deletions
92
main.py
92
main.py
|
|
@ -256,12 +256,18 @@ def changer_statut_devis(doc_id: str, req: StatutRequest):
|
||||||
|
|
||||||
|
|
||||||
@app.post("/sage/devis/list", dependencies=[Depends(verify_token)])
|
@app.post("/sage/devis/list", dependencies=[Depends(verify_token)])
|
||||||
def devis_list(limit: int = 100, statut: Optional[int] = None):
|
def devis_list(
|
||||||
|
limit: int = 100, statut: Optional[int] = None, inclure_lignes: bool = Query(True)
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
📋 Liste tous les devis avec filtres optionnels
|
📋 Liste tous les devis avec filtres optionnels
|
||||||
Utilise le cache pour performances optimales
|
|
||||||
|
|
||||||
✅ CORRECTION: Ajout de win32com.client.CastTo et Query parameters
|
Args:
|
||||||
|
limit: Nombre max de devis à retourner
|
||||||
|
statut: Filtre par statut (optionnel)
|
||||||
|
inclure_lignes: Si True, charge les lignes de chaque devis (par défaut: True)
|
||||||
|
|
||||||
|
✅ AMÉLIORATION: Charge maintenant les lignes de chaque devis
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if not sage or not sage.cial:
|
if not sage or not sage.cial:
|
||||||
|
|
@ -271,11 +277,13 @@ def devis_list(limit: int = 100, statut: Optional[int] = None):
|
||||||
factory = sage.cial.FactoryDocumentVente
|
factory = sage.cial.FactoryDocumentVente
|
||||||
devis_list = []
|
devis_list = []
|
||||||
index = 1
|
index = 1
|
||||||
max_iterations = limit * 3 # Marge de sécurité
|
max_iterations = limit * 3
|
||||||
erreurs_consecutives = 0
|
erreurs_consecutives = 0
|
||||||
max_erreurs = 50
|
max_erreurs = 50
|
||||||
|
|
||||||
logger.info(f"🔍 Recherche devis (limit={limit}, statut={statut})")
|
logger.info(
|
||||||
|
f"🔍 Recherche devis (limit={limit}, statut={statut}, inclure_lignes={inclure_lignes})"
|
||||||
|
)
|
||||||
|
|
||||||
while (
|
while (
|
||||||
len(devis_list) < limit
|
len(devis_list) < limit
|
||||||
|
|
@ -288,7 +296,6 @@ def devis_list(limit: int = 100, statut: Optional[int] = None):
|
||||||
logger.debug(f"Fin de liste à l'index {index}")
|
logger.debug(f"Fin de liste à l'index {index}")
|
||||||
break
|
break
|
||||||
|
|
||||||
# ✅ CRITIQUE: Utiliser win32com.client.CastTo
|
|
||||||
doc = win32com.client.CastTo(persist, "IBODocumentVente3")
|
doc = win32com.client.CastTo(persist, "IBODocumentVente3")
|
||||||
doc.Read()
|
doc.Read()
|
||||||
|
|
||||||
|
|
@ -328,6 +335,74 @@ def devis_list(limit: int = 100, statut: Optional[int] = None):
|
||||||
if client_cache:
|
if client_cache:
|
||||||
client_intitule = client_cache.get("intitule", "")
|
client_intitule = client_cache.get("intitule", "")
|
||||||
|
|
||||||
|
# ✅✅ NOUVEAU: Charger les lignes si demandé
|
||||||
|
lignes = []
|
||||||
|
if inclure_lignes:
|
||||||
|
try:
|
||||||
|
factory_lignes = getattr(doc, "FactoryDocumentLigne", None)
|
||||||
|
if not factory_lignes:
|
||||||
|
factory_lignes = getattr(
|
||||||
|
doc, "FactoryDocumentVenteLigne", None
|
||||||
|
)
|
||||||
|
|
||||||
|
if factory_lignes:
|
||||||
|
ligne_index = 1
|
||||||
|
while ligne_index <= 100: # Max 100 lignes par devis
|
||||||
|
try:
|
||||||
|
ligne_persist = factory_lignes.List(ligne_index)
|
||||||
|
if ligne_persist is None:
|
||||||
|
break
|
||||||
|
|
||||||
|
ligne = win32com.client.CastTo(
|
||||||
|
ligne_persist, "IBODocumentLigne3"
|
||||||
|
)
|
||||||
|
ligne.Read()
|
||||||
|
|
||||||
|
# Charger 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.append(
|
||||||
|
{
|
||||||
|
"article": article_ref,
|
||||||
|
"designation": getattr(
|
||||||
|
ligne, "DL_Design", ""
|
||||||
|
),
|
||||||
|
"quantite": float(
|
||||||
|
getattr(ligne, "DL_Qte", 0.0)
|
||||||
|
),
|
||||||
|
"prix_unitaire": float(
|
||||||
|
getattr(
|
||||||
|
ligne, "DL_PrixUnitaire", 0.0
|
||||||
|
)
|
||||||
|
),
|
||||||
|
"montant_ht": float(
|
||||||
|
getattr(ligne, "DL_MontantHT", 0.0)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
ligne_index += 1
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(f"Erreur ligne {ligne_index}: {e}")
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(f"Erreur chargement lignes: {e}")
|
||||||
|
|
||||||
devis_list.append(
|
devis_list.append(
|
||||||
{
|
{
|
||||||
"numero": getattr(doc, "DO_Piece", ""),
|
"numero": getattr(doc, "DO_Piece", ""),
|
||||||
|
|
@ -337,6 +412,7 @@ def devis_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,
|
||||||
|
"lignes": lignes, # ✅ Lignes incluses
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -355,8 +431,10 @@ def devis_list(limit: int = 100, statut: Optional[int] = None):
|
||||||
break
|
break
|
||||||
|
|
||||||
nb_avec_client = sum(1 for d in devis_list if d["client_intitule"])
|
nb_avec_client = sum(1 for d in devis_list if d["client_intitule"])
|
||||||
|
nb_avec_lignes = sum(1 for d in devis_list if d.get("lignes"))
|
||||||
logger.info(
|
logger.info(
|
||||||
f"✅ {len(devis_list)} devis retournés ({nb_avec_client} avec client)"
|
f"✅ {len(devis_list)} devis retournés "
|
||||||
|
f"({nb_avec_client} avec client, {nb_avec_lignes} avec lignes)"
|
||||||
)
|
)
|
||||||
|
|
||||||
return {"success": True, "data": devis_list}
|
return {"success": True, "data": devis_list}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue