From d078276d1aaf5bd8a20ef9105d686fd5c9c11cd5 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Wed, 18 Aug 2021 21:27:05 +0300 Subject: [PATCH] Correct rounding --- lib/data/models/invoice_model.dart | 8 ++++---- lib/ui/app/invoice/invoice_item_view.dart | 11 ++++++++++- lib/ui/invoice/edit/invoice_edit_items_desktop.dart | 8 ++++++-- lib/ui/reports/invoice_item_report.dart | 2 +- lib/ui/reports/quote_item_report.dart | 2 +- lib/utils/formatting.dart | 11 +++++++++++ 6 files changed, 33 insertions(+), 9 deletions(-) diff --git a/lib/data/models/invoice_model.dart b/lib/data/models/invoice_model.dart index b64045335..4d4ed03c3 100644 --- a/lib/data/models/invoice_model.dart +++ b/lib/data/models/invoice_model.dart @@ -1251,7 +1251,7 @@ abstract class InvoiceItemEntity if (rate == 0) { return 0; } - final lineTotal = total(invoice); + final lineTotal = total(invoice, precision); if (invoice.usesInclusiveTaxes) { taxAmount = lineTotal - (lineTotal / (1 + (rate / 100))); } else { @@ -1266,9 +1266,9 @@ abstract class InvoiceItemEntity } double netTotal(InvoiceEntity invoice, int precision) => - total(invoice) - taxAmount(invoice, precision); + total(invoice, precision) - taxAmount(invoice, precision); - double total(InvoiceEntity invoice) { + double total(InvoiceEntity invoice, int precision) { var total = quantity * cost; if (discount != 0) { @@ -1279,7 +1279,7 @@ abstract class InvoiceItemEntity } } - return round(total, 2); + return round(total, precision); } bool get isTask => typeId == TYPE_TASK; diff --git a/lib/ui/app/invoice/invoice_item_view.dart b/lib/ui/app/invoice/invoice_item_view.dart index 9cf74cf06..a9294b52d 100644 --- a/lib/ui/app/invoice/invoice_item_view.dart +++ b/lib/ui/app/invoice/invoice_item_view.dart @@ -1,4 +1,6 @@ +import 'package:flutter_redux/flutter_redux.dart'; import 'package:invoiceninja_flutter/data/models/entities.dart'; +import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:flutter/material.dart'; @@ -24,6 +26,12 @@ class InvoiceItemListTile extends StatelessWidget { clientId: invoice.clientId, formatNumberType: FormatNumberType.double); final localization = AppLocalization.of(context); + final store = StoreProvider.of(context); + final state = store.state; + final client = state.clientState.get(invoice.clientId); + final precision = + state.staticState.currencyMap[client.currencyId].precision; + String subtitle = '$qty x $cost'; if (invoiceItem.discount != 0) { @@ -99,7 +107,8 @@ class InvoiceItemListTile extends StatelessWidget { title: Row( children: [ Expanded(child: Text(invoiceItem.productKey)), - Text(formatNumber(invoiceItem.total(invoice), context, + Text(formatNumber( + invoiceItem.total(invoice, precision), context, clientId: invoice.clientId)), ], ), diff --git a/lib/ui/invoice/edit/invoice_edit_items_desktop.dart b/lib/ui/invoice/edit/invoice_edit_items_desktop.dart index 950ecff38..16f7ba53d 100644 --- a/lib/ui/invoice/edit/invoice_edit_items_desktop.dart +++ b/lib/ui/invoice/edit/invoice_edit_items_desktop.dart @@ -82,7 +82,11 @@ class _InvoiceEditItemsDesktopState extends State { final viewModel = widget.viewModel; final state = viewModel.state; final company = state.company; + final invoice = viewModel.invoice; + final client = state.clientState.get(invoice.clientId); + final precision = + state.staticState.currencyMap[client.currencyId]?.precision ?? 2; final lineItems = invoice.lineItems.toList(); final includedLineItems = lineItems.where((lineItem) { return (lineItem.typeId == InvoiceItemEntity.TYPE_TASK && @@ -687,11 +691,11 @@ class _InvoiceEditItemsDesktopState extends State { padding: const EdgeInsets.only(right: kTableColumnGap), child: TextFormField( key: ValueKey( - '__total_${index}_${lineItems[index].total(invoice)}_${invoice.clientId}__'), + '__total_${index}_${lineItems[index].total(invoice, precision)}_${invoice.clientId}__'), readOnly: true, enabled: false, initialValue: formatNumber( - lineItems[index].total(invoice), context, + lineItems[index].total(invoice, precision), context, clientId: invoice.clientId), textAlign: TextAlign.right, ), diff --git a/lib/ui/reports/invoice_item_report.dart b/lib/ui/reports/invoice_item_report.dart index 251157970..251f8c13c 100644 --- a/lib/ui/reports/invoice_item_report.dart +++ b/lib/ui/reports/invoice_item_report.dart @@ -135,7 +135,7 @@ ReportResult lineItemReport( value = lineItem.notes; break; case InvoiceItemReportFields.total: - value = lineItem.total(invoice); + value = lineItem.total(invoice, precision); break; case InvoiceItemReportFields.productKey: value = lineItem.productKey; diff --git a/lib/ui/reports/quote_item_report.dart b/lib/ui/reports/quote_item_report.dart index a2e6185bf..c16ea3cbb 100644 --- a/lib/ui/reports/quote_item_report.dart +++ b/lib/ui/reports/quote_item_report.dart @@ -131,7 +131,7 @@ ReportResult lineItemReport( value = lineItem.notes; break; case QuoteItemReportFields.total: - value = lineItem.total(invoice); + value = lineItem.total(invoice, precision); break; case QuoteItemReportFields.productKey: value = lineItem.productKey; diff --git a/lib/utils/formatting.dart b/lib/utils/formatting.dart index 8422936e3..0c28fda49 100644 --- a/lib/utils/formatting.dart +++ b/lib/utils/formatting.dart @@ -14,6 +14,17 @@ import 'package:invoiceninja_flutter/redux/company/company_selectors.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; double round(double value, int precision) { + var rounded = value; + + // Workaround for floating point issues + if ('$value'.contains('9999999')) { + rounded = _round(value, precision + 1); + } + + return _round(rounded, precision); +} + +double _round(double value, int precision) { if (value == null || value.isNaN) { return 0; }