feat: print void

This commit is contained in:
efrilm 2025-09-01 22:36:26 +07:00
parent 0d91d43866
commit 3624f75bea
3 changed files with 273 additions and 1 deletions

View File

@ -165,6 +165,39 @@ Future<void> onPrintRecipt(
} }
} }
Future<void> onPrinVoidRecipt(
context, {
required Order order,
required List<OrderItem> productItemVoid,
required int totalVoid,
}) async {
final receiptPrinter =
await ProductLocalDatasource.instance.getPrinterByCode('receipt');
final authData = await AuthLocalDataSource().getAuthData();
final settings = await SettingsLocalDatasource().getTax();
final outlet = await OutletLocalDatasource().get();
if (receiptPrinter != null) {
try {
final printValue = await PrintDataoutputs.instance.printVoidOrder(
order,
authData.user?.name ?? "",
settings.value,
receiptPrinter.paper.toIntegerFromText,
totalVoid,
outlet,
productItemVoid);
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')),
);
}
}
}
Future<Uint8List> generateBarcodeAsUint8List(String data) async { Future<Uint8List> generateBarcodeAsUint8List(String data) async {
// 1. Buat barcode instance (code128, qrCode, dll) // 1. Buat barcode instance (code128, qrCode, dll)
final barcode = Barcode.code128(); final barcode = Barcode.code128();

View File

@ -1002,6 +1002,239 @@ class PrintDataoutputs {
return bytes; return bytes;
} }
Future<List<int>> printVoidOrder(
Order order,
String chashierName,
int taxPercentage,
int paper,
int nominalDikembalikan,
Outlet outlet,
List<OrderItem> productItemVoid,
) 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(outlet.name ?? "",
styles: const PosStyles(
bold: true,
align: PosAlign.center,
height: PosTextSize.size1,
width: PosTextSize.size1,
));
bytes += generator.text(outlet.address ?? "",
styles: const PosStyles(bold: false, align: PosAlign.center));
bytes += generator.text(outlet.phoneNumber ?? "",
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: 'Status',
width: 8,
styles: const PosStyles(align: PosAlign.left),
),
PosColumn(
text: 'Dibatalkan',
width: 4,
styles: const PosStyles(align: PosAlign.right),
),
]);
for (final product in (productItemVoid ?? <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 ${productItemVoid.length} 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: 'Dikembalikan',
width: 6,
styles: const PosStyles(align: PosAlign.left),
),
PosColumn(
text: nominalDikembalikan.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( Future<List<int>> printQRIS(
int totalPrice, Uint8List imageQris, int paper) async { int totalPrice, Uint8List imageQris, int paper) async {
List<int> bytes = []; List<int> bytes = [];

View File

@ -3,6 +3,7 @@ import 'package:enaklo_pos/core/components/spaces.dart';
import 'package:enaklo_pos/core/extensions/build_context_ext.dart'; import 'package:enaklo_pos/core/extensions/build_context_ext.dart';
import 'package:enaklo_pos/core/extensions/date_time_ext.dart'; import 'package:enaklo_pos/core/extensions/date_time_ext.dart';
import 'package:enaklo_pos/core/extensions/int_ext.dart'; import 'package:enaklo_pos/core/extensions/int_ext.dart';
import 'package:enaklo_pos/core/function/app_function.dart';
import 'package:enaklo_pos/presentation/home/pages/dashboard_page.dart'; import 'package:enaklo_pos/presentation/home/pages/dashboard_page.dart';
import 'package:enaklo_pos/presentation/void/painter/pattern_painter.dart'; import 'package:enaklo_pos/presentation/void/painter/pattern_painter.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -632,5 +633,10 @@ class _SuccessVoidPageState extends State<SuccessVoidPage>
); );
} }
void _printVoidReceipt() {} void _printVoidReceipt() {
onPrinVoidRecipt(context,
order: widget.voidedOrder,
productItemVoid: widget.voidedItems ?? [],
totalVoid: widget.voidAmount);
}
} }