|
|
|
|
@@ -10,6 +10,7 @@ import 'package:nb_utils/nb_utils.dart';
|
|
|
|
|
import 'package:print_bluetooth_thermal/print_bluetooth_thermal.dart';
|
|
|
|
|
|
|
|
|
|
import '../Const/api_config.dart';
|
|
|
|
|
import '../Screens/Products/Model/product_model.dart';
|
|
|
|
|
import '../Screens/Products/add product/modle/create_product_model.dart';
|
|
|
|
|
import '../constant.dart';
|
|
|
|
|
import '../model/sale_transaction_model.dart';
|
|
|
|
|
@@ -23,6 +24,7 @@ class SalesThermalPrinterInvoice {
|
|
|
|
|
Future<void> printSalesTicket(
|
|
|
|
|
{required PrintSalesTransactionModel printTransactionModel,
|
|
|
|
|
required List<SalesDetails>? productList,
|
|
|
|
|
List<Product>? products,
|
|
|
|
|
required BuildContext context}) async {
|
|
|
|
|
bool? isConnected = await PrintBluetoothThermal.connectionStatus;
|
|
|
|
|
bool defould = (printTransactionModel.personalInformationModel.data?.invoiceLanguage == 'english' ||
|
|
|
|
|
@@ -36,8 +38,10 @@ class SalesThermalPrinterInvoice {
|
|
|
|
|
|
|
|
|
|
if (defould) {
|
|
|
|
|
bytes = is80mm
|
|
|
|
|
? await getSalesTicket80mm(printTransactionModel: printTransactionModel, productList: productList)
|
|
|
|
|
: await getSalesTicket58mm(printTransactionModel: printTransactionModel, productList: productList);
|
|
|
|
|
? await getSalesTicket80mm(
|
|
|
|
|
printTransactionModel: printTransactionModel, productList: productList, products: products)
|
|
|
|
|
: await getSalesTicket58mm(
|
|
|
|
|
printTransactionModel: printTransactionModel, productList: productList, products: products);
|
|
|
|
|
} else {
|
|
|
|
|
final bool isRTL = rtlLang.contains(await getLanguageName());
|
|
|
|
|
|
|
|
|
|
@@ -62,7 +66,9 @@ class SalesThermalPrinterInvoice {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<List<int>> getSalesTicket58mm(
|
|
|
|
|
{required PrintSalesTransactionModel printTransactionModel, required List<SalesDetails>? productList}) async {
|
|
|
|
|
{required PrintSalesTransactionModel printTransactionModel,
|
|
|
|
|
required List<SalesDetails>? productList,
|
|
|
|
|
List<Product>? products}) async {
|
|
|
|
|
List<DateTime> returnedDates = [];
|
|
|
|
|
String productName({required num detailsId}) {
|
|
|
|
|
final details = productList?[productList.indexWhere((element) => element.id == detailsId)];
|
|
|
|
|
@@ -258,11 +264,11 @@ class SalesThermalPrinterInvoice {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bytes += generator.row([
|
|
|
|
|
PosColumn(text: 'SL', width: 1, styles: const PosStyles(align: PosAlign.left, bold: true)),
|
|
|
|
|
PosColumn(text: 'Product', width: 4, styles: const PosStyles(align: PosAlign.left, bold: true)),
|
|
|
|
|
PosColumn(text: 'Qty', width: 1, styles: const PosStyles(align: PosAlign.center, bold: true)),
|
|
|
|
|
PosColumn(text: 'VAT/Tax', width: 2, styles: const PosStyles(align: PosAlign.center, bold: true)),
|
|
|
|
|
PosColumn(text: 'Amount', width: 4, styles: const PosStyles(align: PosAlign.right, bold: true)),
|
|
|
|
|
PosColumn(text: 'Item', width: 4, styles: const PosStyles(align: PosAlign.left, bold: true)),
|
|
|
|
|
PosColumn(text: 'Qt', width: 1, styles: const PosStyles(align: PosAlign.center, bold: true)),
|
|
|
|
|
PosColumn(text: 'Price', width: 3, styles: const PosStyles(align: PosAlign.center, bold: true)),
|
|
|
|
|
PosColumn(text: '%', width: 1, styles: const PosStyles(align: PosAlign.center, bold: true)),
|
|
|
|
|
PosColumn(text: 'Amount', width: 3, styles: const PosStyles(align: PosAlign.right, bold: true)),
|
|
|
|
|
]);
|
|
|
|
|
bytes += generator.hr();
|
|
|
|
|
List.generate(productList?.length ?? 1, (index) {
|
|
|
|
|
@@ -279,14 +285,16 @@ class SalesThermalPrinterInvoice {
|
|
|
|
|
final name = "${productList?[index].product?.productName ?? ''}"
|
|
|
|
|
"${productList?[index].product?.productType == ProductType.variant.name ? ' [${productList?[index].stock?.batchNo ?? ''}]' : ''}";
|
|
|
|
|
|
|
|
|
|
final double qty = getProductQuantity(detailsId: productList?[index].id ?? 0).toDouble();
|
|
|
|
|
final double price = num.tryParse(productList?[index].price.toString() ?? '0')?.toDouble() ?? 0;
|
|
|
|
|
final double discount = num.tryParse(productList?[index].discount.toString() ?? '0')?.toDouble() ?? 0;
|
|
|
|
|
final product = products?.firstWhere((element) => element.id == productList?[index].productId,
|
|
|
|
|
orElse: () => Product());
|
|
|
|
|
final double vatPercent = num.tryParse(product?.vat?.rate.toString() ?? '0')?.toDouble() ?? 0;
|
|
|
|
|
final double amountExVat = (price * qty) - (discount * qty);
|
|
|
|
|
final double vatAmount = (amountExVat * vatPercent) / 100;
|
|
|
|
|
|
|
|
|
|
bytes += generator.row([
|
|
|
|
|
PosColumn(
|
|
|
|
|
text: '${index + 1}',
|
|
|
|
|
width: 1,
|
|
|
|
|
styles: const PosStyles(
|
|
|
|
|
align: PosAlign.left,
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
PosColumn(
|
|
|
|
|
text: name,
|
|
|
|
|
width: 4,
|
|
|
|
|
@@ -295,19 +303,23 @@ class SalesThermalPrinterInvoice {
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
PosColumn(
|
|
|
|
|
text: formatPointNumber(getProductQuantity(detailsId: productList?[index].id ?? 0)),
|
|
|
|
|
text: formatPointNumber(qty),
|
|
|
|
|
width: 1,
|
|
|
|
|
styles: const PosStyles(align: PosAlign.center),
|
|
|
|
|
),
|
|
|
|
|
PosColumn(
|
|
|
|
|
text: formatPointNumber(0),
|
|
|
|
|
width: 2,
|
|
|
|
|
text: formatPointNumber(price),
|
|
|
|
|
width: 3,
|
|
|
|
|
styles: const PosStyles(align: PosAlign.center),
|
|
|
|
|
),
|
|
|
|
|
PosColumn(
|
|
|
|
|
text:
|
|
|
|
|
"${((productList?[index].price ?? 0) * getProductQuantity(detailsId: productList?[index].id ?? 0)) - ((productList?[index].discount ?? 0) * getProductQuantity(detailsId: productList?[index].id ?? 0))}",
|
|
|
|
|
width: 4,
|
|
|
|
|
text: "${vatPercent % 1 == 0 ? vatPercent.toInt() : vatPercent}",
|
|
|
|
|
width: 1,
|
|
|
|
|
styles: const PosStyles(align: PosAlign.center),
|
|
|
|
|
),
|
|
|
|
|
PosColumn(
|
|
|
|
|
text: formatPointNumber(amountExVat),
|
|
|
|
|
width: 3,
|
|
|
|
|
styles: const PosStyles(align: PosAlign.right),
|
|
|
|
|
),
|
|
|
|
|
]);
|
|
|
|
|
@@ -602,7 +614,9 @@ class SalesThermalPrinterInvoice {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<List<int>> getSalesTicket80mm(
|
|
|
|
|
{required PrintSalesTransactionModel printTransactionModel, required List<SalesDetails>? productList}) async {
|
|
|
|
|
{required PrintSalesTransactionModel printTransactionModel,
|
|
|
|
|
required List<SalesDetails>? productList,
|
|
|
|
|
List<Product>? products}) async {
|
|
|
|
|
List<DateTime> returnedDates = [];
|
|
|
|
|
String productName({required num detailsId}) {
|
|
|
|
|
final details = productList?[productList.indexWhere((element) => element.id == detailsId)];
|
|
|
|
|
@@ -816,13 +830,12 @@ class SalesThermalPrinterInvoice {
|
|
|
|
|
bytes += generator.emptyLines(1);
|
|
|
|
|
|
|
|
|
|
///____________Products_Section_________________________________
|
|
|
|
|
bytes += generator.hr();
|
|
|
|
|
bytes += generator.row([
|
|
|
|
|
PosColumn(text: 'SL', width: 1, styles: const PosStyles(align: PosAlign.left, bold: true)),
|
|
|
|
|
PosColumn(text: 'Product', width: 5, styles: const PosStyles(align: PosAlign.left, bold: true)),
|
|
|
|
|
PosColumn(text: 'QTY', width: 1, styles: const PosStyles(align: PosAlign.center, bold: true)),
|
|
|
|
|
PosColumn(text: 'VAT/Tax', width: 2, styles: const PosStyles(align: PosAlign.center, bold: true)),
|
|
|
|
|
PosColumn(text: 'Amount', width: 3, styles: const PosStyles(align: PosAlign.right, bold: true)),
|
|
|
|
|
PosColumn(text: 'Item', width: 1, styles: const PosStyles(align: PosAlign.left, bold: true)),
|
|
|
|
|
PosColumn(text: 'Qt', width: 1, styles: const PosStyles(align: PosAlign.center, bold: true)),
|
|
|
|
|
PosColumn(text: 'Price', width: 2, styles: const PosStyles(align: PosAlign.center, bold: true)),
|
|
|
|
|
PosColumn(text: '%', width: 2, styles: const PosStyles(align: PosAlign.center, bold: true)),
|
|
|
|
|
PosColumn(text: 'Amount(Ex Vat)', width: 3, styles: const PosStyles(align: PosAlign.right, bold: true)),
|
|
|
|
|
]);
|
|
|
|
|
bytes += generator.hr();
|
|
|
|
|
List.generate(productList?.length ?? 1, (index) {
|
|
|
|
|
@@ -838,34 +851,42 @@ class SalesThermalPrinterInvoice {
|
|
|
|
|
|
|
|
|
|
final name = "${productList?[index].product?.productName ?? ''}"
|
|
|
|
|
"${productList?[index].product?.productType == ProductType.variant.name ? ' [${productList?[index].stock?.batchNo ?? ''}]' : ''}";
|
|
|
|
|
|
|
|
|
|
final double qty = getProductQuantity(detailsId: productList?[index].id ?? 0).toDouble();
|
|
|
|
|
final double price = num.tryParse(productList?[index].price.toString() ?? '0')?.toDouble() ?? 0;
|
|
|
|
|
final double discount = num.tryParse(productList?[index].discount.toString() ?? '0')?.toDouble() ?? 0;
|
|
|
|
|
final product = products?.firstWhere((element) => element.id == productList?[index].productId,
|
|
|
|
|
orElse: () => Product());
|
|
|
|
|
final double vatPercent = num.tryParse(product?.vat?.rate.toString() ?? '0')?.toDouble() ?? 0;
|
|
|
|
|
final double amountExVat = (price * qty) - (discount * qty);
|
|
|
|
|
final double vatAmount = (amountExVat * vatPercent) / 100;
|
|
|
|
|
|
|
|
|
|
bytes += generator.row([
|
|
|
|
|
PosColumn(
|
|
|
|
|
text: '${index + 1}',
|
|
|
|
|
width: 1,
|
|
|
|
|
styles: const PosStyles(
|
|
|
|
|
align: PosAlign.left,
|
|
|
|
|
)),
|
|
|
|
|
PosColumn(
|
|
|
|
|
text:
|
|
|
|
|
"${productList?[index].product?.productName ?? ''}${productList?[index].product?.productType == ProductType.variant.name ? ' [${productList?[index].stock?.batchNo ?? ''}]' : ''}",
|
|
|
|
|
width: 5,
|
|
|
|
|
width: 1,
|
|
|
|
|
styles: const PosStyles(
|
|
|
|
|
align: PosAlign.left,
|
|
|
|
|
)),
|
|
|
|
|
PosColumn(
|
|
|
|
|
text: formatPointNumber(getProductQuantity(detailsId: productList?[index].id ?? 0), addComma: true),
|
|
|
|
|
text: formatPointNumber(qty, addComma: true),
|
|
|
|
|
width: 1,
|
|
|
|
|
styles: const PosStyles(align: PosAlign.center)),
|
|
|
|
|
PosColumn(
|
|
|
|
|
text: formatPointNumber(0, addComma: true),
|
|
|
|
|
text: formatPointNumber(price, addComma: true),
|
|
|
|
|
width: 2,
|
|
|
|
|
styles: const PosStyles(
|
|
|
|
|
align: PosAlign.center,
|
|
|
|
|
)),
|
|
|
|
|
PosColumn(
|
|
|
|
|
text: formatPointNumber(
|
|
|
|
|
(productList?[index].price ?? 0) * getProductQuantity(detailsId: productList?[index].id ?? 0),
|
|
|
|
|
addComma: true),
|
|
|
|
|
text: "${vatPercent % 1 == 0 ? vatPercent.toInt() : vatPercent}",
|
|
|
|
|
width: 2,
|
|
|
|
|
styles: const PosStyles(
|
|
|
|
|
align: PosAlign.center,
|
|
|
|
|
)),
|
|
|
|
|
PosColumn(
|
|
|
|
|
text: formatPointNumber(amountExVat, addComma: true),
|
|
|
|
|
width: 3,
|
|
|
|
|
styles: const PosStyles(align: PosAlign.right)),
|
|
|
|
|
]);
|
|
|
|
|
|