From 6b3fefcdbbf58c8a6284b0b5b4f71b77c5cfeb02 Mon Sep 17 00:00:00 2001 From: Arnold Moyaux Date: Mon, 20 Nov 2017 14:12:49 +0100 Subject: [PATCH] [FIX] stock: use float tools in order to compare float are used in quants thus we should use the float utility tools in order to compare them. --- addons/stock/models/stock_quant.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/addons/stock/models/stock_quant.py b/addons/stock/models/stock_quant.py index 2b2a226aa5d..c84bc6f67ed 100644 --- a/addons/stock/models/stock_quant.py +++ b/addons/stock/models/stock_quant.py @@ -6,6 +6,7 @@ from psycopg2 import OperationalError, Error from odoo import api, fields, models, _ from odoo.exceptions import UserError, ValidationError from odoo.osv import expression +from odoo.tools.float_utils import float_compare, float_is_zero import logging @@ -71,7 +72,7 @@ class StockQuant(models.Model): @api.constrains('quantity') def check_quantity(self): for quant in self: - if quant.quantity > 1 and quant.lot_id and quant.product_id.tracking == 'serial': + if float_compare(quant.quantity, 1, precision_rounding=quant.product_uom_id.rounding) > 0 and quant.lot_id and quant.product_id.tracking == 'serial': raise ValidationError(_('A serial number should only be linked to a single product.')) @api.constrains('in_date', 'lot_id') @@ -152,12 +153,13 @@ class StockQuant(models.Model): """ self = self.sudo() quants = self._gather(product_id, location_id, lot_id=lot_id, package_id=package_id, owner_id=owner_id, strict=strict) + rounding = product_id.uom_id.rounding if product_id.tracking == 'none': available_quantity = sum(quants.mapped('quantity')) - sum(quants.mapped('reserved_quantity')) if allow_negative: return available_quantity else: - return available_quantity if available_quantity >= 0.0 else 0.0 + return available_quantity if float_compare(available_quantity, 0.0, precision_rounding=rounding) >= 0.0 else 0.0 else: availaible_quantities = {lot_id: 0.0 for lot_id in list(set(quants.mapped('lot_id'))) + ['untracked']} for quant in quants: @@ -168,7 +170,7 @@ class StockQuant(models.Model): if allow_negative: return sum(availaible_quantities.values()) else: - return sum([available_quantity for available_quantity in availaible_quantities.values() if available_quantity > 0]) + return sum([available_quantity for available_quantity in availaible_quantities.values() if float_compare(available_quantity, 0, precision_rounding=rounding) > 0]) @api.model def _update_available_quantity(self, product_id, location_id, quantity, lot_id=None, package_id=None, owner_id=None, in_date=None): @@ -188,6 +190,7 @@ class StockQuant(models.Model): """ self = self.sudo() quants = self._gather(product_id, location_id, lot_id=lot_id, package_id=package_id, owner_id=owner_id, strict=True) + rounding = product_id.uom_id.rounding if lot_id: incoming_dates = quants.mapped('in_date') # `mapped` already filtered out falsy items @@ -210,7 +213,7 @@ class StockQuant(models.Model): 'in_date': in_date, }) # cleanup empty quants - if quant.quantity == 0 and quant.reserved_quantity == 0: + if float_is_zero(quant.quantity, precision_rounding=rounding) and float_is_zero(quant.reserved_quantity, precision_rounding=rounding): quant.unlink() break except OperationalError as e: @@ -244,18 +247,19 @@ class StockQuant(models.Model): was done and how much the system was able to reserve on it """ self = self.sudo() + rounding = product_id.uom_id.rounding quants = self._gather(product_id, location_id, lot_id=lot_id, package_id=package_id, owner_id=owner_id, strict=strict) available_quantity = self._get_available_quantity(product_id, location_id, lot_id=lot_id, package_id=package_id, owner_id=owner_id, strict=strict) - if quantity > 0 and quantity > available_quantity: + if float_compare(quantity, 0, precision_rounding=rounding) > 0 and float_compare(quantity, available_quantity, precision_rounding=rounding) > 0: raise UserError(_('It is not possible to reserve more products than you have in stock.')) - elif quantity < 0 and abs(quantity) > sum(quants.mapped('reserved_quantity')): + elif float_compare(quantity, 0, precision_rounding=rounding) < 0 and float_compare(abs(quantity), sum(quants.mapped('reserved_quantity')), precision_rounding=rounding) > 0: raise UserError(_('It is not possible to unreserve more products than you have in stock.')) reserved_quants = [] for quant in quants: - if quantity > 0: + if float_compare(quantity, 0, precision_rounding=rounding) > 0: max_quantity_on_quant = quant.quantity - quant.reserved_quantity - if max_quantity_on_quant <= 0: + if float_compare(max_quantity_on_quant, 0, precision_rounding=rounding) <= 0: continue max_quantity_on_quant = min(max_quantity_on_quant, quantity) quant.reserved_quantity += max_quantity_on_quant @@ -269,7 +273,7 @@ class StockQuant(models.Model): quantity += max_quantity_on_quant available_quantity += max_quantity_on_quant - if quantity == 0 or available_quantity == 0: + if float_is_zero(quantity, precision_rounding=rounding) or float_is_zero(available_quantity, precision_rounding=rounding): break return reserved_quants