From 1207eeff13950f2b93d9d24582ce5934db0f42ad Mon Sep 17 00:00:00 2001 From: Stephane Date: Sun, 3 Aug 2025 22:04:25 +0300 Subject: [PATCH] impression --- lib/services/pdf_service.dart | 440 +++++++++++++++++++--------------- 1 file changed, 242 insertions(+), 198 deletions(-) diff --git a/lib/services/pdf_service.dart b/lib/services/pdf_service.dart index f9510b0..c18a76f 100644 --- a/lib/services/pdf_service.dart +++ b/lib/services/pdf_service.dart @@ -71,223 +71,267 @@ class PlatformPrintService { pdf.addPage( pw.Page( pageFormat: ticket58mmFormat, + margin: const pw.EdgeInsets.all(2), // 🔧 Marges minimales build: (pw.Context context) { - return pw.Column( - crossAxisAlignment: pw.CrossAxisAlignment.center, - children: [ - // En-tête Restaurant (centré et compact) - pw.Text( - restaurantInfo['nom']!, - style: pw.TextStyle( - fontSize: titleSize, - fontWeight: pw.FontWeight.bold, - ), - textAlign: pw.TextAlign.center, - ), - - pw.SizedBox(height: 1), - - pw.Text( - restaurantInfo['adresse']!, - style: pw.TextStyle(fontSize: smallSize), - textAlign: pw.TextAlign.center, - ), - - pw.Text( - restaurantInfo['ville']!, - style: pw.TextStyle(fontSize: smallSize), - textAlign: pw.TextAlign.center, - ), - - pw.Text( - 'Tel: ${restaurantInfo['contact']!}', - style: pw.TextStyle(fontSize: smallSize), - textAlign: pw.TextAlign.center, - ), - - pw.SizedBox(height: 3), - - // Ligne de séparation - pw.Container( - width: double.infinity, - height: 0.5, - color: PdfColors.black, - ), - - pw.SizedBox(height: 2), - - // Informations ticket - pw.Row( - mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, - children: [ - pw.Text( - 'Ticket: $factureNumber', + return pw.Container( + width: double.infinity, // 🔧 Forcer la largeur complète + child: pw.Column( + crossAxisAlignment: + pw.CrossAxisAlignment.start, // 🔧 Alignement à gauche + children: [ + // En-tête Restaurant (centré et compact) + pw.Container( + width: double.infinity, + child: pw.Text( + restaurantInfo['nom']!, style: pw.TextStyle( - fontSize: bodySize, + fontSize: titleSize, fontWeight: pw.FontWeight.bold, ), + textAlign: pw.TextAlign.center, ), - pw.Text( - 'Via: ${commande.tablename ?? 'Table inconnue'}', - style: pw.TextStyle(fontSize: bodySize), - ), - ], - ), + ), + + pw.SizedBox(height: 1), - pw.SizedBox(height: 1), + pw.Container( + width: double.infinity, + child: pw.Text( + restaurantInfo['adresse']!, + style: pw.TextStyle(fontSize: smallSize), + textAlign: pw.TextAlign.center, + ), + ), - pw.Row( - mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, - children: [ - pw.Text( - _formatDate(dateTime), + pw.Container( + width: double.infinity, + child: pw.Text( + restaurantInfo['ville']!, style: pw.TextStyle(fontSize: smallSize), + textAlign: pw.TextAlign.center, ), - pw.Text( - _formatTime(dateTime), + ), + + pw.Container( + width: double.infinity, + child: pw.Text( + 'Tel: ${restaurantInfo['contact']!}', style: pw.TextStyle(fontSize: smallSize), + textAlign: pw.TextAlign.center, ), - ], - ), - - pw.SizedBox(height: 2), - - // Ligne de séparation - pw.Container( - width: double.infinity, - height: 0.5, - color: PdfColors.black, - ), - - pw.SizedBox(height: 2), - - // Articles (format très compact) - ...commande.items - .map( - (item) => pw.Container( - margin: const pw.EdgeInsets.only(bottom: 1), - child: pw.Column( - crossAxisAlignment: pw.CrossAxisAlignment.start, - children: [ - // Nom du plat - pw.Text( - '${item.menuNom}', - style: pw.TextStyle(fontSize: bodySize), - maxLines: 2, - ), - - // Quantité, prix unitaire et total sur une ligne - pw.Row( - mainAxisAlignment: - pw.MainAxisAlignment.spaceBetween, - children: [ - pw.Text( - '${item.quantite}x ${item.prixUnitaire.toStringAsFixed(2)}MGA', - style: pw.TextStyle(fontSize: smallSize), + ), + + pw.SizedBox(height: 3), + + // Ligne de séparation + pw.Container( + width: double.infinity, + height: 0.5, + color: PdfColors.black, + ), + + pw.SizedBox(height: 2), + + // Informations ticket + pw.Container( + width: double.infinity, + child: pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text( + 'Ticket: $factureNumber', + style: pw.TextStyle( + fontSize: bodySize, + fontWeight: pw.FontWeight.bold, + ), + ), + ], + ), + ), + + pw.SizedBox(height: 1), + + pw.Container( + width: double.infinity, + child: pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text( + _formatDate(dateTime), + style: pw.TextStyle(fontSize: smallSize), + ), + pw.Text( + _formatTime(dateTime), + style: pw.TextStyle(fontSize: smallSize), + ), + ], + ), + ), + + pw.SizedBox(height: 2), + + // Ligne de séparation + pw.Container( + width: double.infinity, + height: 0.5, + color: PdfColors.black, + ), + + pw.SizedBox(height: 2), + + // Articles (format très compact) + ...commande.items + .map( + (item) => pw.Container( + width: double.infinity, // 🔧 Largeur complète + margin: const pw.EdgeInsets.only(bottom: 1), + child: pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + // Nom du plat + pw.Container( + width: double.infinity, + child: pw.Text( + '${item.menuNom}', + style: pw.TextStyle(fontSize: bodySize), + maxLines: 2, ), - pw.Text( - '${(item.prixUnitaire * item.quantite).toStringAsFixed(2)}MGA', - style: pw.TextStyle( - fontSize: bodySize, - fontWeight: pw.FontWeight.bold, - ), + ), + + // Quantité, prix unitaire et total sur une ligne + pw.Container( + width: double.infinity, + child: pw.Row( + mainAxisAlignment: + pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text( + '${item.quantite}x ${item.prixUnitaire.toStringAsFixed(2)}MGA', + style: pw.TextStyle(fontSize: smallSize), + ), + pw.Text( + '${(item.prixUnitaire * item.quantite).toStringAsFixed(2)}MGA', + style: pw.TextStyle( + fontSize: bodySize, + fontWeight: pw.FontWeight.bold, + ), + ), + ], ), - ], - ), - ], + ), + ], + ), ), - ), - ) - .toList(), - - pw.SizedBox(height: 2), - - // Ligne de séparation - pw.Container( - width: double.infinity, - height: 0.5, - color: PdfColors.black, - ), - - pw.SizedBox(height: 2), - - // Total - pw.Row( - mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, - children: [ - pw.Text( - 'TOTAL', - style: pw.TextStyle( - fontSize: titleSize, - fontWeight: pw.FontWeight.bold, - ), + ) + .toList(), + + pw.SizedBox(height: 2), + + // Ligne de séparation + pw.Container( + width: double.infinity, + height: 0.5, + color: PdfColors.black, + ), + + pw.SizedBox(height: 2), + + // Total + pw.Container( + width: double.infinity, + child: pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text( + 'TOTAL', + style: pw.TextStyle( + fontSize: titleSize, + fontWeight: pw.FontWeight.bold, + ), + ), + pw.Text( + '${commande.totalTtc.toStringAsFixed(2)}MGA', + style: pw.TextStyle( + fontSize: titleSize, + fontWeight: pw.FontWeight.bold, + ), + ), + ], + ), + ), + + pw.SizedBox(height: 3), + + // Mode de paiement + pw.Container( + width: double.infinity, + child: pw.Text( + 'Paiement: ${paymentMethod.toLowerCase()}', + style: pw.TextStyle(fontSize: bodySize), + textAlign: pw.TextAlign.center, ), - pw.Text( - '${commande.totalTtc.toStringAsFixed(2)}MGA', + ), + + pw.SizedBox(height: 3), + + // Ligne de séparation + pw.Container( + width: double.infinity, + height: 0.5, + color: PdfColors.black, + ), + + pw.SizedBox(height: 2), + + // Message de remerciement + pw.Container( + width: double.infinity, + child: pw.Text( + 'Merci de votre visite !', style: pw.TextStyle( - fontSize: titleSize, - fontWeight: pw.FontWeight.bold, + fontSize: bodySize, + fontStyle: pw.FontStyle.italic, ), + textAlign: pw.TextAlign.center, ), - ], - ), - - pw.SizedBox(height: 3), - - // Mode de paiement - pw.Text( - 'Paiement: ${_getPaymentMethodText(paymentMethod)}', - style: pw.TextStyle(fontSize: bodySize), - textAlign: pw.TextAlign.center, - ), - - pw.SizedBox(height: 3), - - // Ligne de séparation - pw.Container( - width: double.infinity, - height: 0.5, - color: PdfColors.black, - ), - - pw.SizedBox(height: 2), - - // Message de remerciement - pw.Text( - 'Merci de votre visite !', - style: pw.TextStyle( - fontSize: bodySize, - fontStyle: pw.FontStyle.italic, ), - textAlign: pw.TextAlign.center, - ), - - pw.Text( - 'A bientôt !', - style: pw.TextStyle(fontSize: smallSize), - textAlign: pw.TextAlign.center, - ), - - pw.SizedBox(height: 3), - - // Code de suivi (optionnel) - pw.Text( - 'Code: ${factureNumber}', - style: pw.TextStyle(fontSize: smallSize), - textAlign: pw.TextAlign.center, - ), - - pw.SizedBox(height: 4), - - // Ligne de découpe - pw.Text( - '- - - - - - - - - - - - - - - -', - style: pw.TextStyle(fontSize: smallSize), - textAlign: pw.TextAlign.center, - ), - - pw.SizedBox(height: 2), - ], + + pw.Container( + width: double.infinity, + child: pw.Text( + 'A bientôt !', + style: pw.TextStyle(fontSize: smallSize), + textAlign: pw.TextAlign.center, + ), + ), + + pw.SizedBox(height: 3), + + // Code de suivi (optionnel) + pw.Container( + width: double.infinity, + child: pw.Text( + 'Code: ${factureNumber}', + style: pw.TextStyle(fontSize: smallSize), + textAlign: pw.TextAlign.center, + ), + ), + + pw.SizedBox(height: 4), + + // Ligne de découpe + pw.Container( + width: double.infinity, + child: pw.Text( + '- - - - - - - - - - - - - - - -', + style: pw.TextStyle(fontSize: smallSize), + textAlign: pw.TextAlign.center, + ), + ), + + pw.SizedBox(height: 2), + ], + ), ); }, ),