first commit
This commit is contained in:
198
lib/pdf_report/combo_report/combo_report_pdf.dart
Normal file
198
lib/pdf_report/combo_report/combo_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
135
lib/pdf_report/due_report/due_report_excel.dart
Normal file
135
lib/pdf_report/due_report/due_report_excel.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
241
lib/pdf_report/due_report/due_report_pdf.dart
Normal file
241
lib/pdf_report/due_report/due_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
15
lib/pdf_report/due_report/due_status.dart
Normal file
15
lib/pdf_report/due_report/due_status.dart
Normal 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";
|
||||
}
|
||||
}
|
||||
113
lib/pdf_report/expense_report/expense_report_excel.dart
Normal file
113
lib/pdf_report/expense_report/expense_report_excel.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
210
lib/pdf_report/expense_report/expense_report_pdf.dart
Normal file
210
lib/pdf_report/expense_report/expense_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
230
lib/pdf_report/expire_report/expire_report_pdf.dart
Normal file
230
lib/pdf_report/expire_report/expire_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
114
lib/pdf_report/income_report/income_report_excel.dart
Normal file
114
lib/pdf_report/income_report/income_report_excel.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
217
lib/pdf_report/income_report/income_report_pdf.dart
Normal file
217
lib/pdf_report/income_report/income_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
57
lib/pdf_report/ledger_report/generate_pdf_date_range.dart
Normal file
57
lib/pdf_report/ledger_report/generate_pdf_date_range.dart
Normal 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};
|
||||
}
|
||||
297
lib/pdf_report/ledger_report/ledger_report_excel.dart
Normal file
297
lib/pdf_report/ledger_report/ledger_report_excel.dart
Normal 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');
|
||||
// }
|
||||
// }
|
||||
216
lib/pdf_report/ledger_report/ledger_report_pdf.dart
Normal file
216
lib/pdf_report/ledger_report/ledger_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
204
lib/pdf_report/ledger_report_pdf/customer_ledger_report_pdf.dart
Normal file
204
lib/pdf_report/ledger_report_pdf/customer_ledger_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
204
lib/pdf_report/ledger_report_pdf/supplier_ledger_report_pdf.dart
Normal file
204
lib/pdf_report/ledger_report_pdf/supplier_ledger_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
289
lib/pdf_report/loss_profit_report/loss_profit_pdf.dart
Normal file
289
lib/pdf_report/loss_profit_report/loss_profit_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
146
lib/pdf_report/loss_profit_report/loss_profit_report_excel.dart
Normal file
146
lib/pdf_report/loss_profit_report/loss_profit_report_excel.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
209
lib/pdf_report/party/party_wise_loss_profit_report_pdf.dart
Normal file
209
lib/pdf_report/party/party_wise_loss_profit_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
152
lib/pdf_report/party/top_5_customer_report_pdf.dart
Normal file
152
lib/pdf_report/party/top_5_customer_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
150
lib/pdf_report/party/top_5_supplier_report_pdf.dart
Normal file
150
lib/pdf_report/party/top_5_supplier_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
133
lib/pdf_report/purchase_report/purchase_report_excel.dart
Normal file
133
lib/pdf_report/purchase_report/purchase_report_excel.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
239
lib/pdf_report/purchase_report/purchase_report_pdf.dart
Normal file
239
lib/pdf_report/purchase_report/purchase_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
161
lib/pdf_report/purchase_return_report/purchase_return_excel.dart
Normal file
161
lib/pdf_report/purchase_return_report/purchase_return_excel.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
273
lib/pdf_report/purchase_return_report/purchase_returned_pdf.dart
Normal file
273
lib/pdf_report/purchase_return_report/purchase_returned_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
132
lib/pdf_report/sales_report/sales_report_excel.dart
Normal file
132
lib/pdf_report/sales_report/sales_report_excel.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
239
lib/pdf_report/sales_report/sales_report_pdf.dart
Normal file
239
lib/pdf_report/sales_report/sales_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
160
lib/pdf_report/sales_retunrn_report/sales_returned_excel.dart
Normal file
160
lib/pdf_report/sales_retunrn_report/sales_returned_excel.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
271
lib/pdf_report/sales_retunrn_report/sales_returned_pdf.dart
Normal file
271
lib/pdf_report/sales_retunrn_report/sales_returned_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
84
lib/pdf_report/stock_report_pdf/stock_report_excel.dart
Normal file
84
lib/pdf_report/stock_report_pdf/stock_report_excel.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
195
lib/pdf_report/stock_report_pdf/stock_report_pdf.dart
Normal file
195
lib/pdf_report/stock_report_pdf/stock_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
192
lib/pdf_report/top_five_product_report/top_five_product_pdf.dart
Normal file
192
lib/pdf_report/top_five_product_report/top_five_product_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
209
lib/pdf_report/transactions/all_transaction_report_pdf.dart
Normal file
209
lib/pdf_report/transactions/all_transaction_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
181
lib/pdf_report/transactions/balance_sheet_report_pdf.dart
Normal file
181
lib/pdf_report/transactions/balance_sheet_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
227
lib/pdf_report/transactions/cashflow_report_pdf.dart
Normal file
227
lib/pdf_report/transactions/cashflow_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
212
lib/pdf_report/transactions/daybook_report_pdf.dart
Normal file
212
lib/pdf_report/transactions/daybook_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
171
lib/pdf_report/transactions/subscription_report_pdf.dart
Normal file
171
lib/pdf_report/transactions/subscription_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
232
lib/pdf_report/transactions/tax_report_pdf.dart
Normal file
232
lib/pdf_report/transactions/tax_report_pdf.dart
Normal 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');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user