196 lines
7.9 KiB
Dart
196 lines
7.9 KiB
Dart
|
|
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;
|
||
|
|
}
|
||
|
|
}
|