""" đŸ§Ș 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")