Commit 3e5ca320 authored by Jérome Perrin's avatar Jérome Perrin

accounting: round in grouping when no section currency is set

Grouping feature checks that the sum of all selected lines == 0, which
is often not the case as the values are float. For that, our approach
is to round the values with the precision of the accounting currency,
since these precisions are usually small (typically 0, 2 or 3), we
don't have problems with rounding. Using the section currency is not
just a workaround for rounding, it's also correct because we don't
consider more precise amounts in accounting transaction lines.

The problem with this approach was for the case where no accounting
currency is set on the section organisation, in that case we did not
round and this sometimes led to "grouping is impossible" errors that
are hard to find for users. At this level it's better to use a default
rounding precision that would make it possible to use the grouping
feature even when section currency is not set.
parent 0162ede8
Pipeline #24355 passed with stage
in 0 seconds
......@@ -75,12 +75,14 @@ changed_line_list = []
for (node, section, mirror_section, _), line_info_list in lines_per_node.items():
if node is None:
continue
total_price = sum([l['total_price'] for l in line_info_list])
# get the currency rounding for this section
# get the currency rounding for this section, with a fallback that something that would
# allow grouping in case precision is not defined.
currency_precision = 5
if section:
default_currency = portal.restrictedTraverse(section).getPriceCurrencyValue()
if default_currency is not None:
total_price = round(total_price, default_currency.getQuantityPrecision())
currency_precision = default_currency.getQuantityPrecision()
total_price = round(sum([l['total_price'] for l in line_info_list]), currency_precision)
if total_price == 0 or allow_grouping_with_different_quantity:
# we should include mirror node in the id_group, but this would reset
# id generators and generate grouping references that were already used.
......
......@@ -3786,6 +3786,61 @@ class TestTransactions(AccountingTestCase):
self.tic()
self.assertFalse(payment.line_with_grouping_reference.getGroupingReference())
def test_grouping_reference_rounding(self):
"""Reproduction of a bug that grouping was not possible because of rounding error
>>> 0.1 + 0.2 - 0.3 == 0
False
"""
invoice = self._makeOne(
title='Invoice',
destination_section_value=self.organisation_module.client_1,
lines=(dict(source_value=self.account_module.goods_purchase,
source_debit=0.3),
dict(source_value=self.account_module.receivable,
source_credit=0.1,
id='line_1'),
dict(source_value=self.account_module.receivable,
source_credit=0.2,
id='line_2')))
payment = self._makeOne(
title='Invoice Payment',
portal_type='Payment Transaction',
source_payment_value=self.section.newContent(
portal_type='Bank Account'),
destination_section_value=self.organisation_module.client_1,
lines=(dict(source_value=self.account_module.receivable,
id='line_3',
source_debit=0.3),
dict(source_value=self.account_module.bank,
source_credit=0.3,)))
self.tic()
grouped = invoice.AccountingTransaction_guessGroupedLines(
accounting_transaction_line_uid_list=(
invoice.line_1.getUid(),
invoice.line_2.getUid(),
payment.line_3.getUid(),
))
self.assertEqual(
sorted(grouped),
sorted([
invoice.line_1.getRelativeUrl(),
invoice.line_2.getRelativeUrl(),
payment.line_3.getRelativeUrl(),
]))
self.tic()
def test_grouping_reference_rounding_without_accounting_currency_on_section(self):
accounting_currency = self.section.getPriceCurrency()
self.assertTrue(accounting_currency)
self.section.setPriceCurrency(None)
try:
self.test_grouping_reference_rounding()
finally:
self.abort()
self.section.setPriceCurrency(accounting_currency)
self.tic()
def test_automatically_setting_grouping_reference(self):
invoice = self._makeOne(
title='First Invoice',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment