first commit

This commit is contained in:
2026-02-07 15:57:09 +07:00
commit 157096f164
1153 changed files with 415766 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
import 'dart:io';
import 'package:excel/excel.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:mobile_pos/Screens/Products/Model/product_model.dart';
import 'package:mobile_pos/Screens/Products/Model/product_total_stock_model.dart';
import 'package:mobile_pos/model/business_info_model.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
Future<void> generateStockReportExcel(
BuildContext context,
List<Product>? data,
BusinessInformationModel? business,
ProductListResponse? totalStock,
) async {
EasyLoading.show(status: 'Generating Excel');
try {
final excel = Excel.createExcel();
final sheet = excel['Stock Report'];
sheet.appendRow([TextCellValue(business?.data?.companyName ?? '')]);
sheet.cell(CellIndex.indexByString("A1")).cellStyle;
// Row 2: Report Title
sheet.appendRow([TextCellValue('Stock Report')]);
sheet.cell(CellIndex.indexByString("A2")).cellStyle;
sheet.appendRow([]);
// Row 5: Header
final headerRowIndex = sheet.maxRows;
sheet.appendRow([
TextCellValue('SL'),
TextCellValue('Product Name'),
TextCellValue('Quantity'),
TextCellValue('Cost'),
]);
sheet.appendRow([]);
// Apply bold style to each header cell only
for (var i = 0; i < 5; i++) {
sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: headerRowIndex)).cellStyle;
}
if (data != null) {
for (int i = 0; i < data.length; i++) {
final stockValue = data[i].stocks != null && data[i].stocks!.isNotEmpty ? data[i].stocks?.last.productPurchasePrice : 0;
sheet.appendRow([
TextCellValue('${i + 1}'),
TextCellValue(data[i].productName ?? 'n/a'),
TextCellValue(data[i].stocksSumProductStock.toString()),
TextCellValue(stockValue.toString()),
]);
}
}
final totalRowIndex = sheet.maxRows;
sheet.appendRow([
TextCellValue('Total'),
TextCellValue(''),
TextCellValue(''),
TextCellValue(totalStock!.totalStockValue.toStringAsFixed(2)),
]);
for (var i = 0; i < 5; i++) {
sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: totalRowIndex)).cellStyle;
}
final dir = await getApplicationDocumentsDirectory();
final filePath = '${dir.path}/${business?.data?.companyName ?? "Company"}_stock_report.xlsx';
final file = File(filePath);
await file.writeAsBytes(excel.encode()!);
EasyLoading.showSuccess('Report Generated');
await OpenFile.open(filePath);
} catch (e) {
EasyLoading.showError('Error: $e');
debugPrint('Error during Excel generation: $e');
}
}

View File

@@ -0,0 +1,195 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:mobile_pos/Screens/Products/Model/product_model.dart';
import 'package:mobile_pos/constant.dart';
import 'package:path_provider/path_provider.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:printing/printing.dart';
import '../../Screens/PDF/pdf.dart';
import '../../Screens/Products/Model/product_total_stock_model.dart';
import '../../model/business_info_model.dart';
Future<void> generateStockReportPdf(BuildContext context, List<Product>? data, BusinessInformationModel? business, ProductListResponse? stockValue, bool? isLowStock) async {
if (data == null || business == null) {
EasyLoading.showError('Invalid data for report generation');
return;
}
final pw.Document pdf = pw.Document();
try {
EasyLoading.show(status: 'Generating PDF...');
double totalStockValue = 0;
// for (var item in data) {
// if (item.stocks != null && item.stocks!.isNotEmpty && item.totalStockValue != null) {
// totalStockValue += item.totalStockValue! * item.stocks!.last.productPurchasePrice!.toDouble();
// }
// }
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business.data?.companyName.toString() ?? '',
style: pw.TextStyle(
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
'Stock Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
),
),
pw.SizedBox(height: 4),
],
),
);
},
footer: (pw.Context context) {
return pw.Row(
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
children: [
pw.Text('${business.data?.developByLevel ?? ''} ${business.data?.developBy ?? ''}'),
pw.Text('Page-${context.pageNumber}'),
],
);
},
build: (pw.Context context) {
final List<List<String>> tableData = [];
for (int i = 0; i < data.length; i++) {
final stockPrice = (data[i].stocks != null && data[i].stocks!.isNotEmpty) ? data[i].stocks!.last.productPurchasePrice?.toString() ?? '0' : '0';
tableData.add([
'${i + 1}',
data[i].productName ?? 'n/a',
data[i].stocksSumProductStock?.toString() ?? '0',
stockPrice,
]);
}
return [
pw.SizedBox(height: 16),
pw.Table.fromTextArray(
headers: ['SL', 'Product Name', 'Quantity', 'Cost'],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
border: pw.TableBorder.all(color: PdfColor.fromInt(0xffD9D9D9)),
headerStyle: pw.TextStyle(
fontWeight: pw.FontWeight.bold,
color: PdfColors.white,
),
rowDecoration: const pw.BoxDecoration(
color: PdfColors.white,
),
oddRowDecoration: pw.BoxDecoration(
color: PdfColor.fromInt(0xffF7F7F7),
),
cellPadding: const pw.EdgeInsets.all(8),
columnWidths: {
0: const pw.FlexColumnWidth(1),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
},
),
pw.Table.fromTextArray(
border: const pw.TableBorder(
left: pw.BorderSide(color: PdfColor.fromInt(0xffD9D9D9)),
right: pw.BorderSide(color: PdfColor.fromInt(0xffD9D9D9)),
bottom: pw.BorderSide(color: PdfColor.fromInt(0xffD9D9D9)),
),
columnWidths: {
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(2),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
},
data: [
[
'Total',
'',
'',
isLowStock == true ? totalStockValue.toStringAsFixed(2) : stockValue?.totalStockValue?.toStringAsFixed(2) ?? '0.00',
]
],
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
headerStyle: pw.TextStyle(
fontWeight: pw.FontWeight.bold,
color: PdfColors.white,
),
cellAlignment: pw.Alignment.center,
cellPadding: const pw.EdgeInsets.all(8),
),
];
},
),
);
// Save the PDF
final bytes = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final timestamp = DateTime.now().millisecondsSinceEpoch;
final file = File('${dir.path}/$appsName-stock-report-$timestamp.pdf');
await file.writeAsBytes(bytes);
// Dismiss loading before navigation
await EasyLoading.dismiss();
//------print pdf------------------
if (context.mounted) {
await Printing.layoutPdf(
name: 'Stock Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// if (context.mounted) {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
// }
} catch (e) {
await EasyLoading.dismiss();
if (context.mounted) {
EasyLoading.showError('Failed to generate PDF: ${e.toString()}');
}
debugPrint('Error during PDF generation: $e');
}
}