From 05de60cbf91e62ca03eee8fe91c0856dbd687941 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Tue, 2 Dec 2014 13:02:18 +0000 Subject: [PATCH] [FIX] Correct floating number handling for _procure_orderpoint_confirm Fixes comparison with min_quantity orderpoint in scheduler - basic floating point math issue in procurement scheduler when comparing current quantity with orderpoint minimum quantity. In certain cases floating point comparison could result in e.g 400.0 < 400.0 == True due to typical floating point comparison issues, as Odoo doesn't use Decimal types where the issue doesn't exist. Fixes early exiting out of the loop cycle, in case qty is already near zero. Fixes the new procurement creation check, to not do that if it's close enough to zero already, to be considered a floating point math error, not really non-zero. These combined (or at least the last one) avoid each supply_method == buy pending in draft PO's getting a zero quantity extra procurement order each time the scheduler runs. Otherwise there could be hundreds of zero quantity procurement orders pending, which makes the confirming of the PO take hours, due to creating hundreds of stock moves for each order line. Use float_compare helper to solve all these with floating point type for now, instead of the more evasion possibility of converting to Decimal module. Two potential bad comparisons remain, add FIXME notes for now until further analysis. Also: Float rounding on reste when comparing and on the procurement qty --- addons/stock/procurement.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py index c105ed6c017..7b067ed7e3b 100644 --- a/addons/stock/procurement.py +++ b/addons/stock/procurement.py @@ -22,7 +22,7 @@ from openerp.osv import fields, osv from openerp.tools.translate import _ -from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT +from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, float_compare, float_round from openerp import SUPERUSER_ID from dateutil.relativedelta import relativedelta from datetime import datetime @@ -352,21 +352,21 @@ class procurement_order(osv.osv): prods = self._product_virtual_get(cr, uid, op) if prods is None: continue - if prods < op.product_min_qty: + if float_compare(prods, op.product_min_qty, precision_rounding=op.product_uom.rounding) < 0: qty = max(op.product_min_qty, op.product_max_qty) - prods - reste = op.qty_multiple > 0 and qty % op.qty_multiple or 0.0 - if reste > 0: + if float_compare(reste, 0.0, precision_rounding=op.product_uom.rounding) > 0: qty += op.qty_multiple - reste - if qty <= 0: + if float_compare(qty, 0.0, precision_rounding=op.product_uom.rounding) <= 0: continue qty -= orderpoint_obj.subtract_procurements(cr, uid, op, context=context) - if qty > 0: + qty_rounded = float_round(qty, precision_rounding=op.product_uom.rounding) + if qty_rounded > 0: proc_id = procurement_obj.create(cr, uid, - self._prepare_orderpoint_procurement(cr, uid, op, qty, context=context), + self._prepare_orderpoint_procurement(cr, uid, op, qty_rounded, context=context), context=context) self.check(cr, uid, [proc_id]) self.run(cr, uid, [proc_id])