diff options
| author | William Henrotin <whe@odoo.com> | 2019-08-08 09:19:28 +0000 |
|---|---|---|
| committer | William Henrotin <whe@odoo.com> | 2019-08-13 07:54:38 +0000 |
| commit | fff2a30afba8b8f13ca03b1719f4e3c93174d1ae (patch) | |
| tree | a18fd91d7390688898570d79ddb66d99472d644a /addons/sale_mrp | |
| parent | c2c9d6d143af7f00bb07e391fe494c2496cdad88 (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.py | 48 | ||||
| -rw-r--r-- | addons/sale_mrp/tests/test_sale_mrp_flow.py | 32 |
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' : |
