diff options
| author | Arnold Moyaux <arm@odoo.com> | 2018-06-27 10:19:18 +0200 |
|---|---|---|
| committer | Arnold Moyaux <arm@odoo.com> | 2018-08-13 15:38:34 +0200 |
| commit | 1e160dffd375ef5bb5ceb7ec34ee172944719b03 (patch) | |
| tree | dd2b13ed7ecec5b1f786d72030719f771b5645bf /addons/mrp/tests | |
| parent | 177981b09f7a765021bfb87401b39875edf91584 (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__.py | 1 | ||||
| -rw-r--r-- | addons/mrp/tests/test_bom.py | 5 | ||||
| -rw-r--r-- | addons/mrp/tests/test_stock.py | 2 | ||||
| -rw-r--r-- | addons/mrp/tests/test_warehouse_multistep_manufacturing.py | 169 |
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) |
