creer_client opérationelle
This commit is contained in:
parent
57c05082c0
commit
557f43bd18
3 changed files with 717 additions and 819 deletions
12
diagnostic_crystal.txt
Normal file
12
diagnostic_crystal.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
======================================================================
|
||||
DIAGNOSTIC CRYSTAL REPORTS
|
||||
======================================================================
|
||||
|
||||
Installation détectée: True
|
||||
DLL trouvées:
|
||||
ProgID valides:
|
||||
Architecture OK: False
|
||||
|
||||
PROBLÈMES:
|
||||
|
||||
SOLUTIONS:
|
||||
File diff suppressed because it is too large
Load diff
571
test.py
571
test.py
|
|
@ -1,316 +1,323 @@
|
|||
"""
|
||||
🧪 TEST GÉNÉRATION PDF AVEC CRYSTAL REPORTS
|
||||
À lancer immédiatement après installation Crystal
|
||||
🔬 DIAGNOSTIC APPROFONDI CRYSTAL REPORTS
|
||||
Découvre pourquoi Crystal ne fonctionne pas après redémarrage
|
||||
"""
|
||||
|
||||
import win32com.client
|
||||
import os
|
||||
import time
|
||||
import logging
|
||||
import winreg
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
def diagnostic_complet_crystal():
|
||||
"""Diagnostic exhaustif de l'installation Crystal"""
|
||||
|
||||
|
||||
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)
|
||||
print("🔬 DIAGNOSTIC APPROFONDI CRYSTAL REPORTS")
|
||||
print("="*70)
|
||||
|
||||
try:
|
||||
# 1. Instancier Crystal
|
||||
print("\n1. Instanciation Crystal Runtime...")
|
||||
problemes = []
|
||||
solutions = []
|
||||
|
||||
prog_ids = [
|
||||
"CrystalRuntime.Application.140",
|
||||
"CrystalRuntime.Application.13",
|
||||
"CrystalRuntime.Application.12",
|
||||
]
|
||||
# ==========================================
|
||||
# 1. VÉRIFIER SI CRYSTAL EST INSTALLÉ
|
||||
# ==========================================
|
||||
print("\n📁 1. Vérification présence des fichiers...")
|
||||
|
||||
crystal = None
|
||||
prog_id_utilisee = None
|
||||
chemins_installation = [
|
||||
r"C:\Program Files\SAP BusinessObjects",
|
||||
r"C:\Program Files (x86)\SAP BusinessObjects",
|
||||
r"C:\Program Files\SAP\Crystal Reports",
|
||||
r"C:\Program Files (x86)\SAP\Crystal Reports",
|
||||
]
|
||||
|
||||
for prog_id in prog_ids:
|
||||
crystal_trouve = False
|
||||
chemin_crystal = None
|
||||
|
||||
for chemin in chemins_installation:
|
||||
if os.path.exists(chemin):
|
||||
print(f" ✅ Dossier trouvé : {chemin}")
|
||||
crystal_trouve = True
|
||||
chemin_crystal = chemin
|
||||
|
||||
# Afficher taille
|
||||
try:
|
||||
crystal = win32com.client.Dispatch(prog_id)
|
||||
prog_id_utilisee = prog_id
|
||||
print(f" ✅ {prog_id}")
|
||||
break
|
||||
total_size = 0
|
||||
for dirpath, dirnames, filenames in os.walk(chemin):
|
||||
for f in filenames:
|
||||
fp = os.path.join(dirpath, f)
|
||||
try:
|
||||
total_size += os.path.getsize(fp)
|
||||
except:
|
||||
pass
|
||||
|
||||
size_mb = total_size / (1024 * 1024)
|
||||
print(f" Taille : {size_mb:.1f} MB")
|
||||
|
||||
if size_mb < 100:
|
||||
print(f" ⚠️ Taille suspecte (attendu: 300-800 MB)")
|
||||
problemes.append("Installation incomplète (taille trop petite)")
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ {prog_id}: {e}")
|
||||
print(f" ⚠️ Impossible de calculer taille : {e}")
|
||||
else:
|
||||
print(f" ❌ Absent : {chemin}")
|
||||
|
||||
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
|
||||
if not crystal_trouve:
|
||||
print("\n❌ PROBLÈME MAJEUR : Crystal Reports n'est pas installé")
|
||||
problemes.append("Crystal Reports non installé")
|
||||
solutions.append("Télécharger et installer SAP Crystal Reports Runtime")
|
||||
return {"problemes": problemes, "solutions": solutions, "installe": False}
|
||||
|
||||
print(f"\n✅ Crystal opérationnel : {prog_id_utilisee}")
|
||||
# ==========================================
|
||||
# 2. CHERCHER LES DLL CRITIQUES
|
||||
# ==========================================
|
||||
print("\n📦 2. Recherche DLL critiques...")
|
||||
|
||||
# 2. Vérifier méthodes disponibles
|
||||
print("\n2. Vérification méthodes d'export...")
|
||||
dll_critiques = {
|
||||
'crpe32.dll': 'Crystal Reports Print Engine (CRITIQUE)',
|
||||
'crxf_pdf.dll': 'Export PDF (CRITIQUE)',
|
||||
'crdb_adoplus.dll': 'Connexion base de données',
|
||||
'CrystalDecisions.CrystalReports.Engine.dll': 'Moteur Crystal .NET',
|
||||
}
|
||||
|
||||
methodes_requises = ['OpenReport', 'Export']
|
||||
dll_trouvees = {}
|
||||
|
||||
for methode in methodes_requises:
|
||||
if hasattr(crystal, methode):
|
||||
print(f" ✅ {methode}()")
|
||||
else:
|
||||
print(f" ❌ {methode}() manquante")
|
||||
for dll_nom, description in dll_critiques.items():
|
||||
trouve = False
|
||||
|
||||
print("\n✅ Crystal Reports est prêt pour générer des PDF !")
|
||||
return True
|
||||
for root, dirs, files in os.walk(chemin_crystal):
|
||||
if dll_nom.lower() in [f.lower() for f in files]:
|
||||
dll_path = os.path.join(root, dll_nom)
|
||||
dll_trouvees[dll_nom] = dll_path
|
||||
print(f" ✅ {dll_nom}")
|
||||
print(f" {dll_path}")
|
||||
trouve = True
|
||||
break
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ ERREUR : {e}")
|
||||
return False
|
||||
if not trouve:
|
||||
print(f" ❌ {dll_nom} - {description}")
|
||||
if "CRITIQUE" in description:
|
||||
problemes.append(f"{dll_nom} manquante")
|
||||
|
||||
if len(dll_trouvees) < 2:
|
||||
print("\n ⚠️ Trop peu de DLL trouvées - Installation corrompue")
|
||||
problemes.append("DLL manquantes - Installation corrompue")
|
||||
solutions.append("Réinstaller Crystal Reports Runtime")
|
||||
|
||||
def tester_pdf_avec_sage(sage_connector, numero: str, type_doc: int):
|
||||
"""
|
||||
Test de génération PDF via Sage avec Crystal
|
||||
# ==========================================
|
||||
# 3. VÉRIFIER LE REGISTRE
|
||||
# ==========================================
|
||||
print("\n📋 3. Vérification registre Windows...")
|
||||
|
||||
Args:
|
||||
sage_connector: Instance de ton SageConnector
|
||||
numero: Numéro document (ex: "FA00123")
|
||||
type_doc: Type document (0=devis, 60=facture, etc.)
|
||||
prog_ids = [
|
||||
"CrystalRuntime.Application.140",
|
||||
"CrystalRuntime.Application.13",
|
||||
"CrystalRuntime.Application.12",
|
||||
"CrystalRuntime.Application",
|
||||
"CrystalDesignRunTime.Application",
|
||||
]
|
||||
|
||||
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)
|
||||
prog_ids_trouves = []
|
||||
|
||||
for prog_id in prog_ids:
|
||||
try:
|
||||
# Vérifier existence
|
||||
key = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, prog_id)
|
||||
print(f" ✅ {prog_id}")
|
||||
|
||||
# Lire le CLSID
|
||||
try:
|
||||
clsid_key = winreg.OpenKey(key, "CLSID")
|
||||
clsid, _ = winreg.QueryValueEx(clsid_key, "")
|
||||
print(f" CLSID: {clsid}")
|
||||
|
||||
# Vérifier que le CLSID existe aussi
|
||||
try:
|
||||
clsid_path = f"CLSID\\{clsid}"
|
||||
clsid_key_check = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, clsid_path)
|
||||
|
||||
# Lire InprocServer32 (chemin DLL)
|
||||
try:
|
||||
server_key = winreg.OpenKey(clsid_key_check, "InprocServer32")
|
||||
dll_path, _ = winreg.QueryValueEx(server_key, "")
|
||||
print(f" DLL: {dll_path}")
|
||||
|
||||
# Vérifier que la DLL existe
|
||||
if not os.path.exists(dll_path):
|
||||
print(f" ❌ DLL INTROUVABLE: {dll_path}")
|
||||
problemes.append(f"{prog_id}: DLL manquante ({dll_path})")
|
||||
else:
|
||||
prog_ids_trouves.append(prog_id)
|
||||
|
||||
except:
|
||||
print(f" ⚠️ InprocServer32 non trouvé")
|
||||
|
||||
except:
|
||||
print(f" ❌ CLSID {clsid} non trouvé dans registre")
|
||||
problemes.append(f"{prog_id}: CLSID cassé")
|
||||
|
||||
except:
|
||||
print(f" ⚠️ Pas de CLSID")
|
||||
|
||||
winreg.CloseKey(key)
|
||||
|
||||
except:
|
||||
print(f" ❌ {prog_id}")
|
||||
|
||||
if not prog_ids_trouves:
|
||||
print("\n ⚠️ Aucun ProgID valide - Enregistrement COM échoué")
|
||||
problemes.append("ProgID non enregistrés correctement")
|
||||
solutions.append("Réenregistrer les DLL Crystal avec regsvr32")
|
||||
|
||||
# ==========================================
|
||||
# 4. VÉRIFIER ARCHITECTURE (32 vs 64 bit)
|
||||
# ==========================================
|
||||
print("\n🔧 4. Vérification architecture...")
|
||||
|
||||
# Architecture Python
|
||||
python_arch = "64-bit" if sys.maxsize > 2**32 else "32-bit"
|
||||
print(f" Python : {python_arch}")
|
||||
|
||||
# Architecture système
|
||||
import platform
|
||||
sys_arch = platform.machine()
|
||||
print(f" Système : {sys_arch}")
|
||||
|
||||
# Détecter architecture Crystal installée
|
||||
crystal_arch = None
|
||||
if dll_trouvees:
|
||||
first_dll = list(dll_trouvees.values())[0]
|
||||
if "win64_x64" in first_dll or "x64" in first_dll:
|
||||
crystal_arch = "64-bit"
|
||||
elif "win32_x86" in first_dll or "x86" in first_dll:
|
||||
crystal_arch = "32-bit"
|
||||
|
||||
if crystal_arch:
|
||||
print(f" Crystal : {crystal_arch}")
|
||||
|
||||
if python_arch != crystal_arch:
|
||||
print(f"\n ❌ INCOMPATIBILITÉ ARCHITECTURE")
|
||||
print(f" Python {python_arch} ne peut pas utiliser Crystal {crystal_arch}")
|
||||
problemes.append(f"Incompatibilité: Python {python_arch} vs Crystal {crystal_arch}")
|
||||
solutions.append(f"Réinstaller Crystal en version {python_arch}")
|
||||
|
||||
# ==========================================
|
||||
# 5. VÉRIFIER SERVICES WINDOWS
|
||||
# ==========================================
|
||||
print("\n🔄 5. Vérification services Windows...")
|
||||
|
||||
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
|
||||
result = subprocess.run(
|
||||
['sc', 'query', 'type=', 'service'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
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)
|
||||
services_crystal_attendus = [
|
||||
"SAP Crystal Reports",
|
||||
"Crystal Reports",
|
||||
"CrystalReports",
|
||||
]
|
||||
|
||||
from fastapi import HTTPException
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail={
|
||||
"error": message,
|
||||
"recommandation": "Consulter les logs pour analyse détaillée"
|
||||
}
|
||||
)
|
||||
services_trouves = []
|
||||
for service in services_crystal_attendus:
|
||||
if service.lower() in result.stdout.lower():
|
||||
services_trouves.append(service)
|
||||
print(f" ✅ Service trouvé: {service}")
|
||||
|
||||
if not services_trouves:
|
||||
print(f" ⚠️ Aucun service Crystal trouvé")
|
||||
print(f" (Normal pour Runtime léger)")
|
||||
|
||||
except Exception as e:
|
||||
print(f" ⚠️ Impossible de vérifier services: {e}")
|
||||
|
||||
# ==========================================
|
||||
# 6. TEST INSTANCIATION COM DÉTAILLÉ
|
||||
# ==========================================
|
||||
print("\n🧪 6. Test instanciation COM détaillé...")
|
||||
|
||||
import win32com.client
|
||||
|
||||
for prog_id in prog_ids_trouves:
|
||||
print(f"\n Test: {prog_id}")
|
||||
try:
|
||||
obj = win32com.client.Dispatch(prog_id)
|
||||
print(f" ✅ Instanciation RÉUSSIE")
|
||||
|
||||
# Lister méthodes disponibles
|
||||
print(f" Méthodes disponibles:")
|
||||
for attr in dir(obj):
|
||||
if not attr.startswith('_') and callable(getattr(obj, attr, None)):
|
||||
print(f" - {attr}()")
|
||||
|
||||
return {
|
||||
"problemes": problemes,
|
||||
"solutions": solutions,
|
||||
"installe": True,
|
||||
"prog_id_fonctionnel": prog_id
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Échec: {e}")
|
||||
print(f" Type erreur: {type(e).__name__}")
|
||||
print(f" Code: {e.args if hasattr(e, 'args') else 'N/A'}")
|
||||
|
||||
# ==========================================
|
||||
# 7. RÉSUMÉ ET RECOMMANDATIONS
|
||||
# ==========================================
|
||||
print("\n" + "="*70)
|
||||
print("📊 RÉSUMÉ DU DIAGNOSTIC")
|
||||
print("="*70)
|
||||
|
||||
print(f"\n📁 Installation détectée: {'OUI' if crystal_trouve else 'NON'}")
|
||||
print(f"📦 DLL trouvées: {len(dll_trouvees)}/{len(dll_critiques)}")
|
||||
print(f"📋 ProgID valides: {len(prog_ids_trouves)}")
|
||||
print(f"🔧 Architecture: Python {python_arch}, Crystal {crystal_arch or 'INCONNUE'}")
|
||||
|
||||
if problemes:
|
||||
print(f"\n❌ PROBLÈMES DÉTECTÉS ({len(problemes)}):")
|
||||
for i, pb in enumerate(problemes, 1):
|
||||
print(f" {i}. {pb}")
|
||||
|
||||
if solutions:
|
||||
print(f"\n💡 SOLUTIONS RECOMMANDÉES:")
|
||||
for i, sol in enumerate(solutions, 1):
|
||||
print(f" {i}. {sol}")
|
||||
|
||||
print("\n" + "="*70)
|
||||
|
||||
return {
|
||||
"problemes": problemes,
|
||||
"solutions": solutions,
|
||||
"installe": crystal_trouve,
|
||||
"dll_trouvees": list(dll_trouvees.keys()),
|
||||
"prog_ids_valides": prog_ids_trouves,
|
||||
"architecture_ok": python_arch == crystal_arch if crystal_arch else False
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("🚀 LANCEMENT TESTS CRYSTAL REPORTS")
|
||||
resultats = diagnostic_complet_crystal()
|
||||
|
||||
# Test 1 : Crystal seul
|
||||
crystal_ok = test_crystal_pdf_simple()
|
||||
print("\n💾 Résultats sauvegardés dans diagnostic_crystal.txt")
|
||||
|
||||
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")
|
||||
# Sauvegarder dans fichier
|
||||
with open("diagnostic_crystal.txt", "w", encoding="utf-8") as f:
|
||||
f.write("="*70 + "\n")
|
||||
f.write("DIAGNOSTIC CRYSTAL REPORTS\n")
|
||||
f.write("="*70 + "\n\n")
|
||||
|
||||
f.write(f"Installation détectée: {resultats['installe']}\n")
|
||||
f.write(f"DLL trouvées: {', '.join(resultats.get('dll_trouvees', []))}\n")
|
||||
f.write(f"ProgID valides: {', '.join(resultats.get('prog_ids_valides', []))}\n")
|
||||
f.write(f"Architecture OK: {resultats.get('architecture_ok', False)}\n\n")
|
||||
|
||||
f.write("PROBLÈMES:\n")
|
||||
for pb in resultats['problemes']:
|
||||
f.write(f" - {pb}\n")
|
||||
|
||||
f.write("\nSOLUTIONS:\n")
|
||||
for sol in resultats['solutions']:
|
||||
f.write(f" - {sol}\n")
|
||||
Loading…
Reference in a new issue