From 19738a5ff57be886d57d9940877ccf5d05e58b53 Mon Sep 17 00:00:00 2001 From: Sudipto Chandra Date: Thu, 10 Jun 2021 14:59:29 +0600 Subject: [PATCH] Keeps initial product quantity unchanged Previously, the product quantity was being decreased as new sales was being created. But the generated product report required to display the original product quantity. After this changes, the original product quantity will remain untouched. A new variable will be introduced to track number of units sold. Available units will be determined on the fly. While editing product, the price and quantity can not be modified after more than 1 units has been sold. --- lib/src/blocs/repository.dart | 4 +- lib/src/models/product.dart | 20 +++++- lib/src/models/product_report.dart | 8 ++- lib/src/models/report.dart | 4 +- lib/src/models/sales_record.dart | 32 +++++----- lib/src/models/sales_report.dart | 4 +- lib/src/pages/widgets/home_page_drawer.dart | 18 ++++-- .../pages/widgets/product_form_dialog.dart | 10 +-- lib/src/pages/widgets/product_item.dart | 23 ++++--- .../pages/widgets/product_report_view.dart | 9 ++- lib/src/pages/widgets/report_page_widget.dart | 2 +- lib/src/pages/widgets/sale_form_dialog.dart | 13 ++-- lib/src/pages/widgets/sales_preview.dart | 10 +-- lib/src/pages/widgets/sales_report_view.dart | 10 +-- lib/src/utils/generate_product_report.dart | 64 +++++++++++-------- lib/src/utils/generate_sales_report.dart | 61 +++++++++--------- pubspec.yaml | 2 +- 17 files changed, 167 insertions(+), 127 deletions(-) diff --git a/lib/src/blocs/repository.dart b/lib/src/blocs/repository.dart index a97bf82..fed01fb 100644 --- a/lib/src/blocs/repository.dart +++ b/lib/src/blocs/repository.dart @@ -142,8 +142,8 @@ class Repository { final doc = _products.doc(sales.productId); return doc.get().then((snapshot) { final product = snapshot.data()!; - assert(product.quantity >= sales.quantity); - doc.update({'quantity': product.quantity - sales.quantity}); + assert(product.availableUnits >= sales.quantity); + doc.update({'units_sold': product.unitsSold + sales.quantity}); return _sales.add(sales); }); } diff --git a/lib/src/models/product.dart b/lib/src/models/product.dart index 75f3433..68fc04c 100644 --- a/lib/src/models/product.dart +++ b/lib/src/models/product.dart @@ -6,15 +6,21 @@ export 'package:sales_tracker/src/models/item.dart'; class Product extends Item { late final String name; late final double unitCost; + late final int unitsSold; - double get cost => quantity * unitCost; + double get totalCost => quantity * unitCost; + + int get availableUnits => quantity - unitsSold; + + double get availableCost => availableUnits * unitCost; Product({ required this.name, required this.unitCost, required int quantity, required DateTime date, - }) : super( + }) : unitsSold = 0, + super( date: date, quantity: quantity, ); @@ -23,18 +29,26 @@ class Product extends Item { : super.fromJson(id, data) { name = data.remove('name'); unitCost = data.remove('unit_price'); + unitsSold = data.remove('units_sold') ?? 0; } Map toJson() { final data = super.toJson(); data['name'] = name; data['unit_price'] = unitCost; + data['units_sold'] = unitsSold; return data; } } extension ProductFormat on Product { + String get unitsSoldStr => unitsSold.toString(); + + String get availableUnitsStr => availableUnits.toString(); + String get unitCostStr => formatCurrency(unitCost); - String get costStr => formatCurrency(cost); + String get totalCostStr => formatCurrency(totalCost); + + String get availableCostStr => formatCurrency(availableCost); } diff --git a/lib/src/models/product_report.dart b/lib/src/models/product_report.dart index 192e307..9de87a8 100644 --- a/lib/src/models/product_report.dart +++ b/lib/src/models/product_report.dart @@ -5,8 +5,11 @@ import 'package:sales_tracker/src/utils/formatters.dart'; export 'package:sales_tracker/src/models/report.dart'; class ProductReport extends Report { + late final int totalSold; late final double totalCost; + int get remainingUnits => totalUnits - totalSold; + ProductReport({ required DateTime startTime, required DateTime endTime, @@ -16,11 +19,14 @@ class ProductReport extends Report { endTime: endTime, items: products, ) { + int sold = 0; double cost = 0; for (final item in products) { - cost += item.cost; + sold += item.unitsSold; + cost += item.totalCost; } totalCost = cost; + totalSold = sold; } } diff --git a/lib/src/models/report.dart b/lib/src/models/report.dart index f40dc9d..3437f3a 100644 --- a/lib/src/models/report.dart +++ b/lib/src/models/report.dart @@ -6,7 +6,7 @@ class Report { final DateTime endTime; final List items; final Map> groups = {}; - late final int totalItems; + late final int totalUnits; Report({ required this.items, @@ -28,7 +28,7 @@ class Report { groups.putIfAbsent(group, () => []); groups[group]!.add(item); } - totalItems = total; + totalUnits = total; } } diff --git a/lib/src/models/sales_record.dart b/lib/src/models/sales_record.dart index d2ddc89..36d8c59 100644 --- a/lib/src/models/sales_record.dart +++ b/lib/src/models/sales_record.dart @@ -7,26 +7,26 @@ export 'package:sales_tracker/src/models/item.dart'; class SalesRecord extends Item { late final String productId; late final String productName; - late final double unitBuyPrice; - late final double unitSellPrice; + late final double unitCost; + late final double unitPrice; - double get buyingPrice => quantity * unitBuyPrice; + double get totalCost => quantity * unitCost; - double get sellingPrice => quantity * unitSellPrice; + double get totalPrice => quantity * unitPrice; - double get profit => sellingPrice - buyingPrice; + double get profit => totalPrice - totalCost; - double get profitPerUnit => (sellingPrice - buyingPrice) / quantity; + double get profitPerUnit => (totalPrice - totalCost) / quantity; SalesRecord({ required Product product, - required this.unitSellPrice, + required this.unitPrice, required int quantity, required DateTime date, }) : assert(product.id != null), productId = product.id!, productName = product.name, - unitBuyPrice = product.unitCost, + unitCost = product.unitCost, super( date: date, quantity: quantity, @@ -36,28 +36,28 @@ class SalesRecord extends Item { : super.fromJson(id, data) { productId = data.remove('product_id'); productName = data.remove('product_name'); - unitBuyPrice = data.remove('buy_price'); - unitSellPrice = data.remove('sell_price'); + unitCost = data.remove('buy_price') ?? 0; + unitPrice = data.remove('sell_price') ?? 0; } Map toJson() { final data = super.toJson(); data['product_id'] = productId; data['product_name'] = productName; - data['buy_price'] = unitBuyPrice; - data['sell_price'] = unitSellPrice; + data['buy_price'] = unitCost; + data['sell_price'] = unitPrice; return data; } } extension SalesRecordFormat on SalesRecord { - String get unitBuyPriceStr => formatCurrency(unitBuyPrice); + String get unitCostStr => formatCurrency(unitCost); - String get unitSellPriceStr => formatCurrency(unitSellPrice); + String get unitPriceStr => formatCurrency(unitPrice); - String get buyingPriceStr => formatCurrency(buyingPrice); + String get totalCostStr => formatCurrency(totalCost); - String get sellingPriceStr => formatCurrency(sellingPrice); + String get totalPriceStr => formatCurrency(totalPrice); String get profitStr => formatCurrency(profit); diff --git a/lib/src/models/sales_report.dart b/lib/src/models/sales_report.dart index 7fef8a8..a1da4be 100644 --- a/lib/src/models/sales_report.dart +++ b/lib/src/models/sales_report.dart @@ -22,8 +22,8 @@ class SalesReport extends Report { double cost = 0; double price = 0; for (final record in sales) { - cost += record.buyingPrice; - price += record.sellingPrice; + cost += record.totalCost; + price += record.totalPrice; } totalCost = cost; totalPrice = price; diff --git a/lib/src/pages/widgets/home_page_drawer.dart b/lib/src/pages/widgets/home_page_drawer.dart index 03a2bd3..37855d9 100644 --- a/lib/src/pages/widgets/home_page_drawer.dart +++ b/lib/src/pages/widgets/home_page_drawer.dart @@ -77,7 +77,9 @@ class HomePageDrawer extends StatelessWidget { Widget buildUserName() { final user = FirebaseAuth.instance.currentUser; - if (user?.displayName == null) return Container(); + if (user?.displayName == null) { + return Container(); + } return Text( user!.displayName!, textAlign: TextAlign.center, @@ -133,7 +135,7 @@ class HomePageDrawer extends StatelessWidget { ), onTap: () async { await SalesReportPage.display(context); - Navigator.of(context).pop(); + Navigator.of(context, rootNavigator: true).pop(); }, ); } @@ -146,9 +148,9 @@ class HomePageDrawer extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5), ), - onTap: () { - Navigator.of(context).pop(); - ProductFormDialog.display(context); + onTap: () async { + await ProductFormDialog.display(context); + Navigator.of(context, rootNavigator: true).pop(); }, ); } @@ -173,13 +175,15 @@ class HomePageDrawer extends StatelessWidget { TextButton( child: Text('Continue'), onPressed: () { - Navigator.of(context).pop(); Repository.of(context).clearAllData(); + Navigator.of(context).pop(); }, ), TextButton( child: Text('Cancel'), - onPressed: () => Navigator.of(context).pop(), + onPressed: () { + Navigator.of(context, rootNavigator: true).pop(); + }, ), ], ), diff --git a/lib/src/pages/widgets/product_form_dialog.dart b/lib/src/pages/widgets/product_form_dialog.dart index 69243fe..b5bd2e9 100644 --- a/lib/src/pages/widgets/product_form_dialog.dart +++ b/lib/src/pages/widgets/product_form_dialog.dart @@ -6,8 +6,8 @@ import 'package:sales_tracker/src/models/product.dart'; import 'package:sales_tracker/src/pages/widgets/error_message.dart'; class ProductFormDialog extends StatelessWidget { - static void display(BuildContext context, [Product? product]) { - Navigator.of(context).push( + static Future display(BuildContext context, [Product? product]) { + return Navigator.of(context, rootNavigator: true).push( MaterialPageRoute( maintainState: false, fullscreenDialog: true, @@ -31,7 +31,7 @@ class ProductFormDialog extends StatelessWidget { unitPriceInput = TextEditingController(text: product?.unitCost.toString()); quantityInput = TextEditingController(text: product?.quantity.toString()); dateInput = TextEditingController( - text: product?.date != null ? _dateFormatter.format(product!.date) : '', + text: _dateFormatter.format(product?.date ?? DateTime.now()), ); } @@ -119,11 +119,12 @@ class ProductFormDialog extends StatelessWidget { Widget buildUnitPriceInput(BuildContext context) { return TextField( + enabled: product == null || product!.unitsSold == 0, controller: unitPriceInput, keyboardType: TextInputType.number, textInputAction: TextInputAction.next, decoration: InputDecoration( - labelText: 'Cost Per Unit', + labelText: 'Cost Per Unit', ), onEditingComplete: () { FocusScope.of(context).nextFocus(); @@ -142,6 +143,7 @@ class ProductFormDialog extends StatelessWidget { Widget buildQuantityInput(BuildContext context) { return TextField( + enabled: product == null || product!.unitsSold == 0, controller: quantityInput, keyboardType: TextInputType.number, textInputAction: TextInputAction.next, diff --git a/lib/src/pages/widgets/product_item.dart b/lib/src/pages/widgets/product_item.dart index 70dbedf..fc13f21 100644 --- a/lib/src/pages/widgets/product_item.dart +++ b/lib/src/pages/widgets/product_item.dart @@ -32,7 +32,7 @@ class ProductItemTile extends StatelessWidget { buildDeleteAction(context), buildEditAction(context), ], - secondaryActions: product.quantity > 0 + secondaryActions: product.availableUnits > 0 ? [ buildSaleAction(context), ] @@ -71,7 +71,7 @@ class ProductItemTile extends StatelessWidget { return CircleAvatar( backgroundColor: Colors.grey.shade300, child: Text( - '${product.quantity > 99 ? '99+' : product.quantity}', + '${product.availableUnits > 99 ? '99+' : product.availableUnits}', style: TextStyle( fontFamily: 'monospace', fontWeight: FontWeight.bold, @@ -98,21 +98,28 @@ class ProductItemTile extends StatelessWidget { Widget buildPrice() { return Container( - constraints: BoxConstraints( - minWidth: 75, - ), + // constraints: BoxConstraints( + // minWidth: 75, + // ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( - product.costStr, + product.unitCostStr, style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, ), ), + // Text( + // '${product.availableUnits} × ${product.unitCostStr}', + // style: TextStyle( + // fontSize: 12, + // color: Colors.grey, + // ), + // ), Text( - '${product.quantity} × ${product.unitCostStr}', + 'per unit', style: TextStyle( fontSize: 12, color: Colors.grey, @@ -124,7 +131,7 @@ class ProductItemTile extends StatelessWidget { } void _saleProduct(BuildContext context) { - if (product.quantity > 0) { + if (product.availableUnits > 0) { SaleFormDialog.display(context, product); } } diff --git a/lib/src/pages/widgets/product_report_view.dart b/lib/src/pages/widgets/product_report_view.dart index e31f8eb..a9f2d80 100644 --- a/lib/src/pages/widgets/product_report_view.dart +++ b/lib/src/pages/widgets/product_report_view.dart @@ -10,7 +10,7 @@ class ProductReportView extends StatelessWidget { @override Widget build(BuildContext context) { - if (report.totalItems == 0) { + if (report.totalUnits == 0) { return buildEmptyMessage(); } @@ -28,10 +28,9 @@ class ProductReportView extends StatelessWidget { children += [ Divider(height: 1), SizedBox(height: 10), - buildItemRow( - 'Total Products', '${report.items.length}', Colors.grey[700]), + buildItemRow('Products', '${report.items.length}', Colors.grey[700]), SizedBox(height: 10), - buildItemRow('Total Quantity', '${report.totalItems}', Colors.grey[700]), + buildItemRow('Total Units', '${report.totalUnits}', Colors.grey[700]), SizedBox(height: 10), Divider(height: 1), SizedBox(height: 10), @@ -106,7 +105,7 @@ class ProductReportView extends StatelessWidget { ), Text(' = '), Text( - product.costStr.padRight(10, ' '), + product.totalCostStr.padRight(10, ' '), style: TextStyle( fontFamily: 'monospace', fontSize: 12, diff --git a/lib/src/pages/widgets/report_page_widget.dart b/lib/src/pages/widgets/report_page_widget.dart index 1a0e2db..1a15d1b 100644 --- a/lib/src/pages/widgets/report_page_widget.dart +++ b/lib/src/pages/widgets/report_page_widget.dart @@ -66,7 +66,7 @@ class ReportPageWidget extends StatelessWidget { } Widget buildSaveAsPdfButton(BuildContext context, T report) { - if (report.totalItems == 0) { + if (report.totalUnits == 0) { return Container(); } return ListTile( diff --git a/lib/src/pages/widgets/sale_form_dialog.dart b/lib/src/pages/widgets/sale_form_dialog.dart index fe4dde7..875abf3 100644 --- a/lib/src/pages/widgets/sale_form_dialog.dart +++ b/lib/src/pages/widgets/sale_form_dialog.dart @@ -127,12 +127,9 @@ class SaleFormDialog extends StatelessWidget { textInputAction: TextInputAction.next, decoration: InputDecoration( labelText: 'Item Quantity', - helperText: '${product.quantity} items available', + helperText: '${product.availableUnits} items available', ), - onEditingComplete: () { - if (int.parse(quantityInput.text) > product.quantity) { - quantityInput.text = product.quantity.toString(); - } + onSubmitted: (_) { FocusScope.of(context).nextFocus(); }, inputFormatters: [ @@ -162,9 +159,9 @@ class SaleFormDialog extends StatelessWidget { if (quantity == null || quantity < 0) { return _showError(context, 'Invalid Quantity'); } - if (quantity > product.quantity) { + if (quantity > product.availableUnits) { return _showError(context, - 'Insufficient Quantity. Maximum ${product.quantity} available.'); + 'Insufficient Quantity. Maximum ${product.availableUnits} available.'); } if (unitPrice == null || unitPrice < 0) { return _showError(context, 'Invalid Price'); @@ -175,7 +172,7 @@ class SaleFormDialog extends StatelessWidget { product: product, date: date, quantity: quantity, - unitSellPrice: unitPrice, + unitPrice: unitPrice, ); _confirmSale(context, record); diff --git a/lib/src/pages/widgets/sales_preview.dart b/lib/src/pages/widgets/sales_preview.dart index a06ec42..26add3e 100644 --- a/lib/src/pages/widgets/sales_preview.dart +++ b/lib/src/pages/widgets/sales_preview.dart @@ -22,17 +22,17 @@ class SalesPreview extends StatelessWidget { SizedBox(height: 5), buildLabelRow('Product', record.productName), SizedBox(height: 5), - buildLabelRow('Product Cost', record.unitBuyPriceStr), + buildLabelRow('Product Cost', record.unitCostStr), SizedBox(height: 5), - buildLabelRow('Available', '${product.quantity} ps.'), + buildLabelRow('Available', '${product.availableUnits} ps.'), SizedBox(height: 5), - buildLabelRow('Selling Price', record.unitSellPriceStr), + buildLabelRow('Selling Price', record.unitPriceStr), SizedBox(height: 5), buildLabelRow('Sell Quantity', '${record.quantity} ps.'), Divider(), - buildLabelRow('Total Cost', record.buyingPriceStr), + buildLabelRow('Total Cost', record.totalCostStr), SizedBox(height: 5), - buildLabelRow('Total Price', record.sellingPriceStr), + buildLabelRow('Total Price', record.totalPriceStr), SizedBox(height: 5), buildLabelRow('Profit per Unit', record.profitPerUnitStr), Divider(), diff --git a/lib/src/pages/widgets/sales_report_view.dart b/lib/src/pages/widgets/sales_report_view.dart index e637d7b..142e5d4 100644 --- a/lib/src/pages/widgets/sales_report_view.dart +++ b/lib/src/pages/widgets/sales_report_view.dart @@ -10,7 +10,7 @@ class SalesReportView extends StatelessWidget { @override Widget build(BuildContext context) { - if (report.totalItems == 0) { + if (report.totalUnits == 0) { return buildEmptyMessage(); } @@ -30,7 +30,7 @@ class SalesReportView extends StatelessWidget { SizedBox(height: 10), buildItemRow('Total Sales', '${report.items.length}', Colors.grey[700]), SizedBox(height: 10), - buildItemRow('Items Sold', '${report.totalItems}', Colors.grey[700]), + buildItemRow('Units Sold', '${report.totalUnits}', Colors.grey[700]), SizedBox(height: 10), Divider(height: 1), SizedBox(height: 10), @@ -40,7 +40,7 @@ class SalesReportView extends StatelessWidget { SizedBox(height: 10), Divider(height: 1), SizedBox(height: 10), - buildItemRow('Total Profit', report.profitStr), + buildItemRow('Net Profit', report.profitStr), ]; return ListView( @@ -101,7 +101,7 @@ class SalesReportView extends StatelessWidget { Text(' × '), Expanded( child: Text( - '${record.productName} @ ${record.unitSellPriceStr}', + '${record.productName} @ ${record.unitPriceStr}', softWrap: true, style: TextStyle( fontSize: 12, @@ -111,7 +111,7 @@ class SalesReportView extends StatelessWidget { ), Text(' = '), Text( - record.sellingPriceStr.padRight(10, ' '), + record.totalPriceStr.padRight(10, ' '), style: TextStyle( fontFamily: 'monospace', fontSize: 12, diff --git a/lib/src/utils/generate_product_report.dart b/lib/src/utils/generate_product_report.dart index 0cd4353..c37193d 100644 --- a/lib/src/utils/generate_product_report.dart +++ b/lib/src/utils/generate_product_report.dart @@ -3,8 +3,8 @@ import 'dart:typed_data'; import 'package:flutter/services.dart'; import 'package:pdf/pdf.dart'; import 'package:pdf/widgets.dart' as pw; -import 'package:sales_tracker/src/models/product_report.dart'; import 'package:sales_tracker/src/models/product.dart'; +import 'package:sales_tracker/src/models/product_report.dart'; Future generateProductReport(ProductReport report) async { final regularFont = await rootBundle.load('lib/res/RobotoSlab-Regular.ttf'); @@ -31,18 +31,13 @@ Future generateProductReport(ProductReport report) async { return [ buildHeader(report), buildSalesTable(report), - pw.Divider( - height: 20, - thickness: 1, - color: PdfColors.grey300, - ), - buildSummaryItem('Total Products', '${report.items.length} ps.'), - buildSummaryItem('Total Item Quantity', '${report.totalItems} ps.'), - pw.Divider( - height: 20, - thickness: 1, - color: PdfColors.grey300, - ), + pw.Divider(height: 20, thickness: 1, color: PdfColors.grey300), + buildSummaryItem('Products', '${report.items.length} ps.'), + buildSummaryItem('Initial Units', '${report.totalUnits} ps.'), + pw.Divider(height: 20, thickness: 1, color: PdfColors.grey300), + buildSummaryItem('Sold Units', '${report.totalSold} ps.'), + buildSummaryItem('Remaining Units', '${report.remainingUnits} ps.'), + pw.Divider(height: 20, thickness: 1, color: PdfColors.grey300), buildSummaryItem('Total Cost', report.totalCostStr), ]; }, @@ -75,8 +70,9 @@ pw.Widget buildSalesTable(ProductReport report) { children: [ buildHeadCell('Date'), buildHeadCell('Item Name'), + buildHeadCell('Sold'), + buildHeadCell('Units'), buildHeadCell('Unit Cost'), - buildHeadCell('Quantity'), buildHeadCell('Total Cost'), ], decoration: pw.BoxDecoration( @@ -88,9 +84,10 @@ pw.Widget buildSalesTable(ProductReport report) { children: [ buildItemCell(product.dateStr), buildItemCell(product.name), - buildItemCell(product.unitCostStr), + buildItemCell(product.unitsSoldStr), buildItemCell(product.quantityStr), - buildItemCell(product.costStr), + buildItemCell(product.unitCostStr), + buildItemCell(product.totalCostStr), ], ), ), @@ -100,18 +97,29 @@ pw.Widget buildSalesTable(ProductReport report) { pw.Widget buildHeader(ProductReport report) { return pw.Container( - padding: pw.EdgeInsets.symmetric(vertical: 10, horizontal: 5), - margin: pw.EdgeInsets.only(bottom: 20), - alignment: pw.Alignment.center, - child: pw.Text( - 'Sales Report (${report.startTimeStr} to ${report.endTimeStr})', - textAlign: pw.TextAlign.center, - style: pw.TextStyle( - fontSize: 24.0, - fontWeight: pw.FontWeight.bold, - ), - ), - ); + padding: pw.EdgeInsets.symmetric(vertical: 10, horizontal: 5), + margin: pw.EdgeInsets.only(bottom: 20), + alignment: pw.Alignment.center, + child: pw.Column(children: [ + pw.Text( + 'Product Report', + textAlign: pw.TextAlign.center, + style: pw.TextStyle( + fontSize: 24.0, + fontWeight: pw.FontWeight.bold, + ), + ), + pw.SizedBox(height: 5), + pw.Text( + '${report.startTimeStr} ~ ${report.endTimeStr}', + textAlign: pw.TextAlign.center, + style: pw.TextStyle( + fontSize: 18.0, + color: PdfColors.grey700, + fontWeight: pw.FontWeight.bold, + ), + ), + ])); } pw.Widget buildHeadCell(String text) { diff --git a/lib/src/utils/generate_sales_report.dart b/lib/src/utils/generate_sales_report.dart index b1d3ad6..95681db 100644 --- a/lib/src/utils/generate_sales_report.dart +++ b/lib/src/utils/generate_sales_report.dart @@ -3,8 +3,8 @@ import 'dart:typed_data'; import 'package:flutter/services.dart'; import 'package:pdf/pdf.dart'; import 'package:pdf/widgets.dart' as pw; -import 'package:sales_tracker/src/models/sales_report.dart'; import 'package:sales_tracker/src/models/sales_record.dart'; +import 'package:sales_tracker/src/models/sales_report.dart'; Future generateSalesReport(SalesReport report) async { final regularFont = await rootBundle.load('lib/res/RobotoSlab-Regular.ttf'); @@ -31,20 +31,12 @@ Future generateSalesReport(SalesReport report) async { return [ buildHeader(report), buildSalesTable(report), - pw.Divider( - height: 20, - thickness: 1, - color: PdfColors.grey300, - ), - buildSummaryItem('Total Records', '${report.items.length} ps.'), - buildSummaryItem('Total Item Quantity', '${report.totalItems} ps.'), - buildSummaryItem('Production Cost', report.totalCostStr), + pw.Divider(height: 20, thickness: 1, color: PdfColors.grey300), + buildSummaryItem('Records', '${report.items.length} ps.'), + buildSummaryItem('Total Units', '${report.totalUnits} ps.'), buildSummaryItem('Selling Price', report.totalPriceStr), - pw.Divider( - height: 20, - thickness: 1, - color: PdfColors.grey300, - ), + buildSummaryItem('Production Cost', report.totalCostStr), + pw.Divider(height: 20, thickness: 1, color: PdfColors.grey300), buildSummaryItem('Net Profit', report.profitStr), ]; }, @@ -77,7 +69,7 @@ pw.Widget buildSalesTable(SalesReport report) { children: [ buildHeadCell('Date'), buildHeadCell('Item Name'), - buildHeadCell('Quantity'), + buildHeadCell('Units'), buildHeadCell('Cost'), buildHeadCell('Price'), buildHeadCell('Profit'), @@ -92,8 +84,8 @@ pw.Widget buildSalesTable(SalesReport report) { buildItemCell(record.dateStr), buildItemCell(record.productName), buildItemCell(record.quantityStr), - buildItemCell(record.buyingPriceStr), - buildItemCell(record.sellingPriceStr), + buildItemCell(record.totalCostStr), + buildItemCell(record.totalPriceStr), buildItemCell(record.profitStr), ], ), @@ -104,18 +96,29 @@ pw.Widget buildSalesTable(SalesReport report) { pw.Widget buildHeader(SalesReport report) { return pw.Container( - padding: pw.EdgeInsets.symmetric(vertical: 10, horizontal: 5), - margin: pw.EdgeInsets.only(bottom: 20), - alignment: pw.Alignment.center, - child: pw.Text( - 'Sales Report (${report.startTimeStr} to ${report.endTimeStr})', - textAlign: pw.TextAlign.center, - style: pw.TextStyle( - fontSize: 24.0, - fontWeight: pw.FontWeight.bold, - ), - ), - ); + padding: pw.EdgeInsets.symmetric(vertical: 10, horizontal: 5), + margin: pw.EdgeInsets.only(bottom: 20), + alignment: pw.Alignment.center, + child: pw.Column(children: [ + pw.Text( + 'Sales Report', + textAlign: pw.TextAlign.center, + style: pw.TextStyle( + fontSize: 24.0, + fontWeight: pw.FontWeight.bold, + ), + ), + pw.SizedBox(height: 5), + pw.Text( + '${report.startTimeStr} ~ ${report.endTimeStr}', + textAlign: pw.TextAlign.center, + style: pw.TextStyle( + fontSize: 18.0, + color: PdfColors.grey700, + fontWeight: pw.FontWeight.bold, + ), + ), + ])); } pw.Widget buildHeadCell(String text) { diff --git a/pubspec.yaml b/pubspec.yaml index 0721e3d..076387b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: sales_tracker description: A generic sales tracking application publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 1.2.4+7 +version: 1.3.0+8 environment: sdk: ">=2.13.0 <3.0.0"