[FIX] fields.float: always round floats when persisting
authorOlivier Dony <odo@openerp.com>
Wed, 21 Dec 2011 01:11:00 +0000 (02:11 +0100)
committerOlivier Dony <odo@openerp.com>
Wed, 21 Dec 2011 01:11:00 +0000 (02:11 +0100)
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
openerp/osv/fields.py

index fcead83..450719a 100644 (file)
         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"
 -
     !python {model: res.currency}: |
index ea1b6d9..5a40eaf 100644 (file)
@@ -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: