mirror of
https://github.com/frappe/erpnext.git
synced 2026-02-15 23:54:59 +00:00
fix(accounts): dynamic zero cutoff (#48899)
* fix(accounts): dynamic zero cutoff
The cutoff for displaying zero values in accounting reports has so far been hardcoded to 0.005, giving wrong results for currencies that require a higher precision. This PR changes this to a dynamic value calculated from the Currency's _Fraction Units_.
* style: fix typo
(cherry picked from commit 6972f161b8)
Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
This commit is contained in:
@@ -38,6 +38,7 @@ from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement
|
||||
get_report_summary as get_pl_summary,
|
||||
)
|
||||
from erpnext.accounts.report.utils import convert, convert_to_presentation_currency
|
||||
from erpnext.accounts.utils import get_zero_cutoff
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
@@ -563,7 +564,7 @@ def prepare_data(accounts, start_date, end_date, balance_must_be, companies, com
|
||||
|
||||
row[company] = flt(d.get(company, 0.0), 3)
|
||||
|
||||
if abs(row[company]) >= 0.005:
|
||||
if abs(row[company]) >= get_zero_cutoff(filters.presentation_currency):
|
||||
# ignore zero values
|
||||
has_value = True
|
||||
total += flt(row[company])
|
||||
|
||||
@@ -12,6 +12,7 @@ from erpnext.accounts.report.financial_statements import (
|
||||
filter_out_zero_value_rows,
|
||||
)
|
||||
from erpnext.accounts.report.trial_balance.trial_balance import validate_filters
|
||||
from erpnext.accounts.utils import get_zero_cutoff
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
@@ -154,7 +155,7 @@ def prepare_data(accounts, filters, company_currency, dimension_list):
|
||||
for dimension in dimension_list:
|
||||
row[frappe.scrub(dimension)] = flt(d.get(frappe.scrub(dimension), 0.0), 3)
|
||||
|
||||
if abs(row[frappe.scrub(dimension)]) >= 0.005:
|
||||
if abs(row[frappe.scrub(dimension)]) >= get_zero_cutoff(company_currency):
|
||||
# ignore zero values
|
||||
has_value = True
|
||||
total += flt(d.get(frappe.scrub(dimension), 0.0), 3)
|
||||
|
||||
@@ -18,7 +18,7 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||
get_dimension_with_children,
|
||||
)
|
||||
from erpnext.accounts.report.utils import convert_to_presentation_currency, get_currency
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
from erpnext.accounts.utils import get_fiscal_year, get_zero_cutoff
|
||||
|
||||
|
||||
def get_period_list(
|
||||
@@ -304,7 +304,7 @@ def prepare_data(accounts, balance_must_be, period_list, company_currency, accum
|
||||
|
||||
row[period.key] = flt(d.get(period.key, 0.0), 3)
|
||||
|
||||
if abs(row[period.key]) >= 0.005:
|
||||
if abs(row[period.key]) >= get_zero_cutoff(company_currency):
|
||||
# ignore zero values
|
||||
has_value = True
|
||||
total += flt(row[period.key])
|
||||
|
||||
@@ -12,6 +12,7 @@ from erpnext.accounts.report.financial_statements import (
|
||||
filter_out_zero_value_rows,
|
||||
)
|
||||
from erpnext.accounts.report.trial_balance.trial_balance import validate_filters
|
||||
from erpnext.accounts.utils import get_zero_cutoff
|
||||
|
||||
value_fields = ("income", "expense", "gross_profit_loss")
|
||||
|
||||
@@ -149,7 +150,7 @@ def prepare_data(accounts, filters, total_row, parent_children_map, based_on):
|
||||
for key in value_fields:
|
||||
row[key] = flt(d.get(key, 0.0), 3)
|
||||
|
||||
if abs(row[key]) >= 0.005:
|
||||
if abs(row[key]) >= get_zero_cutoff(company_currency):
|
||||
# ignore zero values
|
||||
has_value = True
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ from erpnext.accounts.report.financial_statements import (
|
||||
set_gl_entries_by_account,
|
||||
)
|
||||
from erpnext.accounts.report.utils import convert_to_presentation_currency, get_currency
|
||||
from erpnext.accounts.utils import get_zero_cutoff
|
||||
|
||||
value_fields = (
|
||||
"opening_debit",
|
||||
@@ -413,7 +414,7 @@ def prepare_data(accounts, filters, parent_children_map, company_currency):
|
||||
for key in value_fields:
|
||||
row[key] = flt(d.get(key, 0.0), 3)
|
||||
|
||||
if abs(row[key]) >= 0.005:
|
||||
if abs(row[key]) >= get_zero_cutoff(company_currency):
|
||||
# ignore zero values
|
||||
has_value = True
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ from erpnext.accounts.party import get_party_shipping_address
|
||||
from erpnext.accounts.utils import (
|
||||
get_future_stock_vouchers,
|
||||
get_voucherwise_gl_entries,
|
||||
get_zero_cutoff,
|
||||
sort_stock_vouchers_by_posting_date,
|
||||
)
|
||||
from erpnext.stock.doctype.item.test_item import make_item
|
||||
@@ -156,6 +157,11 @@ class TestUtils(unittest.TestCase):
|
||||
self.assertSequenceEqual(doc_name[0:2], ("SUP", fiscal_year))
|
||||
frappe.db.set_default("supp_master_name", "Supplier Name")
|
||||
|
||||
def test_get_zero_cutoff(self):
|
||||
self.assertEqual(get_zero_cutoff(None), 0.005)
|
||||
self.assertEqual(get_zero_cutoff("EUR"), 0.005)
|
||||
self.assertEqual(get_zero_cutoff("BHD"), 0.0005)
|
||||
|
||||
|
||||
ADDRESS_RECORDS = [
|
||||
{
|
||||
|
||||
@@ -27,6 +27,7 @@ from frappe.utils import (
|
||||
now,
|
||||
nowdate,
|
||||
)
|
||||
from frappe.utils.caching import site_cache
|
||||
from pypika import Order
|
||||
from pypika.functions import Coalesce
|
||||
from pypika.terms import ExistsCriterion
|
||||
@@ -1130,6 +1131,29 @@ def get_currency_precision():
|
||||
return precision
|
||||
|
||||
|
||||
def get_fraction_units(currency: str) -> int:
|
||||
"""Returns the number of fraction units for a currency."""
|
||||
fraction_units = frappe.db.get_value("Currency", currency, "fraction_units")
|
||||
|
||||
if fraction_units is None:
|
||||
fraction_units = 100
|
||||
|
||||
return fraction_units
|
||||
|
||||
|
||||
@site_cache()
|
||||
def get_zero_cutoff(currency: str) -> float:
|
||||
"""Returns the zero cutoff for a currency.
|
||||
|
||||
For example, if the Fraction Units for a currency are set to 100, then the zero cutoff is 0.005.
|
||||
We don't want to display values less than the zero cutoff.
|
||||
This value was chosen for compatibility with the previous hard-coded value of 0.005.
|
||||
"""
|
||||
fraction_units = get_fraction_units(currency)
|
||||
|
||||
return 0.5 / (fraction_units or 1)
|
||||
|
||||
|
||||
def get_held_invoices(party_type, party):
|
||||
"""
|
||||
Returns a list of names Purchase Invoices for the given party that are on hold
|
||||
|
||||
Reference in New Issue
Block a user