diff --git a/lib/core/function/app_function.dart b/lib/core/function/app_function.dart index 4e9fd1a..33a82db 100644 --- a/lib/core/function/app_function.dart +++ b/lib/core/function/app_function.dart @@ -3,6 +3,7 @@ import 'dart:developer'; import 'package:enaklo_pos/core/extensions/string_ext.dart'; import 'package:enaklo_pos/core/utils/printer_service.dart'; import 'package:enaklo_pos/data/dataoutputs/print_dataoutputs.dart'; +import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart'; import 'package:enaklo_pos/data/datasources/product_local_datasource.dart'; import 'package:enaklo_pos/data/models/response/order_response_model.dart'; import 'package:enaklo_pos/presentation/home/models/product_quantity.dart'; @@ -20,10 +21,6 @@ Future onPrint( final barPrinter = await ProductLocalDatasource.instance.getPrinterByCode('bar'); - log("Checker printer: ${checkerPrinter?.toMap()}"); - log("Kitchen printer: ${kitchenPrinter?.toMap()}"); - log("Bar printer: ${barPrinter?.toMap()}"); - // Checker printer if (checkerPrinter != null) { try { @@ -90,3 +87,37 @@ Future onPrint( } } } + +Future onPrintRecipt( + context, { + required Order order, + required String paymentMethod, + required int nominalBayar, + required int kembalian, + required int taxPercentage, +}) async { + final receiptPrinter = + await ProductLocalDatasource.instance.getPrinterByCode('receipt'); + final authData = await AuthLocalDataSource().getAuthData(); + + if (receiptPrinter != null) { + try { + final printValue = await PrintDataoutputs.instance.printOrderV4( + order, + authData.user?.name ?? "", + paymentMethod, + nominalBayar, + kembalian, + taxPercentage, + receiptPrinter.paper.toIntegerFromText, + ); + await PrinterService() + .printWithPrinter(receiptPrinter, printValue, context); + } catch (e) { + log("Error printing receipt order: $e"); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Error printing receipt order: $e')), + ); + } + } +} diff --git a/lib/data/dataoutputs/print_dataoutputs.dart b/lib/data/dataoutputs/print_dataoutputs.dart index 613a338..59d2d9d 100644 --- a/lib/data/dataoutputs/print_dataoutputs.dart +++ b/lib/data/dataoutputs/print_dataoutputs.dart @@ -1,5 +1,6 @@ import 'dart:math'; +import 'package:enaklo_pos/data/models/response/order_response_model.dart'; import 'package:esc_pos_utils_plus/esc_pos_utils_plus.dart'; import 'package:flutter/services.dart'; import 'package:enaklo_pos/core/extensions/int_ext.dart'; @@ -739,6 +740,263 @@ class PrintDataoutputs { return bytes; } + Future> printOrderV4( + Order order, + String chashierName, + String paymentMethod, + int nominalBayar, + int kembalian, + int taxPercentage, + int paper, + ) async { + List bytes = []; + + final profile = await CapabilityProfile.load(); + final generator = + Generator(paper == 58 ? PaperSize.mm58 : PaperSize.mm80, profile); + + bytes += generator.reset(); + + bytes += generator.text('Guapatlu Khas Bakmi Jambi', + styles: const PosStyles( + bold: true, + align: PosAlign.center, + height: PosTextSize.size1, + width: PosTextSize.size1, + )); + + bytes += generator.text('Gading Boulevard w2, No 25, Jakarta', + styles: const PosStyles(bold: false, align: PosAlign.center)); + bytes += generator.text('085-77777-3839', + styles: const PosStyles(bold: false, align: PosAlign.center)); + + bytes += generator.text( + paper == 80 + ? '------------------------------------------------' + : '--------------------------------', + styles: const PosStyles(bold: false, align: PosAlign.center)); + + bytes += generator.row([ + PosColumn( + text: DateFormat('dd MMM yyyy').format(DateTime.now()), + width: 6, + styles: const PosStyles(align: PosAlign.left), + ), + PosColumn( + text: DateFormat('HH:mm').format(DateTime.now()), + width: 6, + styles: const PosStyles(align: PosAlign.right), + ), + ]); + bytes += generator.row([ + PosColumn( + text: 'Receipt Number', + width: 6, + styles: const PosStyles(align: PosAlign.left), + ), + PosColumn( + text: 'JF-${DateFormat('yyyyMMddhhmm').format(DateTime.now())}', + width: 6, + styles: const PosStyles(align: PosAlign.right), + ), + ]); + + bytes += generator.row([ + PosColumn( + text: 'Order ID', + width: 6, + styles: const PosStyles(align: PosAlign.left), + ), + PosColumn( + text: Random().nextInt(100000).toString(), + width: 6, + styles: const PosStyles(align: PosAlign.right), + ), + ]); + bytes += generator.row([ + PosColumn( + text: 'Bill Name', + width: 6, + styles: const PosStyles(align: PosAlign.left), + ), + PosColumn( + text: order.metadata?['customer_name'] ?? '', + width: 6, + styles: const PosStyles(align: PosAlign.right), + ), + ]); + bytes += generator.row([ + PosColumn( + text: 'Collected By', + width: 6, + styles: const PosStyles(align: PosAlign.left), + ), + PosColumn( + text: chashierName, + width: 6, + styles: const PosStyles(align: PosAlign.right), + ), + ]); + bytes += generator.row([ + PosColumn( + text: 'Pembayaran', + width: 8, + styles: const PosStyles(align: PosAlign.left), + ), + PosColumn( + text: paymentMethod, + width: 4, + styles: const PosStyles(align: PosAlign.right), + ), + ]); + + bytes += generator.text( + paper == 80 + ? '------------------------------------------------' + : '--------------------------------', + styles: const PosStyles(bold: false, align: PosAlign.center)); + bytes += generator.text('Dine In', + styles: const PosStyles(bold: true, align: PosAlign.center)); + bytes += generator.text( + paper == 80 + ? '------------------------------------------------' + : '--------------------------------', + styles: const PosStyles(bold: false, align: PosAlign.center)); + for (final product in (order.orderItems ?? [])) { + bytes += generator.row([ + PosColumn( + text: '${product.quantity} x ${product.productName}', + width: 8, + styles: const PosStyles(bold: true, align: PosAlign.left), + ), + PosColumn( + text: (product.totalPrice ?? 0).currencyFormatRpV2, + width: 4, + styles: const PosStyles(bold: true, align: PosAlign.right), + ), + ]); + } + bytes += generator.text( + paper == 80 + ? '------------------------------------------------' + : '--------------------------------', + styles: const PosStyles(bold: false, align: PosAlign.center)); + + bytes += generator.row([ + PosColumn( + text: 'Subtotal ${order.orderItems?.length ?? "0"} Product', + width: 6, + styles: const PosStyles(align: PosAlign.left), + ), + PosColumn( + text: (order.subtotal ?? 0).currencyFormatRpV2, + width: 6, + styles: const PosStyles(align: PosAlign.right), + ), + ]); + + bytes += generator.row([ + PosColumn( + text: 'Discount', + width: 6, + styles: const PosStyles(align: PosAlign.left), + ), + PosColumn( + text: (order.discountAmount ?? 0).currencyFormatRpV2, + width: 6, + styles: const PosStyles(align: PosAlign.right), + ), + ]); + + // Only show tax if it's greater than 0 + if ((order.taxAmount ?? 0) > 0) { + bytes += generator.row([ + PosColumn( + text: 'Tax PB1 ($taxPercentage%)', + width: 6, + styles: const PosStyles(align: PosAlign.left), + ), + PosColumn( + text: (order.taxAmount ?? 0).currencyFormatRpV2, + width: 6, + styles: const PosStyles(align: PosAlign.right), + ), + ]); + } + + // Only show service charge if it's greater than 0 + // if (serviceCharge > 0) { + // bytes += generator.row([ + // PosColumn( + // text: 'Service Charge($serviceChargePercentage%)', + // width: 6, + // styles: const PosStyles(align: PosAlign.left), + // ), + // PosColumn( + // text: serviceCharge.currencyFormatRpV2, + // width: 6, + // styles: const PosStyles(align: PosAlign.right), + // ), + // ]); + // } + bytes += generator.text( + paper == 80 + ? '------------------------------------------------' + : '--------------------------------', + styles: const PosStyles(bold: false, align: PosAlign.center)); + bytes += generator.row([ + PosColumn( + text: 'Total', + width: 6, + styles: const PosStyles(bold: true, align: PosAlign.left), + ), + PosColumn( + text: '${order.totalAmount ?? ""}'.currencyFormatRpV2, + width: 6, + styles: const PosStyles(bold: true, align: PosAlign.right), + ), + ]); + bytes += generator.row([ + PosColumn( + text: 'Dibayar', + width: 6, + styles: const PosStyles(align: PosAlign.left), + ), + PosColumn( + text: nominalBayar.currencyFormatRpV2, + width: 6, + styles: const PosStyles(align: PosAlign.right), + ), + ]); + bytes += generator.row([ + PosColumn( + text: 'Kembali', + width: 6, + styles: const PosStyles(align: PosAlign.left), + ), + PosColumn( + text: kembalian.currencyFormatRpV2, + width: 6, + styles: const PosStyles(align: PosAlign.right), + ), + ]); + bytes += generator.text( + paper == 80 + ? '------------------------------------------------' + : '--------------------------------', + styles: const PosStyles(bold: false, align: PosAlign.center)); + // bytes += generator.text('Notes', + // styles: const PosStyles(bold: false, align: PosAlign.center)); + // bytes += generator.text('Pass Wifi: fic14jilid2', + // styles: const PosStyles(bold: false, align: PosAlign.center)); + // //terima kasih + // bytes += generator.text('Terima Kasih', + // styles: const PosStyles(bold: true, align: PosAlign.center)); + paper == 80 ? bytes += generator.feed(3) : bytes += generator.feed(1); + bytes += generator.cut(); + return bytes; + } + Future> printQRIS( int totalPrice, Uint8List imageQris, int paper) async { List bytes = []; diff --git a/lib/presentation/home/pages/confirm_payment_page.dart b/lib/presentation/home/pages/confirm_payment_page.dart index 37f6f82..7fdacb0 100644 --- a/lib/presentation/home/pages/confirm_payment_page.dart +++ b/lib/presentation/home/pages/confirm_payment_page.dart @@ -961,6 +961,23 @@ class _ConfirmPaymentPageState extends State { ) => products, ); + int tax = state.maybeWhen( + orElse: () => 0, + loaded: ( + products, + discountModel, + discount, + discountAmount, + tax, + serviceCharge, + totalQuantity, + totalPrice, + draftName, + orderType, + deliveryType, + ) => + tax, + ); return Container( padding: EdgeInsets.all(16), @@ -1018,6 +1035,11 @@ class _ConfirmPaymentPageState extends State { .pushReplacement(SuccessOrderPage( productQuantity: items, order: data, + paymentMethod: + selectedPaymentMethod?.name ?? "", + nominalBayar: totalPriceController + .text.toIntegerFromText, + taxPercentage: tax, )); }, error: (message) => AppFlushbar.showError( diff --git a/lib/presentation/success/pages/success_order_page.dart b/lib/presentation/success/pages/success_order_page.dart index ea9ab59..7253aea 100644 --- a/lib/presentation/success/pages/success_order_page.dart +++ b/lib/presentation/success/pages/success_order_page.dart @@ -11,8 +11,18 @@ import 'package:flutter/material.dart'; class SuccessOrderPage extends StatefulWidget { final List productQuantity; final Order order; - const SuccessOrderPage( - {super.key, required this.order, required this.productQuantity}); + final String paymentMethod; + final int nominalBayar; + final int taxPercentage; + + const SuccessOrderPage({ + super.key, + required this.order, + required this.productQuantity, + required this.paymentMethod, + required this.nominalBayar, + required this.taxPercentage, + }); @override State createState() => _SuccessOrderPageState(); @@ -991,6 +1001,15 @@ class _SuccessOrderPageState extends State child: InkWell( borderRadius: BorderRadius.circular(16), onTap: () async { + onPrintRecipt( + context, + order: widget.order, + paymentMethod: widget.paymentMethod, + nominalBayar: widget.nominalBayar, + kembalian: widget.nominalBayar - + (widget.order.totalAmount ?? 0), + taxPercentage: widget.taxPercentage, + ); onPrint( context, productQuantity: widget.productQuantity,