diff --git a/main.py b/main.py index 05398ea..ba90551 100644 --- a/main.py +++ b/main.py @@ -256,12 +256,18 @@ def changer_statut_devis(doc_id: str, req: StatutRequest): @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 - 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: 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 devis_list = [] index = 1 - max_iterations = limit * 3 # Marge de sécurité + max_iterations = limit * 3 erreurs_consecutives = 0 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 ( 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}") break - # ✅ CRITIQUE: Utiliser win32com.client.CastTo doc = win32com.client.CastTo(persist, "IBODocumentVente3") doc.Read() @@ -328,6 +335,74 @@ def devis_list(limit: int = 100, statut: Optional[int] = None): if client_cache: 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( { "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_ttc": float(getattr(doc, "DO_TotalTTC", 0.0)), "statut": doc_statut, + "lignes": lignes, # ✅ Lignes incluses } ) @@ -355,8 +431,10 @@ def devis_list(limit: int = 100, statut: Optional[int] = None): break 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( - 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}