summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirti Choudhary <kic@odoo.com>2018-07-25 18:24:34 +0530
committerArnold Moyaux <arm@odoo.com>2018-08-06 14:04:27 +0200
commit09ba95b2d06760d7486ebb587af2099cccb8955f (patch)
treeb53b594312fe577ea1576b93d2f1e7914110b146
parentcaf86edbc42eed3bd95fffc36b5a699837a9ce4a (diff)
[FIX] mrp, mrp_byproduct: Pull/push rule on warehouse level for MO/Unbuild Order.
Finished product moves from a MO where created without warehouse_id. It implies that push rule based on warehouse where not trigger on those moves confirmation. This commit adds warehouse_id on unbuild/production's finished/raw moves. It also add a test for this behavior. Task ID - 1865574
-rw-r--r--addons/mrp/models/mrp_production.py1
-rw-r--r--addons/mrp/models/mrp_unbuild.py3
-rw-r--r--addons/mrp/tests/test_unbuild.py125
-rw-r--r--addons/mrp_byproduct/models/mrp_production.py1
4 files changed, 129 insertions, 1 deletions
diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py
index 64ed220b5b6..758cd1a2953 100644
--- a/addons/mrp/models/mrp_production.py
+++ b/addons/mrp/models/mrp_production.py
@@ -364,6 +364,7 @@ class MrpProduction(models.Model):
'location_dest_id': self.location_dest_id.id,
'company_id': self.company_id.id,
'production_id': self.id,
+ 'warehouse_id': self.location_dest_id.get_warehouse().id,
'origin': self.name,
'group_id': self.procurement_group_id.id,
'propagate': self.propagate,
diff --git a/addons/mrp/models/mrp_unbuild.py b/addons/mrp/models/mrp_unbuild.py
index 0f892beeb90..a611cfa2031 100644
--- a/addons/mrp/models/mrp_unbuild.py
+++ b/addons/mrp/models/mrp_unbuild.py
@@ -157,6 +157,7 @@ class MrpUnbuild(models.Model):
'product_uom_qty': unbuild.product_qty,
'location_id': unbuild.location_id.id,
'location_dest_id': unbuild.product_id.property_stock_production.id,
+ 'warehouse_id': unbuild.location_id.get_warehouse().id,
'origin': unbuild.name,
'consume_unbuild_id': unbuild.id,
})
@@ -189,6 +190,7 @@ class MrpUnbuild(models.Model):
'procure_method': 'make_to_stock',
'location_dest_id': self.location_dest_id.id,
'location_id': raw_move.location_dest_id.id,
+ 'warehouse_id': self.location_dest_id.get_warehouse().id,
'unbuild_id': self.id,
})
@@ -203,6 +205,7 @@ class MrpUnbuild(models.Model):
'procure_method': 'make_to_stock',
'location_dest_id': self.location_dest_id.id,
'location_id': self.product_id.property_stock_production.id,
+ 'warehouse_id': self.location_dest_id.get_warehouse().id,
'unbuild_id': self.id,
})
diff --git a/addons/mrp/tests/test_unbuild.py b/addons/mrp/tests/test_unbuild.py
index 505e47c4b13..bb6b01cd67d 100644
--- a/addons/mrp/tests/test_unbuild.py
+++ b/addons/mrp/tests/test_unbuild.py
@@ -450,4 +450,127 @@ class TestUnbuild(TestMrpCommon):
ml = mo.finished_move_line_ids[0].consume_line_ids.filtered(lambda m: m.product_id == p1 and m.lot_produced_id == lot_finished_1)
self.assertEqual(ml[0].qty_done, 12.0, 'Should have consumed 12 for the first lot')
ml = mo.finished_move_line_ids[1].consume_line_ids.filtered(lambda m: m.product_id == p1 and m.lot_produced_id == lot_finished_2)
- self.assertEqual(ml[0].qty_done, 8.0, 'Should have consumed 8 for the second lot') \ No newline at end of file
+ self.assertEqual(ml[0].qty_done, 8.0, 'Should have consumed 8 for the second lot')
+
+ def test_unbuild_with_routes(self):
+ """ This test creates a MO of a stockable product (Table). A new route for rule QC/Unbuild -> Stock
+ is created with Warehouse -> True.
+ The unbuild order should revert the consumed components into QC/Unbuild location for quality check
+ and then a picking should be generated for transferring components from QC/Unbuild location to stock.
+ """
+ StockQuant = self.env['stock.quant']
+ ProductObj = self.env['product.product']
+ # Create new QC/Unbuild location
+ warehouse = self.env.ref('stock.warehouse0')
+ unbuild_location = self.env['stock.location'].create({
+ 'name': 'QC/Unbuild',
+ 'usage': 'internal',
+ 'location_id': warehouse.view_location_id.id
+ })
+
+ # Create a product route containing a stock rule that will move product from QC/Unbuild location to stock
+ product_route = self.env['stock.location.route'].create({
+ 'name': 'QC/Unbuild -> Stock',
+ 'warehouse_selectable': True,
+ 'warehouse_ids': [(4, warehouse.id)],
+ 'rule_ids': [(0, 0, {
+ 'name': 'Send Matrial QC/Unbuild -> Stock',
+ 'action': 'push',
+ 'picking_type_id': self.ref('stock.picking_type_internal'),
+ 'location_src_id': unbuild_location.id,
+ 'location_id': self.stock_location.id,
+ })],
+ })
+
+ # Create a stockable product and its components
+ finshed_product = ProductObj.create({
+ 'name': 'Table',
+ 'type': 'product',
+ })
+ component1 = ProductObj.create({
+ 'name': 'Table head',
+ 'type': 'product',
+ })
+ component2 = ProductObj.create({
+ 'name': 'Table stand',
+ 'type': 'product',
+ })
+
+ # Create bom and add components
+ bom = self.env['mrp.bom'].create({
+ 'product_id': finshed_product.id,
+ 'product_tmpl_id': finshed_product.product_tmpl_id.id,
+ 'product_uom_id': self.uom_unit.id,
+ 'product_qty': 1.0,
+ 'type': 'normal',
+ 'bom_line_ids': [
+ (0, 0, {'product_id': component1.id, 'product_qty': 1}),
+ (0, 0, {'product_id': component2.id, 'product_qty': 1})
+ ]})
+
+ # Set on hand quantity
+ StockQuant._update_available_quantity(component1, self.stock_location, 1)
+ StockQuant._update_available_quantity(component2, self.stock_location, 1)
+
+ # Create mo
+ mo = self.env['mrp.production'].create({
+ 'name': 'MO 1',
+ 'product_id': finshed_product.id,
+ 'product_uom_id': finshed_product.uom_id.id,
+ 'product_qty': 1.0,
+ 'bom_id': bom.id,
+ })
+ self.assertEqual(len(mo), 1, 'MO should have been created')
+ mo.action_assign()
+
+ # Produce the final product
+ produce_form = Form(self.env['mrp.product.produce'].with_context({
+ 'active_id': mo.id,
+ 'active_ids': [mo.id],
+ }))
+ produce_form.product_qty = 1.0
+ produce_wizard = produce_form.save()
+ produce_wizard.do_produce()
+
+ mo.button_mark_done()
+ self.assertEqual(mo.state, 'done', "Production order should be in done state.")
+
+ # Check quantity in stock before unbuild
+ self.assertEqual(StockQuant._get_available_quantity(finshed_product, self.stock_location), 1, 'Table should be available in stock')
+ self.assertEqual(StockQuant._get_available_quantity(component1, self.stock_location), 0, 'Table head should not be available in stock')
+ self.assertEqual(StockQuant._get_available_quantity(component2, self.stock_location), 0, 'Table stand should not be available in stock')
+
+ # ---------------------------------------------------
+ # Unbuild
+ # ---------------------------------------------------
+
+ # Create an unbuild order of the finished product and set the destination loacation = QC/Unbuild
+ self.env['mrp.unbuild'].create({
+ 'product_id': finshed_product.id,
+ 'bom_id': bom.id,
+ 'product_qty': 1.0,
+ 'product_uom_id': self.uom_unit.id,
+ 'mo_id': mo.id,
+ 'location_id': self.stock_location.id,
+ 'location_dest_id': unbuild_location.id
+ }).action_unbuild()
+
+ # Check the available quantity of components and final product in stock
+ self.assertEqual(StockQuant._get_available_quantity(finshed_product, self.stock_location), 0, 'Table should not be available in stock as it is unbuild')
+ self.assertEqual(StockQuant._get_available_quantity(component1, self.stock_location), 0, 'Table head should not be available in stock as it is in QC/Unbuild location')
+ self.assertEqual(StockQuant._get_available_quantity(component2, self.stock_location), 0, 'Table stand should not be available in stock as it is in QC/Unbuild location')
+
+ # Find new generated picking
+ picking = self.env['stock.picking'].search([('product_id', 'in', [component1.id, component2.id])])
+ self.assertEqual(picking.location_id.id, unbuild_location.id, 'Wrong source location in picking')
+ self.assertEqual(picking.location_dest_id.id, self.stock_location.id, 'Wrong destination location in picking')
+
+ # Transfer it
+ for ml in picking.move_ids_without_package:
+ ml.quantity_done = 1
+ picking.action_done()
+
+ # Check the available quantity of components and final product in stock
+ self.assertEqual(StockQuant._get_available_quantity(finshed_product, self.stock_location), 0, 'Table should not be available in stock')
+ self.assertEqual(StockQuant._get_available_quantity(component1, self.stock_location), 1, 'Table head should be available in stock as the picking is transferred')
+ self.assertEqual(StockQuant._get_available_quantity(component2, self.stock_location), 1, 'Table stand should be available in stock as the picking is transferred')
diff --git a/addons/mrp_byproduct/models/mrp_production.py b/addons/mrp_byproduct/models/mrp_production.py
index 05584d0d019..e89bdd855a9 100644
--- a/addons/mrp_byproduct/models/mrp_production.py
+++ b/addons/mrp_byproduct/models/mrp_production.py
@@ -27,6 +27,7 @@ class MrpProduction(models.Model):
'location_dest_id': production.location_dest_id.id,
'operation_id': sub_product.operation_id.id,
'production_id': production.id,
+ 'warehouse_id': production.location_dest_id.get_warehouse().id,
'origin': production.name,
'unit_factor': qty1 / (production.product_qty - production.qty_produced),
'subproduct_id': sub_product.id