[FIX] product: _compute_qty: first round before ceiling, to avoid pathological cases
authorCedric Snauwaert <csn@openerp.com>
Wed, 24 Sep 2014 14:09:28 +0000 (16:09 +0200)
committerOlivier Dony <odo@openerp.com>
Wed, 24 Sep 2014 15:11:26 +0000 (17:11 +0200)
Fixes problem when we try to sell 12 units of a product and change it to 1 dozen,
the algorithm was then trying to recompute the original amount and was getting
12,0000048 as a result which was then passed to the ceiling method, getting 13.0!

See also previous commit and issue #1125, PR #1126

addons/product/product.py

index 83ab818..da0ce6f 100644 (file)
@@ -29,6 +29,7 @@ from openerp.osv import osv, fields
 from openerp.tools.translate import _
 
 import openerp.addons.decimal_precision as dp
+from openerp.tools.float_utils import float_round
 
 def ean_checksum(eancode):
     """returns the checksum of an ean string of length 13, returns -1 if the string has the wrong length"""
@@ -176,7 +177,10 @@ class product_uom(osv.osv):
                 raise osv.except_osv(_('Error!'), _('Conversion from Product UoM %s to Default UoM %s is not possible as they both belong to different Category!.') % (from_unit.name,to_unit.name,))
             else:
                 return qty
-        amount = qty / from_unit.factor
+        # First round to the precision of the original unit, so that
+        # float representation errors do not bias the following ceil()
+        # e.g. with 1 / (1/12) we could get 12.0000048, ceiling to 13! 
+        amount = float_round(qty/from_unit.factor, precision_rounding=from_unit.rounding)
         if to_unit:
             amount = ceiling(amount * to_unit.factor, to_unit.rounding)
         return amount