Skip to content

Instantly share code, notes, and snippets.

@ANNASBlackHat
Created March 14, 2024 12:55
Show Gist options
  • Save ANNASBlackHat/9577fb6a8e5a86d0bc19800afa26436e to your computer and use it in GitHub Desktop.
Save ANNASBlackHat/9577fb6a8e5a86d0bc19800afa26436e to your computer and use it in GitHub Desktop.
Captain Order
import 'dart:core';
import 'package:intl/intl.dart';
void main() {
// Create dummy SalesEntity
var sales = dummySales();
// Create dummy PrinterTicketEntity
var tickets = PrinterTicketEntity(
printersettingTicketId: 1,
name: 'Ticket 1',
detail: [
PrinterTicketDetail(productSubcategoryFkid: 1),
],
);
// Call the function
var result = getPrintCaptainOrderFormat(sales, tickets);
// Print the result
print(result);
}
String getPrintCaptainOrderFormat(
SalesEntity sales,
PrinterTicketEntity? tickets, {
int? paperSize,
bool isReprint = false,
}) {
var header = '';
var teks = '';
var footer = '';
var printed = 0;
var MAX = getMaxCharacter(paperSize ?? 58);
try {
sales.orderList.sort((a, b) => a.tmpId.compareTo(b.tmpId));
var ordersToPrint =
sales.orderList.where((element) => element.qty > element.printed);
header += "CAPTAIN ORDER".center(MAX) + '\n';
header += " BILL INFORMATION ".center(MAX, "=") + '\n\n';
if (tickets != null) {
teks += "#${tickets.name}\n";
}
if (sales.displayNota.isNotEmpty) {
teks += "No Nota : ${sales.displayNota}".width(MAX) + '\n';
}
teks += "Pelanggan : ${sales.customer}".width(MAX) + '\n';
if (sales.table.isNotEmpty) {
teks += "Meja : ${sales.table}".width(MAX) + '\n';
}
var operator = ordersToPrint.first.employeeName;
if (operator != null) {
teks += "Nama Operator : $operator".width(MAX) + '\n';
}
teks += "Nama Login : ${sales.employeeName}".width(MAX) + '\n';
teks +=
"Tanggal : ${sales.timeModified.dateTimeFormat('HH:mm dd/MM/yyyy')}"
.width(MAX) +
'\n\n';
var ticketSubCategories =
tickets?.detail?.map((e) => e.productSubcategoryFkid) ?? [];
ordersToPrint.forEach((orders) {
var isParentPrinted = false;
if (tickets == null ||
(ticketSubCategories.isNotEmpty &&
ticketSubCategories
.any((it) => it == orders.product?.productSubcategoryFkid))) {
var qty = orders.qty - orders.printed;
if (sales.status == "Refund") {
orders.qty = orders.qty * -1;
orders.subTotal = orders.subTotal * -1;
}
var name = orders.isItemVoid
? "VOID: ${orders.product?.name}"
: orders.product.name;
var table = sales.table.isNotEmpty ? "/${sales.table}" : "";
var customer = (sales.customer.length ?? 0) <= 6
? sales.customer
: sales.customer.substring(0, 6);
teks += (qty.toCurrency() + "x").width(5);
teks += (name ?? '').width(MAX - 5 - 10, max: MAX, before: 5);
teks += " #$customer$table".widthRight(10) + '\n';
printed++;
isParentPrinted = true;
}
orders.extra.forEach((extra) {
if (tickets == null ||
(ticketSubCategories.isNotEmpty &&
ticketSubCategories
.any((it) => it == extra.product.productSubcategoryFkid))) {
teks += "\n";
var prefix = isParentPrinted
? "[EXTRA] ${orders.qty - orders.printed}x "
: "- ";
var name = "$prefix" +
(orders.isItemVoid
? "VOID: ${extra.product.name}"
: "${extra.product.name}");
teks += name.width(24) + '\n';
printed++;
}
});
if (isParentPrinted && orders.note != null) {
teks += "(${orders.note})".width(32) + '\n';
}
teks += "\n";
});
if (sales.status == "Refund") {
teks += " #Refund #Refund #Refund #Refund".center(MAX) + '\n\n';
}
if (isReprint) {
teks += " REPRINT ".center(MAX, "=") + '\n';
teks += " REPRINT ".center(MAX, "=") + '\n';
}
teks += "\n\n";
} catch (e) {
print("Create nota order error. $e");
}
return printed > 0 ? header + teks + footer : "";
}
int getMaxCharacter(int? paperSize) {
switch (paperSize) {
case 75:
return 40;
case 80:
return 48;
default:
return 32;
}
}
extension IntExtension on int? {
String toCurrency({String prefix = ''}) {
var num = NumberFormat.decimalPattern();
try {
return prefix + num.format(this ?? 0);
} catch (e) {
return '${prefix}0';
}
}
String dateTimeFormat([String? format]) {
final DateFormat sdf = DateFormat(format ?? 'dd-MM-yyyy HH:mm');
return sdf.format(DateTime.fromMillisecondsSinceEpoch(this ?? 0));
}
}
extension StringExtensions on String {
String safeRepeat(int? count) {
return count != null && count > 0 ? this * count : '';
}
String loop(int w) {
var newVal = '';
for (var i = 0; i < w; i++) {
newVal += this;
}
return newVal;
}
String width(int width, {int max = 32, int before = 0}) {
try {
var cursor = 0;
var wordSplit = StringBuffer();
do {
var suffix = '';
var start = cursor;
var end = (start + width) < length ? start + width : length;
var cutWord = substring(start, end);
var lastSpace = cutWord.contains(' ') && end != length
? cutWord.lastIndexOf(' ')
: cutWord.length;
if (lastSpace < (width ~/ 2) && (width - 1) < cutWord.length) {
lastSpace = width - 1;
cursor--;
suffix = '-';
}
cursor += lastSpace + 1;
suffix += cursor < length
? ' '.padRight(max - (before + lastSpace)) + '\n'
: ' '.padRight(width - (before + lastSpace));
wordSplit.write(cutWord.substring(0, lastSpace) + suffix);
} while (cursor < length);
return wordSplit.toString();
} catch (e) {
// Handle error
}
// Fallback logic
return padRight(width);
}
String widthRight(int w) {
return padLeft(w);
}
String center(int width, [String flanks = ' ']) {
if (length == width) {
return this;
} else if (length < width) {
var center = width ~/ 2;
var flank = center - (length ~/ 2);
var newValue = StringBuffer();
for (var i = 0; i < flank; i++) {
newValue.write(flanks);
}
newValue.write(this);
for (var i = newValue.length; i < width; i++) {
newValue.write(flanks);
}
return newValue.toString();
} else {
// Handle case where length > width
}
return '';
}
}
class PrinterTicketEntity {
final int printersettingTicketId;
final int? printerSettingFkid;
final int? dataModified;
final String? settingType;
final String? name;
final List<PrinterTicketDetail> detail;
final int? dataCreated;
PrinterTicketEntity({
required this.printersettingTicketId,
this.printerSettingFkid,
this.dataModified,
this.settingType,
this.name,
this.detail = const [],
this.dataCreated,
});
}
class PrinterTicketDetail {
final int? productSubcategoryFkid;
final int? dataModified;
final int? printersettingTicketFkid;
PrinterTicketDetail({
this.productSubcategoryFkid,
this.dataModified,
this.printersettingTicketFkid,
});
}
class SalesEntity {
String displayNota;
String customer;
int timeCreated;
String payment;
String table;
List<Payment> payments;
List<Order> orderList;
List<Promotion> promotions;
Discount? discount;
List<Tax>? taxes;
int grandTotal;
String status;
SalesTagEntity? salesTag;
int customersQty;
String employeeName;
int timeModified;
SalesEntity({
required this.displayNota,
required this.customer,
required this.timeCreated,
required this.payment,
required this.table,
required this.payments,
required this.orderList,
required this.promotions,
this.discount,
this.taxes,
required this.grandTotal,
required this.status,
this.salesTag,
this.customersQty = 1,
required this.employeeName,
required this.timeModified,
});
factory SalesEntity.fromJson(Map<String, dynamic> json) {
return SalesEntity(
displayNota: json['displayNota'] ?? '',
customer: json['customer'] ?? '',
timeCreated: json['timeCreated'] ?? 0,
payment: json['payment'] ?? '',
table: json['table'] ?? '',
payments: (json['payments'] ?? [])
.map<Payment>((paymentJson) => Payment.fromJson(paymentJson))
.toList(),
orderList: (json['orderList'] ?? [])
.map<Order>((orderJson) => Order.fromJson(orderJson))
.toList(),
promotions: (json['promotions'] ?? [])
.map<Promotion>((promotionJson) => Promotion.fromJson(promotionJson))
.toList(),
discount:
json['discount'] != null ? Discount.fromJson(json['discount']) : null,
taxes: (json['taxes'] ?? [])
.map<Tax>((taxJson) => Tax.fromJson(taxJson))
.toList(),
grandTotal: json['grandTotal'] ?? 0,
status: json['status'] ?? '',
salesTag: json['salesTag'] != null
? SalesTagEntity.fromJson(json['salesTag'])
: null,
employeeName: json['employee_name'] ?? '',
timeModified: json['time_modified'] ?? 0,
);
}
}
class SalesTagEntity {
final int salesTagId;
final int adminFkid;
final String dataStatus;
final int dateCreated;
final int dateModified;
final String name;
SalesTagEntity({
required this.salesTagId,
required this.adminFkid,
required this.dataStatus,
required this.dateCreated,
required this.dateModified,
required this.name,
});
factory SalesTagEntity.fromJson(Map<String, dynamic> json) {
return SalesTagEntity(
salesTagId: json['salesTagId'],
adminFkid: json['adminFkid'],
dataStatus: json['dataStatus'],
dateCreated: json['dateCreated'],
dateModified: json['dateModified'],
name: json['name'],
);
}
}
// Outlet model
class Outlet {
String name;
String? receiptAddress;
String? receiptPhone;
String? receiptNote;
String? receiptSocialmedia;
Outlet({
required this.name,
this.receiptAddress,
this.receiptPhone,
this.receiptNote,
this.receiptSocialmedia,
});
}
// Employee model
class Employee {
String name;
Employee({
required this.name,
});
}
// Payment model
class Payment {
String method;
int pay;
Bank? bank;
int total;
Payment({
required this.method,
required this.pay,
this.bank,
required this.total,
});
factory Payment.fromJson(Map<String, dynamic> json) {
return Payment(
method: json['method'] ?? '',
pay: json['pay'] ?? 0,
bank: json['bank'] != null
? Bank.fromJson(json['bank'])
: null, // Assuming Bank has a fromJson method
total: json['total'] ?? 0,
);
}
}
// Order model
class Order {
String? note;
bool isItemVoid;
Product product;
int qty;
int subTotal;
List<Order> extra;
Promotion? promotion;
Discount discount;
String? extraType;
int printed;
int tmpId;
String employeeName;
Order({
this.note,
required this.isItemVoid,
required this.product,
required this.qty,
required this.subTotal,
required this.extra,
this.promotion,
required this.discount,
this.extraType,
required this.printed,
required this.tmpId,
required this.employeeName,
});
factory Order.fromJson(Map<String, dynamic> json) {
return Order(
note: json['note'],
isItemVoid: json['isItemVoid'] ?? false,
product: Product.fromJson(json['product']),
qty: json['qty'] ?? 0,
subTotal: json['subTotal'] ?? 0,
extra: (json['extra'] as List<dynamic>?)
?.map((e) => Order.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
promotion: json['promotion'] != null
? Promotion.fromJson(json['promotion'] as Map<String, dynamic>)
: null,
discount: Discount.fromJson(json['discount']),
extraType: json['extraType'],
printed: json['printed'] ?? 0,
tmpId: json['tmp_id'] ?? 0,
employeeName: json['employee_name']);
}
}
// Product model
class Product {
int productId;
String? name;
int productSubcategoryFkid;
int productDetailId;
Product({
required this.productId,
this.name,
required this.productSubcategoryFkid,
required this.productDetailId,
});
factory Product.fromJson(Map<String, dynamic> json) {
return Product(
productId: json['productId'],
name: json['name'],
productSubcategoryFkid: json['productSubcategoryFkid'],
productDetailId: json['productDetailId'],
);
}
}
// Promotion model
class Promotion {
String? name;
String? displayVoucher;
int promotionValue;
String? pomotionTypeFkid;
Promotion({
this.name,
this.displayVoucher,
required this.promotionValue,
this.pomotionTypeFkid,
});
factory Promotion.fromJson(Map<String, dynamic> json) {
return Promotion(
name: json['name'],
displayVoucher: json['displayVoucher'],
promotionValue: json['promotionValue'],
pomotionTypeFkid: json['pomotionTypeFkid'],
);
}
}
// Discount model
class Discount {
int discount;
int voucher;
int discountNominal;
int voucherNominal;
String discountType;
String? discountInfo;
String? voucherInfo;
Discount({
required this.discount,
required this.voucher,
required this.discountNominal,
required this.voucherNominal,
required this.discountType,
this.discountInfo,
this.voucherInfo,
});
factory Discount.fromJson(Map<String, dynamic> json) {
return Discount(
discount: json['discount'],
voucher: json['voucher'],
discountNominal: json['discountNominal'],
voucherNominal: json['voucherNominal'],
discountType: json['discountType'],
discountInfo: json['discountInfo'],
voucherInfo: json['voucherInfo'],
);
}
}
// Tax model
class Tax {
String? name;
int total;
String category;
Tax({
this.name,
required this.total,
required this.category,
});
factory Tax.fromJson(Map<String, dynamic> json) {
return Tax(
name: json['name'],
total: json['total'],
category: json['category'],
);
}
}
// Bank model
class Bank {
String name;
int bankId;
Bank({
required this.name,
required this.bankId,
});
factory Bank.fromJson(Map<String, dynamic> json) {
return Bank(
name: json['name'] ?? '',
bankId: json['bankId'] ?? 0,
);
}
}
SalesEntity dummySales() {
return SalesEntity(
employeeName: "Kartika",
timeModified: DateTime.now().millisecondsSinceEpoch,
displayNota: '1001',
customer: 'John Doe',
timeCreated: DateTime.now().millisecondsSinceEpoch,
payment: 'CASH',
table: 'Table 5',
payments: [
Payment(
method: 'CARD',
pay: 5000,
total: 5000,
bank: Bank(name: 'BCA', bankId: 1),
),
],
orderList: [
Order(
printed: 0,
tmpId: DateTime.now().millisecondsSinceEpoch,
employeeName: "Feni",
isItemVoid: false,
product: Product(
productId: 1,
name: 'Ayam Goreng',
productSubcategoryFkid: 1,
productDetailId: 1),
qty: 2,
subTotal: 20000,
extra: [],
promotion: Promotion(
name: "Promo Coblosan",
promotionValue: 500,
pomotionTypeFkid: '15',
),
discount: Discount(
discount: 5,
voucher: 0,
discountNominal: 2500,
voucherNominal: 0,
discountInfo: 'Flash Deals',
discountType: Constant.TYPE_NOMINAL),
),
Order(
printed: 0,
tmpId: DateTime.now().millisecondsSinceEpoch,
employeeName: "Feni",
isItemVoid: false,
product: Product(
productId: 2,
name: 'Es Teh',
productDetailId: 2,
productSubcategoryFkid: 2),
qty: 1,
subTotal: 2000,
extra: [],
promotion: null,
discount: Discount(
discount: 0,
voucher: 0,
discountNominal: 0,
voucherNominal: 0,
discountType: Constant.TYPE_NOMINAL),
),
],
promotions: [],
discount: Discount(
discount: 5,
voucher: 0,
discountNominal: 1000,
voucherNominal: 0,
discountInfo: 'Diskon Karyawan',
discountType: Constant.TYPE_PERCENT),
taxes: [
Tax(name: 'Tax Pb1', total: 50, category: "tax"),
Tax(name: 'Service', total: 10, category: "service"),
],
grandTotal: 5000,
status: 'Success');
}
Outlet dummyOutlet() {
return Outlet(
name: 'Outlet ABC',
receiptAddress: '123 Main Street',
receiptPhone: '123-456-7890',
receiptNote: 'Thank you for your visit!',
receiptSocialmedia: '@OutletABC',
);
}
class Constant {
static const String TYPE_NOMINAL = "nominal";
static const String TYPE_PERCENT = "percentage";
static const String PROMO_TYPE_FREE_MEMBER = "free_member";
static const String PROMO_TYPE_FREE = "free";
static const String PROMO_TYPE_DISCOUNT_VOUCHER = "discount_voucher";
static const String PROMO_TYPE_FREE_VOUCHER = "free_voucher";
static const String PROMO_TYPE_SPECIAL_PRICE_VOUCHER =
"special_price_voucher";
static const String TAX_CATEGORY_DISC = "disc";
static const String TAX_CATEGORY_VOUCHER = "voucher";
static const String PRINTER_CODE_LOGO = "[CUT]";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment