Last active
February 13, 2024 08:40
-
-
Save ANNASBlackHat/f8111fa7812466937286a151c9a08304 to your computer and use it in GitHub Desktop.
Generate Close Shift Recap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:core'; | |
import 'package:intl/intl.dart'; | |
import 'dart:convert'; | |
import 'package:collection/collection.dart'; | |
import 'dart:math'; | |
void main() { | |
// Create dummy data | |
SalesEntity sales = dummySales(); | |
Outlet outlet = dummyOutlet(); | |
Employee employee = Employee(name: 'Jane Doe'); | |
List<CashRecapEntity> cashRecaps = generateDummyCashRecap(); | |
List<TmpSalesEntity> pending = generateDummyTmpSales(5); | |
List<OperationalCost> operationalCost = generateDummyOperationalCost(2); | |
String? printerRule = | |
'{"sales":true,"paymentmedia":true,"groupsales":true,"refund":true,"time":true,"tax":true,"itemsales":true,"avgpaxbill":true,"fifo":true,"actual":true,"opcostdetail":true,"entertainincome":true}'; | |
List<SubCategoryEntity> categories = generateDummySubCategories(2); | |
// Call the function with the dummy data | |
String cashRecapFormat = getCashRecapFormat( | |
cashRecaps, | |
outlet, // Make sure to replace outlet with actual outlet object | |
[sales], // Make sure to replace sales with actual sales list | |
pending, | |
operationalCost, | |
printerRule, | |
categories, | |
paperSize: 58, | |
watermark: "#REPRINT#", | |
openShifts: [], // Optionally provide openShifts if needed | |
isRecap: true, // Set isRecap flag as needed | |
); | |
// Print the formatted cash recap | |
print(cashRecapFormat); | |
} | |
String getCashRecapFormat( | |
List<CashRecapEntity> cashRecaps, | |
Outlet outlet, | |
List<SalesEntity> sales, | |
List<TmpSalesEntity> pending, | |
List<OperationalCost> op, | |
String? printerRule, | |
List<SubCategoryEntity> categories, | |
{int? paperSize = 58, | |
String? watermark, | |
List<OpenShiftEntity> openShifts = const [], | |
bool isRecap = false}) { | |
StringBuffer nota = StringBuffer("[CUT]"); | |
int MAX = getMaxCharacter(paperSize); | |
nota.writeln(); | |
RolePrinterClosing defaultRule = RolePrinterClosing( | |
sales: true, paymentmedia: true, groupsales: true, refund: true); | |
RolePrinterClosing rule = defaultRule; //printerRule != null | |
if (printerRule != null) { | |
try { | |
rule = RolePrinterClosing.fromJson(json.decode(printerRule)); | |
} catch (e) { | |
print('error ${e}'); | |
} | |
} | |
List<CashRecapEntity> cashRecapSorted = cashRecaps | |
..sort((a, b) => a.timeCreated.compareTo(b.timeCreated)); | |
String dateFormat = "dd/MM/yyyy"; | |
if (rule.time) { | |
dateFormat += " HH:mm"; | |
} | |
String date = cashRecapSorted.isNotEmpty | |
? cashRecapSorted.first.timeCreated.dateTimeFormat(dateFormat) | |
: DateFormat(dateFormat).format(DateTime.now()); | |
try { | |
List<String> cashier = []; | |
cashRecaps.forEach((it) { | |
if (!cashier.contains(it.employeeName.toUpperCase())) { | |
cashier.add(it.employeeName.toUpperCase()); | |
} | |
}); | |
String sw = "#".safeRepeat(watermark?.split("\n").length ?? 0); | |
String title = | |
isRecap ? "LAPORAN REKAP TUTUP KASIR" : "LAPORAN TUTUP KASIR"; | |
nota.writeln(outlet.name.trim().center(MAX)); | |
nota.writeln(outlet.receiptAddress?.center(MAX)); | |
nota.writeln("=".loop(MAX)); | |
nota.writeln("${sw}${title}${sw}".center(MAX)); | |
nota.writeln("Kasir : ${cashier.join(', ')}".width(MAX)); | |
nota.writeln("Tanggal : $date".width(MAX)); | |
nota.writeln(); | |
List<SalesEntity> salesSuccess = | |
sales.where((p) => p.status.toLowerCase() == "success").toList(); | |
List<SalesEntity> netSales = salesSuccess | |
.where((p) => | |
p.payment.toUpperCase().contains("CASH") || | |
p.payment.toUpperCase().contains("CARD") || | |
p.payment.toUpperCase().contains("PIUTANG")) | |
.toList(); | |
List<Payment> payments = salesSuccess.expand((it) => it.payments).toList(); | |
int totalNetSales = payments | |
.where((it) => | |
it.method.toLowerCase() == "cash" || | |
it.method.toLowerCase() == "card" || | |
it.method.toLowerCase() == "piutang") | |
.map((it) => it.total) | |
.fold(0, (prev, elem) => prev + elem); | |
int netSalesTotal = netSales | |
.map((it) => it.grandTotal) | |
.fold(0, (prev, elem) => prev + elem); | |
List<Order> orders = salesSuccess | |
.expand((it) => it.orderList) | |
.where((it) => !it.isItemVoid) | |
.toList(); | |
List<Order> ordersVoid = salesSuccess | |
.expand((it) => it.orderList) | |
.where((it) => it.isItemVoid) | |
.toList(); | |
List<Order> ordersCombined = (rule.itemsales || rule.groupsales) | |
? orders.expand((it) => it.extra).toList() | |
: []; | |
ordersCombined.addAll(orders); | |
List<Order> ordersVoidCombined = (rule.itemsales || rule.groupsales) | |
? ordersVoid.expand((it) => it.extra).toList() | |
: []; | |
ordersVoidCombined.addAll(ordersVoid); | |
List<Promotion> promotions = orders | |
.where((it) => it.promotion != null) | |
.map((it) => it.promotion!) | |
.toList(); | |
promotions.addAll(ordersVoid | |
.where((it) => it.promotion != null) | |
.map((it) => it.promotion!)); | |
salesSuccess | |
.where((it) => it.promotions != null) | |
.expand((it) => it.promotions!) | |
.forEach((promo) { | |
promotions.add( | |
Promotion(name: promo.name, promotionValue: promo.promotionValue)); | |
}); | |
int totalPromotion = promotions | |
.map((it) => it.promotionValue) | |
.fold(0, (prev, elem) => prev + elem); | |
int discTotal = totalPromotion; | |
int allQty = 0; | |
netSales.forEach((sales) { | |
discTotal += sales.discount?.discountNominal ?? 0; | |
sales.orderList | |
.where((it) => !it.isItemVoid && it.discount.discountNominal > 0) | |
.forEach((o) => discTotal += o.discount.discountNominal); | |
sales.taxes?.forEach((t) { | |
if (t.category == Constant.TAX_CATEGORY_DISC) { | |
discTotal += t.total; | |
} | |
}); | |
sales.orderList.forEach((order) { | |
int helper = order.isItemVoid ? -1 : 1; | |
allQty += (order.qty.abs() * helper); | |
order.extra.forEach((extra) => allQty += (extra.qty.abs() * helper)); | |
}); | |
}); | |
nota.writeln(" SALES ".center(MAX, "=")); | |
nota.write("Item Sales".width(MAX - 4 - 15)); | |
nota.write(allQty.toCurrency().width(5)); | |
nota.writeln((totalNetSales + discTotal).toCurrency().widthRight(15)); | |
nota.write("Discount Sales".width(MAX - 15)); | |
nota.writeln(discTotal.toCurrency().widthRight(15)); | |
nota.writeln("-".loop(MAX)); | |
nota.write("Net Sales".width(MAX - 15)); | |
nota.writeln(totalNetSales.toCurrency().widthRight(15)); | |
nota.writeln(); | |
int totalMedia = 0; | |
int totalCard = 0; | |
int totalCash = 0; | |
if (rule.paymentmedia) nota.writeln(" MEDIA ".center(MAX, "=")); | |
List<String> medias = ["Cash", "Card", "Piutang"]; | |
medias.forEach((media) { | |
List<Payment> pay = payments | |
.where((it) => it.method.toLowerCase() == media.toLowerCase()) | |
.toList(); | |
int total = | |
pay.map((it) => it.total).fold(0, (prev, elem) => prev + elem); | |
if (media.toLowerCase() == "card") { | |
Map<int, List<Payment>> bankList = | |
groupBy(payments, (payment) => payment.bank!.bankId); | |
bankList.forEach((key, value) { | |
int totalBank = | |
value.map((it) => it.total).fold(0, (prev, elem) => prev + elem); | |
totalCard += totalBank; | |
if (rule.paymentmedia) { | |
nota.write(value.first.bank!.name.width(MAX - 15)); | |
nota.writeln(totalBank.toCurrency().width(15)); | |
} | |
}); | |
} | |
if (media.toLowerCase() == "cash") totalCash += total; | |
totalMedia += total; | |
if (rule.paymentmedia) { | |
nota.write(media.width(MAX - 13)); | |
nota.writeln(total.toCurrency().widthRight(13)); | |
} | |
}); | |
nota.writeln("-".loop(MAX)); | |
nota.writeln("Grand Total : ".widthRight(MAX - 13) + | |
totalMedia.toCurrency().widthRight(13)); | |
nota.writeln(); | |
int allTax = 0; | |
if (rule.tax) { | |
nota.writeln(" TAX ".center(MAX, "=")); | |
List<Tax> allTaxes = netSales.expand((it) => it.taxes!).toList(); | |
List<Tax> taxServices = allTaxes | |
.where((it) => | |
it.total > 0 && | |
(it.category == "service" || it.category == "tax")) | |
.toList(); | |
Map<String?, List<Tax>> groupedTaxes = | |
groupBy(taxServices, (tax) => tax.name); | |
groupedTaxes.forEach((key, value) { | |
int total = | |
value.map((it) => it.total).fold(0, (prev, elem) => prev + elem); | |
allTax += total; | |
nota.write(key?.width(MAX - 11)); | |
nota.writeln(total.toCurrency().widthRight(11)); | |
}); | |
nota.writeln("-".loop(MAX)); | |
nota.writeln("Grand Total : ".widthRight(MAX - 13) + | |
allTax.toCurrency().widthRight(13)); | |
nota.writeln(); | |
} | |
if (rule.itemsales) { | |
nota.writeln(" ITEM SALES ".center(MAX, "=")); | |
int allTotal = 0; | |
int allQtyItemSales = 0; | |
ordersVoidCombined.forEach((it) { | |
it.extraType = it.extraType == "link" ? "link" : ""; | |
}); | |
categories.sortedBy((it) => it.name).forEach((category) { | |
List<Order> orderFilter = ordersCombined | |
.where((it) => | |
it.product.productSubcategoryFkid == category.productCategoryId) | |
.toList(); | |
if (orderFilter.isNotEmpty) { | |
StringBuffer items = StringBuffer(); | |
orderFilter.forEach((it) { | |
it.extraType = it.extraType == "link" ? "link" : ""; | |
}); | |
List<Order> extraSorted = | |
orderFilter.sortedBy((it) => it.extraType!).toList(); | |
Map<String, List<Order>> salesGroup = groupBy(extraSorted, | |
(it) => "${it.product.productDetailId}#${it.extraType}"); | |
bool isFirstExtra = true; | |
salesGroup.forEach((prodId, orderList) { | |
int qty = orderList | |
.map((it) => it.qty) | |
.fold(0, (prev, elem) => prev + elem); | |
int subTotal = orderList | |
.map((it) => it.subTotal) | |
.fold(0, (prev, elem) => prev + elem); | |
int productId = int.parse(prodId.substring(0, prodId.indexOf("#"))); | |
String extraType = prodId.substring(prodId.indexOf("#") + 1); | |
ordersVoidCombined | |
.where((voidOrder) => | |
voidOrder.product.productDetailId == productId && | |
voidOrder.extraType == extraType) | |
.forEach((voidOrder) { | |
qty -= (voidOrder.qty.abs()); | |
subTotal -= (voidOrder.subTotal.abs()); | |
}); | |
if (qty > 0) { | |
if (extraType.isNotEmpty && isFirstExtra) { | |
isFirstExtra = false; | |
items.writeln( | |
"[${extraType == "link" ? "LINK MENU" : extraType.toUpperCase()}]" | |
.width(MAX)); | |
} | |
items.write(orderList.first.product.name?.width(MAX - 5 - 11)); | |
items.write(qty.toString().center(5)); | |
items.writeln(subTotal.toCurrency().widthRight(11)); | |
allTotal += subTotal; | |
allQtyItemSales += qty; | |
} | |
}); | |
if (items.isNotEmpty) { | |
nota.writeln("#${category.name}".width(MAX)); | |
nota.write(items); | |
} | |
} | |
}); | |
nota.writeln("-" * MAX); | |
nota.writeln("Grand Total : ".widthRight(MAX - 5 - 11) + | |
allQtyItemSales.toString().center(5) + | |
allTotal.toCurrency().widthRight(11)); | |
nota.writeln('\n'); | |
} | |
if (rule.groupsales) { | |
int itemSalesTotal = 0; | |
int itemSalesQty = 0; | |
nota.writeln(" GROUP SALES ".center(MAX, "=")); | |
categories.sortedBy((it) => it.name).forEach((category) { | |
List<Order> orderFilter = ordersCombined | |
.where((it) => | |
it.product.productSubcategoryFkid == | |
category.productCategoryId && | |
!it.isItemVoid) | |
.toList(); | |
int total = orderFilter | |
.map((it) => it.subTotal) | |
.fold(0, (prev, elem) => prev + elem); | |
int qty = orderFilter | |
.map((it) => it.qty) | |
.fold(0, (prev, elem) => prev + elem); | |
if (ordersVoidCombined.isNotEmpty) { | |
Map<int, List<Order>> salesGroup = | |
groupBy(orderFilter, (it) => it.product.productDetailId); | |
salesGroup.forEach((prodId, _) { | |
ordersVoidCombined | |
.where((it) => it.product.productDetailId == prodId) | |
.forEach((orderVoid) { | |
qty -= orderVoid.qty.abs(); | |
total -= (orderVoid.subTotal.abs()); | |
}); | |
}); | |
} | |
if (total > 0 || qty > 0) { | |
itemSalesQty += qty; | |
itemSalesTotal += total; | |
nota.write(category.name.width(MAX - 5 - 11)); | |
nota.write(qty.toString().center(5)); | |
nota.writeln(total.toCurrency().widthRight(11)); | |
} | |
}); | |
nota.writeln("-".loop(MAX)); | |
nota.writeln("Grand Total : ".widthRight(MAX - 5 - 11) + | |
itemSalesQty.toCurrency().center(5) + | |
itemSalesTotal.toCurrency().widthRight(11)); | |
nota.writeln('\n'); | |
} | |
if (promotions.isNotEmpty) { | |
nota.writeln(" PROMOTIONS ".center(MAX, "=")); | |
Map<String?, List<Promotion>> promotionGroup = | |
groupBy(promotions, (it) => it.name); | |
promotionGroup.forEach((name, promoList) { | |
int totalPromo = promoList | |
.map((it) => it.promotionValue) | |
.fold(0, (prev, elem) => (prev ?? 0) + (elem ?? 0)); | |
nota.write(name?.width(MAX - 11)); | |
nota.writeln(totalPromo.toCurrency().widthRight(11)); | |
}); | |
nota.writeln("-".loop(MAX)); | |
nota.writeln("Grand Total".widthRight(MAX - 16) + | |
totalPromotion.toCurrency().widthRight(16)); | |
nota.writeln('\n'); | |
} | |
List<Tax> allTaxes = netSales.expand((it) => it.taxes!).toList(); | |
int totalTax = allTaxes | |
.where((it) => | |
it.total > 0 && (it.category == "service" || it.category == "tax")) | |
.map((it) => it.total) | |
.fold(0, (prev, elem) => prev + elem); | |
int totalOdb = netSalesTotal - totalTax + discTotal; | |
nota.writeln(" SALES RECAP ".center(MAX, "=")); | |
nota.write("Total ODB".width(MAX - 13)); | |
nota.writeln(totalOdb.toCurrency().widthRight(13)); | |
nota.write("Discount".width(MAX - 13)); | |
nota.writeln(discTotal.toCurrency().widthRight(13)); | |
nota.write("After disc.".width(MAX - 13)); | |
nota.writeln((totalOdb - discTotal).toCurrency().widthRight(13)); | |
List<Tax> taxServices = allTaxes | |
.where((it) => | |
it.total > 0 && (it.category == "service" || it.category == "tax")) | |
.toList(); | |
Map<String?, List<Tax>> groupedTaxes = | |
groupBy(taxServices, (it) => it.name); | |
groupedTaxes.forEach((key, value) { | |
int total = | |
value.map((it) => it.total).fold(0, (prev, elem) => prev + elem); | |
nota.write(key?.width(MAX - 13)); | |
nota.writeln(total.toCurrency().widthRight(13)); | |
}); | |
nota.writeln("\n\n"); | |
int pendingBillTotal = cashRecaps | |
.map((it) => it.pendingBillTotal) | |
.fold(0, (prev, elem) => prev + elem); | |
if (pendingBillTotal > 0) { | |
nota.writeln(" PENDING BILL ".center(32, "=")); | |
nota.writeln("Grand Total : ".widthRight(MAX - 16) + | |
pendingBillTotal.toCurrency().widthRight(11)); | |
nota.writeln(); | |
} else if (pending.isNotEmpty && | |
date == DateFormat(dateFormat).format(DateTime.now())) { | |
nota.writeln(" PENDING BILL ".center(32, "=")); | |
pendingBillTotal = 0; | |
int pendingBillQty = 0; | |
List<SalesEntity> salesPending = pending.map((e) { | |
return SalesEntity.fromJson(json.decode(e.sales)); | |
}).toList(); | |
List<Order> orderPending = | |
salesPending.expand((it) => it.orderList).toList(); | |
Map<int, List<Order>> orderGroup = | |
groupBy(orderPending, (it) => it.product.productDetailId); | |
orderGroup.forEach((_, orderList) { | |
int totalQty = orderList | |
.map((it) => it.isItemVoid ? (it.qty.abs()) * -1 : it.qty) | |
.fold(0, (prev, elem) => prev + elem); | |
int totalSubtotal = orderList | |
.map((it) => it.isItemVoid ? (it.subTotal.abs()) * -1 : it.subTotal) | |
.fold(0, (prev, elem) => prev + elem); | |
nota.write(orderList.first.product.name?.width(MAX - 5 - 8)); | |
nota.write(totalQty.toCurrency().width(5)); | |
nota.writeln(totalSubtotal.toCurrency().widthRight(8)); | |
pendingBillTotal += totalSubtotal; | |
pendingBillQty += totalQty; | |
}); | |
nota.writeln("-".loop(MAX)); | |
nota.writeln("Grand Total".widthRight(MAX - 5 - 11) + | |
pendingBillQty.toCurrency().center(5) + | |
pendingBillTotal.toCurrency().widthRight(11)); | |
nota.writeln(); | |
} | |
List<Order> salesVoid = salesSuccess | |
.expand((it) => it.orderList) | |
.where((it) => it.isItemVoid) | |
.toList(); | |
if (salesVoid.isNotEmpty) { | |
nota.writeln(" VOID ".center(MAX, "=")); | |
int subtotalExtra = 0; | |
salesVoid.forEach((v) { | |
nota.write(v.product?.name | |
?.width(MAX - 5 - 11)); // 3 spasi antara menu dan qty | |
nota.write(v.qty.toCurrency().center(5)); | |
nota.writeln(((v.subTotal.abs())).toCurrency().widthRight(11)); | |
v.extra.forEach((e) { | |
nota.write("- ${e.product.name}" | |
.width(MAX - 5 - 11)); // 3 spasi antara menu dan qty | |
nota.write(e.qty.toCurrency().center(5)); | |
nota.writeln(((e.subTotal.abs())).toCurrency().widthRight(11)); | |
subtotalExtra += (e.subTotal.abs()); | |
}); | |
}); | |
int totalVoid = salesVoid | |
.map((it) => (it.subTotal.abs())) | |
.fold(0, (prev, elem) => (prev) + elem); | |
totalVoid -= subtotalExtra; | |
nota.writeln("-".loop(MAX)); | |
nota.writeln("Grand Total : ".widthRight(MAX - 13) + | |
totalVoid.toCurrency().widthRight(13)); | |
nota.writeln(); | |
} | |
List<SalesEntity> refund = | |
sales.where((it) => it.status?.toLowerCase() == "refund").toList(); | |
if (refund.isNotEmpty) { | |
nota.writeln(" REFUND ".center(MAX, "=")); | |
refund.forEach((sale) { | |
int totalTax = sale.taxes | |
?.map((it) => it.total) | |
.fold(0, (prev, elem) => (prev ?? 0) + elem) ?? | |
0; | |
int avgTax = totalTax ~/ (sale.orderList.length ?? 1); | |
sale.orderList.forEach((order) { | |
nota.write(order.product.name?.width(MAX - 5 - 10)); | |
nota.write(order.qty.toString().center(5)); | |
nota.writeln((order.subTotal + avgTax).toCurrency().widthRight(10)); | |
order.extra.forEach((extra) { | |
nota.write(("- " + (extra.product.name ?? '')).width(MAX - 5 - 10)); | |
nota.write(extra.qty.toString().center(5)); | |
nota.writeln(extra.subTotal.toCurrency().widthRight(10)); | |
}); | |
}); | |
}); | |
int allRefund = refund | |
.map((it) => it.grandTotal) | |
.fold(0, (prev, elem) => prev + elem); | |
nota.writeln("-".loop(MAX)); | |
List<Tax> taxesRefund = refund.expand((it) => it.taxes!).toList(); | |
Map<String?, List<Tax>> taxesRefundGroup = | |
groupBy(taxesRefund, (p) => p.name); | |
taxesRefundGroup.forEach((taxName, taxValues) { | |
int taxTotal = taxValues | |
.map((it) => it.total) | |
.fold(0, (prev, elem) => prev + elem); | |
nota.write(taxName?.width(MAX - 10)); | |
nota.writeln(taxTotal.toCurrency().widthRight(10)); | |
}); | |
nota.writeln("Grand Total : ".widthRight(MAX - 13) + | |
allRefund.toCurrency().widthRight(13)); | |
nota.writeln(); | |
} | |
if (rule.avgpaxbill) { | |
int allPax = salesSuccess | |
.map((it) => it.customersQty) | |
.fold(0, (prev, elem) => prev + elem); | |
int avgPax = allPax > 0 ? netSalesTotal ~/ allPax : 0; | |
nota.write("Total Pax".width(MAX - 8)); | |
nota.writeln(allPax.toCurrency().widthRight(8)); | |
nota.write("Avg Pax".width(MAX - 8)); | |
nota.writeln(avgPax.toCurrency().widthRight(8)); | |
nota.write("Total Bill".width(MAX - 8)); | |
nota.writeln(salesSuccess.length.toCurrency().widthRight(8)); | |
nota.writeln("Avg Bill".width(MAX - 10) + | |
(netSalesTotal ~/ (sales.isEmpty ? 1 : sales.length)) | |
.toCurrency() | |
.widthRight(10)); | |
nota.writeln(); | |
} | |
if (rule.fifo) { | |
double earlyCash = openShifts | |
.map((it) => it.earlyCash) | |
.fold(0, (prev, elem) => prev + elem); | |
nota.writeln(" FIFO ".center(MAX, "=")); | |
nota.write("Kas Awal".width(MAX - 10)); | |
nota.writeln(earlyCash.toInt().toCurrency().widthRight(10)); | |
int cashIn = 0; | |
nota.write("Kas Masuk".width(MAX - 11)); | |
nota.writeln(cashIn.toCurrency().widthRight(11)); | |
nota.write("Pendapatan Tunai".width(MAX - 13)); | |
nota.writeln(totalCash.toCurrency().width(13)); | |
nota.write("Pendapatan Kartu".width(MAX - 13)); | |
nota.writeln(totalCard.toCurrency().width(13)); | |
nota.write("Total Pendapatan".width(MAX - 10)); | |
nota.writeln((totalCash + totalCard).toCurrency().widthRight(10)); | |
nota.write("Kas Keluar".width(MAX - 9)); | |
nota.writeln((0).toCurrency().widthRight(9)); | |
nota.writeln("-".loop(MAX)); | |
int sisa = totalCash + totalCard + earlyCash.toInt(); | |
nota.writeln( | |
"Sisa : ".widthRight(MAX - 13) + sisa.toCurrency().widthRight(13)); | |
nota.writeln(); | |
} | |
if (rule.actual) { | |
int totalActualCash = | |
cashRecaps.map((it) => it.cash).fold(0, (prev, elem) => prev + elem); | |
int totalActualCard = | |
cashRecaps.map((it) => it.card).fold(0, (prev, elem) => prev + elem); | |
nota.writeln(" AKTUAL ".center(MAX, "=")); | |
nota.write("Cash".width(MAX - 13)); | |
nota.writeln(totalActualCash.toCurrency().widthRight(13)); | |
nota.write("Card".width(MAX - 13)); | |
nota.writeln(totalActualCard.toCurrency().widthRight(13)); | |
nota.writeln("-".loop(MAX)); | |
nota.writeln("Total : ".widthRight(MAX - 13) + | |
(totalActualCash + totalActualCard).toCurrency().widthRight(13)); | |
nota.writeln('\n'); | |
nota.writeln("SELISIH : ".widthRight(MAX - 13) + | |
((totalActualCash + totalActualCard) - (totalCash + totalCard)) | |
.toCurrency() | |
.widthRight(13)); | |
nota.writeln("\n\n"); | |
} | |
int totalOP = | |
op.map((it) => it.total.toInt()).fold(0, (prev, elem) => prev + elem); | |
if (rule.opcostdetail && op.isNotEmpty) { | |
nota.writeln(" OPERATIONAL COST ".center(MAX, "=")); | |
op.forEach((operationalCost) { | |
nota.write(operationalCost.opcostName.width(MAX - 13)); | |
nota.writeln((operationalCost.total ?? 0).toCurrency().widthRight(13)); | |
}); | |
nota.writeln("\n\n"); | |
} | |
nota.writeln(" CASHFLOW ".center(MAX, "=")); | |
nota.write("Net Sales".width(MAX - 15)); | |
nota.writeln((totalNetSales + discTotal).toCurrency().widthRight(15)); | |
nota.write("Operational Cost".width(MAX - 15)); | |
nota.writeln((totalOP).toCurrency().widthRight(15)); | |
nota.writeln("-".loop(MAX)); | |
nota.writeln("Total Cashflow : ".widthRight(MAX - 13) + | |
((totalNetSales + discTotal) - totalOP).toCurrency().widthRight(13)); | |
nota.writeln(); | |
nota.writeln(" PURCHASING ".center(MAX, "=")); | |
nota.write("Operational Cost".width(MAX - 10)); | |
nota.writeln((totalOP).toCurrency().widthRight(10)); | |
nota.write("Purchase Cash".width(MAX - 10)); | |
nota.writeln((0).toCurrency().widthRight(10)); | |
nota.write("Purchase Hutang".width(MAX - 10)); | |
nota.writeln((0).toCurrency().widthRight(10)); | |
nota.writeln('\n'); | |
int totalDutyMeals = salesSuccess | |
.where((it) => it.payment.toLowerCase().contains("duty meals")) | |
.map((it) => it.grandTotal) | |
.fold(0, (prev, elem) => prev + elem); | |
int totalCompliment = salesSuccess | |
.where((it) => it.payment.toLowerCase().contains("compliment")) | |
.map((it) => it.grandTotal) | |
.fold(0, (prev, elem) => prev + elem); | |
int allDiscTotal = totalPromotion; | |
int allVoucherTotal = 0; | |
salesSuccess.forEach((s) { | |
allDiscTotal += s.discount?.discountNominal ?? 0; | |
allVoucherTotal += s.discount?.voucherNominal ?? 0; | |
s.orderList.forEach((o) => allDiscTotal += o.discount.discountNominal); | |
s.taxes?.forEach((t) { | |
if (t.category == Constant.TAX_CATEGORY_DISC) { | |
allDiscTotal += t.total; | |
} else if (t.category == Constant.TAX_CATEGORY_VOUCHER) { | |
allVoucherTotal += t.total; | |
} | |
}); | |
}); | |
watermark?.split("\n").forEach((it) => nota.writeln(it.width(MAX))); | |
nota.writeln(); | |
if (rule.entertainincome) { | |
List<int> typesFree = [ | |
Constant.PROMO_TYPE_FREE_MEMBER, | |
Constant.PROMO_TYPE_FREE | |
]; | |
List<int> typeVoucher = [ | |
Constant.PROMO_TYPE_DISCOUNT_VOUCHER, | |
Constant.PROMO_TYPE_FREE_VOUCHER, | |
Constant.PROMO_TYPE_SPECIAL_PRICE_VOUCHER | |
]; | |
int allFree = 0; | |
int promoVoucher = 0; | |
(orders + ordersVoid).forEach((order) { | |
int helper = order.isItemVoid ? -1 : 1; | |
if (typesFree.contains(order.promotion?.pomotionTypeFkid)) { | |
allFree += (order.promotion?.promotionValue ?? 0).abs() * helper; | |
} else if (typeVoucher.contains(order.promotion?.pomotionTypeFkid)) { | |
promoVoucher += (order.promotion?.promotionValue ?? 0).abs() * helper; | |
} | |
if ((order.discount.discountNominal).abs() >= (order.subTotal).abs()) { | |
allFree += (order.subTotal).abs() * helper; | |
} | |
}); | |
// allDiscTotal is containing free and promo voucher, so we have to subtract it | |
int discAll = allDiscTotal - allFree - promoVoucher; | |
int voucher = allVoucherTotal + promoVoucher; | |
int entertainTotal = totalDutyMeals + totalCompliment + discAll + voucher; | |
nota.writeln(" ENTERTAIN INCOME ".center(MAX, "=")); | |
nota.write("Compliment".width(MAX - 9)); | |
nota.writeln(totalCompliment.toCurrency().widthRight(9)); | |
nota.write("Discount All".width(MAX - 9)); | |
nota.writeln(discAll.toCurrency().widthRight(9)); | |
nota.write("Free".width(MAX - 9)); | |
nota.writeln(allFree.toCurrency().widthRight(9)); | |
nota.write("Voucher".width(MAX - 9)); | |
nota.writeln(voucher.toCurrency().widthRight(9)); | |
nota.write("Duty Meals".width(MAX - 9)); | |
nota.writeln(totalDutyMeals.toCurrency().widthRight(9)); | |
nota.writeln('\n'); | |
nota.write("Entertain Income +".width(MAX - 11)); | |
nota.writeln( | |
(entertainTotal + netSalesTotal).toCurrency().widthRight(11)); | |
nota.writeln("Net Sales".width(MAX)); | |
nota.writeln('\n\n\n'); | |
} | |
} catch (e) { | |
print("Generate Nota tutup kasir error $e"); | |
} | |
return nota.toString(); | |
} | |
int getMaxCharacter(int? paperSize) { | |
switch (paperSize) { | |
case 75: | |
return 40; | |
case 80: | |
return 48; | |
default: | |
return 32; | |
} | |
} | |
class Constant { | |
static const String TYPE_NOMINAL = "nominal"; | |
static const String TYPE_PERCENT = "percentage"; | |
static const int PROMO_TYPE_SPECIAL_PRICE = 4; | |
static const int PROMO_TYPE_DISCOUNT = 5; | |
static const int PROMO_TYPE_FREE = 6; | |
static const int PROMO_TYPE_SPECIAL_PRICE_MEMBER = 7; | |
static const int PROMO_TYPE_DISCOUNT_MEMBER = 8; | |
static const int PROMO_TYPE_FREE_MEMBER = 9; | |
static const int PROMO_TYPE_SPECIAL_PRICE_VOUCHER = 11; | |
static const int PROMO_TYPE_DISCOUNT_VOUCHER = 12; | |
static const int PROMO_TYPE_FREE_VOUCHER = 13; | |
static const int PROMO_TYPE_DEALS = 15; | |
static const String TAX_CATEGORY_DISC = "disc"; | |
static const String TAX_CATEGORY_VOUCHER = "voucher"; | |
} | |
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 ''; | |
} | |
} | |
SalesEntity dummySales() { | |
return SalesEntity( | |
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( | |
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: 5, | |
), | |
discount: Discount( | |
discount: 5, | |
voucher: 0, | |
discountNominal: 2500, | |
voucherNominal: 0, | |
discountInfo: 'Flash Deals', | |
discountType: Constant.TYPE_NOMINAL), | |
), | |
Order( | |
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', | |
); | |
} | |
List<CashRecapEntity> generateDummyCashRecap() { | |
return [ | |
CashRecapEntity( | |
id: 1, | |
timeCreated: DateTime.now() | |
.millisecondsSinceEpoch, // Dummy timeCreated using current timestamp | |
employeeName: "John Doe", | |
pendingBillTotal: 100, | |
cash: 500, | |
card: 300, | |
), | |
CashRecapEntity( | |
id: 2, | |
timeCreated: DateTime.now() | |
.millisecondsSinceEpoch, // Dummy timeCreated using current timestamp | |
employeeName: "Jane Smith", | |
pendingBillTotal: 50, | |
cash: 300, | |
card: 200, | |
), | |
]; | |
} | |
List<TmpSalesEntity> generateDummyTmpSales(int count) { | |
List<TmpSalesEntity> tmpSalesList = []; | |
for (int i = 0; i < count; i++) { | |
tmpSalesList.add( | |
TmpSalesEntity( | |
id: i + 1, | |
sales: | |
'Sales data ${Random().nextInt(100)}', // Generate random sales data | |
), | |
); | |
} | |
return tmpSalesList; | |
} | |
// Function to generate dummy data for OperationalCost | |
List<OperationalCost> generateDummyOperationalCost(int count) { | |
List<OperationalCost> operationalCostList = []; | |
for (int i = 0; i < count; i++) { | |
operationalCostList.add( | |
OperationalCost( | |
id: i + 1, | |
opcostName: | |
'Operational Cost ${Random().nextInt(100)}', // Generate random opcost name | |
total: Random().nextInt(10000), // Generate random total | |
), | |
); | |
} | |
return operationalCostList; | |
} | |
// Function to generate dummy data for SubCategoryEntity | |
List<SubCategoryEntity> generateDummySubCategories(int count) { | |
List<SubCategoryEntity> subCategoryList = []; | |
for (int i = 0; i < count; i++) { | |
subCategoryList.add( | |
SubCategoryEntity( | |
id: i + 1, | |
name: | |
'Subcategory ${Random().nextInt(100)}', // Generate random subcategory name | |
productCategoryId: i + | |
1, // Generate random productCategoryId (assuming there are 10 categories) | |
), | |
); | |
} | |
return subCategoryList; | |
} | |
// SalesEntity model | |
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; | |
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}); | |
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, | |
); | |
} | |
} | |
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; | |
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}); | |
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'], | |
); | |
} | |
} | |
// 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; | |
int? 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, | |
); | |
} | |
} | |
class CashRecapEntity { | |
int id; | |
int timeCreated; | |
String employeeName; | |
int pendingBillTotal; | |
int cash; | |
int card; | |
CashRecapEntity({ | |
required this.id, | |
required this.timeCreated, | |
required this.employeeName, | |
required this.pendingBillTotal, | |
required this.cash, | |
required this.card, | |
}); | |
factory CashRecapEntity.fromJson(Map<String, dynamic> json) { | |
return CashRecapEntity( | |
id: json['id'] as int, | |
timeCreated: json['time_created'] as int, | |
employeeName: json['employee_name'] as String, | |
pendingBillTotal: json['pending_bill_total'] as int, | |
cash: json['cash'] as int, | |
card: json['card'] as int, | |
); | |
} | |
Map<String, dynamic> toJson() { | |
return { | |
'id': id, | |
'time_created': timeCreated, | |
'employee_name': employeeName, | |
'pending_bill_total': pendingBillTotal, | |
'cash': cash, | |
'card': card, | |
}; | |
} | |
} | |
class TmpSalesEntity { | |
int id; | |
String sales; // Assuming this is a JSON string representing sales data | |
TmpSalesEntity({ | |
required this.id, | |
required this.sales, | |
}); | |
factory TmpSalesEntity.fromJson(Map<String, dynamic> json) { | |
return TmpSalesEntity( | |
id: json['id'] as int, | |
sales: json['sales'] as String, | |
); | |
} | |
Map<String, dynamic> toJson() { | |
return { | |
'id': id, | |
'sales': sales, | |
}; | |
} | |
} | |
class OperationalCost { | |
int id; | |
String opcostName; | |
int total; | |
OperationalCost({ | |
required this.id, | |
required this.opcostName, | |
required this.total, | |
}); | |
factory OperationalCost.fromJson(Map<String, dynamic> json) { | |
return OperationalCost( | |
id: json['id'] as int, | |
opcostName: json['opcostName'] as String, | |
total: (json['total'] as num).toInt(), | |
); | |
} | |
Map<String, dynamic> toJson() { | |
return { | |
'id': id, | |
'opcostName': opcostName, | |
'total': total, | |
}; | |
} | |
} | |
class SubCategoryEntity { | |
int id; | |
String name; | |
int productCategoryId; | |
SubCategoryEntity({ | |
required this.id, | |
required this.name, | |
required this.productCategoryId, | |
}); | |
factory SubCategoryEntity.fromJson(Map<String, dynamic> json) { | |
return SubCategoryEntity( | |
id: json['id'] as int, | |
name: json['name'] as String, | |
productCategoryId: json['productCategoryId'] as int, | |
); | |
} | |
Map<String, dynamic> toJson() { | |
return { | |
'id': id, | |
'name': name, | |
'productCategoryId': productCategoryId, | |
}; | |
} | |
} | |
class OpenShiftEntity { | |
int id; | |
double earlyCash; | |
OpenShiftEntity({ | |
required this.id, | |
required this.earlyCash, | |
}); | |
factory OpenShiftEntity.fromJson(Map<String, dynamic> json) { | |
return OpenShiftEntity( | |
id: json['id'] as int, | |
earlyCash: json['earlyCash'] as double, | |
); | |
} | |
Map<String, dynamic> toJson() { | |
return { | |
'id': id, | |
'earlyCash': earlyCash, | |
}; | |
} | |
} | |
class RolePrinterClosing { | |
final bool sales; | |
final bool paymentmedia; | |
final bool groupsales; | |
final bool refund; | |
final bool time; | |
final bool tax; | |
final bool itemsales; | |
final bool avgpaxbill; | |
final bool fifo; | |
final bool actual; | |
final bool opcostdetail; | |
final bool entertainincome; | |
RolePrinterClosing({ | |
this.sales = false, | |
this.paymentmedia = false, | |
this.groupsales = false, | |
this.refund = false, | |
this.time = false, | |
this.tax = false, | |
this.itemsales = false, | |
this.avgpaxbill = false, | |
this.fifo = false, | |
this.actual = false, | |
this.opcostdetail = false, | |
this.entertainincome = false, | |
}); | |
factory RolePrinterClosing.fromJson(Map<String, dynamic> json) { | |
return RolePrinterClosing( | |
sales: json['sales'] ?? false, | |
paymentmedia: json['paymentmedia'] ?? false, | |
groupsales: json['groupsales'] ?? false, | |
refund: json['refund'] ?? false, | |
time: json['time'] ?? false, | |
tax: json['tax'] ?? false, | |
itemsales: json['itemsales'] ?? false, | |
avgpaxbill: json['avgpaxbill'] ?? false, | |
fifo: json['fifo'] ?? false, | |
actual: json['actual'] ?? false, | |
opcostdetail: json['opcostdetail'] ?? false, | |
entertainincome: json['entertainincome'] ?? false, | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment