diff --git a/api.py b/api.py index 7a1086f..166f5af 100644 --- a/api.py +++ b/api.py @@ -3896,7 +3896,60 @@ async def statistiques_utilisateurs(session: AsyncSession = Depends(get_session) logger.error(f"❌ Erreur stats utilisateurs: {e}") raise HTTPException(500, str(e)) +@app.get("/modeles", tags=["PDF"]) +async def get_modeles_disponibles(): + """Liste tous les modèles PDF disponibles""" + try: + modeles = sage_client.lister_modeles_disponibles() + return modeles + except Exception as e: + logger.error(f"Erreur listage modèles: {e}") + raise HTTPException(500, str(e)) + +@app.get("/documents/{numero}/pdf", tags=["Documents"]) +async def get_document_pdf( + numero: str, + type_doc: int = Query(..., description="0=devis, 60=facture, etc."), + modele: str = Query(None, description="Nom du modèle (ex: 'Facture client logo.bgc')"), + download: bool = Query(False, description="Télécharger au lieu d'afficher") +): + """ + 📄 Génère et retourne le PDF d'un document + + Exemples: + - GET /documents/DE00001/pdf?type_doc=0 + - GET /documents/FA00123/pdf?type_doc=60&modele=Facture client logo.bgc + - GET /documents/FA00123/pdf?type_doc=60&download=true + """ + try: + # Récupérer le PDF (en bytes) + pdf_bytes = sage_client.generer_pdf_document( + numero=numero, + type_doc=type_doc, + modele=modele, + base64_encode=False # On veut les bytes bruts + ) + + # Retourner le PDF + from fastapi.responses import Response + + disposition = "attachment" if download else "inline" + filename = f"{numero}.pdf" + + return Response( + content=pdf_bytes, + media_type="application/pdf", + headers={ + "Content-Disposition": f'{disposition}; filename="{filename}"' + } + ) + + except Exception as e: + logger.error(f"Erreur génération PDF: {e}") + raise HTTPException(500, str(e)) + + # ===================================================== # LANCEMENT # ===================================================== diff --git a/sage_client.py b/sage_client.py index 6b9325c..7aa034a 100644 --- a/sage_client.py +++ b/sage_client.py @@ -428,5 +428,60 @@ class SageGatewayClient: return None -# Instance globale + def lister_modeles_disponibles(self) -> Dict: + """Liste les modèles Crystal Reports disponibles""" + try: + r = requests.get( + f"{self.url}/sage/modeles/list", + headers=self.headers, + timeout=30 + ) + r.raise_for_status() + return r.json().get("data", {}) + except requests.exceptions.RequestException as e: + logger.error(f"❌ Erreur listage modèles: {e}") + raise + + + def generer_pdf_document( + self, + numero: str, + type_doc: int, + modele: str = None, + base64_encode: bool = True + ) -> Union[bytes, str, Dict]: + """ + Génère un PDF d'un document Sage + + Returns: + Dict: Avec pdf_base64 si base64_encode=True + bytes: Contenu PDF brut si base64_encode=False + """ + try: + params = { + "type_doc": type_doc, + "base64_encode": base64_encode + } + + if modele: + params["modele"] = modele + + r = requests.get( + f"{self.url}/sage/documents/{numero}/pdf", + params=params, + headers=self.headers, + timeout=60 # PDF peut prendre du temps + ) + r.raise_for_status() + + if base64_encode: + return r.json().get("data", {}) + else: + return r.content + + except requests.exceptions.RequestException as e: + logger.error(f"❌ Erreur génération PDF: {e}") + raise + + sage_client = SageGatewayClient()