2026-05-25 23:33:49 +07:00

478 lines
13 KiB
Dart

import 'package:esc_pos_utils_plus/esc_pos_utils_plus.dart';
import '../../../common/extension/extension.dart';
import '../../../domain/order/order.dart';
import '../../../domain/outlet/outlet.dart';
import 'receipt_component_builder.dart';
class PrintUi {
Future<List<int>> printOrder({
required Order order,
required Outlet outlet,
required String cashierName,
int paper = 58,
}) async {
List<int> bytes = [];
final profile = await CapabilityProfile.load();
final generator = Generator(
paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
profile,
);
final builder = ReceiptComponentBuilder(
generator: generator,
paperSize: paper,
);
bytes += generator.reset();
bytes += builder.header(
outletName: outlet.name,
address: outlet.address,
phoneNumber: outlet.phoneNumber,
);
bytes += builder.orderInfo(
orderNumber: order.orderNumber,
customerName: order.metadata['customer_name'] ?? '-',
cashierName: cashierName,
paymentMethod: order.payments.last.paymentMethodName,
tableNumber: order.tableNumber,
);
bytes += builder.orderType(order.orderType);
bytes += builder.emptyLines(1);
for (final item in order.orderItemNotCancelled) {
bytes += builder.orderItem(
productName: item.productName,
quantity: item.quantity,
unitPrice: item.unitPrice.currencyFormatRpV2,
totalPrice: item.totalPrice.currencyFormatRpV2,
variantName: item.productVariantName,
notes: item.notes,
);
}
bytes += builder.summary(
totalItems: order.orderItems.length,
subtotal: order.subtotal.currencyFormatRpV2,
discount: order.discountAmount.currencyFormatRpV2,
total: order.totalAmount.currencyFormatRpV2,
paid: order.totalPaid.currencyFormatRpV2,
);
bytes += builder.footer();
return bytes;
}
Future<List<int>> printChecker({
required Order order,
required Outlet outlet,
required String cashierName,
int paper = 58,
}) async {
List<int> bytes = [];
final profile = await CapabilityProfile.load();
final generator = Generator(
paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
profile,
);
final builder = ReceiptComponentBuilder(
generator: generator,
paperSize: paper,
);
bytes += generator.reset();
// Header
bytes += builder.textCenter('Table Checker', bold: true);
bytes += builder.separator();
bytes += builder.textCenter(
'Table : ${order.tableNumber.isNotEmpty ? order.tableNumber : '-'}',
bold: true,
);
bytes += builder.separator();
// Order info — label : value, left aligned
bytes += builder.orderInfoSimple(
orderNumber: order.orderNumber,
orderType: order.orderType,
cashierName: cashierName,
);
bytes += builder.separator();
// Items — qty NAMA (uppercase), variant indent
for (final item in order.orderItems) {
final name = item.productName.toUpperCase();
bytes += builder.itemText('${item.quantity} $name');
if (item.productVariantName.isNotEmpty) {
bytes += builder.itemText(' ${item.productVariantName.toUpperCase()}', bold: false);
}
if (item.notes.isNotEmpty) {
bytes += builder.itemText(' *${item.notes}', bold: false);
}
}
bytes += builder.separator();
bytes += builder.cutOnly();
return bytes;
}
Future<List<int>> printKitchen({
required Order order,
required Outlet outlet,
required String cashierName,
int paper = 58,
}) async {
List<int> bytes = [];
final profile = await CapabilityProfile.load();
final generator = Generator(
paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
profile,
);
final builder = ReceiptComponentBuilder(
generator: generator,
paperSize: paper,
);
for (final item in order.orderItems) {
bytes += generator.reset();
// Header
bytes += builder.textCenter('Kitchen', bold: true);
bytes += builder.separator();
bytes += builder.textCenter(
'Table : ${order.tableNumber.isNotEmpty ? order.tableNumber : '-'}',
bold: true,
);
bytes += builder.separator();
// Order info
bytes += builder.orderInfoSimple(
orderNumber: order.orderNumber,
orderType: order.orderType,
cashierName: cashierName,
);
bytes += builder.separator();
// Single item
final name = item.productName.toUpperCase();
bytes += builder.itemText('${item.quantity} $name');
if (item.productVariantName.isNotEmpty) {
bytes += builder.itemText(' ${item.productVariantName.toUpperCase()}', bold: false);
}
if (item.notes.isNotEmpty) {
bytes += builder.itemText(' *${item.notes}', bold: false);
}
bytes += builder.separator();
bytes += builder.cutOnly();
}
return bytes;
}
Future<List<int>> printBar({
required Order order,
required Outlet outlet,
required String cashierName,
int paper = 58,
}) async {
List<int> bytes = [];
final profile = await CapabilityProfile.load();
final generator = Generator(
paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
profile,
);
final builder = ReceiptComponentBuilder(
generator: generator,
paperSize: paper,
);
for (final item in order.orderItems) {
bytes += generator.reset();
bytes += builder.separator();
bytes += builder.printerType(printerType: 'BAR');
bytes += builder.separator();
bytes += builder.dateTime(DateTime.now());
bytes += builder.orderInfo(
orderNumber: order.orderNumber,
customerName: order.metadata['customer_name'] ?? '-',
cashierName: cashierName,
tableNumber: order.tableNumber,
);
bytes += builder.separator();
bytes += builder.emptyLines(1);
bytes += builder.orderItem(
productName: item.productName,
quantity: item.quantity,
unitPrice: item.unitPrice.currencyFormatRpV2,
totalPrice: item.totalPrice.currencyFormatRpV2,
variantName: item.productVariantName,
notes: item.notes,
);
bytes += builder.separator();
bytes += builder.footer();
}
return bytes;
}
Future<List<int>> printTicket({
required Order order,
required Outlet outlet,
int paper = 58,
}) async {
List<int> bytes = [];
final profile = await CapabilityProfile.load();
final generator = Generator(
paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
profile,
);
final builder = ReceiptComponentBuilder(
generator: generator,
paperSize: paper,
);
bytes += generator.reset();
bytes += builder.header(
outletName: outlet.name,
address: outlet.address,
phoneNumber: outlet.phoneNumber,
);
bytes += builder.dateTime(DateTime.now());
bytes += builder.row2Columns('Code No.', order.orderNumber);
bytes += builder.separator();
bytes += builder.emptyLines(2);
bytes += builder.qrCode('1267128127182182');
bytes += builder.emptyLines(1);
bytes += builder.textCenter('1267128127182182');
bytes += builder.emptyLines(2);
bytes += builder.footer();
return bytes;
}
Future<List<int>> printCashier({
required Order order,
required Outlet outlet,
required String cashierName,
int paper = 58,
}) async {
List<int> bytes = [];
final profile = await CapabilityProfile.load();
final generator = Generator(
paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
profile,
);
final builder = ReceiptComponentBuilder(
generator: generator,
paperSize: paper,
);
bytes += generator.reset();
bytes += builder.header(
outletName: outlet.name,
address: outlet.address,
phoneNumber: outlet.phoneNumber,
);
bytes += builder.orderInfo(
orderNumber: order.orderNumber,
customerName: order.metadata['customer_name'] ?? '-',
cashierName: cashierName,
paymentMethod: order.payments.isEmpty
? null
: order.payments.last.paymentMethodName,
tableNumber: order.tableNumber,
);
bytes += builder.orderType(order.orderType);
bytes += builder.emptyLines(1);
for (final item in order.orderItemNotCancelled) {
bytes += builder.orderItem(
productName: item.productName,
quantity: item.quantity,
unitPrice: item.unitPrice.currencyFormatRpV2,
totalPrice: item.totalPrice.currencyFormatRpV2,
variantName: item.productVariantName,
notes: item.notes,
);
}
bytes += builder.summary(
totalItems: order.orderItems.length,
subtotal: order.subtotal.currencyFormatRpV2,
discount: order.discountAmount.currencyFormatRpV2,
total: order.totalAmount.currencyFormatRpV2,
paid: order.totalPaid.currencyFormatRpV2,
);
bytes += builder.footer(message: 'Kasir');
return bytes;
}
Future<List<int>> printVoid({
required Order order,
required Outlet outlet,
required String cashierName,
int paper = 58,
}) async {
List<int> bytes = [];
final profile = await CapabilityProfile.load();
final generator = Generator(
paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
profile,
);
final builder = ReceiptComponentBuilder(
generator: generator,
paperSize: paper,
);
bytes += generator.reset();
bytes += builder.header(
outletName: outlet.name,
address: outlet.address,
phoneNumber: outlet.phoneNumber,
);
bytes += builder.dateTime(DateTime.now());
bytes += builder.orderInfo(
orderNumber: order.orderNumber,
customerName: order.metadata['customer_name'] ?? '-',
cashierName: cashierName,
paymentMethod: order.payments.isEmpty
? null
: order.payments.last.paymentMethodName,
tableNumber: order.tableNumber,
);
bytes += builder.orderType('Void');
bytes += builder.emptyLines(1);
for (final item in order.orderItems) {
bytes += builder.orderItem(
productName: item.productName,
quantity: item.quantity,
unitPrice: item.unitPrice.currencyFormatRpV2,
totalPrice: item.totalPrice.currencyFormatRpV2,
variantName: item.productVariantName,
notes: item.notes,
);
}
bytes += builder.summary(
totalItems: order.orderItems.length,
subtotal: order.subtotal.currencyFormatRpV2,
discount: order.discountAmount.currencyFormatRpV2,
total: order.totalAmount.currencyFormatRpV2,
paid: order.totalPaid.currencyFormatRpV2,
);
bytes += builder.footer(message: 'Kasir');
return bytes;
}
Future<List<int>> printSplit({
required Order order,
required Outlet outlet,
required String cashierName,
int paper = 58,
}) async {
List<int> bytes = [];
final profile = await CapabilityProfile.load();
final generator = Generator(
paper == 58 ? PaperSize.mm58 : PaperSize.mm80,
profile,
);
final builder = ReceiptComponentBuilder(
generator: generator,
paperSize: paper,
);
bytes += generator.reset();
bytes += builder.header(
outletName: outlet.name,
address: outlet.address,
phoneNumber: outlet.phoneNumber,
);
bytes += builder.dateTime(DateTime.now());
bytes += builder.orderInfo(
orderNumber: order.orderNumber,
customerName: order.metadata['customer_name'] ?? '-',
cashierName: cashierName,
paymentMethod: order.payments.isEmpty
? null
: order.payments.last.paymentMethodName,
tableNumber: order.tableNumber,
);
bytes += builder.orderType('Split');
bytes += builder.row2Columns(
'Split',
'${order.payments.last.splitNumber} / ${order.payments.last.splitTotal}',
);
bytes += builder.separator();
bytes += builder.emptyLines(1);
for (final item in order.orderItems) {
bytes += builder.orderItem(
productName: item.productName,
quantity: item.quantity,
unitPrice: item.unitPrice.currencyFormatRpV2,
totalPrice: item.totalPrice.currencyFormatRpV2,
variantName: item.productVariantName,
notes: item.notes,
);
}
bytes += builder.emptyLines(1);
bytes += builder.summary(
totalItems: 0,
subtotal: order.payments.last.amount.currencyFormatRpV2,
discount: 0.currencyFormatRpV2,
total: order.payments.last.amount.currencyFormatRpV2,
paid: order.payments.last.amount.currencyFormatRpV2,
);
bytes += builder.footer(message: 'Terima Kasih');
return bytes;
}
}