[IMP] odoo.tools: add rounding_mode and amount_rounding to formatLang
Adds the possibility to give formatLang() a 'rounding_mode' (any Decimal rounding mode)
and an amount_rounding ('decimals', 'units', 'thousands', 'millions' and 'lakhs').
'amount_rounding' will display the amount in the given unit. For example, 10456 in 'thousands' will be 10.
task-3626894
closes odoo/odoo#151314
Related: odoo/enterprise#55218
Signed-off-by: John Laterre (jol) <jol@odoo.com>
This commit is contained in:
@@ -583,6 +583,28 @@ class TestFormatLang(TransactionCase):
|
||||
# If we have a 'dp' and 'currency_obj', we use the decimal precision of 'dp' and the format of 'currency_obj'.
|
||||
self.assertEqual(misc.formatLang(self.env, 100, dp=decimal_precision.name, currency_obj=currency_object), '100.000%sfL' % u'\N{NO-BREAK SPACE}')
|
||||
|
||||
def test_rounding_method(self):
|
||||
self.assertEqual(misc.formatLang(self.env, 100.205), '100.20') # Default is 'HALF-EVEN'
|
||||
self.assertEqual(misc.formatLang(self.env, 100.215), '100.22') # Default is 'HALF-EVEN'
|
||||
|
||||
self.assertEqual(misc.formatLang(self.env, 100.205, rounding_method='HALF-UP'), '100.21')
|
||||
self.assertEqual(misc.formatLang(self.env, 100.215, rounding_method='HALF-UP'), '100.22')
|
||||
|
||||
self.assertEqual(misc.formatLang(self.env, 100.205, rounding_method='HALF-DOWN'), '100.20')
|
||||
self.assertEqual(misc.formatLang(self.env, 100.215, rounding_method='HALF-DOWN'), '100.21')
|
||||
|
||||
def test_rounding_unit(self):
|
||||
self.assertEqual(misc.formatLang(self.env, 1000000.00), '1,000,000.00')
|
||||
self.assertEqual(misc.formatLang(self.env, 1000000.00, rounding_unit='units'), '1,000,000')
|
||||
self.assertEqual(misc.formatLang(self.env, 1000000.00, rounding_unit='thousands'), '1,000')
|
||||
self.assertEqual(misc.formatLang(self.env, 1000000.00, rounding_unit='lakhs'), '10')
|
||||
self.assertEqual(misc.formatLang(self.env, 1000000.00, rounding_unit="millions"), '1')
|
||||
|
||||
def test_rounding_method_and_rounding_unit(self):
|
||||
self.assertEqual(misc.formatLang(self.env, 1822060000, rounding_method='HALF-UP', rounding_unit='lakhs'), '18,221')
|
||||
self.assertEqual(misc.formatLang(self.env, 1822050000, rounding_method='HALF-UP', rounding_unit='lakhs'), '18,221')
|
||||
self.assertEqual(misc.formatLang(self.env, 1822049900, rounding_method='HALF-UP', rounding_unit='lakhs'), '18,220')
|
||||
|
||||
|
||||
class TestUrlValidate(BaseCase):
|
||||
def test_url_validate(self):
|
||||
|
||||
+46
-12
@@ -1373,24 +1373,58 @@ def babel_locale_parse(lang_code):
|
||||
except:
|
||||
return babel.Locale.parse("en_US")
|
||||
|
||||
def formatLang(env, value, digits=2, grouping=True, monetary=False, dp=None, currency_obj=None):
|
||||
def formatLang(env, value, digits=2, grouping=True, monetary=False, dp=None, currency_obj=None, rounding_method='HALF-EVEN', rounding_unit='decimals'):
|
||||
"""
|
||||
Assuming 'Account' decimal.precision=3:
|
||||
formatLang(value) -> digits=2 (default)
|
||||
formatLang(value, digits=4) -> digits=4
|
||||
formatLang(value, dp='Account') -> digits=3
|
||||
formatLang(value, digits=5, dp='Account') -> digits=5
|
||||
This function will format a number `value` to the appropriate format of the language used.
|
||||
|
||||
:param Object env: The environment.
|
||||
:param float value: The value to be formatted.
|
||||
:param int digits: The number of decimals digits.
|
||||
:param bool grouping: Usage of language grouping or not.
|
||||
:param bool monetary: Usage of thousands separator or not.
|
||||
.. deprecated:: 13.0
|
||||
:param str dp: Name of the decimals precision to be used. This will override ``digits``
|
||||
and ``currency_obj`` precision.
|
||||
:param Object currency_obj: Currency to be used. This will override ``digits`` precision.
|
||||
:param str rounding_method: The rounding method to be used:
|
||||
**'HALF-UP'** will round to the closest number with ties going away from zero,
|
||||
**'HALF-DOWN'** will round to the closest number with ties going towards zero,
|
||||
**'HALF_EVEN'** will round to the closest number with ties going to the closest
|
||||
even number,
|
||||
**'UP'** will always round away from 0,
|
||||
**'DOWN'** will always round towards 0.
|
||||
:param str rounding_unit: The rounding unit to be used:
|
||||
**decimals** will round to decimals with ``digits`` or ``dp`` precision,
|
||||
**units** will round to units without any decimals,
|
||||
**thousands** will round to thousands without any decimals,
|
||||
**lakhs** will round to lakhs without any decimals,
|
||||
**millions** will round to millions without any decimals.
|
||||
|
||||
:returns: The value formatted.
|
||||
:rtype: str
|
||||
"""
|
||||
# We don't want to return 0
|
||||
if isinstance(value, str) and not value:
|
||||
if value == '':
|
||||
return ''
|
||||
|
||||
if dp:
|
||||
digits = env['decimal.precision'].precision_get(dp)
|
||||
elif currency_obj:
|
||||
digits = currency_obj.decimal_places
|
||||
if rounding_unit == 'decimals':
|
||||
if dp:
|
||||
digits = env['decimal.precision'].precision_get(dp)
|
||||
elif currency_obj:
|
||||
digits = currency_obj.decimal_places
|
||||
else:
|
||||
digits = 0
|
||||
|
||||
rounded_value = float_round(value, precision_digits=digits, rounding_method='HALF-EVEN')
|
||||
rounding_unit_mapping = {
|
||||
'decimals': 1,
|
||||
'thousands': 10**3,
|
||||
'lakhs': 10**5,
|
||||
'millions': 10**6,
|
||||
}
|
||||
|
||||
value /= rounding_unit_mapping.get(rounding_unit, 1)
|
||||
|
||||
rounded_value = float_round(value, precision_digits=digits, rounding_method=rounding_method)
|
||||
formatted_value = get_lang(env).format(f'%.{digits}f', rounded_value, grouping=grouping, monetary=monetary)
|
||||
|
||||
if currency_obj and currency_obj.symbol:
|
||||
|
||||
Reference in New Issue
Block a user