From e410b81cc4adba82e5619849da802ecb7b3e44ec Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 21 Dec 2011 02:11:00 +0100 Subject: [PATCH] [FIX] fields.float: always round floats when persisting Added test to try a full round-trip to the database as well to make sure the automatic rounding is working properly. lp bug: https://launchpad.net/bugs/882036 fixed bzr revid: odo@openerp.com-20111221011100-gybt9pjdfpg4wc86 --- openerp/addons/base/test/base_test.yml | 20 ++++++++++++++++++++ openerp/osv/fields.py | 17 +++++++++++------ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/openerp/addons/base/test/base_test.yml b/openerp/addons/base/test/base_test.yml index fcead834d93..450719af046 100644 --- a/openerp/addons/base/test/base_test.yml +++ b/openerp/addons/base/test/base_test.yml @@ -267,6 +267,26 @@ try_round(457.5, '460.00', precision_rounding=5) try_round(457.1, '456.00', precision_rounding=3) +- + "Float precision tests: check that proper rounding is performed for float persistence" +- + !python {model: res.currency}: | + currency = self.browse(cr, uid, ref('base.EUR')) + res_currency_rate = self.pool.get('res.currency.rate') + from tools import float_compare, float_is_zero, float_round, float_repr + def try_roundtrip(value, expected, self=self, cr=cr, currency=currency, + res_currency_rate=res_currency_rate): + rate_id = res_currency_rate.create(cr, 1, {'name':'2000-01-01', + 'rate': value, + 'currency_id': currency.id}) + rate = res_currency_rate.read(cr, 1, rate_id, ['rate'])['rate'] + assert rate == expected, 'Roundtrip error: got %s back from db, expected %s' % (rate, expected) + # res.currency.rate uses 6 digits of precision by default + try_roundtrip(2.6748955, 2.674896) + try_roundtrip(-2.6748955, -2.674896) + try_roundtrip(10000.999999, 10000.999999) + try_roundtrip(-10000.999999, -10000.999999) + - "Float precision tests: verify that invalid parameters are forbidden" - diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index ea1b6d93329..5a40eaff5fa 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -239,8 +239,10 @@ class float(_column): def digits_change(self, cr): if self.digits_compute: self.digits = self.digits_compute(cr) + if self.digits: precision, scale = self.digits - self._symbol_set = ('%s', lambda x: float_repr(float_round(__builtin__.float(x or 0.0), precision_digits=scale), + self._symbol_set = ('%s', lambda x: float_repr(float_round(__builtin__.float(x or 0.0), + precision_digits=scale), precision_digits=scale)) class date(_column): @@ -992,11 +994,14 @@ class function(_column): self._symbol_set = integer._symbol_set def digits_change(self, cr): - if self.digits_compute: - self.digits = self.digits_compute(cr) - precision, scale = self.digits - self._symbol_set = ('%s', lambda x: float_repr(float_round(__builtin__.float(x or 0.0), precision_digits=scale), - precision_digits=scale)) + if self._type == 'float': + if self.digits_compute: + self.digits = self.digits_compute(cr) + if self.digits: + precision, scale = self.digits + self._symbol_set = ('%s', lambda x: float_repr(float_round(__builtin__.float(x or 0.0), + precision_digits=scale), + precision_digits=scale)) def search(self, cr, uid, obj, name, args, context=None): if not self._fnct_search: