feat: print on receipt
This commit is contained in:
parent
811ae06e58
commit
8022fa6b32
@ -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<void> 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<void> onPrint(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> 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')),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<List<int>> printOrderV4(
|
||||
Order order,
|
||||
String chashierName,
|
||||
String paymentMethod,
|
||||
int nominalBayar,
|
||||
int kembalian,
|
||||
int taxPercentage,
|
||||
int paper,
|
||||
) async {
|
||||
List<int> 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 ?? <OrderItem>[])) {
|
||||
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<List<int>> printQRIS(
|
||||
int totalPrice, Uint8List imageQris, int paper) async {
|
||||
List<int> bytes = [];
|
||||
|
||||
@ -961,6 +961,23 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
|
||||
) =>
|
||||
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<ConfirmPaymentPage> {
|
||||
.pushReplacement(SuccessOrderPage(
|
||||
productQuantity: items,
|
||||
order: data,
|
||||
paymentMethod:
|
||||
selectedPaymentMethod?.name ?? "",
|
||||
nominalBayar: totalPriceController
|
||||
.text.toIntegerFromText,
|
||||
taxPercentage: tax,
|
||||
));
|
||||
},
|
||||
error: (message) => AppFlushbar.showError(
|
||||
|
||||
@ -11,8 +11,18 @@ import 'package:flutter/material.dart';
|
||||
class SuccessOrderPage extends StatefulWidget {
|
||||
final List<ProductQuantity> 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<SuccessOrderPage> createState() => _SuccessOrderPageState();
|
||||
@ -991,6 +1001,15 @@ class _SuccessOrderPageState extends State<SuccessOrderPage>
|
||||
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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user