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,198 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.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/Income/Model/income_modle.dart';
import '../../Screens/PDF/pdf.dart';
import '../../model/business_info_model.dart';
import '../ledger_report/generate_pdf_date_range.dart';
Future<void> generateComboReportPdf(
BuildContext context,
List<Product>? data,
BusinessInformationModel? business,
) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
double totalAmount = 0;
// Calculate totals from data
if (data != null) {
for (var item in data) {
totalAmount += item.productSalePrice ?? 0;
}
}
// print('--font family---$ttf---------------');
try {
pdf.addPage(pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Combo Product Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
],
),
);
},
//-----------------pdf footer-------------
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++) {
tableData.add([
'${i + 1}',
data[i].productName ?? '',
data[i].productCode ?? '',
data[i].comboProducts?.length.toString() ?? '',
data[i].unit?.unitName ?? '',
data[i].productSalePrice.toString() ?? '',
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
'SL',
'Product Name',
'Code',
'Product',
'Unit',
'Price',
],
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(1),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(2),
3: const pw.FlexColumnWidth(2),
4: const pw.FlexColumnWidth(2),
5: const pw.FlexColumnWidth(2),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(2),
3: const pw.FlexColumnWidth(2),
4: const pw.FlexColumnWidth(2),
5: const pw.FlexColumnWidth(2),
},
data: [
[
'Total',
'',
'',
'',
'',
totalAmount.toStringAsFixed(2),
]
],
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),
),
];
}));
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/${appsName}-combo.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Combo Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,135 @@
import 'dart:io';
import 'package:excel/excel.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/Screens/Due%20Calculation/Model/due_collection_model.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import '../../model/business_info_model.dart';
import '../../model/sale_transaction_model.dart';
import 'due_status.dart';
Future<void> generateDueReportExcel(
BuildContext context,
List<DueCollection>? data,
BusinessInformationModel? business,
DateTime? fromDate,
DateTime? toDate,
) async {
EasyLoading.show(status: 'Generating Excel');
try {
final excel = Excel.createExcel();
final sheet = excel['Sales Report'];
// ---- DATE RANGE ----
String fromStr = fromDate != null ? DateFormat('dd-MM-yyyy').format(fromDate) : '';
String toStr = toDate != null ? DateFormat('dd-MM-yyyy').format(toDate!) : '';
// ---- TOTAL CALCULATION ----
double total = 0;
double totalPaid = 0;
double totalDue = 0;
if (data != null) {
for (var item in data) {
total += item.totalDue ?? 0;
totalPaid += item.payDueAmount ?? 0;
totalDue += item.dueAmountAfterPay ?? 0;
}
}
// ----------------------------- //
// HEADER ROWS //
// ----------------------------- //
// Row 1: Company Name
sheet.appendRow([TextCellValue(business?.data?.companyName ?? '')]);
// Row 2: Report Title
sheet.appendRow([TextCellValue('Due Report')]);
// Row 3: Duration
sheet.appendRow([
TextCellValue('Duration: $fromStr to $toStr'),
]);
// Row 4: Empty Space
sheet.appendRow([]);
// Row 5: Table Headers
final headerStartRow = sheet.maxRows;
sheet.appendRow([
TextCellValue('Reference'),
TextCellValue('Date'),
TextCellValue('Name'),
TextCellValue('Status'),
TextCellValue('Total'),
TextCellValue('Paid'),
TextCellValue('Due'),
]);
// Apply bold header style
for (int i = 0; i < 7; i++) {
sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: headerStartRow)).cellStyle;
}
// Row 6: Space before data
sheet.appendRow([]);
// ----------------------------- //
// TABLE DATA ROWS //
// ----------------------------- //
if (data != null) {
for (var item in data) {
final status = getDueStatus(item);
sheet.appendRow([
TextCellValue(item.invoiceNumber ?? 'n/a'),
TextCellValue(DateFormat('dd-MM-yyyy').format(DateTime.parse(item.paymentDate.toString()))),
TextCellValue(item.party?.name ?? 'n/a'),
TextCellValue(status),
TextCellValue((item.totalDue ?? 0).toStringAsFixed(2)),
TextCellValue((item.payDueAmount ?? 0).toStringAsFixed(2)),
TextCellValue((item.dueAmountAfterPay ?? 0).toStringAsFixed(2)),
]);
}
}
// ----------------------------- //
// TOTAL ROW //
// ----------------------------- //
final totalRowIndex = sheet.maxRows;
sheet.appendRow([
TextCellValue('Total'),
TextCellValue(''),
TextCellValue(''),
TextCellValue(''),
TextCellValue(total.toStringAsFixed(2)),
TextCellValue(totalPaid.toStringAsFixed(2)),
TextCellValue(totalDue.toStringAsFixed(2)),
]);
// Apply bold style
for (int i = 0; i < 7; i++) {
sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: totalRowIndex)).cellStyle;
}
// ----------------------------- //
// SAVE FILE //
// ----------------------------- //
final dir = await getApplicationDocumentsDirectory();
final filePath = '${dir.path}/${business?.data?.companyName ?? "Company"}_Due_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('Excel Generation Error: $e');
}
}

View File

@@ -0,0 +1,241 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/Screens/Due%20Calculation/Model/due_collection_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 '../../model/business_info_model.dart';
import 'due_status.dart';
Future<void> generateDueReportPdf(BuildContext context, List<DueCollection>? data, BusinessInformationModel? business, DateTime? fromDate, DateTime? toDate) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
double total = 0;
double totalDue = 0;
double totalPaid = 0;
// Calculate totals from data
if (data != null) {
for (var item in data) {
final totalAmounts = item.totalDue ?? 0;
total += totalAmounts;
}
}
//total due
if (data != null) {
for (var item in data) {
final due = item.dueAmountAfterPay ?? 0;
totalDue += due;
}
}
//total paid
if (data != null) {
for (var item in data) {
final paid = item.payDueAmount ?? 0;
totalPaid += paid;
}
}
try {
pdf.addPage(pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Due Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null ? 'Duration: ${DateFormat('dd-MM-yyyy').format(fromDate)} to ${DateFormat('dd-MM-yyyy').format(toDate!)}' : '',
style: pw.TextStyle(
font: interFont,
fontSize: 12,
),
),
],
),
);
},
//-----------------pdf footer-------------
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 status = getDueStatus(data[i]);
tableData.add([
// '${i + 1}',
data[i].invoiceNumber ?? 'n/a',
DateFormat('dd-MM-yyyy').format(DateTime.parse(data[i].paymentDate.toString())),
data[i].party!.name ?? 'n/a',
// data[i]. ?? 'n/a',
status,
data[i].totalDue.toString(),
data[i].payDueAmount.toString(),
data[i].dueAmountAfterPay.toString(),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
// 'SL',
'Reference',
'Date',
'Name',
'Status',
'Total',
'Paid',
'Due',
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
data: [
[
'Total',
'',
'',
'',
formatPointNumber(total),
formatPointNumber(totalPaid),
formatPointNumber(totalDue),
]
],
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),
),
];
}));
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/${appsName}-due-report.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Due Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,15 @@
import '../../Screens/Due Calculation/Model/due_collection_model.dart';
String getDueStatus(DueCollection item) {
final totalDue = item.totalDue ?? 0;
final paid = item.payDueAmount ?? 0;
final dueAfterPay = item.dueAmountAfterPay ?? totalDue;
if (dueAfterPay == 0) {
return "Paid";
} else if (paid > 0 && dueAfterPay > 0) {
return "Partial Paid";
} else {
return "Unpaid";
}
}

View File

@@ -0,0 +1,113 @@
import 'dart:io';
import 'package:excel/excel.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/Screens/Expense/Model/expense_modle.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import '../../model/business_info_model.dart';
import '../ledger_report/generate_pdf_date_range.dart';
Future<void> generateExpenseReportExcel(
BuildContext context,
List<Expense>? data,
BusinessInformationModel? business,
DateTime? fromDate,
DateTime? toDate,
String selectedTime,
) async {
EasyLoading.show(status: 'Generating Excel');
try {
final excel = Excel.createExcel();
final sheet = excel['Expense Report'];
final pdfRange = getPdfDateRangeForSelectedTime(
selectedTime,
fromDate: fromDate,
toDate: toDate,
);
final fromStr = pdfRange['from']!;
final toStr = pdfRange['to']!;
double totalAmount = data?.fold(0, (sum, item) => sum! + (item.amount ?? 0)) ?? 0;
// // Styles
// final businessStyle = CellStyle(bold: true, fontSize: 12);
// final titleStyle = CellStyle(bold: true, fontSize: 12);
// final headerStyle = CellStyle(bold: true, fontSize: 12);
// final footerStyle = CellStyle(bold: true, fontSize: 12);
// Row 1: Company Name
sheet.appendRow([TextCellValue(business?.data?.companyName ?? '')]);
sheet.cell(CellIndex.indexByString("A1")).cellStyle;
// Row 2: Report Title
sheet.appendRow([TextCellValue('Expense Report')]);
sheet.cell(CellIndex.indexByString("A2")).cellStyle;
// Row 3: Duration
sheet.appendRow([
TextCellValue('Duration: $fromStr to $toStr'),
]);
// Row 4: Empty for spacing
sheet.appendRow([]);
// Row 5: Header
final headerRowIndex = sheet.maxRows;
sheet.appendRow([
TextCellValue('SL'),
TextCellValue('Date'),
TextCellValue('Expense For'),
TextCellValue('Category'),
TextCellValue('Amount'),
]);
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++) {
sheet.appendRow([
TextCellValue('${i + 1}'),
TextCellValue(DateFormat('dd-MM-yyyy').format(DateTime.parse(data[i].expenseDate.toString()))),
TextCellValue(data[i].expanseFor ?? 'n/a'),
TextCellValue(data[i].category?.categoryName ?? 'n/a'),
TextCellValue(data[i].amount?.toStringAsFixed(2) ?? '0.00'),
]);
}
}
final totalRowIndex = sheet.maxRows;
sheet.appendRow([
TextCellValue('Total'),
TextCellValue(''),
TextCellValue(''),
TextCellValue(''),
TextCellValue(totalAmount.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"}_Expense_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,210 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/Screens/Expense/Model/expense_modle.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 '../../model/business_info_model.dart';
import '../ledger_report/generate_pdf_date_range.dart';
Future<void> generateExpenseReportPdf(
BuildContext context, List<Expense>? data, BusinessInformationModel? business, DateTime? fromDate, DateTime? toDate, String selectedTime) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
double totalAmount = 0;
// Calculate totals from data
if (data != null) {
for (var item in data) {
totalAmount += item.amount ?? 0;
}
}
// Calculate correct PDF date range
final pdfDateRange = getPdfDateRangeForSelectedTime(
selectedTime,
fromDate: fromDate,
toDate: toDate,
);
final fromDateStr = pdfDateRange['from']!;
final toDateStr = pdfDateRange['to']!;
try {
pdf.addPage(pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Expense Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
'$fromDateStr TO $toDateStr',
style: pw.TextStyle(
font: interFont,
fontSize: 12,
),
),
],
),
);
},
//-----------------pdf footer-------------
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++) {
tableData.add([
'${i + 1}',
DateFormat('dd-MM-yyyy').format(DateTime.parse(data[i].expenseDate.toString())),
data[i].expanseFor ?? 'n/a',
data[i].category?.categoryName.toString() ?? 'n/a',
data[i].amount.toString(),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
'SL',
'Date',
'Income For',
'Category',
'Amount',
],
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(1),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(4),
4: const pw.FlexColumnWidth(2),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(2),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(4),
4: const pw.FlexColumnWidth(2),
},
data: [
[
'Total',
'',
'',
'',
totalAmount.toStringAsFixed(2),
]
],
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),
),
];
}));
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-expesne-report.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Expense Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,230 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/Screens/Products/Model/product_model.dart';
import 'package:mobile_pos/constant.dart';
import 'package:mobile_pos/model/business_info_model.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';
Future<void> generateExpireReportPdf(BuildContext context, List<Product>? data, BusinessInformationModel? business,
DateTime? fromDate, DateTime? toDate) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
double totalPurchase = 0;
double totalSalePrice = 0;
// Calculate totals from data
if (data != null) {
for (var item in data) {
totalPurchase += item.stocks?.first.productPurchasePrice ?? 0;
}
}
if (data != null) {
for (var item in data) {
totalSalePrice += item.stocks?.first.productSalePrice ?? 0;
}
}
// print('--font family---$ttf---------------');
try {
pdf.addPage(pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Expired List',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null
? 'Duration: ${DateFormat('dd-MM-yyyy').format(fromDate)} to ${DateFormat('dd-MM-yyyy').format(toDate!)}'
: '',
style: pw.TextStyle(
font: interFont,
fontSize: 12,
),
),
],
),
);
},
//-----------------pdf footer-------------
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++) {
tableData.add([
'${i + 1}',
data[i].productName ?? 'n/a',
data[i].productCode ?? 'n/a',
data[i].stocks!.first.productStock.toString(),
data[i].stocks!.first.expireDate ?? 'n/a',
data[i].stocks!.first.productPurchasePrice.toString(),
data[i].stocks!.first.productSalePrice.toString(),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
'SL',
'Product',
'Code',
'Stock',
'Expired In',
'Purchase',
'Sale',
],
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(4),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(3),
6: const pw.FlexColumnWidth(3),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(2),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.centerLeft,
6: pw.Alignment.centerLeft,
},
data: [
[
'Total',
'',
'',
'',
'',
'',
totalPurchase.toStringAsFixed(2),
totalSalePrice.toStringAsFixed(2),
]
],
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),
),
];
}));
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-expire-list-report.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
if (context.mounted) {
await Printing.layoutPdf(
name: 'Expire List',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,145 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/Screens/Income/Model/income_category.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/Income/Model/income_modle.dart';
import '../../Screens/PDF/pdf.dart';
import '../../model/business_info_model.dart';
import '../ledger_report/generate_pdf_date_range.dart';
Future<void> generateIncomeCategoryReportPdf(
BuildContext context,
List<IncomeCategory>? data,
BusinessInformationModel? business,
) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
double totalAmount = 0;
// print('--font family---$ttf---------------')
try {
pdf.addPage(pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Income Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
],
),
);
},
//-----------------pdf footer-------------
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++) {
tableData.add(['${i + 1}', data[i].categoryName ?? '', data[i].categoryDescription ?? '']);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
'SL',
'Category Name',
'Category Description',
],
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(1),
1: const pw.FlexColumnWidth(2),
2: const pw.FlexColumnWidth(2),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
},
),
];
}));
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/${appsName}-income_category.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Income Category Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,114 @@
import 'dart:io';
import 'package:excel/excel.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import '../../Screens/Income/Model/income_modle.dart';
import '../../model/business_info_model.dart';
import '../ledger_report/generate_pdf_date_range.dart';
Future<void> generateIncomeReportExcel(
BuildContext context,
List<Income>? data,
BusinessInformationModel? business,
String selectedTime,
DateTime? fromDate,
DateTime? toDate,
) async {
EasyLoading.show(status: 'Generating Excel');
try {
final excel = Excel.createExcel();
final sheet = excel['Income Report'];
final pdfRange = getPdfDateRangeForSelectedTime(
selectedTime,
fromDate: fromDate,
toDate: toDate,
);
final fromStr = pdfRange['from']!;
final toStr = pdfRange['to']!;
double totalAmount = data?.fold(0, (sum, item) => sum! + (item.amount ?? 0)) ?? 0;
// // Styles
// final businessStyle = CellStyle(bold: true, fontSize: 12);
// final titleStyle = CellStyle(bold: true, fontSize: 12);
// final headerStyle = CellStyle(bold: true, fontSize: 12);
// final footerStyle = CellStyle(bold: true, fontSize: 12);
// Row 1: Company Name
sheet.appendRow([TextCellValue(business?.data?.companyName ?? '')]);
sheet.cell(CellIndex.indexByString("A1")).cellStyle;
// Row 2: Report Title
sheet.appendRow([TextCellValue('Income Report')]);
sheet.cell(CellIndex.indexByString("A2")).cellStyle;
// Row 3: Duration
sheet.appendRow([
TextCellValue('Duration: $fromStr to $toStr'),
]);
// Row 4: Empty for spacing
sheet.appendRow([]);
// Row 5: Header
final headerRowIndex = sheet.maxRows;
sheet.appendRow([
TextCellValue('SL'),
TextCellValue('Date'),
TextCellValue('Income For'),
TextCellValue('Category'),
TextCellValue('Amount'),
]);
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++) {
sheet.appendRow([
TextCellValue('${i + 1}'),
TextCellValue(DateFormat('dd-MM-yyyy').format(DateTime.parse(data[i].incomeDate.toString()))),
TextCellValue(data[i].incomeFor ?? 'n/a'),
TextCellValue(data[i].category?.categoryName ?? 'n/a'),
TextCellValue(data[i].amount?.toStringAsFixed(2) ?? '0.00'),
]);
}
}
final totalRowIndex = sheet.maxRows;
sheet.appendRow([
TextCellValue('Total'),
TextCellValue(''),
TextCellValue(''),
TextCellValue(''),
TextCellValue(totalAmount.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"}_Income_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,217 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.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/Income/Model/income_modle.dart';
import '../../Screens/PDF/pdf.dart';
import '../../model/business_info_model.dart';
import '../ledger_report/generate_pdf_date_range.dart';
Future<void> generateIncomeReportPdf(
BuildContext context,
List<Income>? data,
BusinessInformationModel? business,
DateTime? fromDate,
DateTime? toDate,
String selectedTime,
) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
double totalAmount = 0;
// Calculate totals from data
if (data != null) {
for (var item in data) {
totalAmount += item.amount ?? 0;
}
}
// print('--font family---$ttf---------------');
// Calculate correct PDF date range
final pdfDateRange = getPdfDateRangeForSelectedTime(
selectedTime,
fromDate: fromDate,
toDate: toDate,
);
final fromDateStr = pdfDateRange['from']!;
final toDateStr = pdfDateRange['to']!;
try {
pdf.addPage(pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Income Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
'$fromDateStr TO $toDateStr',
style: pw.TextStyle(
font: interFont,
fontSize: 12,
),
),
],
),
);
},
//-----------------pdf footer-------------
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++) {
tableData.add([
'${i + 1}',
DateFormat('dd-MM-yyyy').format(DateTime.parse(data[i].incomeDate.toString())),
data[i].incomeFor ?? 'n/a',
data[i].category?.categoryName.toString() ?? 'n/a',
data[i].amount.toString(),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
'SL',
'Date',
'Income For',
'Category',
'Amount',
],
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(1),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(4),
4: const pw.FlexColumnWidth(2),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(2),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(4),
4: const pw.FlexColumnWidth(2),
},
data: [
[
'Total',
'',
'',
'',
totalAmount.toStringAsFixed(2),
]
],
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),
),
];
}));
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/${appsName}-income.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Income Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,57 @@
Map<String, String> getPdfDateRangeForSelectedTime(
String selectedTime, {
DateTime? fromDate,
DateTime? toDate,
}) {
DateTime now = DateTime.now();
DateTime start;
DateTime end;
switch (selectedTime.toLowerCase()) {
case 'today':
start = DateTime(now.year, now.month, now.day);
end = start;
break;
case 'yesterday':
start = DateTime(now.year, now.month, now.day).subtract(const Duration(days: 1));
end = start;
break;
case 'last_seven_days':
end = now;
start = now.subtract(const Duration(days: 6));
break;
case 'last_thirty_days':
end = now;
start = now.subtract(const Duration(days: 29));
break;
case 'current_month':
start = DateTime(now.year, now.month, 1);
end = DateTime(now.year, now.month + 1, 0);
break;
case 'last_month':
final lastMonth = DateTime(now.year, now.month - 1, 1);
start = lastMonth;
end = DateTime(lastMonth.year, lastMonth.month + 1, 0);
break;
case 'current_year':
start = DateTime(now.year, 1, 1);
end = DateTime(now.year, 12, 31);
break;
case 'custom_date':
start = fromDate ?? now;
end = toDate ?? now;
break;
default:
start = now;
end = now;
}
final fromStr = "${start.day.toString().padLeft(2, '0')}-"
"${start.month.toString().padLeft(2, '0')}-"
"${start.year}";
final toStr = "${end.day.toString().padLeft(2, '0')}-"
"${end.month.toString().padLeft(2, '0')}-"
"${end.year}";
return {'from': fromStr, 'to': toStr};
}

View File

@@ -0,0 +1,297 @@
import 'dart:io';
import 'package:excel/excel.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/constant.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import '../../Screens/party ledger/model/party_ledger_model.dart';
import '../../model/business_info_model.dart';
import 'generate_pdf_date_range.dart';
Future<void> generateLedgerReportExcel(
BuildContext context,
List<PartyLedgerModel>? data,
BusinessInformationModel business,
DateTime? fromDate,
DateTime? toDate,
String selectedTime,
) async {
EasyLoading.show(status: 'Generating Excel');
try {
if (data == null || data.isEmpty) {
EasyLoading.showInfo('No transactions available');
return;
}
// Create Excel
final excel = Excel.createExcel();
final sheet = excel['Party Ledger'];
// ---------------------------
// CALCULATE TOTALS
// ---------------------------
double creditBalance = 0;
double debitBalance = 0;
// for (var item in data) {
// if (item.type == 'credit') {
// creditBalance += item.amount ?? 0;
// } else {
// debitBalance += item.amount ?? 0;
// }
// }
for (var item in data) {
creditBalance += item.creditAmount ?? 0;
}
for (var item in data) {
debitBalance += item.debitAmount ?? 0;
}
// ---------------------------
// DATE RANGE (same as PDF)
// ---------------------------
final pdfRange = getPdfDateRangeForSelectedTime(
selectedTime,
fromDate: fromDate,
toDate: toDate,
);
final fromStr = pdfRange['from']!;
final toStr = pdfRange['to']!;
// ---------------------------
// HEADER SECTION
// ---------------------------
sheet.appendRow([
// TextCellValue(business.data?.companyName ?? ''),
TextCellValue(appsName),
]);
sheet.appendRow([
TextCellValue('Party Ledger'),
]);
sheet.appendRow([
TextCellValue('Duration: $fromStr to $toStr'),
]);
sheet.appendRow([]); // empty space row
// ---------------------------
// TABLE HEADER
// ---------------------------
final headerRow = sheet.maxRows;
sheet.appendRow([
TextCellValue('Date'),
TextCellValue('Reference No'),
TextCellValue('Description'),
TextCellValue('Credit'),
TextCellValue('Debit'),
TextCellValue('Balance'),
]);
// Style header row (bold)
for (int col = 0; col < 6; col++) {
final cell = sheet.cell(
CellIndex.indexByColumnRow(columnIndex: col, rowIndex: headerRow),
);
cell.cellStyle = CellStyle(bold: true);
}
sheet.appendRow([]);
// ---------------------------
// TABLE DATA
// ---------------------------
for (var item in data) {
bool isOpening = item.platform == 'opening_balance';
sheet.appendRow([
TextCellValue(DateFormat('dd-MM-yyyy').format(DateTime.parse(item.date.toString()))),
TextCellValue(item.invoiceNumber ?? ''),
TextCellValue(
isOpening ? "Opening" : item.platform?.replaceAll('_', ' ') ?? 'Transaction',
),
TextCellValue((item.creditAmount ?? 0).toStringAsFixed(2)),
TextCellValue((item.debitAmount ?? 0).toStringAsFixed(2)),
TextCellValue((item.balance ?? 0).toStringAsFixed(2)),
]);
}
// ---------------------------
// TOTAL ROW
// ---------------------------
final totalRow = sheet.maxRows;
sheet.appendRow([
TextCellValue(''),
TextCellValue(''),
TextCellValue('Total'),
TextCellValue(creditBalance.toStringAsFixed(2)),
TextCellValue(debitBalance.toStringAsFixed(2)),
TextCellValue((data.last.balance ?? 0).toStringAsFixed(2)),
]);
// Make TOTAL row bold
for (int col = 0; col < 6; col++) {
final cell = sheet.cell(
CellIndex.indexByColumnRow(columnIndex: col, rowIndex: totalRow),
);
cell.cellStyle = CellStyle(bold: true);
}
// ---------------------------
// SAVE FILE
// ---------------------------
final dir = await getApplicationDocumentsDirectory();
final timestamp = DateTime.now().millisecondsSinceEpoch;
final filePath = '${dir.path}/${business.data?.companyName ?? "Company"}_Ledger_Report_$timestamp.xlsx';
final file = File(filePath);
await file.writeAsBytes(excel.encode()!);
EasyLoading.showSuccess('Excel Generated Successfully!');
await OpenFile.open(filePath);
} catch (e) {
EasyLoading.showError("Error: $e");
debugPrint("Excel Error: $e");
}
}
// Future<void> generateLedgerReportExcel(
// BuildContext context,
// List<PartyLedgerModel>? data,
// BusinessInformationModel? business,
// DateTime? fromDate,
// DateTime? toDate,
// ) async {
// EasyLoading.show(status: 'Generating Excel');
//
// try {
// if (data == null) {
// EasyLoading.showError('Invalid data provided');
// return;
// }
//
// // Create Excel file & sheet
// final excel = Excel.createExcel();
// final sheet = excel['Party Ledger'];
//
// double creditBalance = 0;
// double debitBalance = 0;
//
// for (var item in data) {
// if (item.type == 'credit') {
// creditBalance += item.amount ?? 0;
// } else {
// debitBalance += item.amount ?? 0;
// }
// }
//
// // ---------------------------
// // HEADER SECTION
// // ---------------------------
//
// // Row 1: Company Name
// sheet.appendRow([
// TextCellValue(business?.data?.companyName ?? ''),
// ]);
//
// // Row 2: Report Title
// sheet.appendRow([
// TextCellValue('Party Ledger'),
// ]);
//
// // Row 3: Date Range
// if (fromDate != null && toDate != null) {
// final String formattedFrom = DateFormat('dd-MM-yyyy').format(fromDate);
// final String formattedTo = DateFormat('dd-MM-yyyy').format(toDate);
//
// sheet.appendRow([
// TextCellValue('Duration: $formattedFrom to $formattedTo'),
// ]);
// }
//
// // Empty row
// sheet.appendRow([]);
//
// // ---------------------------
// // LEDGER TABLE HEADER
// // ---------------------------
// final headerRowIndex = sheet.maxRows;
//
// sheet.appendRow([
// TextCellValue('Date'),
// TextCellValue('Invoice No'),
// TextCellValue('Details'),
// TextCellValue('Credit'),
// TextCellValue('Debit'),
// TextCellValue('Balance'),
// ]);
//
// // Add space row
// sheet.appendRow([]);
//
// // Apply bold style on table header
// for (var i = 0; i < 6; i++) {
// sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: headerRowIndex)).cellStyle;
// }
//
// // ---------------------------
// // LEDGER TABLE BODY
// // ---------------------------
// for (int i = 0; i < data.length; i++) {
// final item = data[i];
// final isOpening = item.platform == 'opening_balance';
//
// sheet.appendRow([
// TextCellValue(item.date ?? 'n/a'),
// TextCellValue(item.invoiceNumber ?? ''),
// TextCellValue(isOpening ? "Opening" : item.platform?.replaceAll('_', ' ') ?? 'Transaction'),
// TextCellValue(item.type == 'credit' ? (item.amount ?? 0).toStringAsFixed(2) : '0.00'),
// TextCellValue(item.type != 'credit' ? (item.amount ?? 0).toStringAsFixed(2) : '0.00'),
// TextCellValue((item.balance ?? 0).toStringAsFixed(2)),
// ]);
// }
//
// // ---------------------------
// // TOTAL ROW
// // ---------------------------
// final totalRowIndex = sheet.maxRows;
//
// sheet.appendRow([
// TextCellValue(''),
// TextCellValue(''),
// TextCellValue('Total'),
// TextCellValue(creditBalance.toStringAsFixed(2)),
// TextCellValue(debitBalance.toStringAsFixed(2)),
// TextCellValue((data.last.balance ?? 0).toStringAsFixed(2)),
// ]);
//
// // Make total row bold
// for (var i = 0; i < 6; i++) {
// sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: totalRowIndex)).cellStyle;
// }
//
// // ---------------------------
// // SAVE FILE
// // ---------------------------
// final dir = await getApplicationDocumentsDirectory();
// final filePath = '${dir.path}/${business?.data?.companyName ?? "Company"}_Ledger_Report.xlsx';
//
// final file = File(filePath);
// await file.writeAsBytes(excel.encode()!);
//
// EasyLoading.showSuccess('Ledger Excel Generated!');
// await OpenFile.open(filePath);
// } catch (e) {
// EasyLoading.showError('Error: $e');
// debugPrint('Ledger Excel Error: $e');
// }
// }

View File

@@ -0,0 +1,216 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/Screens/Customers/Model/parties_model.dart';
import 'package:mobile_pos/Screens/Products/Model/product_model.dart';
import 'package:mobile_pos/Screens/party%20ledger/model/party_ledger_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 '../../currency.dart';
import '../../model/business_info_model.dart';
import 'generate_pdf_date_range.dart';
Future<void> generateLedgerReportPdf(
BuildContext context,
List<PartyLedgerModel>? data,
BusinessInformationModel business,
DateTime? fromDate,
DateTime? toDate,
String selectedTime, // pass selected filter
) async {
if (data == null || data.isEmpty) {
EasyLoading.showInfo('No transactions to generate PDF');
return;
}
final pdf = pw.Document();
try {
EasyLoading.show(status: 'Generating PDF...');
double creditBalance = 0;
double debitBalance = 0;
// for (var item in data) {
// if (item.type == 'credit') creditBalance += item.amount ?? 0;
// if (item.type != 'credit') debitBalance += item.amount ?? 0;
// }
for (var item in data) {
creditBalance += item.creditAmount ?? 0;
}
for (var item in data) {
debitBalance += item.debitAmount ?? 0;
}
// Calculate correct PDF date range
final pdfDateRange = getPdfDateRangeForSelectedTime(
selectedTime,
fromDate: fromDate,
toDate: toDate,
);
final fromDateStr = pdfDateRange['from']!;
final toDateStr = pdfDateRange['to']!;
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: const pw.EdgeInsets.symmetric(horizontal: 16),
header: (context) => pw.Center(
child: pw.Column(
children: [
pw.Text(appsName, style: pw.TextStyle(fontSize: 20, fontWeight: pw.FontWeight.bold)),
pw.Text('Party Ledger', style: pw.TextStyle(fontSize: 16, fontWeight: pw.FontWeight.bold)),
pw.SizedBox(height: 2),
pw.Text('$fromDateStr TO $toDateStr', style: const pw.TextStyle(fontSize: 14)),
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 isOpening = data[i].platform == 'opening_balance';
// final stockPrice = (data[i].stocks != null && data[i].stocks!.isNotEmpty) ? data[i].stocks!.last.productPurchasePrice?.toString() ?? '0' : '0';
tableData.add([
DateFormat('dd-MM-yyyy').format(DateTime.parse(data[i].date.toString())),
data[i].invoiceNumber ?? '--',
isOpening ? "Opening" : (data[i].platform?.replaceAll('_', ' ') ?? 'Transaction'),
'$currency${data[i].creditAmount ?? 0}',
'$currency${data[i].debitAmount ?? 0}',
'$currency${data[i].balance ?? 0}',
]);
}
return [
pw.SizedBox(height: 16),
pw.Table.fromTextArray(
headers: [
'Date',
'Reference No',
'Description',
'Credit',
'Debit',
'Balance',
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffF7F7F7),
),
border: pw.TableBorder.all(color: PdfColor.fromInt(0xffD9D9D9)),
headerStyle: pw.TextStyle(
fontWeight: pw.FontWeight.bold,
color: PdfColors.black,
),
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(3),
1: const pw.FlexColumnWidth(4),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(3),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
},
),
pw.Table.fromTextArray(
border: pw.TableBorder.all(color: PdfColor.fromInt(0xffD9D9D9)),
columnWidths: {
0: const pw.FlexColumnWidth(3),
1: const pw.FlexColumnWidth(4),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(3),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
},
data: [
[
'',
'',
'Total',
creditBalance,
debitBalance,
data.last.balance,
]
],
// headerDecoration: const pw.BoxDecoration(
// color: PdfColor.fromInt(0xffF7F7F7),
// ),
headerStyle: pw.TextStyle(
fontWeight: pw.FontWeight.bold,
color: PdfColors.black,
),
cellAlignment: pw.Alignment.center,
cellPadding: const pw.EdgeInsets.all(8),
),
];
},
),
);
final bytes = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final timestamp = DateTime.now().millisecondsSinceEpoch;
final file = File('${dir.path}/$appsName-leger-report-$timestamp.pdf');
await file.writeAsBytes(bytes);
await EasyLoading.dismiss();
if (context.mounted) {
await Printing.layoutPdf(
name: 'Leger Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// if (context.mounted) {
// Navigator.push(context, MaterialPageRoute(builder: (_) => PDFViewerPage(path: file.path)));
// }
} catch (e) {
await EasyLoading.dismiss();
EasyLoading.showError('Failed to generate PDF: $e');
}
}

View File

@@ -0,0 +1,204 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.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/Customers/Model/parties_model.dart';
import '../../model/business_info_model.dart';
Future<void> generateCustomerLedgerReportPdf(
BuildContext context, List<Party>? data, BusinessInformationModel? business) async {
final pw.Document pdf = pw.Document();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
final totalAmount = data?.fold<num>(0, (previousValue, element) => previousValue + (element.totalSaleAmount ?? 0));
final paidAmount = data?.fold<num>(0, (previousValue, element) => previousValue + (element.totalSalePaid ?? 0));
final dueAmount = data?.fold<num>(0, (previousValue, element) => previousValue + (element.due ?? 0));
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Customer Ledger Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
],
),
);
},
//-----------------pdf footer-------------
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++) {
tableData.add([
data[i].name ?? 'n/a',
data[i].phone ?? 'n/a',
formatPointNumber(data[i].saleCount ?? 0),
formatPointNumber(data[i].totalSaleAmount ?? 0),
formatPointNumber(data[i].totalSalePaid ?? 0),
formatPointNumber(data[i].due ?? 0),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"Customer Name ",
"Phone ",
"Total Sales ",
"Amount ",
"Paid ",
"Total Sale Due",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
data: [
[
'Total',
'',
'',
formatPointNumber(totalAmount ?? 0),
formatPointNumber(paidAmount ?? 0),
formatPointNumber(dueAmount ?? 0),
]
],
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),
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-customer-ledger.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,204 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.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/Customers/Model/parties_model.dart';
import '../../model/business_info_model.dart';
Future<void> generateSupplierLedgerReportPdf(
BuildContext context, List<Party>? data, BusinessInformationModel? business) async {
final pw.Document pdf = pw.Document();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
final totalAmount = data?.fold<num>(0, (previousValue, element) => previousValue + (element.totalSaleAmount ?? 0));
final paidAmount = data?.fold<num>(0, (previousValue, element) => previousValue + (element.totalSalePaid ?? 0));
final dueAmount = data?.fold<num>(0, (previousValue, element) => previousValue + (element.due ?? 0));
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Supplier Ledger Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
],
),
);
},
//-----------------pdf footer-------------
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++) {
tableData.add([
data[i].name ?? 'n/a',
data[i].phone ?? 'n/a',
formatPointNumber(data[i].saleCount ?? 0),
formatPointNumber(data[i].totalSaleAmount ?? 0),
formatPointNumber(data[i].totalSalePaid ?? 0),
formatPointNumber(data[i].due ?? 0),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"Supplier Name ",
"Phone ",
"Total Purchases ",
"Amount ",
"Paid ",
"Total Purchase Due",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
data: [
[
'Total',
'',
'',
formatPointNumber(totalAmount ?? 0),
formatPointNumber(paidAmount ?? 0),
formatPointNumber(dueAmount ?? 0),
]
],
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),
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-customer-ledger.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,222 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart' as intl;
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 '../../model/bill_wise_loss_profit_report_model.dart' as bwlprm;
import '../../model/business_info_model.dart';
Future<void> generateBillWiseLossProfitReportPdf(
BuildContext context,
bwlprm.BillWiseLossProfitReportModel data,
BusinessInformationModel? business,
DateTime? fromDate,
DateTime? toDate,
) async {
final pw.Document pdf = pw.Document();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Bill Wise Profit',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null
? 'Duration: ${intl.DateFormat('dd-MM-yyyy').format(fromDate)} to ${intl.DateFormat('dd-MM-yyyy').format(toDate!)}'
: '',
style: pw.TextStyle(
fontSize: 12,
),
),
],
),
);
},
//-----------------pdf footer-------------
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 _transactions = [...?data.transactions];
final List<List<String>> tableData = [];
for (int i = 0; i < (data.transactions?.length ?? 0); i++) {
final _transaction = _transactions[i];
tableData.add([
"${i + 1}",
_transaction.invoiceNumber ?? "N/A",
_transaction.transactionDate == null
? "N/A"
: intl.DateFormat("dd MMM, yyyy").format(_transaction.transactionDate!),
_transaction.partyName ?? "N/A",
formatPointNumber(_transaction.totalAmount ?? 0),
formatPointNumber(_transaction.isProfit ? (_transaction.lossProfit ?? 0) : 0),
formatPointNumber(_transaction.isProfit ? 0 : (_transaction.lossProfit ?? 0).abs()),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"SL",
"Invoice",
"Date",
"Name",
"Sales",
"Profit",
"Loss",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(1.25),
1: const pw.FlexColumnWidth(2),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(3),
6: const pw.FlexColumnWidth(3),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(3),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
data: [
[
"Total",
"",
"",
"",
formatPointNumber(data.totalSaleAmount ?? 0, addComma: true),
formatPointNumber(data.totalProfit ?? 0, addComma: true),
formatPointNumber((data.totalLoss ?? 0).abs(), addComma: true),
]
],
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),
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-customer-ledger.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,289 @@
import 'dart:async';
import 'dart:io';
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.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 '../../model/business_info_model.dart';
import '../../model/loss_profit_model.dart' as model;
Future<void> generateLossProfitReportPdf(BuildContext context, model.LossProfitModel data,
BusinessInformationModel? business, DateTime? fromDate, DateTime? toDate) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Profit & Loss',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null
? 'Duration: ${DateFormat('dd-MM-yyyy').format(fromDate)} to ${DateFormat('dd-MM-yyyy').format(toDate!)}'
: '',
style: pw.TextStyle(
font: interFont,
fontSize: 12,
),
),
],
),
);
},
//-----------------pdf footer-------------
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 _length = math.max((data.expenseSummary?.length ?? 0), (data.incomeSummary?.length ?? 0));
final List<List<String>> tableData = [];
for (int i = 0; i < _length; i++) {
final _income = (i < (data.incomeSummary?.length ?? 0)) ? data.incomeSummary![i] : null;
final _expense = (i < (data.expenseSummary?.length ?? 0)) ? data.expenseSummary![i] : null;
tableData.add([
// Income Type
_income?.type ?? '',
_income?.totalIncome == null ? '' : formatPointNumber(_income!.totalIncome!),
// Expense Type
_expense?.type ?? '',
_expense?.totalExpense == null ? '' : formatPointNumber(_expense!.totalExpense!),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"Income type",
"Amount",
"Expenses Types",
"Amount",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(6),
1: const pw.FlexColumnWidth(4),
2: const pw.FlexColumnWidth(6),
3: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.centerLeft,
1: pw.Alignment.centerRight,
2: pw.Alignment.centerLeft,
3: pw.Alignment.centerRight,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(6),
1: const pw.FlexColumnWidth(4),
2: const pw.FlexColumnWidth(6),
3: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.centerLeft,
1: pw.Alignment.centerRight,
2: pw.Alignment.centerLeft,
3: pw.Alignment.centerRight,
},
data: [
[
"Gross Profit",
formatPointNumber(data.grossIncomeProfit ?? 0),
"Total Expense",
formatPointNumber(data.totalExpenses ?? 0),
]
],
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),
),
// Net Profit (Incomes - Expense)
pw.Container(
padding: pw.EdgeInsets.symmetric(horizontal: 16, vertical: 10),
alignment: pw.Alignment.center,
decoration: pw.BoxDecoration(
border: pw.Border(bottom: pw.BorderSide(color: PdfColor.fromHex("D8D8D880"))),
),
child: pw.Text(
"Net Profit (Incomes - Expense) =${formatPointNumber(data.netProfit ?? 0, addComma: true)}",
textAlign: pw.TextAlign.center,
style: pw.TextStyle(
// font: interFont,
fontSize: 14,
fontWeight: pw.FontWeight.bold,
),
),
),
pw.SizedBox.square(dimension: 16),
// Overview Containers
pw.Row(
mainAxisAlignment: pw.MainAxisAlignment.center,
children: [
// Gross Profit
pw.Expanded(
child: pw.Container(
padding: pw.EdgeInsets.symmetric(horizontal: 30, vertical: 10),
decoration: pw.BoxDecoration(
border: pw.Border.all(color: PdfColor.fromHex('121535')),
borderRadius: pw.BorderRadius.circular(4),
),
child: pw.Column(
mainAxisSize: pw.MainAxisSize.min,
children: [
pw.Text(formatPointNumber(data.cartGrossProfit ?? 0)),
pw.SizedBox.square(dimension: 4),
pw.Text('Gross Profit'),
],
),
),
),
pw.SizedBox.square(dimension: 10),
// Total Expenses
pw.Expanded(
child: pw.Container(
padding: pw.EdgeInsets.symmetric(horizontal: 30, vertical: 10),
decoration: pw.BoxDecoration(
border: pw.Border.all(color: PdfColor.fromHex('121535')),
borderRadius: pw.BorderRadius.circular(4),
),
child: pw.Column(
mainAxisSize: pw.MainAxisSize.min,
children: [
pw.Text(formatPointNumber(data.totalCardExpense ?? 0)),
pw.SizedBox.square(dimension: 4),
pw.Text('Total Expenses'),
],
),
),
),
pw.SizedBox.square(dimension: 10),
// Net Profit
pw.Expanded(
child: pw.Container(
padding: pw.EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: pw.BoxDecoration(
border: pw.Border.all(color: PdfColor.fromHex('121535')),
borderRadius: pw.BorderRadius.circular(4),
),
child: pw.Column(
mainAxisSize: pw.MainAxisSize.min,
children: [
pw.Text(formatPointNumber(data.cardNetProfit ?? 0)),
pw.SizedBox.square(dimension: 4),
pw.Text('Net Profit'),
],
),
),
),
],
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-loss-profit-report.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Loss Profit Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,146 @@
import 'dart:io';
import 'package:excel/excel.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import '../../model/business_info_model.dart';
import '../../model/loss_profit_model.dart' as lpmodel;
Future<void> generateLossProfitReportExcel(
BuildContext context,
lpmodel.LossProfitModel data,
BusinessInformationModel? business,
DateTime? fromDate,
DateTime? toDate,
) async {
EasyLoading.show(status: 'Generating Excel');
try {
final excel = Excel.createExcel();
final sheet = excel['Loss & Profit Report'];
// ---- DATE RANGE ----
String fromStr = fromDate != null ? DateFormat('dd-MM-yyyy').format(fromDate) : '';
String toStr = toDate != null ? DateFormat('dd-MM-yyyy').format(toDate!) : '';
// ---- TOTAL CALCULATIONS ----
double totalProfit = 0;
double totalLoss = 0;
/*
if (data != null) {
for (var item in data) {
final profit = item.detailsSumLossProfit ?? 0;
if (profit.isNegative) {
totalLoss += profit;
} else {
totalProfit += profit;
}
}
}
// ----------------------------- //
// HEADER ROWS
// ----------------------------- //
// Row 1: Company Name
sheet.appendRow([TextCellValue(business?.data?.companyName ?? '')]);
// Row 2: Report Title
sheet.appendRow([TextCellValue('Loss & Profit Report')]);
// Row 3: Duration
sheet.appendRow([
TextCellValue('Duration: $fromStr to $toStr'),
]);
// Row 4: Empty Space
sheet.appendRow([]);
// Row 5: Header Row
final headerStartRow = sheet.maxRows;
sheet.appendRow([
TextCellValue('SL'),
TextCellValue('Invoice'),
TextCellValue('Date'),
TextCellValue('Name'),
TextCellValue('Status'),
TextCellValue('Total'),
TextCellValue('Profit'),
TextCellValue('Loss'),
]);
// Style header bold (Excel library is limited but kept same structure)
for (int i = 0; i < 8; i++) {
sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: headerStartRow)).cellStyle;
}
// Space before data
sheet.appendRow([]);
// ----------------------------- //
// DATA ROWS
// ----------------------------- //
if (data != null) {
for (int i = 0; i < data.length; i++) {
final item = data[i];
sheet.appendRow([
TextCellValue('${i + 1}'),
TextCellValue(item.invoiceNumber ?? 'n/a'),
TextCellValue(DateFormat('dd-MM-yyyy').format(DateTime.parse(item.saleDate.toString()))),
TextCellValue(item.party?.name ?? 'n/a'),
TextCellValue(item.isPaid == true ? 'Paid' : 'Unpaid'),
TextCellValue(item.totalAmount.toString()),
TextCellValue(!item.detailsSumLossProfit!.isNegative ? item.detailsSumLossProfit.toString() : '0'),
TextCellValue(item.detailsSumLossProfit!.isNegative ? item.detailsSumLossProfit.toString() : '0'),
]);
}
}
// ----------------------------- //
// TOTAL ROW
// ----------------------------- //
final totalRow = sheet.maxRows;
sheet.appendRow([
TextCellValue(''),
TextCellValue('Total'),
TextCellValue(''),
TextCellValue(''),
TextCellValue(''),
TextCellValue(''),
TextCellValue(totalProfit.toStringAsFixed(2)),
TextCellValue(totalLoss.toStringAsFixed(2)),
]);
// Style total row
for (int i = 0; i < 8; i++) {
sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: totalRow)).cellStyle;
}
*/
// ----------------------------- //
// SAVE FILE & OPEN
// ----------------------------- //
final dir = await getApplicationDocumentsDirectory();
final filePath = '${dir.path}/${business?.data?.companyName ?? "Company"}_Loss_Profit_Report.xlsx';
final file = File(filePath);
await file.writeAsBytes(excel.encode()!);
EasyLoading.showSuccess('Excel Generated');
await OpenFile.open(filePath);
} catch (e) {
EasyLoading.showError('Error: $e');
print('Excel Generation Error: $e');
}
}

View File

@@ -0,0 +1,209 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.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/Customers/Model/parties_model.dart';
import '../../model/business_info_model.dart';
Future<void> generatePartyWiseLossProfitReportPdf(
BuildContext context, List<Party>? data, BusinessInformationModel? business) async {
final pw.Document pdf = pw.Document();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
final totalSaleAmount =
data?.fold<num>(0, (previousValue, element) => previousValue + (element.totalSaleAmount ?? 0));
final totalProfitAmount = data?.fold<num>(0, (previousValue, party) {
final num profit = party.totalSaleProfit ?? 0;
return previousValue + profit;
});
final totalLossAmount = data?.fold<num>(0, (previousValue, element) {
final num loss = element.totalSaleLoss ?? 0;
return previousValue + loss;
});
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Party Wise Loss & Profit',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
],
),
);
},
//-----------------pdf footer-------------
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 party = data[i];
tableData.add([
"${i + 1}",
party.name ?? 'n/a',
formatPointNumber(party.totalSaleAmount ?? 0),
formatPointNumber(party.totalSaleProfit ?? 0),
formatPointNumber(party.totalSaleLoss ?? 0),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"SL.",
"Party Name",
"Sale Amount",
"Profit",
"Loss",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
data: [
[
'Total',
'',
formatPointNumber(totalSaleAmount ?? 0),
formatPointNumber(totalProfitAmount ?? 0),
formatPointNumber(totalLossAmount ?? 0),
]
],
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),
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-customer-ledger.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,152 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.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/Customers/Model/parties_model.dart';
import '../../model/business_info_model.dart';
Future<void> generateTop5CustomerReportPdf(
BuildContext context, List<Party>? data, BusinessInformationModel? business) async {
final pw.Document pdf = pw.Document();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Top 5 Customers',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
],
),
);
},
//-----------------pdf footer-------------
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 party = data[i];
tableData.add([
party.name ?? 'n/a',
party.phone ?? 'n/a',
party.email ?? 'n/a',
formatPointNumber(party.saleCount ?? 0),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"Customer Name",
"Phone",
"Email",
"Total Sales",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(4),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.centerLeft,
1: pw.Alignment.centerLeft,
2: pw.Alignment.centerLeft,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-customer-ledger.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,150 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.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/Customers/Model/parties_model.dart';
import '../../model/business_info_model.dart';
Future<void> generateTop5SupplierReportPdf(
BuildContext context, List<Party>? data, BusinessInformationModel? business) async {
final pw.Document pdf = pw.Document();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Top 5 Supplier',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
],
),
);
},
//-----------------pdf footer-------------
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 party = data[i];
tableData.add([
party.name ?? 'n/a',
party.phone ?? 'n/a',
party.email ?? 'n/a',
formatPointNumber(party.purchaseCount ?? 0),
formatPointNumber(party.totalPurchaseAmount ?? 0),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"Supplier Name",
"Phone",
"Email",
"Total Purchase",
"Total Amount",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(4),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(2.5),
4: const pw.FlexColumnWidth(2.5),
},
cellAlignments: {
0: pw.Alignment.centerLeft,
1: pw.Alignment.centerLeft,
2: pw.Alignment.centerLeft,
3: pw.Alignment.center,
4: pw.Alignment.center,
},
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-customer-ledger.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,207 @@
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/Customers/Model/parties_model.dart';
import '../../model/business_info_model.dart';
Future<void> generateProductLossProfitReportPdf(
BuildContext context, List<Product>? data, BusinessInformationModel? business) async {
final pw.Document pdf = pw.Document();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
final totalSaleAmount =
data?.fold<num>(0, (previousValue, element) => previousValue + (element.totalSaleAmount ?? 0));
final totalProfitAmount = data?.fold<num>(0, (previousValue, product) {
final num profitLoss = product.totalLossProfit ?? 0;
final num profitAmount = profitLoss > 0 ? profitLoss : 0;
return previousValue + profitAmount;
});
final totalLossAmount = data?.fold<num>(0, (previousValue, element) {
final num profitLoss = element.totalLossProfit ?? 0;
final num lossAmount = profitLoss < 0 ? profitLoss.abs() : 0;
return previousValue + lossAmount;
});
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Product Wise Loss & Profit',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
],
),
);
},
//-----------------pdf footer-------------
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 product = data[i];
final num profitLoss = product.totalLossProfit ?? 0;
final num profitAmount = profitLoss > 0 ? profitLoss : 0;
final num lossAmount = profitLoss < 0 ? profitLoss.abs() : 0;
tableData.add([
"${i + 1}",
product.productName ?? 'n/a',
product.productCode ?? 'n/a',
formatPointNumber(profitAmount),
formatPointNumber(lossAmount),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"SL.",
"Product Name",
"Product Code",
"Profit",
"Loss",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(2),
3: const pw.FlexColumnWidth(2),
4: const pw.FlexColumnWidth(2),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(2),
3: const pw.FlexColumnWidth(2),
4: const pw.FlexColumnWidth(2),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
},
data: [
[
'Total',
'',
'',
formatPointNumber(totalProfitAmount ?? 0),
formatPointNumber(totalLossAmount ?? 0),
]
],
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),
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-product-wise-loss-profit.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Product Wise Loss Profit Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,216 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/Screens/Purchase/Model/purchase_transaction_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 '../../model/business_info_model.dart';
Future<void> generateProductPurchaseReport(BuildContext context, List<PurchaseTransaction>? data,
BusinessInformationModel? business, DateTime? fromDate, DateTime? toDate) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
double totalAmount = 0;
//total due
if (data != null) {
for (var item in data) {
final amount = item.totalAmount ?? 0;
totalAmount += amount;
}
}
try {
pdf.addPage(pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Product Wise Purchase Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null
? 'Duration: ${DateFormat('dd-MM-yyyy').format(fromDate)} to ${DateFormat('dd-MM-yyyy').format(toDate!)}'
: '',
style: pw.TextStyle(
font: interFont,
fontSize: 12,
),
),
],
),
);
},
//-----------------pdf footer-------------
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 detail = data[i].details;
tableData.add([
data[i].invoiceNumber ?? 'n/a',
DateFormat('dd-MM-yyyy').format(DateTime.parse(data[i].purchaseDate.toString())),
data[i].party?.name ?? 'n/a',
detail != null && detail.isNotEmpty ? detail.first.product?.productName ?? 'n/a' : 'n/a',
detail != null && detail.isNotEmpty ? detail.first.quantities.toString() : '0',
formatPointNumber(data[i].totalAmount ?? 0),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
// 'SL',
'Reference',
'Date',
'Supplier',
'Product Name',
'Purchase Qty',
'Total Amount',
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(2),
5: const pw.FlexColumnWidth(2),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(2),
5: const pw.FlexColumnWidth(2),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
},
data: [
[
'Total',
'',
'',
'',
'',
formatPointNumber(totalAmount),
]
],
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),
),
];
}));
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/${appsName}-purchase-report.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Purchase Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,218 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/Screens/Purchase/Model/purchase_transaction_model.dart';
import 'package:mobile_pos/constant.dart';
import 'package:mobile_pos/model/sale_transaction_model.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 '../../model/business_info_model.dart';
Future<void> generateProductSaleReport(BuildContext context, List<SalesTransactionModel>? data,
BusinessInformationModel? business, DateTime? fromDate, DateTime? toDate) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
double totalAmount = 0;
//total due
if (data != null) {
for (var item in data) {
final amount = item.totalAmount ?? 0;
totalAmount += amount;
}
}
try {
pdf.addPage(pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Product Wise Sale Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null
? 'Duration: ${DateFormat('dd-MM-yyyy').format(fromDate)} to ${DateFormat('dd-MM-yyyy').format(toDate!)}'
: '',
style: pw.TextStyle(
font: interFont,
fontSize: 12,
),
),
pw.SizedBox(height: 4),
],
),
);
},
//-----------------pdf footer-------------
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 detail = data[i].salesDetails;
tableData.add([
data[i].invoiceNumber ?? 'n/a',
DateFormat('dd-MM-yyyy').format(DateTime.parse(data[i].saleDate.toString())),
data[i].party?.name ?? 'n/a',
detail != null && detail.isNotEmpty ? detail.first.product?.productName ?? 'n/a' : 'n/a',
detail != null && detail.isNotEmpty ? detail.first.quantities.toString() : '0',
formatPointNumber(data[i].totalAmount ?? 0),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
// 'SL',
'Reference',
'Date',
'Customer',
'Product Name',
'Purchase Qty',
'Total Amount',
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(2),
5: const pw.FlexColumnWidth(2),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(2),
5: const pw.FlexColumnWidth(2),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
},
data: [
[
'Total',
'',
'',
'',
'',
formatPointNumber(totalAmount),
]
],
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),
),
];
}));
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/${appsName}-purchase-report.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Purchase Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,133 @@
import 'dart:io';
import 'package:excel/excel.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/Screens/Purchase/Model/purchase_transaction_model.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import '../../model/business_info_model.dart';
import '../../model/sale_transaction_model.dart';
Future<void> generatePurchaseReportExcel(
BuildContext context,
List<PurchaseTransaction>? data,
BusinessInformationModel? business,
DateTime? fromDate,
DateTime? toDate,
) async {
EasyLoading.show(status: 'Generating Excel');
try {
final excel = Excel.createExcel();
final sheet = excel['Purchase Report'];
// ---- DATE RANGE ----
String fromStr = fromDate != null ? DateFormat('dd-MM-yyyy').format(fromDate) : '';
String toStr = toDate != null ? DateFormat('dd-MM-yyyy').format(toDate) : '';
// ---- TOTAL CALCULATION ----
double total = 0;
double totalPaid = 0;
double totalDue = 0;
if (data != null) {
for (var item in data) {
total += item.totalAmount ?? 0;
totalPaid += item.paidAmount ?? 0;
totalDue += item.dueAmount ?? 0;
}
}
// ----------------------------- //
// HEADER ROWS //
// ----------------------------- //
// Row 1: Company Name
sheet.appendRow([TextCellValue(business?.data?.companyName ?? '')]);
// Row 2: Report Title
sheet.appendRow([TextCellValue('Purchase Report')]);
// Row 3: Duration
sheet.appendRow([
TextCellValue('Duration: $fromStr to $toStr'),
]);
// Row 4: Empty Space
sheet.appendRow([]);
// Row 5: Table Headers
final headerStartRow = sheet.maxRows;
sheet.appendRow([
TextCellValue('Reference'),
TextCellValue('Date'),
TextCellValue('Customer'),
TextCellValue('Status'),
TextCellValue('Total'),
TextCellValue('Paid'),
TextCellValue('Due'),
]);
// Apply bold header style
for (int i = 0; i < 7; i++) {
sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: headerStartRow)).cellStyle;
}
// Row 6: Space before data
sheet.appendRow([]);
// ----------------------------- //
// TABLE DATA ROWS //
// ----------------------------- //
if (data != null) {
for (var item in data) {
sheet.appendRow([
TextCellValue(item.invoiceNumber ?? 'n/a'),
TextCellValue(DateFormat('dd-MM-yyyy').format(DateTime.parse(item.purchaseDate.toString()))),
TextCellValue(item.party?.name ?? 'n/a'),
TextCellValue(item.isPaid == true ? 'Paid' : 'Unpaid'),
TextCellValue((item.totalAmount ?? 0).toStringAsFixed(2)),
TextCellValue((item.paidAmount ?? 0).toStringAsFixed(2)),
TextCellValue((item.dueAmount ?? 0).toStringAsFixed(2)),
]);
}
}
// ----------------------------- //
// TOTAL ROW //
// ----------------------------- //
final totalRowIndex = sheet.maxRows;
sheet.appendRow([
TextCellValue('Total'),
TextCellValue(''),
TextCellValue(''),
TextCellValue(''),
TextCellValue(total.toStringAsFixed(2)),
TextCellValue(totalPaid.toStringAsFixed(2)),
TextCellValue(totalDue.toStringAsFixed(2)),
]);
// Apply bold style
for (int i = 0; i < 7; i++) {
sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: totalRowIndex)).cellStyle;
}
// ----------------------------- //
// SAVE FILE //
// ----------------------------- //
final dir = await getApplicationDocumentsDirectory();
final filePath = '${dir.path}/${business?.data?.companyName ?? "Company"}_Purchase_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('Excel Generation Error: $e');
}
}

View File

@@ -0,0 +1,239 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/Screens/Purchase/Model/purchase_transaction_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 '../../model/business_info_model.dart';
Future<void> generatePurchaseReport(BuildContext context, List<PurchaseTransaction>? data, BusinessInformationModel? business, DateTime? fromDate, DateTime? toDate) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
double total = 0;
double totalDue = 0;
double totalPaid = 0;
// Calculate totals from data
if (data != null) {
for (var item in data) {
final totalAmounts = item.totalAmount ?? 0;
total += totalAmounts;
}
}
//total due
if (data != null) {
for (var item in data) {
final due = item.paidAmount ?? 0;
totalDue += due;
}
}
//total paid
if (data != null) {
for (var item in data) {
final paid = item.dueAmount ?? 0;
totalPaid += paid;
}
}
try {
pdf.addPage(pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Purchase Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null ? 'Duration: ${DateFormat('dd-MM-yyyy').format(fromDate)} to ${DateFormat('dd-MM-yyyy').format(toDate!)}' : '',
style: pw.TextStyle(
font: interFont,
fontSize: 12,
),
),
],
),
);
},
//-----------------pdf footer-------------
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++) {
tableData.add([
// '${i + 1}',
data[i].invoiceNumber ?? 'n/a',
DateFormat('dd-MM-yyyy').format(DateTime.parse(data[i].purchaseDate.toString())),
data[i].party!.name ?? 'n/a',
// data[i]. ?? 'n/a',
data[i].isPaid == true ? 'Paid' : 'Unpaid',
data[i].totalAmount.toString(),
data[i].paidAmount.toString(),
data[i].dueAmount.toString(),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
// 'SL',
'Reference',
'Date',
'Supplier',
'Status',
'Total',
'Paid',
'Due',
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
data: [
[
'Total',
'',
'',
'',
formatPointNumber(total),
formatPointNumber(totalPaid),
formatPointNumber(totalDue),
]
],
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),
),
];
}));
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/${appsName}-purchase-report.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Purchase Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,161 @@
import 'dart:io';
import 'package:excel/excel.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/Screens/Purchase/Model/purchase_transaction_model.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import '../../model/business_info_model.dart';
import '../../model/sale_transaction_model.dart';
Future<void> generatePurchaseReturnReportExcel(
BuildContext context,
List<PurchaseTransaction>? data,
BusinessInformationModel? business,
DateTime? fromDate,
DateTime? toDate,
) async {
EasyLoading.show(status: 'Generating Excel');
try {
final excel = Excel.createExcel();
final sheet = excel['Purchase Return Report'];
// ---- DATE RANGE ----
String fromStr = fromDate != null ? DateFormat('dd-MM-yyyy').format(fromDate) : '';
String toStr = toDate != null ? DateFormat('dd-MM-yyyy').format(toDate) : '';
// ---- TOTAL CALCULATION ----
double total = 0;
double totalPaid = 0;
double totalDue = 0;
num totalReturnedAmount = 0;
if (data != null) {
for (var item in data) {
total += item.totalAmount ?? 0;
totalPaid += item.paidAmount ?? 0;
totalDue += item.dueAmount ?? 0;
}
}
double getReturnedAmountForItem(item) {
double returned = 0;
for (var purchaseReturn in item.purchaseReturns ?? []) {
for (var details in purchaseReturn.purchaseReturnDetails ?? []) {
returned += details.returnAmount ?? 0;
}
}
return returned;
}
if (data != null) {
for (var item in data) {
for (var purchaseReturn in item.purchaseReturns ?? []) {
for (var details in purchaseReturn.purchaseReturnDetails ?? []) {
totalReturnedAmount += details.returnAmount ?? 0;
}
}
}
}
// ----------------------------- //
// HEADER ROWS //
// ----------------------------- //
// Row 1: Company Name
sheet.appendRow([TextCellValue(business?.data?.companyName ?? '')]);
// Row 2: Report Title
sheet.appendRow([TextCellValue('Purchase Returned Report')]);
// Row 3: Duration
sheet.appendRow([
TextCellValue('Duration: $fromStr to $toStr'),
]);
// Row 4: Empty Space
sheet.appendRow([]);
// Row 5: Table Headers
final headerStartRow = sheet.maxRows;
sheet.appendRow([
TextCellValue('Reference'),
TextCellValue('Date'),
TextCellValue('Supplier'),
TextCellValue('Status'),
TextCellValue('Total'),
TextCellValue('Paid'),
TextCellValue('Due'),
TextCellValue('Return Amount'),
]);
// Apply bold header style
for (int i = 0; i < 8; i++) {
sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: headerStartRow)).cellStyle;
}
// Row 6: Space before data
sheet.appendRow([]);
// ----------------------------- //
// TABLE DATA ROWS //
// ----------------------------- //
if (data != null) {
for (var item in data) {
double returnedAmount = getReturnedAmountForItem(item);
sheet.appendRow([
TextCellValue(item.invoiceNumber ?? 'n/a'),
TextCellValue(DateFormat('dd-MM-yyyy').format(DateTime.parse(item.purchaseDate.toString()))),
TextCellValue(item.party?.name ?? 'n/a'),
TextCellValue(item.isPaid == true ? 'Paid' : 'Unpaid'),
TextCellValue((item.totalAmount ?? 0).toStringAsFixed(2)),
TextCellValue((item.paidAmount ?? 0).toStringAsFixed(2)),
TextCellValue((item.dueAmount ?? 0).toStringAsFixed(2)),
TextCellValue(returnedAmount.toStringAsFixed(2)),
]);
}
}
// ----------------------------- //
// TOTAL ROW //
// ----------------------------- //
final totalRowIndex = sheet.maxRows;
sheet.appendRow([
TextCellValue('Total'),
TextCellValue(''),
TextCellValue(''),
TextCellValue(''),
TextCellValue(total.toStringAsFixed(2)),
TextCellValue(totalPaid.toStringAsFixed(2)),
TextCellValue(totalDue.toStringAsFixed(2)),
TextCellValue(totalReturnedAmount.toStringAsFixed(2)),
]);
// Apply bold style
for (int i = 0; i < 8; i++) {
sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: totalRowIndex)).cellStyle;
}
// ----------------------------- //
// SAVE FILE //
// ----------------------------- //
final dir = await getApplicationDocumentsDirectory();
final filePath = '${dir.path}/${business?.data?.companyName ?? "Company"}_purchase_return_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('Excel Generation Error: $e');
}
}

View File

@@ -0,0 +1,273 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/Screens/Purchase/Model/purchase_transaction_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 '../../model/business_info_model.dart';
import '../../model/sale_transaction_model.dart';
Future<void> generatePurchaseReturnReportPdf(
BuildContext context, List<PurchaseTransaction>? data, BusinessInformationModel? business, DateTime? fromDate, DateTime? toDate) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
double total = 0;
double totalDue = 0;
double totalPaid = 0;
num totalReturnedAmount = 0;
// Calculate totals from data
if (data != null) {
for (var item in data) {
final totalAmounts = item.totalAmount ?? 0;
total += totalAmounts;
}
}
//total due
if (data != null) {
for (var item in data) {
final due = item.dueAmount ?? 0;
totalDue += due;
}
}
//total paid
if (data != null) {
for (var item in data) {
final paid = item.paidAmount ?? 0;
totalPaid += paid;
}
}
double getReturnedAmountForItem(item) {
double returned = 0;
for (var purchaseReturn in item.purchaseReturns ?? []) {
for (var details in purchaseReturn.purchaseReturnDetails ?? []) {
returned += details.returnAmount ?? 0;
}
}
return returned;
}
if (data != null) {
for (var item in data) {
for (var purchaseReturn in item.purchaseReturns ?? []) {
for (var details in purchaseReturn.purchaseReturnDetails ?? []) {
totalReturnedAmount += details.returnAmount ?? 0;
}
}
}
}
try {
pdf.addPage(pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Purchase Return Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null ? 'Duration: ${DateFormat('dd-MM-yyyy').format(fromDate)} to ${DateFormat('dd-MM-yyyy').format(toDate!)}' : '',
style: pw.TextStyle(
font: interFont,
fontSize: 12,
),
),
],
),
);
},
//-----------------pdf footer-------------
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++) {
double returnedAmount = getReturnedAmountForItem(data[i]);
tableData.add([
// '${i + 1}',
data[i].invoiceNumber ?? 'n/a',
DateFormat('dd-MM-yyyy').format(DateTime.parse(data[i].purchaseDate.toString())),
data[i].party!.name ?? 'n/a',
// data[i]. ?? 'n/a',
data[i].isPaid == true ? 'Paid' : 'Unpaid',
data[i].totalAmount.toString(),
data[i].paidAmount.toString(),
data[i].dueAmount.toString(),
formatPointNumber(returnedAmount),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
// 'SL',
'Reference',
'Date',
'Supplier',
'Status',
'Total',
'Paid',
'Due',
'Return Amount',
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(4),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(3),
6: const pw.FlexColumnWidth(3),
7: const pw.FlexColumnWidth(3),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
7: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(4),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(3),
6: const pw.FlexColumnWidth(3),
7: const pw.FlexColumnWidth(3),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
7: pw.Alignment.center,
},
data: [
[
'Total',
'',
'',
'',
formatPointNumber(total),
formatPointNumber(totalPaid),
formatPointNumber(totalDue),
formatPointNumber(totalReturnedAmount),
]
],
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),
),
];
}));
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/${appsName}-purhase-return-report.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Purchase Return Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,132 @@
import 'dart:io';
import 'package:excel/excel.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import '../../model/business_info_model.dart';
import '../../model/sale_transaction_model.dart';
Future<void> generateSaleReportExcel(
BuildContext context,
List<SalesTransactionModel>? data,
BusinessInformationModel? business,
DateTime? fromDate,
DateTime? toDate,
) async {
EasyLoading.show(status: 'Generating Excel');
try {
final excel = Excel.createExcel();
final sheet = excel['Sales Report'];
// ---- DATE RANGE ----
String fromStr = fromDate != null ? DateFormat('dd-MM-yyyy').format(fromDate) : '';
String toStr = toDate != null ? DateFormat('dd-MM-yyyy').format(toDate!) : '';
// ---- TOTAL CALCULATION ----
double total = 0;
double totalPaid = 0;
double totalDue = 0;
if (data != null) {
for (var item in data) {
total += item.totalAmount ?? 0;
totalPaid += item.paidAmount ?? 0;
totalDue += item.dueAmount ?? 0;
}
}
// ----------------------------- //
// HEADER ROWS //
// ----------------------------- //
// Row 1: Company Name
sheet.appendRow([TextCellValue(business?.data?.companyName ?? '')]);
// Row 2: Report Title
sheet.appendRow([TextCellValue('Sales Report')]);
// Row 3: Duration
sheet.appendRow([
TextCellValue('Duration: $fromStr to $toStr'),
]);
// Row 4: Empty Space
sheet.appendRow([]);
// Row 5: Table Headers
final headerStartRow = sheet.maxRows;
sheet.appendRow([
TextCellValue('Reference'),
TextCellValue('Date'),
TextCellValue('Customer'),
TextCellValue('Status'),
TextCellValue('Total'),
TextCellValue('Paid'),
TextCellValue('Due'),
]);
// Apply bold header style
for (int i = 0; i < 7; i++) {
sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: headerStartRow)).cellStyle;
}
// Row 6: Space before data
sheet.appendRow([]);
// ----------------------------- //
// TABLE DATA ROWS //
// ----------------------------- //
if (data != null) {
for (var item in data) {
sheet.appendRow([
TextCellValue(item.invoiceNumber ?? 'n/a'),
TextCellValue(DateFormat('dd-MM-yyyy').format(DateTime.parse(item.saleDate.toString()))),
TextCellValue(item.party?.name ?? 'n/a'),
TextCellValue(item.isPaid == true ? 'Paid' : 'Unpaid'),
TextCellValue((item.totalAmount ?? 0).toStringAsFixed(2)),
TextCellValue((item.paidAmount ?? 0).toStringAsFixed(2)),
TextCellValue((item.dueAmount ?? 0).toStringAsFixed(2)),
]);
}
}
// ----------------------------- //
// TOTAL ROW //
// ----------------------------- //
final totalRowIndex = sheet.maxRows;
sheet.appendRow([
TextCellValue('Total'),
TextCellValue(''),
TextCellValue(''),
TextCellValue(''),
TextCellValue(total.toStringAsFixed(2)),
TextCellValue(totalPaid.toStringAsFixed(2)),
TextCellValue(totalDue.toStringAsFixed(2)),
]);
// Apply bold style
for (int i = 0; i < 7; i++) {
sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: totalRowIndex)).cellStyle;
}
// ----------------------------- //
// SAVE FILE //
// ----------------------------- //
final dir = await getApplicationDocumentsDirectory();
final filePath = '${dir.path}/${business?.data?.companyName ?? "Company"}_Sales_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('Excel Generation Error: $e');
}
}

View File

@@ -0,0 +1,239 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.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 '../../model/business_info_model.dart';
import '../../model/sale_transaction_model.dart';
Future<void> generateSaleReportPdf(BuildContext context, List<SalesTransactionModel>? data, BusinessInformationModel? business, DateTime? fromDate, DateTime? toDate) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
double total = 0;
double totalDue = 0;
double totalPaid = 0;
// Calculate totals from data
if (data != null) {
for (var item in data) {
final totalAmounts = item.totalAmount ?? 0;
total += totalAmounts;
}
}
//total due
if (data != null) {
for (var item in data) {
final due = item.paidAmount ?? 0;
totalDue += due;
}
}
//total paid
if (data != null) {
for (var item in data) {
final paid = item.dueAmount ?? 0;
totalPaid += paid;
}
}
try {
pdf.addPage(pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Sales Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null ? 'Duration: ${DateFormat('dd-MM-yyyy').format(fromDate)} to ${DateFormat('dd-MM-yyyy').format(toDate!)}' : '',
style: pw.TextStyle(
font: interFont,
fontSize: 12,
),
),
],
),
);
},
//-----------------pdf footer-------------
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++) {
tableData.add([
// '${i + 1}',
data[i].invoiceNumber ?? 'n/a',
DateFormat('dd-MM-yyyy').format(DateTime.parse(data[i].saleDate.toString())),
data[i].party!.name ?? 'n/a',
// data[i]. ?? 'n/a',
data[i].isPaid == true ? 'Paid' : 'Unpaid',
data[i].totalAmount.toString(),
data[i].paidAmount.toString(),
data[i].dueAmount.toString(),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
// 'SL',
'Reference',
'Date',
'Customer',
'Status',
'Total',
'Paid',
'Due',
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
data: [
[
'Total',
'',
'',
'',
formatPointNumber(total),
formatPointNumber(totalPaid),
formatPointNumber(totalDue),
]
],
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),
),
];
}));
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/${appsName}-loss-profit-report.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,160 @@
import 'dart:io';
import 'package:excel/excel.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import '../../model/business_info_model.dart';
import '../../model/sale_transaction_model.dart';
Future<void> generateSaleReturnReportExcel(
BuildContext context,
List<SalesTransactionModel>? data,
BusinessInformationModel? business,
DateTime? fromDate,
DateTime? toDate,
) async {
EasyLoading.show(status: 'Generating Excel');
try {
final excel = Excel.createExcel();
final sheet = excel['Sales Return Report'];
// ---- DATE RANGE ----
String fromStr = fromDate != null ? DateFormat('dd-MM-yyyy').format(fromDate) : '';
String toStr = toDate != null ? DateFormat('dd-MM-yyyy').format(toDate!) : '';
// ---- TOTAL CALCULATION ----
double total = 0;
double totalPaid = 0;
double totalDue = 0;
num totalReturnedAmount = 0;
if (data != null) {
for (var item in data) {
total += item.totalAmount ?? 0;
totalPaid += item.paidAmount ?? 0;
totalDue += item.dueAmount ?? 0;
}
}
double getReturnedAmountForItem(item) {
double returned = 0;
for (var salesReturn in item.salesReturns ?? []) {
for (var sales in salesReturn.salesReturnDetails ?? []) {
returned += sales.returnAmount ?? 0;
}
}
return returned;
}
if (data != null) {
for (var item in data) {
for (var salesReturn in item.salesReturns ?? []) {
for (var sales in salesReturn.salesReturnDetails ?? []) {
totalReturnedAmount += sales.returnAmount ?? 0;
}
}
}
}
// ----------------------------- //
// HEADER ROWS //
// ----------------------------- //
// Row 1: Company Name
sheet.appendRow([TextCellValue(business?.data?.companyName ?? '')]);
// Row 2: Report Title
sheet.appendRow([TextCellValue('Sales Returned Report')]);
// Row 3: Duration
sheet.appendRow([
TextCellValue('Duration: $fromStr to $toStr'),
]);
// Row 4: Empty Space
sheet.appendRow([]);
// Row 5: Table Headers
final headerStartRow = sheet.maxRows;
sheet.appendRow([
TextCellValue('Reference'),
TextCellValue('Date'),
TextCellValue('Customer'),
TextCellValue('Status'),
TextCellValue('Total'),
TextCellValue('Paid'),
TextCellValue('Due'),
TextCellValue('Return Amount'),
]);
// Apply bold header style
for (int i = 0; i < 8; i++) {
sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: headerStartRow)).cellStyle;
}
// Row 6: Space before data
sheet.appendRow([]);
// ----------------------------- //
// TABLE DATA ROWS //
// ----------------------------- //
if (data != null) {
for (var item in data) {
double returnedAmount = getReturnedAmountForItem(item);
sheet.appendRow([
TextCellValue(item.invoiceNumber ?? 'n/a'),
TextCellValue(DateFormat('dd-MM-yyyy').format(DateTime.parse(item.saleDate.toString()))),
TextCellValue(item.party?.name ?? 'n/a'),
TextCellValue(item.isPaid == true ? 'Paid' : 'Unpaid'),
TextCellValue((item.totalAmount ?? 0).toStringAsFixed(2)),
TextCellValue((item.paidAmount ?? 0).toStringAsFixed(2)),
TextCellValue((item.dueAmount ?? 0).toStringAsFixed(2)),
TextCellValue(returnedAmount.toStringAsFixed(2)),
]);
}
}
// ----------------------------- //
// TOTAL ROW //
// ----------------------------- //
final totalRowIndex = sheet.maxRows;
sheet.appendRow([
TextCellValue('Total'),
TextCellValue(''),
TextCellValue(''),
TextCellValue(''),
TextCellValue(total.toStringAsFixed(2)),
TextCellValue(totalPaid.toStringAsFixed(2)),
TextCellValue(totalDue.toStringAsFixed(2)),
TextCellValue(totalReturnedAmount.toStringAsFixed(2)),
]);
// Apply bold style
for (int i = 0; i < 8; i++) {
sheet.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: totalRowIndex)).cellStyle;
}
// ----------------------------- //
// SAVE FILE //
// ----------------------------- //
final dir = await getApplicationDocumentsDirectory();
final filePath = '${dir.path}/${business?.data?.companyName ?? "Company"}_Sales_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('Excel Generation Error: $e');
}
}

View File

@@ -0,0 +1,271 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.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 '../../model/business_info_model.dart';
import '../../model/sale_transaction_model.dart';
Future<void> generateSaleReturnReportPdf(BuildContext context, List<SalesTransactionModel>? data, BusinessInformationModel? business, DateTime? fromDate, DateTime? toDate) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
double total = 0;
double totalDue = 0;
double totalPaid = 0;
num totalReturnedAmount = 0;
// Calculate totals from data
if (data != null) {
for (var item in data) {
final totalAmounts = item.totalAmount ?? 0;
total += totalAmounts;
}
}
//total due
if (data != null) {
for (var item in data) {
final due = item.dueAmount ?? 0;
totalDue += due;
}
}
//total paid
if (data != null) {
for (var item in data) {
final paid = item.paidAmount ?? 0;
totalPaid += paid;
}
}
double getReturnedAmountForItem(item) {
double returned = 0;
for (var salesReturn in item.salesReturns ?? []) {
for (var sales in salesReturn.salesReturnDetails ?? []) {
returned += sales.returnAmount ?? 0;
}
}
return returned;
}
if (data != null) {
for (var item in data) {
for (var salesReturn in item.salesReturns ?? []) {
for (var sales in salesReturn.salesReturnDetails ?? []) {
totalReturnedAmount += sales.returnAmount ?? 0;
}
}
}
}
try {
pdf.addPage(pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Sales Return Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null ? 'Duration: ${DateFormat('dd-MM-yyyy').format(fromDate)} to ${DateFormat('dd-MM-yyyy').format(toDate!)}' : '',
style: pw.TextStyle(
font: interFont,
fontSize: 12,
),
),
],
),
);
},
//-----------------pdf footer-------------
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++) {
double returnedAmount = getReturnedAmountForItem(data[i]);
tableData.add([
// '${i + 1}',
data[i].invoiceNumber ?? 'n/a',
DateFormat('dd-MM-yyyy').format(DateTime.parse(data[i].saleDate.toString())),
data[i].party!.name ?? 'n/a',
// data[i]. ?? 'n/a',
data[i].isPaid == true ? 'Paid' : 'Unpaid',
data[i].totalAmount.toString(),
data[i].paidAmount.toString(),
data[i].dueAmount.toString(),
formatPointNumber(returnedAmount),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
// 'SL',
'Reference',
'Date',
'Customer',
'Status',
'Total',
'Paid',
'Due',
'Return Amount',
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(4),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(3),
6: const pw.FlexColumnWidth(3),
7: const pw.FlexColumnWidth(3),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
7: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(4),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(3),
6: const pw.FlexColumnWidth(3),
7: const pw.FlexColumnWidth(3),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
7: pw.Alignment.center,
},
data: [
[
'Total',
'',
'',
'',
formatPointNumber(total),
formatPointNumber(totalPaid),
formatPointNumber(totalDue),
formatPointNumber(totalReturnedAmount),
]
],
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),
),
];
}));
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/${appsName}-loss-profit-report.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

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');
}
}

View File

@@ -0,0 +1,192 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.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/Income/Model/income_modle.dart';
import '../../Screens/PDF/pdf.dart';
import '../../model/business_info_model.dart';
import '../ledger_report/generate_pdf_date_range.dart';
Future<void> generateTopFiveReportPdf(
BuildContext context,
List<Product>? data,
BusinessInformationModel? business,
) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
double totalAmount = 0;
// Calculate totals from data
if (data != null) {
for (var item in data) {
totalAmount += item.totalSaleAmount ?? 0;
}
}
// print('--font family---$ttf---------------');
try {
pdf.addPage(pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Top 5 Product Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
],
),
);
},
//-----------------pdf footer-------------
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++) {
tableData.add([
'${i + 1}',
data[i].productName ?? '',
data[i].productCode ?? '',
data[i].saleCount?.toString() ?? '',
data[i].totalSaleAmount?.toString() ?? '',
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
'SL',
'Product Name',
'Product Code',
'Total Sales',
'Total Amount',
],
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(1),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(2),
3: const pw.FlexColumnWidth(2),
4: const pw.FlexColumnWidth(2),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(2),
3: const pw.FlexColumnWidth(2),
4: const pw.FlexColumnWidth(2),
},
data: [
[
'Total',
'',
'',
'',
totalAmount.toStringAsFixed(2),
]
],
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),
),
];
}));
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/${appsName}-top-5-product.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Top 5 Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,209 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart' as intl;
import 'package:mobile_pos/Screens/all_transaction/all_transaction.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/all_transaction/model/transaction_model.dart' as tmodel;
import '../../model/business_info_model.dart';
Future<void> generateAllTransactionReportPdf(
BuildContext context,
tmodel.TransactionModel data,
BusinessInformationModel? business,
DateTime? fromDate,
DateTime? toDate,
) async {
final pw.Document pdf = pw.Document();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'All Transaction Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
],
),
);
},
//-----------------pdf footer-------------
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.data?.length ?? 0); i++) {
final _transaction = [...?data.data][i];
tableData.add([
"${i + 1}",
_transaction.date == null
? "N/A"
: intl.DateFormat('dd MMM, yyyy').format(DateTime.parse(_transaction.date!)),
_transaction.invoiceNo ?? "N/A",
_transaction.platform?.toTitleCase() ?? "N/A",
formatPointNumber(_transaction.amount ?? 0, addComma: DateTime.now().minute.isEven),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"SL.",
"Date",
"Reference",
"Type",
"Amount",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
data: [
[
'Total',
'',
'',
'',
'',
'',
formatPointNumber(data.totalAmount ?? 0),
]
],
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),
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-customer-ledger.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,181 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.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 '../../model/balance_sheet_model.dart' as model;
import '../../model/business_info_model.dart';
Future<void> generateBalanceSheetReportPdf(BuildContext context, model.BalanceSheetModel data,
BusinessInformationModel? business, DateTime? fromDate, DateTime? toDate) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Balance Sheet',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null
? 'Duration: ${DateFormat('dd-MM-yyyy').format(fromDate)} to ${DateFormat('dd-MM-yyyy').format(toDate!)}'
: '',
style: pw.TextStyle(
font: interFont,
fontSize: 12,
),
),
],
),
);
},
//-----------------pdf footer-------------
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.data?.length ?? 0); i++) {
final _asset = data.data?[i];
tableData.add([
// Asset
_asset?.name ?? '',
formatPointNumber(_asset?.amount ?? 0, addComma: true),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: ["Assets", "Amout"],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(5),
1: const pw.FlexColumnWidth(5),
},
cellAlignments: {
0: pw.Alignment.centerLeft,
1: pw.Alignment.centerRight,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(5),
1: const pw.FlexColumnWidth(5),
},
cellAlignments: {
0: pw.Alignment.centerLeft,
1: pw.Alignment.centerRight,
},
data: [
[
"Total",
formatPointNumber(data.totalAsset ?? 0, addComma: true),
]
],
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),
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-loss-profit-report.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Loss Profit Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,227 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart' as intl;
import 'package:mobile_pos/Screens/Report/Screens/cashflow_screen.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 '../../model/business_info_model.dart';
import '../../model/cashflow_model.dart' as cf;
Future<void> generateCashflowReportPdf(BuildContext context, cf.CashflowModel data, BusinessInformationModel? business,
DateTime? fromDate, DateTime? toDate) async {
final pw.Document pdf = pw.Document();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
num initialRunningCash = data.initialRunningCash ?? 0;
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Cash Flow',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
],
),
);
},
//-----------------pdf footer-------------
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.data?.length ?? 0); i++) {
final _transaction = [...?data.data][i];
final _runningCash = _transaction.type == 'credit'
? initialRunningCash + (_transaction.amount ?? 0)
: initialRunningCash - (_transaction.amount ?? 0);
tableData.add(
[
"${i + 1}",
_transaction.date == null ? "N/A" : intl.DateFormat("dd MMM, yyyy").format(_transaction.date!),
_transaction.invoiceNo ?? "N/A",
_transaction.partyName ?? "N/A",
_transaction.type?.toTitleCase() ?? "N/A",
_transaction.type == "credit" ? formatPointNumber(_transaction.amount ?? 0) : "0",
_transaction.type == "debit" ? formatPointNumber(_transaction.amount ?? 0) : "0",
formatPointNumber(initialRunningCash = _runningCash),
_transaction.paymentType ?? _transaction.transactionType?.split('_')[0].toTitleCase() ?? "N/A",
],
);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"SL.",
"Date",
"Invoice",
"Name",
"Type",
"Cash In",
"Cash Out",
"Running Cash",
"Payment",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(4),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(3),
6: const pw.FlexColumnWidth(3),
7: const pw.FlexColumnWidth(3),
8: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
7: pw.Alignment.center,
8: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(4),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(3),
6: const pw.FlexColumnWidth(3),
7: const pw.FlexColumnWidth(3),
8: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
7: pw.Alignment.center,
8: pw.Alignment.center,
},
data: [
[
'Total',
'',
'',
'',
'',
formatPointNumber(data.cashIn ?? 0),
formatPointNumber(data.cashOut ?? 0),
formatPointNumber(initialRunningCash),
'',
]
],
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),
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-customer-ledger.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,212 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.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/all_transaction/model/transaction_model.dart' as tmodel;
import '../../model/business_info_model.dart';
Future<void> generateDayBookReportPdf(BuildContext context, tmodel.TransactionModel data,
BusinessInformationModel? business, DateTime? fromDate, DateTime? toDate) async {
final pw.Document pdf = pw.Document();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
num getMoneyIn(tmodel.TransactionModelData t) {
return t.type == 'credit' ? (t.amount ?? 0) : 0;
}
num getMoneyOut(tmodel.TransactionModelData t) {
return t.type == 'debit' ? (t.amount ?? 0) : 0;
}
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Day Book Report',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
],
),
);
},
//-----------------pdf footer-------------
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.data?.length ?? 0); i++) {
final _transaction = [...?data.data][i];
tableData.add([
_transaction.referenceId?.toString() ?? "",
_transaction.party?.name ?? "",
_transaction.date ?? "",
_transaction.type ?? "",
formatPointNumber(_transaction.totalAmount ?? 0, addComma: true),
formatPointNumber(getMoneyIn(_transaction), addComma: true),
formatPointNumber(getMoneyOut(_transaction), addComma: true),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"Reference",
"Name",
"Date",
"Type",
"Total",
"Money In",
"Money Out",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(4),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
data: [
[
'Total',
'',
'',
'',
formatPointNumber(data.totalAmount ?? 0),
formatPointNumber(data.moneyIn ?? 0),
formatPointNumber(data.moneyOut ?? 0),
]
],
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),
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-customer-ledger.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,215 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart' as intl;
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 '../../model/business_info_model.dart';
import '../../model/product_history_model.dart' as phlm;
Future<void> generateProductWisePurchaseHistoryDetailsReportPdf(
BuildContext context,
phlm.ProductHistoryDetailsModel data,
BusinessInformationModel? business,
DateTime? fromDate,
DateTime? toDate,
) async {
final pw.Document pdf = pw.Document();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
data.productName ?? "N/A",
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null
? 'Duration: ${intl.DateFormat('dd-MM-yyyy').format(fromDate)} to ${intl.DateFormat('dd-MM-yyyy').format(toDate!)}'
: '',
style: pw.TextStyle(fontSize: 12),
),
],
),
);
},
//-----------------pdf footer-------------
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 _transactions = [...?data.items];
final List<List<String>> tableData = [];
for (int i = 0; i < (data.items?.length ?? 0); i++) {
final _transaction = _transactions[i];
tableData.add(
[
"${i + 1}",
_transaction.invoiceNo ?? "N/A",
_transaction.transactionDate != null
? intl.DateFormat('dd-MM-yyyy').format(_transaction.transactionDate!)
: "N/A",
_transaction.type ?? "N/A",
formatPointNumber(_transaction.quantities ?? 0),
formatPointNumber(_transaction.purchasePrice ?? 0, addComma: true),
],
);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.TableHelper.fromTextArray(
headers: [
"SL",
"Invoice",
"Date",
"Type",
"Qty",
"Cost Price",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(1.5),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(4),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
},
),
// Totals row (styled to match)
pw.TableHelper.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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(1.5),
1: const pw.FlexColumnWidth(3),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(4),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
},
data: [
[
'',
'Total',
'',
'',
formatPointNumber(data.totalQuantities ?? 0),
formatPointNumber(data.totalPurchasePrice ?? 0, addComma: true),
]
],
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),
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-customer-ledger.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,213 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart' as intl;
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 '../../model/business_info_model.dart';
import '../../model/product_history_model.dart' as phlm;
Future<void> generateProductWisePurchaseHistoryReportPdf(
BuildContext context,
phlm.ProductHistoryListModel data,
BusinessInformationModel? business,
DateTime? fromDate,
DateTime? toDate,
) async {
final pw.Document pdf = pw.Document();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Product Purchase History',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null
? 'Duration: ${intl.DateFormat('dd-MM-yyyy').format(fromDate)} to ${intl.DateFormat('dd-MM-yyyy').format(toDate!)}'
: '',
style: pw.TextStyle(fontSize: 12),
),
],
),
);
},
//-----------------pdf footer-------------
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 _transactions = [...?data.items];
final List<List<String>> tableData = [];
for (int i = 0; i < (data.items?.length ?? 0); i++) {
final _transaction = _transactions[i];
tableData.add(
[
"${i + 1}",
_transaction.name ?? "N/A",
formatPointNumber(_transaction.purchasePrice ?? 0, addComma: true),
formatPointNumber(_transaction.purchaseQuantity ?? 0),
formatPointNumber(_transaction.saleQuantity ?? 0),
formatPointNumber(_transaction.remainingQuantity ?? 0),
],
);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"SL",
"Name",
"Cost Price",
"Purchase Qty",
"Sold Qty",
"Remaining Qty",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(1.5),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(4),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(1.5),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(4),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
},
data: [
[
'',
'Total',
formatPointNumber(data.totalSalePrice, addComma: true),
formatPointNumber(data.totalPurchaseQuantity ?? 0),
formatPointNumber(data.totalSaleQuantity ?? 0),
formatPointNumber(data.totalRemainingQuantity),
]
],
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),
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-customer-ledger.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,215 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart' as intl;
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 '../../model/business_info_model.dart';
import '../../model/product_history_model.dart' as phlm;
Future<void> generateProductWiseSaleHistoryDetailsReportPdf(
BuildContext context,
phlm.ProductHistoryDetailsModel data,
BusinessInformationModel? business,
DateTime? fromDate,
DateTime? toDate,
) async {
final pw.Document pdf = pw.Document();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
data.productName ?? "N/A",
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null
? 'Duration: ${intl.DateFormat('dd-MM-yyyy').format(fromDate)} to ${intl.DateFormat('dd-MM-yyyy').format(toDate!)}'
: '',
style: pw.TextStyle(fontSize: 12),
),
],
),
);
},
//-----------------pdf footer-------------
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 _transactions = [...?data.items];
final List<List<String>> tableData = [];
for (int i = 0; i < (data.items?.length ?? 0); i++) {
final _transaction = _transactions[i];
tableData.add(
[
"${i + 1}",
_transaction.invoiceNo ?? "N/A",
_transaction.transactionDate != null
? intl.DateFormat('dd-MM-yyyy').format(_transaction.transactionDate!)
: "N/A",
formatPointNumber(_transaction.quantities ?? 0),
formatPointNumber(_transaction.purchasePrice ?? 0, addComma: true),
formatPointNumber(_transaction.salePrice ?? 0, addComma: true),
],
);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"SL",
"Invoice",
"Date",
"Qty",
"Cost Price",
"Sales Price",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(1.5),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(1.5),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
},
data: [
[
'',
'Total',
'',
formatPointNumber(data.totalQuantities ?? 0),
formatPointNumber(data.totalPurchasePrice ?? 0, addComma: true),
formatPointNumber(data.totalSalePrice ?? 0, addComma: true),
]
],
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),
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-customer-ledger.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,213 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart' as intl;
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 '../../model/business_info_model.dart';
import '../../model/product_history_model.dart' as phlm;
Future<void> generateProductWiseSaleHistoryReportPdf(
BuildContext context,
phlm.ProductHistoryListModel data,
BusinessInformationModel? business,
DateTime? fromDate,
DateTime? toDate,
) async {
final pw.Document pdf = pw.Document();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Product Sale History',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null
? 'Duration: ${intl.DateFormat('dd-MM-yyyy').format(fromDate)} to ${intl.DateFormat('dd-MM-yyyy').format(toDate!)}'
: '',
style: pw.TextStyle(fontSize: 12),
),
],
),
);
},
//-----------------pdf footer-------------
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 _transactions = [...?data.items];
final List<List<String>> tableData = [];
for (int i = 0; i < (data.items?.length ?? 0); i++) {
final _transaction = _transactions[i];
tableData.add(
[
"${i + 1}",
_transaction.name ?? "N/A",
formatPointNumber(_transaction.salePrice ?? 0, addComma: true),
formatPointNumber(_transaction.purchaseQuantity ?? 0),
formatPointNumber(_transaction.saleQuantity ?? 0),
formatPointNumber(_transaction.remainingQuantity ?? 0),
],
);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"SL",
"Name",
"Sales Price",
"Purchase Qty",
"Sold Qty",
"Remaining Qty",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(1.5),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(1.5),
1: const pw.FlexColumnWidth(5),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
},
data: [
[
'',
'Total',
formatPointNumber(data.totalSalePrice, addComma: true),
formatPointNumber(data.totalPurchaseQuantity ?? 0),
formatPointNumber(data.totalSaleQuantity ?? 0),
formatPointNumber(data.totalRemainingQuantity),
]
],
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),
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-customer-ledger.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,171 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.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 '../../model/subscription_report_model.dart' as model;
import '../../model/business_info_model.dart';
Future<void> generateSubscriptionReportPdf(BuildContext context, List<model.SubscriptionReportModel> data,
BusinessInformationModel? business, DateTime? fromDate, DateTime? toDate) async {
final pw.Document pdf = pw.Document();
final interFont = await PdfGoogleFonts.notoSansRegular();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Subscription Reports',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null
? 'Duration: ${DateFormat('dd-MM-yyyy').format(fromDate)} to ${DateFormat('dd-MM-yyyy').format(toDate!)}'
: '',
style: pw.TextStyle(
font: interFont,
fontSize: 12,
),
),
],
),
);
},
//-----------------pdf footer-------------
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 _subscription = data[i];
tableData.add([
"${i + 1}",
_subscription.startDate == null ? "N/A" : DateFormat('dd MMM yyyy').format(_subscription.startDate!),
_subscription.name ?? "N/A",
_subscription.startDate == null ? "N/A" : DateFormat('dd MMM yyyy').format(_subscription.startDate!),
_subscription.startDate == null ? "N/A" : DateFormat('dd MMM yyyy').format(_subscription.startDate!),
_subscription.paymentBy ?? "N/A",
_subscription.isPaid ? "Paid" : "Unpaid",
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"SL",
"Date",
"Package",
"Started",
"End",
"Payment By",
"Status",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(2),
1: const pw.FlexColumnWidth(4),
2: const pw.FlexColumnWidth(4),
3: const pw.FlexColumnWidth(4),
4: const pw.FlexColumnWidth(4),
5: const pw.FlexColumnWidth(4),
6: const pw.FlexColumnWidth(4),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
},
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-loss-profit-report.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Loss Profit Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}

View File

@@ -0,0 +1,232 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:intl/intl.dart' as intl;
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 '../../model/business_info_model.dart';
import '../../model/tax_report_model.dart' as trm;
Future<void> generateTaxReportPdf(
BuildContext context,
trm.TaxReportModel data,
BusinessInformationModel? business,
DateTime? fromDate,
DateTime? toDate, {
bool isPurchase = false,
}) async {
final pw.Document pdf = pw.Document();
// Show loading indicator
EasyLoading.show(status: 'Generating PDF');
final _transactions = [...?(isPurchase ? data.purchases : data.sales)];
final _overview = isPurchase ? data.overviews?.firstOrNull : data.overviews?.lastOrNull;
try {
pdf.addPage(
pw.MultiPage(
pageFormat: PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
margin: pw.EdgeInsets.symmetric(horizontal: 16),
//----------------pdf header--------------
header: (pw.Context context) {
return pw.Center(
child: pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.center,
children: [
pw.Text(
business?.data?.companyName.toString() ?? '',
style: pw.TextStyle(
// font: interFont,
fontWeight: pw.FontWeight.bold,
fontSize: 20,
),
),
pw.Text(
// 'বিক্রয় প্রতিবেদন',
'Tax Report (${isPurchase ? 'Purchase' : 'Sales'})',
style: pw.TextStyle(
fontSize: 16,
fontWeight: pw.FontWeight.bold,
// font: ttf,
),
),
pw.SizedBox(height: 4),
pw.Text(
fromDate != null
? 'Duration: ${intl.DateFormat('dd-MM-yyyy').format(fromDate)} to ${intl.DateFormat('dd-MM-yyyy').format(toDate!)}'
: '',
style: pw.TextStyle(
fontSize: 12,
),
),
],
),
);
},
//-----------------pdf footer-------------
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 < _transactions.length; i++) {
final _transaction = _transactions[i];
tableData.add([
"${i + 1}",
_transaction.invoiceNumber ?? "N/A",
_transaction.transactionDate == null
? "N/A"
: intl.DateFormat("dd MMM, yyyy").format(_transaction.transactionDate!),
_transaction.partyName ?? "N/A",
_transaction.amount.toString(),
_transaction.discountAmount.toString(),
_transaction.vatName ?? "",
_transaction.vatAmount.toString(),
]);
}
return [
pw.SizedBox(height: 16),
// Main Table
pw.Table.fromTextArray(
headers: [
"SL",
"Invoice",
"Date",
"Name",
"Amount",
"Discount",
"Vat",
"Vat Value",
],
data: tableData,
headerDecoration: const pw.BoxDecoration(
color: PdfColor.fromInt(0xffC52127),
),
cellAlignment: pw.Alignment.center,
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(1.75),
1: const pw.FlexColumnWidth(2),
2: const pw.FlexColumnWidth(3),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(3),
6: const pw.FlexColumnWidth(3),
7: const pw.FlexColumnWidth(2),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
7: pw.Alignment.center,
},
),
// Totals row (styled to match)
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: <int, pw.TableColumnWidth>{
0: const pw.FlexColumnWidth(3),
1: const pw.FlexColumnWidth(2),
2: const pw.FlexColumnWidth(2),
3: const pw.FlexColumnWidth(3),
4: const pw.FlexColumnWidth(3),
5: const pw.FlexColumnWidth(3),
6: const pw.FlexColumnWidth(3),
7: const pw.FlexColumnWidth(2),
},
cellAlignments: {
0: pw.Alignment.center,
1: pw.Alignment.center,
2: pw.Alignment.center,
3: pw.Alignment.center,
4: pw.Alignment.center,
5: pw.Alignment.center,
6: pw.Alignment.center,
7: pw.Alignment.center,
},
data: [
[
"Total",
"",
"",
"",
formatPointNumber(_overview?.totalAmount ?? 0, addComma: true),
formatPointNumber(_overview?.totalDiscount ?? 0, addComma: true),
"",
formatPointNumber(_overview?.totalDiscount ?? 0, addComma: true),
]
],
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),
),
];
},
),
);
final byteData = await pdf.save();
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/$appsName-customer-ledger.pdf');
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
EasyLoading.showSuccess('Generate Complete');
//print pdf
if (context.mounted) {
await Printing.layoutPdf(
name: 'Sales Report',
usePrinterSettings: true,
dynamicLayout: true,
forceCustomPrintPaper: true,
onLayout: (PdfPageFormat format) async => pdf.save(),
);
}
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PDFViewerPage(path: file.path),
// ),
// );
} catch (e) {
EasyLoading.showError('Error: $e');
print('Error during PDF generation: $e');
}
}