pedido_ticket.dart 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. import 'dart:typed_data';
  2. import 'package:flutter/material.dart';
  3. import 'package:intl/intl.dart';
  4. import 'package:pdf/pdf.dart';
  5. import 'package:pdf/widgets.dart' as pw;
  6. import '../../models/models.dart';
  7. import 'package:printing/printing.dart';
  8. import 'package:flutter/services.dart' show rootBundle;
  9. Future<void> imprimirTicketsJuntos(Pedido pedido) async {
  10. final pdf = pw.Document();
  11. final image = pw.MemoryImage(
  12. (await rootBundle.load('assets/JoshiLogo-BN.png')).buffer.asUint8List(),
  13. );
  14. pdf.addPage(
  15. generarPaginaPrimerTicket(pedido, image),
  16. );
  17. pdf.addPage(
  18. generarPaginaSegundoTicket(pedido),
  19. );
  20. await printPdf(Uint8List.fromList(await pdf.save()));
  21. }
  22. pw.Page generarPaginaPrimerTicket(Pedido pedido, pw.MemoryImage image) {
  23. final numberFormat = NumberFormat('#,##0.00', 'es_MX');
  24. return pw.Page(
  25. pageFormat: PdfPageFormat.roll57,
  26. build: (pw.Context context) {
  27. double total = 0;
  28. final productList = pedido.productos
  29. .map(
  30. (producto) {
  31. final productPrice =
  32. double.parse(producto.producto?.precio ?? '0');
  33. final productTotal = productPrice * (producto.cantidad ?? 1);
  34. final toppingsList = producto.toppings.where((topping) {
  35. final toppingPrice =
  36. double.parse(topping.topping?.precio ?? '0');
  37. return toppingPrice > 0;
  38. }).map((topping) {
  39. final toppingPrice =
  40. double.parse(topping.topping?.precio ?? '0');
  41. total += toppingPrice * (producto.cantidad ?? 1);
  42. return pw.Row(
  43. children: [
  44. pw.Text(
  45. '- ${topping.topping?.nombre ?? "Topping no especificado"}',
  46. style: const pw.TextStyle(fontSize: 7)),
  47. pw.Spacer(),
  48. pw.Text('\$${numberFormat.format(toppingPrice)}',
  49. style: const pw.TextStyle(fontSize: 7)),
  50. ],
  51. );
  52. }).toList();
  53. total += productTotal;
  54. return [
  55. pw.Row(
  56. mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
  57. children: [
  58. pw.Expanded(
  59. flex: 2,
  60. child: pw.Text(
  61. producto.producto?.nombre ??
  62. "Producto no especificado",
  63. style: const pw.TextStyle(fontSize: 7)),
  64. ),
  65. pw.Expanded(
  66. flex: 1,
  67. child: pw.Text('x${producto.cantidad}',
  68. style: const pw.TextStyle(fontSize: 7)),
  69. ),
  70. pw.Padding(
  71. padding: pw.EdgeInsets.only(right: 2),
  72. child: pw.Expanded(
  73. flex: 1,
  74. child: pw.Text(
  75. '\$${numberFormat.format(productPrice)}',
  76. style: const pw.TextStyle(fontSize: 8)),
  77. ),
  78. )
  79. ],
  80. ),
  81. ...toppingsList,
  82. ];
  83. },
  84. )
  85. .expand((e) => e)
  86. .toList();
  87. return pw.Column(
  88. crossAxisAlignment: pw.CrossAxisAlignment.center,
  89. children: [
  90. pw.Padding(
  91. padding: const pw.EdgeInsets.only(right: 15),
  92. child:
  93. pw.Center(child: pw.Image(image, width: 50, height: 50))),
  94. pw.SizedBox(height: 10),
  95. pw.Padding(
  96. padding: const pw.EdgeInsets.only(right: 15),
  97. child: pw.Column(children: [
  98. pw.Padding(
  99. padding: pw.EdgeInsets.only(left: 10),
  100. child: pw.Text('Joshi Papas Tu Sabor tu Estilo',
  101. style: pw.TextStyle(
  102. fontSize: 12, fontWeight: pw.FontWeight.bold))),
  103. pw.SizedBox(height: 10),
  104. pw.Text('Fecha: ${pedido.peticion}',
  105. style: const pw.TextStyle(fontSize: 9)),
  106. pw.Text('JoshiPapas',
  107. style: const pw.TextStyle(fontSize: 9)),
  108. pw.Text('Chihuahua',
  109. style: const pw.TextStyle(fontSize: 9)),
  110. ])),
  111. pw.SizedBox(height: 10),
  112. pw.Text('Pedido: ${pedido.folio}',
  113. style: pw.TextStyle(
  114. fontWeight: pw.FontWeight.bold, fontSize: 10)),
  115. pw.SizedBox(height: 10),
  116. pw.Padding(
  117. padding: const pw.EdgeInsets.only(right: 20),
  118. child: pw.Column(children: productList)),
  119. pw.Divider(),
  120. pw.Row(
  121. mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
  122. children: [
  123. pw.Text('Total:',
  124. style: pw.TextStyle(
  125. fontWeight: pw.FontWeight.bold, fontSize: 9)),
  126. pw.Padding(
  127. padding: const pw.EdgeInsets.only(right: 30),
  128. child: pw.Text('\$${numberFormat.format(total)}',
  129. style: pw.TextStyle(
  130. fontWeight: pw.FontWeight.bold, fontSize: 9)),
  131. ),
  132. ],
  133. ),
  134. pw.SizedBox(height: 5),
  135. pw.Padding(
  136. padding: const pw.EdgeInsets.only(right: 15),
  137. child: pw.Text('¡GRACIAS POR SU COMPRA!',
  138. style: pw.TextStyle(
  139. fontSize: 8, fontWeight: pw.FontWeight.bold))),
  140. pw.Divider(),
  141. pw.SizedBox(height: 20),
  142. pw.Text('.', style: pw.TextStyle(fontSize: 1)),
  143. ]);
  144. });
  145. }
  146. pw.Page generarPaginaSegundoTicket(Pedido pedido) {
  147. return pw.Page(
  148. pageFormat: PdfPageFormat.roll57,
  149. build: (pw.Context context) {
  150. List<pw.Widget> content = [
  151. pw.SizedBox(height: 20),
  152. pw.Text('.', style: pw.TextStyle(fontSize: 1)),
  153. pw.Padding(
  154. padding: const pw.EdgeInsets.only(right: 15),
  155. child: pw.Text('Fecha: ${pedido.peticion}',
  156. style: pw.TextStyle(
  157. fontSize: 9, fontWeight: pw.FontWeight.bold))),
  158. pw.SizedBox(height: 5),
  159. pw.Text('Pedido: ${pedido.folio}',
  160. style: pw.TextStyle(fontWeight: pw.FontWeight.bold, fontSize: 9)),
  161. pw.SizedBox(height: 10),
  162. pw.Text('Cliente: ${pedido.nombreCliente}',
  163. style: pw.TextStyle(fontWeight: pw.FontWeight.bold, fontSize: 9)),
  164. pw.SizedBox(height: 10),
  165. ];
  166. content.addAll(pedido.productos
  167. .map((producto) {
  168. final productPrice =
  169. double.parse(producto.producto?.precio ?? '0');
  170. final productTotal = productPrice * (producto.cantidad ?? 1);
  171. final toppingsList = producto.toppings.map((topping) {
  172. return pw.Row(
  173. children: [
  174. pw.Text(
  175. '-${topping.topping?.nombre ?? "Topping no especificado"}',
  176. style: const pw.TextStyle(fontSize: 7)),
  177. ],
  178. );
  179. }).toList();
  180. return [
  181. pw.Row(
  182. mainAxisAlignment: pw.MainAxisAlignment.start,
  183. children: [
  184. pw.Expanded(
  185. flex: 3,
  186. child: pw.Text(
  187. producto.producto?.nombre ??
  188. "Producto no especificado",
  189. style: const pw.TextStyle(fontSize: 9)),
  190. ),
  191. pw.Expanded(
  192. flex: 1,
  193. child: pw.Text('x${producto.cantidad}',
  194. style: const pw.TextStyle(fontSize: 9)),
  195. ),
  196. ],
  197. ),
  198. ...toppingsList,
  199. ];
  200. })
  201. .expand((e) => e)
  202. .toList());
  203. if (pedido.comentarios != null && pedido.comentarios!.isNotEmpty) {
  204. content.add(pw.SizedBox(height: 10));
  205. content.add(pw.Text('Comentarios:',
  206. style:
  207. pw.TextStyle(fontWeight: pw.FontWeight.bold, fontSize: 9)));
  208. content.add(pw.Padding(
  209. padding: const pw.EdgeInsets.only(right: 15),
  210. child: pw.Text(pedido.comentarios!,
  211. style: const pw.TextStyle(fontSize: 9)),
  212. ));
  213. content.add(pw.Text('.', style: pw.TextStyle(fontSize: 1)));
  214. content.add(pw.SizedBox(height: 20));
  215. content.add(pw.Text('.', style: pw.TextStyle(fontSize: 1)));
  216. }
  217. content.add(pw.Text('.', style: pw.TextStyle(fontSize: 1)));
  218. return pw.Column(
  219. crossAxisAlignment: pw.CrossAxisAlignment.center,
  220. children: content);
  221. });
  222. }
  223. Future<void> printPdf(Uint8List pdfBytes) async {
  224. await Printing.layoutPdf(
  225. onLayout: (PdfPageFormat format) => pdfBytes,
  226. );
  227. }