diff --git a/lib/services/pdf_impression_commande.dart b/lib/services/pdf_impression_commande.dart index f8f4ee7..ed2593d 100644 --- a/lib/services/pdf_impression_commande.dart +++ b/lib/services/pdf_impression_commande.dart @@ -44,13 +44,34 @@ class OrderPrinter { PrinterSettings? _settings; PrinterConnectionStatus _connectionStatus = PrinterConnectionStatus.notConfigured; + DateTime? _lastConfigUpdate; + static const Duration _configCacheTimeout = Duration(minutes: 5); + // Getters publics PrinterSettings? get settings => _settings; PrinterConnectionStatus get connectionStatus => _connectionStatus; - bool get isConfigured => _settings != null && - _settings!.ipAddress != null && - _settings!.ipAddress!.isNotEmpty && - _settings!.port != null; + + // Getter isConfigured modifié pour inclure validation temporelle + bool get isConfigured { + // Vérifier si la configuration existe + if (_settings == null || + _settings!.ipAddress == null || + _settings!.ipAddress!.isEmpty || + _settings!.port == null) { + return false; + } + + // Vérifier si la configuration n'est pas trop ancienne + if (_lastConfigUpdate != null && + DateTime.now().difference(_lastConfigUpdate!) > _configCacheTimeout) { + if (kDebugMode) { + print("⚠️ Configuration expirée, rechargement nécessaire"); + } + return false; + } + + return true; + } // Constantes ESC/POS static const List ESC_CONDENSED_ON = [0x1B, 0x0F]; @@ -73,6 +94,96 @@ class OrderPrinter { static const String rightWord = 'cocher'; static const int padding = 1; + /// Force la réinitialisation complète de l'instance + static void resetInstance() { + if (kDebugMode) { + print("🔄 Réinitialisation complète de l'instance OrderPrinter"); + } + _instance = null; + } + + /// Méthode pour vider complètement le cache et recharger + Future forceClearAndReload() async { + if (kDebugMode) { + print("🧹 Nettoyage complet de la configuration..."); + } + + // Effacer complètement tout + _settings = null; + _lastConfigUpdate = null; + _connectionStatus = PrinterConnectionStatus.notConfigured; + + if (kDebugMode) { + print("🔄 Rechargement forcé depuis l'API..."); + } + + // Attendre un peu pour s'assurer que tout est nettoyé + await Future.delayed(const Duration(milliseconds: 100)); + + // Recharger depuis l'API avec un timeout plus court pour déboguer + try { + var printerSettings = await RestaurantApiService.getPrinterSettings() + .timeout( + const Duration(seconds: 8), + onTimeout: () => throw TimeoutException('Timeout lors de la récupération'), + ); + + if (kDebugMode) { + print("📡 Nouvelle config reçue de l'API:"); + print(" IP: ${printerSettings.ipAddress}"); + print(" Port: ${printerSettings.port}"); + } + + // Validation + if (printerSettings.ipAddress == null || printerSettings.ipAddress!.isEmpty) { + throw ArgumentError('Adresse IP non définie'); + } + + if (printerSettings.port == null || printerSettings.port! <= 0) { + throw ArgumentError('Port invalide'); + } + + if (!_isValidIpAddress(printerSettings.ipAddress!)) { + throw ArgumentError('Format IP invalide: ${printerSettings.ipAddress}'); + } + + // Appliquer la nouvelle configuration + _settings = printerSettings; + _lastConfigUpdate = DateTime.now(); + _connectionStatus = PrinterConnectionStatus.disconnected; + + if (kDebugMode) { + print("✅ Configuration mise à jour avec succès:"); + print(" Nouvelle IP: ${_settings!.ipAddress}"); + print(" Nouveau Port: ${_settings!.port}"); + } + + return true; + + } catch (e) { + if (kDebugMode) { + print("❌ Erreur lors du rechargement forcé: $e"); + } + _connectionStatus = PrinterConnectionStatus.error; + return false; + } + } + + /// Méthode de débogage pour vérifier l'état actuel + void debugCurrentState() { + if (kDebugMode) { + print("🔍 État actuel de OrderPrinter:"); + print(" isConfigured: $isConfigured"); + print(" connectionStatus: $_connectionStatus"); + print(" settings: ${_settings != null ? '${_settings!.ipAddress}:${_settings!.port}' : 'null'}"); + print(" lastConfigUpdate: $_lastConfigUpdate"); + if (_lastConfigUpdate != null) { + final age = DateTime.now().difference(_lastConfigUpdate!); + print(" config age: ${age.inMinutes} minutes"); + } + } + } + /// Initialise la configuration de l'imprimante avec gestion d'erreurs robuste Future initialize() async { try { @@ -80,15 +191,23 @@ class OrderPrinter { if (kDebugMode) { print("🔧 Initialisation de la configuration imprimante..."); + print(" État avant: ${_settings != null ? '${_settings!.ipAddress}:${_settings!.port}' : 'null'}"); } - // Récupération des paramètres avec timeout via votre API + // Forcer la récupération depuis l'API var printerSettings = await RestaurantApiService.getPrinterSettings() .timeout( const Duration(seconds: 10), onTimeout: () => throw TimeoutException('Timeout lors de la récupération des paramètres'), ); + if (kDebugMode) { + print("📡 Réponse de l'API:"); + print(" IP reçue: ${printerSettings.ipAddress}"); + print(" Port reçu: ${printerSettings.port}"); + print(" Nom: ${printerSettings.name}"); + } + // Validation des paramètres if (printerSettings.ipAddress == null || printerSettings.ipAddress!.isEmpty) { throw ArgumentError('Adresse IP de l\'imprimante non définie'); @@ -103,39 +222,62 @@ class OrderPrinter { throw ArgumentError('Format d\'adresse IP invalide: ${printerSettings.ipAddress}'); } - _settings=null; + // Vérifier si la configuration a changé + bool configChanged = _settings == null || + _settings!.ipAddress != printerSettings.ipAddress || + _settings!.port != printerSettings.port; + + if (configChanged) { + if (kDebugMode) { + print("🔄 Changement de configuration détecté:"); + if (_settings != null) { + print(" Ancienne: ${_settings!.ipAddress}:${_settings!.port}"); + } else { + print(" Ancienne: null"); + } + print(" Nouvelle: ${printerSettings.ipAddress}:${printerSettings.port}"); + } + // Réinitialiser le statut de connexion + _connectionStatus = PrinterConnectionStatus.disconnected; + } else { + if (kDebugMode) { + print("ℹ️ Aucun changement de configuration"); + } + } + // Configuration réussie _settings = printerSettings; - _connectionStatus = PrinterConnectionStatus.disconnected; - _settings = PrinterSettings(); - _settings = printerSettings; + _lastConfigUpdate = DateTime.now(); if (kDebugMode) { - print("✅ Imprimante configurée : ${_settings!.ipAddress}:${_settings!.port}"); - if (_settings!.name != null) { - print("📋 Nom: ${_settings!.name}"); - } - if (_settings!.type != null) { - print("🏷️ Type: ${_settings!.type}"); - } + print("✅ Configuration appliquée:"); + print(" IP finale: ${_settings!.ipAddress}"); + print(" Port final: ${_settings!.port}"); + print(" Statut: $_connectionStatus"); } return true; } on TimeoutException catch (e) { _connectionStatus = PrinterConnectionStatus.error; + _settings = null; + _lastConfigUpdate = null; if (kDebugMode) { print("⏰ Timeout lors de l'initialisation: $e"); } return false; } on ArgumentError catch (e) { _connectionStatus = PrinterConnectionStatus.error; + _settings = null; + _lastConfigUpdate = null; if (kDebugMode) { print("❌ Paramètres invalides: $e"); } return false; } catch (e) { _connectionStatus = PrinterConnectionStatus.error; + _settings = null; + _lastConfigUpdate = null; if (kDebugMode) { print("💥 Erreur lors de la récupération des paramètres d'imprimante : $e"); } @@ -143,24 +285,79 @@ class OrderPrinter { } } + /// Nouvelle méthode pour forcer la revalidation + Future forceReload() async { + if (kDebugMode) { + print("🔄 Rechargement forcé de la configuration imprimante"); + } + + // Effacer la configuration actuelle + _settings = null; + _lastConfigUpdate = null; + _connectionStatus = PrinterConnectionStatus.notConfigured; + + // Recharger depuis l'API + return await initialize(); + } + /// Valide le format d'une adresse IP bool _isValidIpAddress(String ip) { final ipRegex = RegExp(r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'); return ipRegex.hasMatch(ip); } + /// Version améliorée du test de connexion avec plus de logs + Future testConnectionWithDebug({ + Duration timeout = const Duration(seconds: 5), + int maxRetries = 3, + }) async { + // Debug de l'état avant test + debugCurrentState(); + + // Vérifier et recharger si nécessaire + if (!isConfigured) { + if (kDebugMode) { + print("🔄 Configuration non valide, rechargement forcé..."); + } + + final reloadSuccess = await forceClearAndReload(); + if (!reloadSuccess) { + return const ConnectionTestResult( + isSuccessful: false, + message: 'Impossible de recharger la configuration', + status: PrinterConnectionStatus.notConfigured, + responseTime: Duration.zero, + ); + } + } + + if (kDebugMode) { + print("🎯 Test de connexion vers: ${_settings!.ipAddress}:${_settings!.port}"); + } + + return await testConnection(timeout: timeout, maxRetries: maxRetries); + } + /// Test de connexion avancé avec métriques Future testConnection({ Duration timeout = const Duration(seconds: 5), int maxRetries = 3, }) async { + // Vérifier et recharger la configuration si nécessaire if (!isConfigured) { - return const ConnectionTestResult( - isSuccessful: false, - message: 'Imprimante non configurée', - status: PrinterConnectionStatus.notConfigured, - responseTime: Duration.zero, - ); + if (kDebugMode) { + print("🔄 Configuration non valide, tentative de rechargement..."); + } + + final reloadSuccess = await initialize(); + if (!reloadSuccess) { + return const ConnectionTestResult( + isSuccessful: false, + message: 'Impossible de recharger la configuration imprimante', + status: PrinterConnectionStatus.notConfigured, + responseTime: Duration.zero, + ); + } } final stopwatch = Stopwatch()..start(); @@ -279,6 +476,10 @@ class OrderPrinter { 'timestamp': DateTime.now().toIso8601String(), 'configured': isConfigured, 'connectionStatus': _connectionStatus.toString(), + 'lastConfigUpdate': _lastConfigUpdate?.toIso8601String(), + 'configAge': _lastConfigUpdate != null + ? DateTime.now().difference(_lastConfigUpdate!).inMinutes + : null, }; if (_settings != null) { @@ -364,6 +565,11 @@ class OrderPrinter { return false; } + // Vérifier si c'est un changement + bool configChanged = _settings == null || + _settings!.ipAddress != ipAddress || + _settings!.port != port; + _settings = PrinterSettings( ipAddress: ipAddress, port: port, @@ -373,7 +579,12 @@ class OrderPrinter { updatedAt: DateTime.now(), ); - _connectionStatus = PrinterConnectionStatus.disconnected; + _lastConfigUpdate = DateTime.now(); + + // Réinitialiser le statut si changement + if (configChanged) { + _connectionStatus = PrinterConnectionStatus.disconnected; + } if (kDebugMode) { print("🔧 Configuration mise à jour: $ipAddress:$port"); @@ -396,12 +607,41 @@ class OrderPrinter { void resetConfiguration() { _settings = null; _connectionStatus = PrinterConnectionStatus.notConfigured; + _lastConfigUpdate = null; if (kDebugMode) { print("🔄 Configuration de l'imprimante réinitialisée"); } } + /// Vérifie si la configuration a changé + bool hasConfigurationChanged(PrinterSettings newSettings) { + if (_settings == null) return true; + + return _settings!.ipAddress != newSettings.ipAddress || + _settings!.port != newSettings.port || + _settings!.name != newSettings.name || + _settings!.type != newSettings.type; + } + + /// Informations de debug + Map getDebugInfo() { + return { + 'isConfigured': isConfigured, + 'connectionStatus': _connectionStatus.toString(), + 'lastConfigUpdate': _lastConfigUpdate?.toIso8601String(), + 'configAge': _lastConfigUpdate != null + ? DateTime.now().difference(_lastConfigUpdate!).inMinutes + : null, + 'settings': _settings != null ? { + 'ipAddress': _settings!.ipAddress, + 'port': _settings!.port, + 'name': _settings!.name, + 'type': _settings!.type, + } : null, + }; + } + /// Méthode pour normaliser les caractères accentués String safePadRight(String text, int width) { // Remplace temporairement les accents par des lettres simples @@ -420,8 +660,28 @@ class OrderPrinter { return normalized.padRight(width); } + Future _ensureValidConfiguration() async { + if (!isConfigured) { + if (kDebugMode) { + print("🔄 Configuration non valide, rechargement..."); + } + final reloaded = await initialize(); + if (!reloaded) { + if (kDebugMode) { + print("❌ Impossible de recharger la configuration imprimante"); + } + return false; + } + } + return true; + } + // Méthodes d'impression optimisées Future printOrderESCPOS(Order order) async { + if (!await _ensureValidConfiguration()) { + return false; + } + final connectionTest = await testConnection(); if (!connectionTest.isSuccessful) { if (kDebugMode) { @@ -508,6 +768,11 @@ class OrderPrinter { } Future printOrderESC80MM(Order order) async { + // Auto-revalidation avant impression + if (!await _ensureValidConfiguration()) { + return false; + } + final connectionTest = await testConnection(); if (!connectionTest.isSuccessful) { if (kDebugMode) { @@ -575,6 +840,10 @@ class OrderPrinter { } Future printOrderESCPOSOptimized(Order order) async { + if (!await _ensureValidConfiguration()) { + return false; + } + final connectionTest = await testConnection(); if (!connectionTest.isSuccessful) { if (kDebugMode) { @@ -686,6 +955,67 @@ class OrderPrinter { } } +// Fonction utilitaire pour forcer la mise à jour +Future forceUpdatePrinterConfig() async { + final printer = OrderPrinter.instance; + + if (kDebugMode) { + print("🔧 Forçage de la mise à jour de configuration..."); + } + + // Méthode 1: Utiliser forceClearAndReload + bool success = await printer.forceClearAndReload(); + + if (success) { + if (kDebugMode) { + print("✅ Configuration mise à jour avec succès"); + } + return true; + } else { + if (kDebugMode) { + print("❌ Échec de la mise à jour, tentative de réinitialisation complète..."); + } + + // Méthode 2: Réinitialisation complète de l'instance + OrderPrinter.resetInstance(); + + // Obtenir la nouvelle instance et initialiser + final newPrinter = OrderPrinter.instance; + return await newPrinter.initialize(); + } +} + +// Fonction pour tester avec débogage complet +Future testPrinterWithFullDebug() async { + final printer = OrderPrinter.instance; + + print("🔍 === DÉBOGAGE COMPLET IMPRIMANTE ==="); + + // État initial + printer.debugCurrentState(); + + // Force la mise à jour + print("🔄 Forçage de la mise à jour..."); + await printer.forceClearAndReload(); + + // État après mise à jour + print("📊 État après mise à jour:"); + printer.debugCurrentState(); + + // Test de connexion + print("🔗 Test de connexion..."); + final result = await printer.testConnectionWithDebug(); + + print("📋 Résultat: ${result.isSuccessful ? '✅' : '❌'} ${result.message}"); + + // Diagnostic complet + print("🏥 Diagnostic complet:"); + final diagnostics = await printer.runDiagnostics(); + diagnostics.forEach((key, value) { + print(" $key: $value"); + }); +} + // Fonctions utilitaires pour rétrocompatibilité Future printOrderPDF(Order order) async { final printer = OrderPrinter.instance;