[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
This commit is contained in:
Mart Raudsepp 2014-12-02 13:02:18 +00:00 committed by Josse Colpaert
parent a300b6e3e7
commit 05de60cbf9
1 changed files with 7 additions and 7 deletions

View File

@ -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])