Correct rounding

This commit is contained in:
Hillel Coren 2021-08-18 21:27:05 +03:00
parent 72d67e3780
commit d078276d1a
6 changed files with 33 additions and 9 deletions

View File

@ -1251,7 +1251,7 @@ abstract class InvoiceItemEntity
if (rate == 0) { if (rate == 0) {
return 0; return 0;
} }
final lineTotal = total(invoice); final lineTotal = total(invoice, precision);
if (invoice.usesInclusiveTaxes) { if (invoice.usesInclusiveTaxes) {
taxAmount = lineTotal - (lineTotal / (1 + (rate / 100))); taxAmount = lineTotal - (lineTotal / (1 + (rate / 100)));
} else { } else {
@ -1266,9 +1266,9 @@ abstract class InvoiceItemEntity
} }
double netTotal(InvoiceEntity invoice, int precision) => 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; var total = quantity * cost;
if (discount != 0) { if (discount != 0) {
@ -1279,7 +1279,7 @@ abstract class InvoiceItemEntity
} }
} }
return round(total, 2); return round(total, precision);
} }
bool get isTask => typeId == TYPE_TASK; bool get isTask => typeId == TYPE_TASK;

View File

@ -1,4 +1,6 @@
import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/data/models/entities.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/ui/app/lists/list_divider.dart';
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -24,6 +26,12 @@ class InvoiceItemListTile extends StatelessWidget {
clientId: invoice.clientId, formatNumberType: FormatNumberType.double); clientId: invoice.clientId, formatNumberType: FormatNumberType.double);
final localization = AppLocalization.of(context); final localization = AppLocalization.of(context);
final store = StoreProvider.of<AppState>(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'; String subtitle = '$qty x $cost';
if (invoiceItem.discount != 0) { if (invoiceItem.discount != 0) {
@ -99,7 +107,8 @@ class InvoiceItemListTile extends StatelessWidget {
title: Row( title: Row(
children: <Widget>[ children: <Widget>[
Expanded(child: Text(invoiceItem.productKey)), Expanded(child: Text(invoiceItem.productKey)),
Text(formatNumber(invoiceItem.total(invoice), context, Text(formatNumber(
invoiceItem.total(invoice, precision), context,
clientId: invoice.clientId)), clientId: invoice.clientId)),
], ],
), ),

View File

@ -82,7 +82,11 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
final viewModel = widget.viewModel; final viewModel = widget.viewModel;
final state = viewModel.state; final state = viewModel.state;
final company = state.company; final company = state.company;
final invoice = viewModel.invoice; 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 lineItems = invoice.lineItems.toList();
final includedLineItems = lineItems.where((lineItem) { final includedLineItems = lineItems.where((lineItem) {
return (lineItem.typeId == InvoiceItemEntity.TYPE_TASK && return (lineItem.typeId == InvoiceItemEntity.TYPE_TASK &&
@ -687,11 +691,11 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
padding: const EdgeInsets.only(right: kTableColumnGap), padding: const EdgeInsets.only(right: kTableColumnGap),
child: TextFormField( child: TextFormField(
key: ValueKey( key: ValueKey(
'__total_${index}_${lineItems[index].total(invoice)}_${invoice.clientId}__'), '__total_${index}_${lineItems[index].total(invoice, precision)}_${invoice.clientId}__'),
readOnly: true, readOnly: true,
enabled: false, enabled: false,
initialValue: formatNumber( initialValue: formatNumber(
lineItems[index].total(invoice), context, lineItems[index].total(invoice, precision), context,
clientId: invoice.clientId), clientId: invoice.clientId),
textAlign: TextAlign.right, textAlign: TextAlign.right,
), ),

View File

@ -135,7 +135,7 @@ ReportResult lineItemReport(
value = lineItem.notes; value = lineItem.notes;
break; break;
case InvoiceItemReportFields.total: case InvoiceItemReportFields.total:
value = lineItem.total(invoice); value = lineItem.total(invoice, precision);
break; break;
case InvoiceItemReportFields.productKey: case InvoiceItemReportFields.productKey:
value = lineItem.productKey; value = lineItem.productKey;

View File

@ -131,7 +131,7 @@ ReportResult lineItemReport(
value = lineItem.notes; value = lineItem.notes;
break; break;
case QuoteItemReportFields.total: case QuoteItemReportFields.total:
value = lineItem.total(invoice); value = lineItem.total(invoice, precision);
break; break;
case QuoteItemReportFields.productKey: case QuoteItemReportFields.productKey:
value = lineItem.productKey; value = lineItem.productKey;

View File

@ -14,6 +14,17 @@ import 'package:invoiceninja_flutter/redux/company/company_selectors.dart';
import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/localization.dart';
double round(double value, int precision) { 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) { if (value == null || value.isNaN) {
return 0; return 0;
} }