The result of the following:
```
float_round(2.5, precision_rounding=0.05, rounding_method='DOWN')
```
is 2.45. Instead, 2.5 is expected.
In case of the `DOWN` method, epsilon should be added, not subtracted.
In the meantime, we introduce a slight reorganization of the method to
make it clearer.
opw-805008
In some countries, we need to be able to make appear on an invoice a rounding line, appearing there only because the smallest
coinage has been removed from the circulation.
For example, in Switerzland invoices have to be rounded to 0.05 CHF because coins of 0.01 CHF and 0.02 CHF aren't used anymore.
Was PR #15231
Was task 30904
In Python 3 round:
* rounds half to even (banker's rounding) rather than up
* returns an int if not given a precision (or given a precision of
None)
* discards the negative sign when rounding to 0
Add a compatibility shim which implements P2 behaviour and at least
allows passing float_utils's tests.
Implementing float_round on top of Decimal was attempted but did not
work: although Decimal.quantize takes a non-integral
Decimal (e.g. ``d.quantize(D('0.001'))``) it only supports integral
powers of 10 and does not support quantizing to e.g. 0.05: while that
will not fail it will just use the exponent for quantization and 0.05
is thus equivalent to 0.01, which is not what we want if e.g. need to
round a value to 5 cents.
This is hinted at but maybe not clearly spelled out by the official
documentation:
> Return a value equal to the first operand after rounding
> and **having the exponent of** the second operand.
Also convert a bunch of hand-rolled currency rounding to just using
the round() method on res.currency.
In Python 3 round:
* rounds half to even (banker's rounding) rather than up
* returns an int if not given a precision (or given a precision of
None)
* discards the negative sign when rounding to 0
Add a compatibility shim which implements P2 behaviour and at least
allows passing float_utils's tests.
Implementing float_round on top of Decimal was attempted but did not
work: although Decimal.quantize takes a non-integral
Decimal (e.g. ``d.quantize(D('0.001'))``) it only supports integral
powers of 10 and does not support quantizing to e.g. 0.05: while that
will not fail it will just use the exponent for quantization and 0.05
is thus equivalent to 0.01, which is not what we want if e.g. need to
round a value to 5 cents.
This is hinted at but maybe not clearly spelled out by the official
documentation:
> Return a value equal to the first operand after rounding
> and **having the exponent of** the second operand.
Also convert a bunch of hand-rolled currency rounding to just using
the round() method on res.currency.
Let `create` and `write` round monetary field values before sending them to the
database. Pass the values to be written to `field.convert_to_column`, so that
the currency can be retrieved from the values, and the value be rounded.
In Python 3:
* various builtins and dict methods were changed to return
view/iterable objects rather than lists
* and the separate Python 2 view/iterable builtins and methods were
removed altogether
This is problematic when using these items as list (which the happens
repeatedly in Odoo), but more viciously when iterating *multiple times*
over them (which also happens, which I've messed up multiple times while
writing this, and which is a pain to debug even when you've just created
the issue).
Convert all code using these to semantics-matching cross-version
helper functions to get the LCD behaviour between P2 and P3, and
forbid the builtins via lint.
issue #8530
In Python 3, ``print`` becomes a builtin function. This is available
in Python 2 by importing the ``print_function`` feature from
``__future__``, the feature is conveniently still available in Python
3 (it just does nothing).
Fixers:
libfuturize.fixes.fix_print_with_import
#8530