update struk

This commit is contained in:
2026-02-09 23:56:18 +07:00
parent d144d24596
commit 34ee0c3c01
4 changed files with 85 additions and 42 deletions

View File

@@ -129,10 +129,15 @@ class ThermalPrinter extends ChangeNotifier {
);
}
Future<void> printSalesThermalInvoiceNow({required PrintSalesTransactionModel transaction, required List<SalesDetails>? productList, required BuildContext context}) async {
Future<void> printSalesThermalInvoiceNow(
{required PrintSalesTransactionModel transaction,
required List<SalesDetails>? productList,
required BuildContext context,
List<Product>? products}) async {
await getBluetooth();
isBluetoothConnected
? SalesThermalPrinterInvoice().printSalesTicket(printTransactionModel: transaction, productList: productList, context: context)
? SalesThermalPrinterInvoice().printSalesTicket(
printTransactionModel: transaction, productList: productList, context: context, products: products)
: listOfBluDialog(context: context);
}

View File

@@ -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)),
]);