316 lines
No EOL
9.6 KiB
Python
316 lines
No EOL
9.6 KiB
Python
"""
|
|
🧪 TEST GÉNÉRATION PDF AVEC CRYSTAL REPORTS
|
|
À lancer immédiatement après installation Crystal
|
|
"""
|
|
|
|
import win32com.client
|
|
import os
|
|
import time
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def test_crystal_pdf_simple():
|
|
"""
|
|
Test rapide de Crystal Reports - sans Sage
|
|
Vérifie juste que Crystal peut s'instancier et exporter
|
|
"""
|
|
print("\n" + "="*70)
|
|
print("🧪 TEST CRYSTAL REPORTS - INSTANCIATION SIMPLE")
|
|
print("="*70)
|
|
|
|
try:
|
|
# 1. Instancier Crystal
|
|
print("\n1. Instanciation Crystal Runtime...")
|
|
|
|
prog_ids = [
|
|
"CrystalRuntime.Application.140",
|
|
"CrystalRuntime.Application.13",
|
|
"CrystalRuntime.Application.12",
|
|
]
|
|
|
|
crystal = None
|
|
prog_id_utilisee = None
|
|
|
|
for prog_id in prog_ids:
|
|
try:
|
|
crystal = win32com.client.Dispatch(prog_id)
|
|
prog_id_utilisee = prog_id
|
|
print(f" ✅ {prog_id}")
|
|
break
|
|
except Exception as e:
|
|
print(f" ❌ {prog_id}: {e}")
|
|
|
|
if not crystal:
|
|
print("\n❌ ÉCHEC : Aucune version de Crystal disponible")
|
|
print(" → Vérifier installation")
|
|
print(" → Redémarrer le serveur si juste installé")
|
|
return False
|
|
|
|
print(f"\n✅ Crystal opérationnel : {prog_id_utilisee}")
|
|
|
|
# 2. Vérifier méthodes disponibles
|
|
print("\n2. Vérification méthodes d'export...")
|
|
|
|
methodes_requises = ['OpenReport', 'Export']
|
|
|
|
for methode in methodes_requises:
|
|
if hasattr(crystal, methode):
|
|
print(f" ✅ {methode}()")
|
|
else:
|
|
print(f" ❌ {methode}() manquante")
|
|
|
|
print("\n✅ Crystal Reports est prêt pour générer des PDF !")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"\n❌ ERREUR : {e}")
|
|
return False
|
|
|
|
|
|
def tester_pdf_avec_sage(sage_connector, numero: str, type_doc: int):
|
|
"""
|
|
Test de génération PDF via Sage avec Crystal
|
|
|
|
Args:
|
|
sage_connector: Instance de ton SageConnector
|
|
numero: Numéro document (ex: "FA00123")
|
|
type_doc: Type document (0=devis, 60=facture, etc.)
|
|
|
|
Returns:
|
|
tuple: (success: bool, pdf_bytes: bytes, message: str)
|
|
"""
|
|
print("\n" + "="*70)
|
|
print(f"🧪 TEST GÉNÉRATION PDF SAGE + CRYSTAL")
|
|
print(f" Document: {numero} (type={type_doc})")
|
|
print("="*70)
|
|
|
|
try:
|
|
# 1. Vérifier connexion Sage
|
|
if not sage_connector.cial:
|
|
return False, None, "Connexion Sage non établie"
|
|
|
|
print("\n1. ✅ Connexion Sage OK")
|
|
|
|
# 2. Vérifier Crystal
|
|
print("\n2. Vérification Crystal...")
|
|
|
|
prog_ids = [
|
|
"CrystalRuntime.Application.140",
|
|
"CrystalRuntime.Application.13",
|
|
"CrystalRuntime.Application.12",
|
|
]
|
|
|
|
crystal_ok = False
|
|
for prog_id in prog_ids:
|
|
try:
|
|
test = win32com.client.Dispatch(prog_id)
|
|
crystal_ok = True
|
|
print(f" ✅ Crystal disponible : {prog_id}")
|
|
break
|
|
except:
|
|
pass
|
|
|
|
if not crystal_ok:
|
|
return False, None, "Crystal Reports non disponible - Redémarrer le serveur"
|
|
|
|
# 3. Chercher modèle .BGC
|
|
print("\n3. Recherche modèle Crystal...")
|
|
|
|
modeles = sage_connector.lister_modeles_crystal()
|
|
|
|
# Déterminer catégorie
|
|
mapping = {0: "devis", 10: "commandes", 30: "livraisons", 60: "factures", 50: "avoirs"}
|
|
categorie = mapping.get(type_doc, "autres")
|
|
|
|
if categorie not in modeles or not modeles[categorie]:
|
|
return False, None, f"Aucun modèle trouvé pour type {type_doc}"
|
|
|
|
modele = modeles[categorie][0]
|
|
chemin_modele = modele["chemin_complet"]
|
|
|
|
print(f" ✅ Modèle : {modele['fichier']}")
|
|
print(f" 📁 Chemin : {chemin_modele}")
|
|
|
|
if not os.path.exists(chemin_modele):
|
|
return False, None, f"Fichier modèle introuvable : {chemin_modele}"
|
|
|
|
# 4. Générer PDF
|
|
print("\n4. Génération PDF...")
|
|
print(" ⏳ Traitement en cours...")
|
|
|
|
start_time = time.time()
|
|
|
|
try:
|
|
# Utiliser ta méthode existante
|
|
pdf_bytes = sage_connector.generer_pdf_document(
|
|
numero=numero,
|
|
type_doc=type_doc,
|
|
modele=modele["fichier"]
|
|
)
|
|
|
|
elapsed = time.time() - start_time
|
|
|
|
if pdf_bytes and len(pdf_bytes) > 500:
|
|
print(f"\n✅ PDF GÉNÉRÉ AVEC SUCCÈS !")
|
|
print(f" 📊 Taille : {len(pdf_bytes):,} octets")
|
|
print(f" ⏱️ Temps : {elapsed:.2f}s")
|
|
|
|
return True, pdf_bytes, "Succès"
|
|
else:
|
|
return False, None, "PDF généré mais vide ou corrompu"
|
|
|
|
except Exception as e:
|
|
elapsed = time.time() - start_time
|
|
print(f"\n❌ ÉCHEC après {elapsed:.2f}s")
|
|
print(f" Erreur : {e}")
|
|
|
|
return False, None, str(e)
|
|
|
|
except Exception as e:
|
|
logger.error(f"Erreur test PDF : {e}", exc_info=True)
|
|
return False, None, str(e)
|
|
|
|
|
|
def analyser_erreur_generation(erreur_msg: str):
|
|
"""
|
|
Analyse une erreur de génération PDF et propose solutions
|
|
"""
|
|
print("\n" + "="*70)
|
|
print("🔍 ANALYSE DE L'ERREUR")
|
|
print("="*70)
|
|
|
|
erreur_lower = erreur_msg.lower()
|
|
|
|
if "access" in erreur_lower or "permission" in erreur_lower:
|
|
print("""
|
|
❌ PROBLÈME : Permissions fichiers
|
|
|
|
💡 SOLUTIONS :
|
|
1. Vérifier que le dossier temporaire est accessible :
|
|
icacls "C:\\Windows\\Temp" /grant Everyone:(OI)(CI)F /T
|
|
|
|
2. Vérifier permissions modèles .BGC :
|
|
icacls "C:\\Users\\Public\\Documents\\Sage" /grant Everyone:(OI)(CI)R /T
|
|
|
|
3. Exécuter l'application avec droits admin (temporairement)
|
|
""")
|
|
|
|
elif "not found" in erreur_lower or "introuvable" in erreur_lower:
|
|
print("""
|
|
❌ PROBLÈME : Fichier modèle introuvable
|
|
|
|
💡 SOLUTIONS :
|
|
1. Vérifier que le modèle .BGC existe :
|
|
dir "C:\\Users\\Public\\Documents\\Sage\\Entreprise 100c\\*.bgc" /s
|
|
|
|
2. Spécifier le chemin complet du modèle
|
|
|
|
3. Utiliser un modèle par défaut Sage
|
|
""")
|
|
|
|
elif "com" in erreur_lower or "dispatch" in erreur_lower:
|
|
print("""
|
|
❌ PROBLÈME : Erreur COM / Crystal Runtime
|
|
|
|
💡 SOLUTIONS :
|
|
1. REDÉMARRER LE SERVEUR (recommandé)
|
|
shutdown /r /t 60
|
|
|
|
2. Réenregistrer les DLL Crystal :
|
|
cd "C:\\Program Files\\SAP BusinessObjects\\Crystal Reports for .NET Framework 4.0\\Common\\SAP BusinessObjects Enterprise XI 4.0\\win64_x64"
|
|
regsvr32 /s crpe32.dll
|
|
regsvr32 /s crxf_pdf.dll
|
|
|
|
3. Vérifier que les services Crystal sont démarrés :
|
|
sc start "SAP Crystal Reports Processing Server"
|
|
""")
|
|
|
|
elif "database" in erreur_lower or "connexion" in erreur_lower:
|
|
print("""
|
|
❌ PROBLÈME : Connexion base de données
|
|
|
|
💡 SOLUTIONS :
|
|
1. Le modèle Crystal doit pouvoir se connecter à la base Sage
|
|
|
|
2. Vérifier les paramètres de connexion dans le modèle
|
|
|
|
3. Utiliser l'API Sage pour passer les données au lieu de
|
|
connecter Crystal directement à la base
|
|
""")
|
|
|
|
else:
|
|
print(f"""
|
|
❌ ERREUR : {erreur_msg}
|
|
|
|
💡 SOLUTIONS GÉNÉRIQUES :
|
|
1. Redémarrer le serveur
|
|
2. Vérifier les logs détaillés
|
|
3. Tester avec un modèle Crystal simple
|
|
4. Utiliser PDF custom en attendant
|
|
""")
|
|
|
|
print("="*70)
|
|
|
|
|
|
# Routes API pour tests
|
|
def creer_routes_test(app, sage_connector):
|
|
"""
|
|
Ajouter ces routes dans main.py pour tester facilement
|
|
"""
|
|
|
|
@app.get("/sage/test-crystal-simple")
|
|
async def test_crystal_simple():
|
|
"""Test Crystal sans Sage"""
|
|
success = test_crystal_pdf_simple()
|
|
return {
|
|
"success": success,
|
|
"message": "Crystal opérationnel" if success else "Crystal non disponible"
|
|
}
|
|
|
|
@app.get("/sage/test-pdf-complet")
|
|
async def test_pdf_complet(
|
|
numero: str = "FA00123",
|
|
type_doc: int = 60
|
|
):
|
|
"""Test génération PDF complète avec Sage + Crystal"""
|
|
|
|
success, pdf_bytes, message = tester_pdf_avec_sage(
|
|
sage_connector, numero, type_doc
|
|
)
|
|
|
|
if success:
|
|
from fastapi.responses import Response
|
|
return Response(
|
|
content=pdf_bytes,
|
|
media_type="application/pdf",
|
|
headers={
|
|
"Content-Disposition": f"attachment; filename={numero}.pdf"
|
|
}
|
|
)
|
|
else:
|
|
# Analyser erreur
|
|
analyser_erreur_generation(message)
|
|
|
|
from fastapi import HTTPException
|
|
raise HTTPException(
|
|
status_code=500,
|
|
detail={
|
|
"error": message,
|
|
"recommandation": "Consulter les logs pour analyse détaillée"
|
|
}
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("🚀 LANCEMENT TESTS CRYSTAL REPORTS")
|
|
|
|
# Test 1 : Crystal seul
|
|
crystal_ok = test_crystal_pdf_simple()
|
|
|
|
if not crystal_ok:
|
|
print("\n⚠️ Crystal non opérationnel")
|
|
print(" → Redémarrer le serveur et relancer")
|
|
else:
|
|
print("\n✅ Crystal OK - Prêt pour génération PDF avec Sage") |