summaryrefslogtreecommitdiff
path: root/addons/mrp/tests
diff options
context:
space:
mode:
authorArnold Moyaux <arm@odoo.com>2018-06-27 10:19:18 +0200
committerArnold Moyaux <arm@odoo.com>2018-08-13 15:38:34 +0200
commit1e160dffd375ef5bb5ceb7ec34ee172944719b03 (patch)
treedd2b13ed7ecec5b1f786d72030719f771b5645bf /addons/mrp/tests
parent177981b09f7a765021bfb87401b39875edf91584 (diff)
[IMP] stock, mrp: picking before and after manufacturing
Currently MRP do not handle multi locations for components. In order to be able to use both feature at the same time, we could: - Improve mrp in order to handle multiple stock.move.line for a componenet stock.move - Add a rule that allow to bring all the good from multiple location to a single location. (was already possible but it requires some configuration) This commit introduce a checkbox on the warehouse in order to automatically configure all the routes/rules/locations/picking_types,... necessary to bring all the components to a single location before running the manufacturing order. Technically it also refactor some stock_warehouse.py methods in order to easily override the picking_type, rules and routes creation. Thank to Hetashree Chauhan <hch@odoo.com> for his help. task_id: 27785
Diffstat (limited to 'addons/mrp/tests')
-rw-r--r--addons/mrp/tests/__init__.py1
-rw-r--r--addons/mrp/tests/test_bom.py5
-rw-r--r--addons/mrp/tests/test_stock.py2
-rw-r--r--addons/mrp/tests/test_warehouse_multistep_manufacturing.py169
4 files changed, 175 insertions, 2 deletions
diff --git a/addons/mrp/tests/__init__.py b/addons/mrp/tests/__init__.py
index ec92be3cee8..ba967b5b60e 100644
--- a/addons/mrp/tests/__init__.py
+++ b/addons/mrp/tests/__init__.py
@@ -3,6 +3,7 @@
from . import test_bom
from . import test_order
from . import test_stock
+from . import test_warehouse_multistep_manufacturing
from . import test_workorder_operation
from . import test_procurement
from . import test_unbuild
diff --git a/addons/mrp/tests/test_bom.py b/addons/mrp/tests/test_bom.py
index 71421216411..0cd8f9effa4 100644
--- a/addons/mrp/tests/test_bom.py
+++ b/addons/mrp/tests/test_bom.py
@@ -66,7 +66,10 @@ class TestBoM(TestMrpCommon):
tmp_picking_type = self.env['stock.picking.type'].create({
'name': 'Manufacturing',
'code': 'mrp_operation',
- 'sequence_id': self.env['ir.sequence'].search([('code', '=', 'mrp.production')], limit=1).id,
+ 'sequence_id': self.env['ir.sequence'].create({
+ 'code': 'mrp.production',
+ 'name': 'tmp_production_sequence',
+ }).id,
})
test_bom_1 = self.env['mrp.bom'].create({
'product_tmpl_id': self.product_5.product_tmpl_id.id,
diff --git a/addons/mrp/tests/test_stock.py b/addons/mrp/tests/test_stock.py
index 571890f7271..8169f742ca6 100644
--- a/addons/mrp/tests/test_stock.py
+++ b/addons/mrp/tests/test_stock.py
@@ -18,7 +18,7 @@ class TestWarehouse(common.TestMrpCommon):
warehouse_1_stock_manager.write({
'manufacture_to_resupply': False
})
- self.assertFalse(self.warehouse_1.manufacture_pull_id)
+ self.assertFalse(self.warehouse_1.manufacture_pull_id.active)
self.assertFalse(self.warehouse_1.manu_type_id.active)
self.assertNotIn(manu_route, warehouse_1_stock_manager._get_all_routes())
warehouse_1_stock_manager.write({
diff --git a/addons/mrp/tests/test_warehouse_multistep_manufacturing.py b/addons/mrp/tests/test_warehouse_multistep_manufacturing.py
new file mode 100644
index 00000000000..570ab7e6069
--- /dev/null
+++ b/addons/mrp/tests/test_warehouse_multistep_manufacturing.py
@@ -0,0 +1,169 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo.tests import Form
+from odoo.addons.mrp.tests.common import TestMrpCommon
+
+
+class TestMultistepManufacturingWarehouse(TestMrpCommon):
+
+ def setUp(self):
+ super(TestMultistepManufacturingWarehouse, self).setUp()
+ # Create warehouse
+ self.customer_location = self.env['ir.model.data'].xmlid_to_res_id('stock.stock_location_customers')
+ warehouse_form = Form(self.env['stock.warehouse'])
+ warehouse_form.name = 'Test Warehouse'
+ warehouse_form.code = 'TWH'
+ self.warehouse = warehouse_form.save()
+
+ self.uom_unit = self.env.ref('uom.product_uom_unit')
+
+ # Create manufactured product
+ product_form = Form(self.env['product.product'])
+ product_form.name = 'Stick'
+ product_form.uom_id = self.uom_unit
+ product_form.uom_po_id = self.uom_unit
+ product_form.type = 'product'
+ product_form.route_ids.clear()
+ product_form.route_ids.add(self.warehouse.manufacture_pull_id.route_id)
+ product_form.route_ids.add(self.warehouse.mto_pull_id.route_id)
+ self.finished_product = product_form.save()
+
+ # Create raw product for manufactured product
+ product_form = Form(self.env['product.product'])
+ product_form.name = 'Raw Stick'
+ product_form.type = 'product'
+ product_form.uom_id = self.uom_unit
+ product_form.uom_po_id = self.uom_unit
+ self.raw_product = product_form.save()
+
+ # Create bom for manufactured product
+ bom_product_form = Form(self.env['mrp.bom'])
+ bom_product_form.product_id = self.finished_product
+ bom_product_form.product_tmpl_id = self.finished_product.product_tmpl_id
+ bom_product_form.product_qty = 1.0
+ bom_product_form.type = 'normal'
+ with bom_product_form.bom_line_ids.new() as bom_line:
+ bom_line.product_id = self.raw_product
+ bom_line.product_qty = 2.0
+
+ self.bom = bom_product_form.save()
+
+ def _check_location_and_routes(self):
+ # Check manufacturing pull rule.
+ self.assertTrue(self.warehouse.manufacture_pull_id)
+ self.assertTrue(self.warehouse.manufacture_pull_id.active, self.warehouse.manufacture_to_resupply)
+ self.assertTrue(self.warehouse.manufacture_pull_id.route_id)
+ # Check new routes created or not.
+ self.assertTrue(self.warehouse.pbm_route_id)
+ # Check location should be created and linked to warehouse.
+ self.assertTrue(self.warehouse.pbm_loc_id)
+ self.assertEqual(self.warehouse.pbm_loc_id.active, self.warehouse.manufacture_steps != 'mrp_one_step', "Input location must be de-active for single step only.")
+ self.assertTrue(self.warehouse.manu_type_id.active)
+
+ def test_00_create_warehouse(self):
+ """ Warehouse testing for direct manufacturing """
+ with Form(self.warehouse) as warehouse:
+ warehouse.manufacture_steps = 'mrp_one_step'
+ self._check_location_and_routes()
+ # Check locations of existing pull rule
+ self.assertFalse(self.warehouse.pbm_route_id.rule_ids, 'only the update of global manufacture route should happen.')
+ self.assertEqual(self.warehouse.manufacture_pull_id.location_id.id, self.warehouse.lot_stock_id.id)
+
+ def test_01_warehouse_twostep_manufacturing(self):
+ """ Warehouse testing for picking before manufacturing """
+ with Form(self.warehouse) as warehouse:
+ warehouse.manufacture_steps = 'pbm'
+ self._check_location_and_routes()
+ self.assertEqual(len(self.warehouse.pbm_route_id.rule_ids), 2)
+ self.assertEqual(self.warehouse.manufacture_pull_id.location_id.id, self.warehouse.lot_stock_id.id)
+
+ def test_02_warehouse_twostep_manufacturing(self):
+ """ Warehouse testing for picking ans store after manufacturing """
+ with Form(self.warehouse) as warehouse:
+ warehouse.manufacture_steps = 'pbm_sam'
+ self._check_location_and_routes()
+ self.assertEqual(len(self.warehouse.pbm_route_id.rule_ids), 2)
+ self.assertEqual(self.warehouse.manufacture_pull_id.location_id.id, self.warehouse.sam_loc_id.id)
+
+ def test_manufacturing_flow(self):
+ """ Simulate a pick pack ship delivery combined with a picking before
+ manufacturing and store after manufacturing. Also ensure that the MO and
+ the moves to stock are created with the generic pull rules.
+ In order to trigger the rule we create a picking to the customer with
+ the 'make to order' procure method
+ """
+ with Form(self.warehouse) as warehouse:
+ warehouse.manufacture_steps = 'pbm_sam'
+ warehouse.delivery_steps = 'pick_pack_ship'
+ self.env['stock.quant']._update_available_quantity(self.raw_product, self.warehouse.lot_stock_id, 4.0)
+ picking_customer = self.env['stock.picking'].create({
+ 'location_id': self.warehouse.wh_output_stock_loc_id.id,
+ 'location_dest_id': self.customer_location,
+ 'partner_id': self.env['ir.model.data'].xmlid_to_res_id('base.res_partner_4'),
+ 'picking_type_id': self.warehouse.out_type_id.id,
+ })
+ self.env['stock.move'].create({
+ 'name': self.finished_product.name,
+ 'product_id': self.finished_product.id,
+ 'product_uom_qty': 2,
+ 'product_uom': self.uom_unit.id,
+ 'picking_id': picking_customer.id,
+ 'location_id': self.warehouse.wh_output_stock_loc_id.id,
+ 'location_dest_id': self.customer_location,
+ 'procure_method': 'make_to_order',
+ 'state': 'draft',
+ })
+ picking_customer.action_confirm()
+ production_order = self.env['mrp.production'].search([('product_id', '=', self.finished_product.id)])
+ self.assertTrue(production_order)
+
+ picking_stock_preprod = self.env['stock.move'].search([
+ ('product_id', '=', self.raw_product.id),
+ ('location_id', '=', self.warehouse.lot_stock_id.id),
+ ('location_dest_id', '=', self.warehouse.pbm_loc_id.id),
+ ('picking_type_id', '=', self.warehouse.pbm_type_id.id)
+ ]).picking_id
+ picking_stock_postprod = self.env['stock.move'].search([
+ ('product_id', '=', self.finished_product.id),
+ ('location_id', '=', self.warehouse.sam_loc_id.id),
+ ('location_dest_id', '=', self.warehouse.lot_stock_id.id),
+ ('picking_type_id', '=', self.warehouse.sam_type_id.id)
+ ]).picking_id
+
+ self.assertTrue(picking_stock_preprod)
+ self.assertTrue(picking_stock_postprod)
+ self.assertEqual(picking_stock_preprod.state, 'confirmed')
+ self.assertEqual(picking_stock_postprod.state, 'waiting')
+
+ picking_stock_preprod.action_assign()
+ picking_stock_preprod.move_line_ids.qty_done = 4
+ picking_stock_preprod.action_done()
+
+ self.assertFalse(self.env['stock.quant']._gather(self.raw_product, self.warehouse.lot_stock_id))
+ self.assertTrue(self.env['stock.quant']._gather(self.raw_product, self.warehouse.pbm_loc_id))
+
+ production_order.action_assign()
+ self.assertEqual(production_order.availability, 'assigned')
+ self.assertEqual(picking_stock_postprod.state, 'waiting')
+
+ produce_form = Form(self.env['mrp.product.produce'].with_context({
+ 'active_id': production_order.id,
+ 'active_ids': [production_order.id],
+ }))
+ produce_form.product_qty = production_order.product_qty
+ product_produce = produce_form.save()
+ product_produce.do_produce()
+ production_order.button_mark_done()
+
+ self.assertFalse(self.env['stock.quant']._gather(self.raw_product, self.warehouse.pbm_loc_id))
+
+ self.assertEqual(picking_stock_postprod.state, 'assigned')
+
+ picking_stock_pick = self.env['stock.move'].search([
+ ('product_id', '=', self.finished_product.id),
+ ('location_id', '=', self.warehouse.lot_stock_id.id),
+ ('location_dest_id', '=', self.warehouse.wh_pack_stock_loc_id.id),
+ ('picking_type_id', '=', self.warehouse.pick_type_id.id)
+ ]).picking_id
+ self.assertEqual(picking_stock_pick.move_lines.move_orig_ids.picking_id, picking_stock_postprod)