Files
kulakpos_app/lib/thermal priting invoices/thermal_invoice_stock.dart

196 lines
7.9 KiB
Dart
Raw Permalink Normal View History

2026-02-07 15:57:09 +07:00
import 'package:esc_pos_utils_plus/esc_pos_utils_plus.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:image/image.dart' as img;
import 'package:intl/intl.dart';
import 'package:mobile_pos/Screens/Products/Model/product_model.dart';
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_total_stock_model.dart';
import '../constant.dart';
import '../model/business_info_model.dart';
import 'network_image.dart';
class StockThermalPrinterInvoice {
///________Sales____________________
Future<void> printStockTicket({
required BusinessInformationModel businessInformationModel,
required List<Product>? productList,
required ProductListResponse stock,
}) async {
bool? isConnected = await PrintBluetoothThermal.connectionStatus;
if (isConnected == true) {
String st = await PrintBluetoothThermal.platformVersion;
List<int> bytes = await getStockTicket(
businessInformationModel: businessInformationModel,
productList: productList,
is80mm: businessInformationModel.data?.invoiceSize == '3_inch_80mm',
stockValue: stock);
if (productList?.isNotEmpty ?? false) {
await PrintBluetoothThermal.writeBytes(bytes);
EasyLoading.showSuccess('Successfully Printed');
} else {
toast('No Product Found');
}
} else {
EasyLoading.showError('Unable to connect with printer');
}
}
Future<List<int>> getStockTicket(
{required BusinessInformationModel businessInformationModel,
required List<Product>? productList,
required bool is80mm,
ProductListResponse? stockValue}) async {
final _logo = await getNetworkImage("${APIConfig.domain}${businessInformationModel.data?.thermalInvoiceLogo}");
String formattedDate = DateFormat('dd/MM/yyyy').format(DateTime.now());
String formattedTime = DateFormat('hh:mm a').format(DateTime.now());
List<int> bytes = [];
CapabilityProfile profile = await CapabilityProfile.load();
final generator = Generator(is80mm ? PaperSize.mm80 : PaperSize.mm58, profile);
///____________Image__________________________________
if (_logo != null && businessInformationModel.data?.showThermalInvoiceLogo == 1) {
final img.Image resized = img.copyResize(
_logo,
width: 184,
);
final img.Image grayscale = img.grayscale(resized);
bytes += generator.imageRaster(grayscale, imageFn: PosImageFn.bitImageRaster);
}
if (businessInformationModel.data?.meta?.showCompanyName == 1) {
bytes += generator.text(
businessInformationModel.data?.companyName ?? '',
styles: const PosStyles(
align: PosAlign.center,
height: PosTextSize.size2,
width: PosTextSize.size2,
),
linesAfter: 1,
);
}
bytes += generator.text(
'Seller :${businessInformationModel.data?.user?.role == "shop-owner" ? 'Admin' : businessInformationModel.data?.user?.name}',
styles: const PosStyles(align: PosAlign.center));
if (businessInformationModel.data?.address != null) {
bytes +=
generator.text(businessInformationModel.data?.address ?? '', styles: const PosStyles(align: PosAlign.center));
}
if (businessInformationModel.data?.meta?.showPhoneNumber == 1) {
if (businessInformationModel.data?.phoneNumber != null) {
bytes += generator.text('Phone : ${businessInformationModel.data?.phoneNumber ?? ''}',
styles: const PosStyles(align: PosAlign.center));
}
}
if (businessInformationModel.data?.meta?.showVat == 1) {
if (businessInformationModel.data?.vatNo != null && businessInformationModel.data?.meta?.showVat == 1) {
bytes += generator.text(
"${businessInformationModel.data?.vatName ?? 'VAT No'}: ${businessInformationModel.data?.vatNo ?? ''}",
styles: const PosStyles(align: PosAlign.center),
linesAfter: 1);
}
}
bytes += generator.text('Stock List',
styles: const PosStyles(
align: PosAlign.center,
underline: true,
height: PosTextSize.size2,
width: PosTextSize.size2,
),
linesAfter: 1);
bytes += generator.text('Date : $formattedDate', styles: const PosStyles(align: PosAlign.left));
bytes += generator.text('Time : $formattedTime', styles: const PosStyles(align: PosAlign.left));
bytes += generator.hr();
bytes += generator.row([
PosColumn(text: 'SL', width: 1, styles: const PosStyles(align: PosAlign.left, bold: true)),
PosColumn(text: 'Item Name', width: is80mm ? 7 : 6, styles: const PosStyles(align: PosAlign.left, bold: true)),
PosColumn(text: 'Qty', width: 2, styles: const PosStyles(align: PosAlign.center, bold: true)),
PosColumn(text: 'Price', width: is80mm ? 2 : 3, styles: const PosStyles(align: PosAlign.right, bold: true)),
]);
bytes += generator.hr();
List.generate(productList?.length ?? 1, (index) {
final stokePrice = productList![index].stocks != null && productList[index].stocks!.isNotEmpty
? productList[index].stocks!.last.productPurchasePrice
: 0;
return bytes += generator.row([
PosColumn(
text: '${index + 1}',
width: 1,
styles: const PosStyles(
align: PosAlign.left,
)),
PosColumn(
text: '${productList[index].productName}',
width: is80mm ? 7 : 6,
styles: const PosStyles(
align: PosAlign.left,
)),
PosColumn(
text: '${productList[index].stocksSumProductStock}',
width: 2,
styles: const PosStyles(align: PosAlign.center)),
PosColumn(
text: (formatPointNumber(stokePrice ?? 0, addComma: true)),
width: is80mm ? 2 : 3,
styles: const PosStyles(align: PosAlign.right)),
]);
});
bytes += generator.hr();
bytes += generator.row([
PosColumn(
text: 'Total Stock value :',
width: 9,
styles: const PosStyles(
align: PosAlign.right,
)),
PosColumn(
text: formatPointNumber(stockValue!.totalStockValue),
width: 3,
styles: const PosStyles(
align: PosAlign.right,
)),
]);
bytes += generator.text('');
// bytes += generator.text('Developed By: $companyName', styles: const PosStyles(align: PosAlign.center), linesAfter: 1);
if (businessInformationModel.data?.gratitudeMessage != null &&
businessInformationModel.data?.showGratitudeMsg == 1) {
bytes += generator.text(
businessInformationModel.data?.gratitudeMessage ?? '',
styles: const PosStyles(align: PosAlign.center, bold: true),
linesAfter: 1,
);
}
if ((businessInformationModel.data?.invoiceNoteLevel != null ||
businessInformationModel.data?.invoiceNote != null) &&
businessInformationModel.data?.showNote == 1) {
bytes += generator.text(
'${businessInformationModel.data?.invoiceNoteLevel ?? ''}: ${businessInformationModel.data?.invoiceNote ?? ''}',
styles: const PosStyles(align: PosAlign.left, bold: false),
linesAfter: 1,
);
}
if (businessInformationModel.data?.developByLink != null) {
bytes += generator.qrcode(
businessInformationModel.data?.developByLink ?? '',
);
bytes += generator.emptyLines(1);
}
if (businessInformationModel.data?.developByLevel != null || businessInformationModel.data?.developBy != null) {
bytes += generator.text(
'${businessInformationModel.data?.developByLevel ?? ''}: ${businessInformationModel.data?.developBy ?? ''}',
styles: const PosStyles(align: PosAlign.center),
linesAfter: 1);
}
bytes += generator.cut();
return bytes;
}
}