summaryrefslogtreecommitdiff
path: root/addons/sale_mrp
diff options
context:
space:
mode:
authorWilliam Henrotin <whe@odoo.com>2019-08-08 09:19:28 +0000
committerWilliam Henrotin <whe@odoo.com>2019-08-13 07:54:38 +0000
commitfff2a30afba8b8f13ca03b1719f4e3c93174d1ae (patch)
treea18fd91d7390688898570d79ddb66d99472d644a /addons/sale_mrp
parentc2c9d6d143af7f00bb07e391fe494c2496cdad88 (diff)
[IMP] sale_stock,sale_mrp: available quantities on sales order
Selling a product you don't have in stock anymore triggers a message without pertinent information about available quantity. This commit adds a little widget on sale order line to inform the salesman there are not enough quantity available. Clicking on it will reveal: * The estimated delivery date * The actual quantity on hand * The quantity forcasted at the estimated delivery date For kit product, the quantities are the maximum occurence of kit available regarding components quantities. Task 2003485 closes odoo/odoo#34336 Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>
Diffstat (limited to 'addons/sale_mrp')
-rw-r--r--addons/sale_mrp/models/sale_mrp.py48
-rw-r--r--addons/sale_mrp/tests/test_sale_mrp_flow.py32
2 files changed, 19 insertions, 61 deletions
diff --git a/addons/sale_mrp/models/sale_mrp.py b/addons/sale_mrp/models/sale_mrp.py
index 33f3bfc40f8..8bba330ca30 100644
--- a/addons/sale_mrp/models/sale_mrp.py
+++ b/addons/sale_mrp/models/sale_mrp.py
@@ -8,6 +8,16 @@ from odoo.tools import float_compare, float_round
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
+ @api.depends('product_uom_qty', 'qty_delivered', 'product_id', 'state')
+ def _compute_qty_to_deliver(self):
+ """The inventory widget should now be visible in more cases if the product is consumable."""
+ super(SaleOrderLine, self)._compute_qty_to_deliver()
+ for line in self:
+ if line.state == 'draft' and line.product_type == 'consu':
+ components = line.product_id.get_components()
+ if components and components != [line.product_id.id]:
+ line.display_qty_widget = True
+
def _compute_qty_delivered(self):
super(SaleOrderLine, self)._compute_qty_delivered()
for order_line in self:
@@ -51,44 +61,6 @@ class SaleOrderLine(models.Model):
components[product] = {'qty': qty, 'uom': to_uom.id}
return components
- def _check_availability(self, product_id):
- """ If the 'product_id' is a kit, this method check if every component's
- availability and catch every warning returned in order to merge them in a single
- comprehensive warning
- """
- bom_kit = self.env['mrp.bom']._bom_find(product=product_id, bom_type='phantom')
- if not bom_kit:
- return super(SaleOrderLine, self)._check_availability(product_id)
-
- kit = product_id
- kit_qty = self.product_uom._compute_quantity(self.product_uom_qty, self.product_id.uom_id)
-
- # We check if we need to display the quantities of each missing components for all warehouses
- kit_by_wh = self.product_id.with_context(warehouse=self.order_id.warehouse_id.id)
- precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
- if float_compare(kit_by_wh.virtual_available, kit_qty, precision_digits=precision) != -1:
- return {}
- ignore_warehouse = float_compare(kit.virtual_available, kit_qty, precision_digits=precision) != -1
-
- message = ''
- boms, bom_sub_lines = bom_kit.explode(kit, kit_qty)
- for bom_line, bom_line_data in bom_sub_lines:
- component = bom_line.product_id
- component_uom_qty = bom_line_data['qty']
- component_qty = bom_line.product_uom_id._compute_quantity(component_uom_qty, bom_line.product_id.uom_id)
- component_warning = self._check_availability_warning(component, component_qty, ignore_warehouse=ignore_warehouse)
- if component_warning:
- message += component_warning['warning']['message'] + '\n'
-
- warning = {}
- if message:
- warning_mess = {
- 'title': _('Not enough inventory!'),
- 'message': message
- }
- warning = {'warning': warning_mess}
- return warning
-
def _get_qty_procurement(self, previous_product_uom_qty=False):
self.ensure_one()
# Specific case when we change the qty on a SO for a kit product.
diff --git a/addons/sale_mrp/tests/test_sale_mrp_flow.py b/addons/sale_mrp/tests/test_sale_mrp_flow.py
index bafa2a17882..a849b8e82c4 100644
--- a/addons/sale_mrp/tests/test_sale_mrp_flow.py
+++ b/addons/sale_mrp/tests/test_sale_mrp_flow.py
@@ -5,7 +5,7 @@ from datetime import datetime
from odoo.tests import common, Form
from odoo.exceptions import UserError
-from odoo.tools import mute_logger
+from odoo.tools import mute_logger, float_compare
class TestSaleMrpFlow(common.SavepointCase):
@@ -1052,9 +1052,8 @@ class TestSaleMrpFlow(common.SavepointCase):
self.assertEquals(kit_parent_wh_order.virtual_available, 0)
self.assertEquals(kit_parent_wh1.virtual_available, 1)
- # A warning message should be returned as there arn't enough quantities available for the sale order
- warning = order_line._onchange_product_id_check_availability()
- self.assertTrue(warning)
+ # Check there arn't enough quantities available for the sale order
+ self.assertTrue(float_compare(order_line.virtual_available_at_date - order_line.product_uom_qty, 0, precision_rounding=line.product_uom.rounding) == -1)
# We receive enoug of each component in Warehouse 2 to make 3 kit_parent
qty_to_process = {
@@ -1075,9 +1074,8 @@ class TestSaleMrpFlow(common.SavepointCase):
self.assertEquals(kit_parent_wh_order.virtual_available, 3)
self.assertEquals(kit_parent_wh1.virtual_available, 1)
- # A warning message should be returned as there arn't enough quantities available for the sale order
- warning = order_line._onchange_product_id_check_availability()
- self.assertTrue(warning)
+ # Check there arn't enough quantities available for the sale order
+ self.assertTrue(float_compare(order_line.virtual_available_at_date - order_line.product_uom_qty, 0, precision_rounding=line.product_uom.rounding) == -1)
# We receive enough of each component in Warehouse 2 to make 7 kit_parent
qty_to_process = {
@@ -1095,10 +1093,6 @@ class TestSaleMrpFlow(common.SavepointCase):
kit_parent_wh_order = self.kit_parent.with_context(warehouse=so.warehouse_id.id)
self.assertEquals(kit_parent_wh_order.virtual_available, 7)
- # Some cache issue prevents the following to work in a test
- #warning = order_line._onchange_product_id_check_availability()
- #self.assertFalse(warning)
-
def test_06_kit_qty_delivered_mixed_uom(self):
"""
Check that the quantities delivered are correct when a kit involves
@@ -1294,9 +1288,8 @@ class TestSaleMrpFlow(common.SavepointCase):
virtual_available_wh_order = kit_uom_in_kit.virtual_available
self.assertEquals(virtual_available_wh_order, 1)
- # A warning message should be returned as there arn't enough quantities available for the sale order
- warning = order_line._onchange_product_id_check_availability()
- self.assertTrue(warning)
+ # Check there arn't enough quantities available for the sale order
+ self.assertTrue(float_compare(order_line.virtual_available_at_date - order_line.product_uom_qty, 0, precision_rounding=line.product_uom.rounding) == -1)
# We receive enough of each component in Warehouse 1 to make 3 kit_uom_in_kit.
# Moves are created instead of only updating the quant quantities in order to trigger every compute fields.
@@ -1308,9 +1301,8 @@ class TestSaleMrpFlow(common.SavepointCase):
}
self._create_move_quantities(qty_to_process, components, warehouse_1)
- # Enough quantities should be available to make 3 kit_uom_in_kit and a warning message should be displayed
- warning = order_line._onchange_product_id_check_availability()
- self.assertTrue(warning)
+ # Check there arn't enough quantities available for the sale order
+ self.assertTrue(float_compare(order_line.virtual_available_at_date - order_line.product_uom_qty, 0, precision_rounding=line.product_uom.rounding) == -1)
kit_uom_in_kit.with_context(warehouse=warehouse_1.id)._compute_quantities()
virtual_available_wh_order = kit_uom_in_kit.virtual_available
self.assertEquals(virtual_available_wh_order, 3)
@@ -1322,12 +1314,6 @@ class TestSaleMrpFlow(common.SavepointCase):
kit_uom_in_kit.with_context(warehouse=warehouse_1.id)._compute_quantities()
self.assertEquals(kit_uom_in_kit.virtual_available, 5)
- # Some cache issue prevents the following to work in a test
-
- # No warning should be raised
- # warning = order_line._onchange_product_id_check_availability()
- # self.assertFalse(warning)
-
def test_10_sale_mrp_kits_routes(self):
# Create a kit 'kit_1' :