Files
apskel-pos-flutter-v2/lib/presentation/components/print/print_ui.dart
T

482 lines
13 KiB
Dart
Raw Normal View History

2025-11-06 18:15:54 +07:00
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,
2026-05-24 00:59:02 +07:00
paperSize: paper,
2025-11-06 18:15:54 +07:00
);
bytes += generator.reset();
bytes += builder.header(
outletName: outlet.name,
address: outlet.address,
phoneNumber: outlet.phoneNumber,
);
bytes += builder.orderInfo(
orderNumber: order.orderNumber,
2026-04-27 17:28:34 +07:00
customerName: order.metadata['customer_name'] ?? '-',
2025-11-06 18:15:54 +07:00
cashierName: cashierName,
paymentMethod: order.payments.last.paymentMethodName,
tableNumber: order.tableNumber,
);
bytes += builder.orderType(order.orderType);
bytes += builder.emptyLines(1);
2026-03-03 19:35:11 +07:00
for (final item in order.orderItemNotCancelled) {
2025-11-06 18:15:54 +07:00
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;
}
2025-11-06 18:28:14 +07:00
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,
2026-05-24 00:59:02 +07:00
paperSize: paper,
2025-11-06 18:28:14 +07:00
);
2026-05-25 20:35:40 +07:00
bytes += generator.reset();
2026-05-25 19:34:31 +07:00
2026-05-25 23:33:49 +07:00
// 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
2026-05-25 20:35:40 +07:00
for (final item in order.orderItems) {
2026-05-25 23:33:49 +07:00
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);
}
2026-05-25 19:34:31 +07:00
}
2025-11-06 18:28:14 +07:00
2026-05-25 20:35:40 +07:00
bytes += builder.separator();
bytes += builder.cutOnly();
2025-11-06 18:28:14 +07:00
return bytes;
}
2025-11-06 18:41:34 +07:00
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,
2026-05-24 00:59:02 +07:00
paperSize: paper,
2025-11-06 18:41:34 +07:00
);
for (final item in order.orderItems) {
bytes += generator.reset();
2026-05-25 23:33:49 +07:00
// Header
2026-05-26 12:14:02 +07:00
bytes += builder.row2Columns('Kitchen', order.orderType, bold: true);
2025-11-06 18:41:34 +07:00
bytes += builder.separator();
2026-05-25 23:33:49 +07:00
bytes += builder.textCenter(
'Table : ${order.tableNumber.isNotEmpty ? order.tableNumber : '-'}',
bold: true,
);
2025-11-06 18:41:34 +07:00
bytes += builder.separator();
2026-05-25 23:33:49 +07:00
// Order info
bytes += builder.orderInfoSimple(
2025-11-06 18:41:34 +07:00
orderNumber: order.orderNumber,
cashierName: cashierName,
);
2026-05-25 23:33:49 +07:00
bytes += builder.separator();
2026-05-25 20:35:40 +07:00
2026-05-25 23:33:49 +07:00
// 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);
2026-05-25 20:35:40 +07:00
}
2025-11-06 18:41:34 +07:00
bytes += builder.separator();
2026-05-25 23:33:49 +07:00
bytes += builder.cutOnly();
2025-11-06 18:41:34 +07:00
}
return bytes;
}
2025-11-06 18:48:28 +07:00
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,
2026-05-24 00:59:02 +07:00
paperSize: paper,
2025-11-06 18:48:28 +07:00
);
for (final item in order.orderItems) {
2025-11-13 13:04:32 +07:00
bytes += generator.reset();
2026-05-25 23:35:24 +07:00
// Header
bytes += builder.textCenter('Bar', bold: true);
2025-11-13 13:04:32 +07:00
bytes += builder.separator();
2026-05-25 23:35:24 +07:00
bytes += builder.textCenter(
'Table : ${order.tableNumber.isNotEmpty ? order.tableNumber : '-'}',
bold: true,
);
2025-11-13 13:04:32 +07:00
bytes += builder.separator();
2026-05-25 23:35:24 +07:00
// Order info
bytes += builder.orderInfoSimple(
2025-11-13 13:04:32 +07:00
orderNumber: order.orderNumber,
2026-05-25 23:35:24 +07:00
orderType: order.orderType,
2025-11-13 13:04:32 +07:00
cashierName: cashierName,
);
bytes += builder.separator();
2026-05-25 23:35:24 +07:00
// 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);
}
2025-11-06 18:48:28 +07:00
2025-11-13 13:04:32 +07:00
bytes += builder.separator();
2026-05-25 23:35:24 +07:00
bytes += builder.cutOnly();
2025-11-13 13:04:32 +07:00
}
2025-11-06 18:48:28 +07:00
return bytes;
}
2025-11-06 18:59:10 +07:00
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,
2026-05-24 00:59:02 +07:00
paperSize: paper,
2025-11-06 18:59:10 +07:00
);
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;
}
2025-11-07 16:29:26 +07:00
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,
2026-05-24 00:59:02 +07:00
paperSize: paper,
2025-11-07 16:29:26 +07:00
);
bytes += generator.reset();
bytes += builder.header(
outletName: outlet.name,
address: outlet.address,
phoneNumber: outlet.phoneNumber,
);
bytes += builder.orderInfo(
orderNumber: order.orderNumber,
2026-04-27 17:28:34 +07:00
customerName: order.metadata['customer_name'] ?? '-',
2025-11-07 16:29:26 +07:00
cashierName: cashierName,
paymentMethod: order.payments.isEmpty
? null
: order.payments.last.paymentMethodName,
tableNumber: order.tableNumber,
);
bytes += builder.orderType(order.orderType);
bytes += builder.emptyLines(1);
2026-03-03 19:35:11 +07:00
for (final item in order.orderItemNotCancelled) {
2025-11-07 16:29:26 +07:00
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;
}
2025-11-10 13:06:06 +07:00
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,
2026-05-24 00:59:02 +07:00
paperSize: paper,
2025-11-10 13:06:06 +07:00
);
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,
2026-04-27 17:28:34 +07:00
customerName: order.metadata['customer_name'] ?? '-',
2025-11-10 13:06:06 +07:00
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;
}
2025-11-10 13:28:18 +07:00
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,
2026-05-24 00:59:02 +07:00
paperSize: paper,
2025-11-10 13:28:18 +07:00
);
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,
2026-04-27 17:28:34 +07:00
customerName: order.metadata['customer_name'] ?? '-',
2025-11-10 13:28:18 +07:00
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}',
);
2026-03-04 23:30:52 +07:00
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);
2025-11-10 13:28:18 +07:00
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,
);
2026-04-03 17:44:04 +07:00
bytes += builder.footer(message: 'Terima Kasih');
2025-11-10 13:28:18 +07:00
return bytes;
}
2025-11-06 18:15:54 +07:00
}