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 printStockTicket({ required BusinessInformationModel businessInformationModel, required List? productList, required ProductListResponse stock, }) async { bool? isConnected = await PrintBluetoothThermal.connectionStatus; if (isConnected == true) { String st = await PrintBluetoothThermal.platformVersion; List 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> getStockTicket( {required BusinessInformationModel businessInformationModel, required List? 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 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; } }