diff options
| author | Jignesh Rathod <jir@openerp.com> | 2015-06-22 19:01:01 +0530 |
|---|---|---|
| committer | Josse Colpaert <jco@odoo.com> | 2015-06-23 13:47:22 +0200 |
| commit | bfbc22cdc20c88889661bb68d6321ec61fda4d0b (patch) | |
| tree | a5e0ecf5760684867ec6d6b28c595257257498d1 | |
| parent | cba690986f7dd9b45b383db57f64db663989e8e8 (diff) | |
[ADD] Sale MRP : ADD test cases of sale mrp with diffrent uom.
| -rw-r--r-- | addons/sale_mrp/tests/__init__.py | 2 | ||||
| -rw-r--r-- | addons/sale_mrp/tests/test_sale_mrp_flow.py | 349 |
2 files changed, 350 insertions, 1 deletions
diff --git a/addons/sale_mrp/tests/__init__.py b/addons/sale_mrp/tests/__init__.py index 35d7ec8ecd9..7871160632c 100644 --- a/addons/sale_mrp/tests/__init__.py +++ b/addons/sale_mrp/tests/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import test_move_explode +from . import test_move_explode, test_sale_mrp_flow diff --git a/addons/sale_mrp/tests/test_sale_mrp_flow.py b/addons/sale_mrp/tests/test_sale_mrp_flow.py new file mode 100644 index 00000000000..3f5b10c7ccc --- /dev/null +++ b/addons/sale_mrp/tests/test_sale_mrp_flow.py @@ -0,0 +1,349 @@ +# -*- coding: utf-8 -*- + +from openerp.tests import common +from datetime import datetime + + +class TestSaleMrpFlow(common.TransactionCase): + + def setUp(self): + super(TestSaleMrpFlow, self).setUp() + # Usefull models + self.SaleOrderLine = self.env['sale.order.line'] + self.SaleOrder = self.env['sale.order'] + self.MrpBom = self.env['mrp.bom'] + self.StockMove = self.env['stock.move'] + self.MrpBomLine = self.env['mrp.bom.line'] + self.ProductUom = self.env['product.uom'] + self.MrpProduction = self.env['mrp.production'] + self.Product = self.env['product.product'] + self.ProcurementOrder = self.env['procurement.order'] + self.Inventory = self.env['stock.inventory'] + self.InventoryLine = self.env['stock.inventory.line'] + self.ProductProduce = self.env['mrp.product.produce'] + + self.partner_agrolite = self.env.ref('base.res_partner_2') + self.categ_unit = self.env.ref('product.product_uom_categ_unit') + self.categ_kgm = self.env.ref('product.product_uom_categ_kgm') + self.stock_location = self.env.ref('stock.stock_location_stock') + self.warehouse = self.env.ref('stock.warehouse0') + self.procurement_jit = self.env.ref('base.module_procurement_jit') + + def test_00_sale_mrp_flow(self): + """ Test sale to mrp flow with diffrent unit of measure.""" + route_manufacture = self.warehouse.manufacture_pull_id.route_id.id + route_mto = self.warehouse.mto_pull_id.route_id.id + + def create_product(name, uom_id, route_ids=[]): + return self.Product.create({ + 'name': name, + 'type': 'product', + 'uom_id': uom_id, + 'uom_po_id': uom_id, + 'route_ids': route_ids}) + + def create_bom_lines(bom_id, product_id, qty, uom_id, bom_type): + self.MrpBomLine.create({ + 'product_id': product_id, + 'product_qty': qty, + 'type': bom_type, + 'bom_id': bom_id, + 'product_uom': uom_id}) + + def create_bom(name, product_tmpl_id, qty, uom_id, bom_type): + return self.MrpBom.create({ + 'name': name, + 'product_tmpl_id': product_tmpl_id, + 'product_qty': qty, + 'type': bom_type, + 'product_efficiency': 1.0, + 'product_uom': uom_id}) + + self.uom_kg = self.ProductUom.create({ + 'name': 'Test-KG', + 'category_id': self.categ_kgm.id, + 'factor_inv': 1, + 'factor': 1, + 'uom_type': 'reference', + 'rounding': 0.000001}) + self.uom_gm = self.ProductUom.create({ + 'name': 'Test-G', + 'category_id': self.categ_kgm.id, + 'uom_type': 'smaller', + 'factor': 1000.0, + 'rounding': 0.001}) + self.uom_unit = self.ProductUom.create({ + 'name': 'Test-Unit', + 'category_id': self.categ_unit.id, + 'factor': 1, + 'uom_type': 'reference', + 'rounding': 1.0}) + self.uom_dozen = self.ProductUom.create({ + 'name': 'Test-DozenA', + 'category_id': self.categ_unit.id, + 'factor_inv': 12, + 'uom_type': 'bigger', + 'rounding': 0.001}) + + # Create product A, B, C, D. + # -------------------------- + product_a = create_product('Product A', self.uom_unit.id, route_ids=[(6, 0, [route_manufacture, route_mto])]) + product_c = create_product('Product C', self.uom_kg.id, route_ids=[]) + product_b = create_product('Product B', self.uom_dozen.id, route_ids=[(6, 0, [route_manufacture, route_mto])]) + product_d = create_product('Product D', self.uom_unit.id, route_ids=[(6, 0, [route_manufacture, route_mto])]) + + # ------------------------------------------------------------------------------------------ + # Bill of materials for product A, B, D. + # ------------------------------------------------------------------------------------------ + + # Bill of materials for Product A. + bom_a = create_bom(product_a.name, product_a.product_tmpl_id.id, 2, self.uom_dozen.id, 'normal') + create_bom_lines(bom_a.id, product_b.id, 3, self.uom_unit.id, 'phantom') + create_bom_lines(bom_a.id, product_c.id, 300.5, self.uom_gm.id, 'normal') + create_bom_lines(bom_a.id, product_d.id, 4, self.uom_unit.id, 'phantom') + create_bom_lines(bom_a.id, product_d.id, 4, self.uom_unit.id, 'normal') + + # Bill of materials for Product B. + bom_b = create_bom(product_b.name, product_b.product_tmpl_id.id, 1, self.uom_unit.id, 'phantom') + create_bom_lines(bom_b.id, product_c.id, 0.400, self.uom_kg.id, 'normal') + + # Bill of materials for Product D. + bom_d = create_bom(product_d.name, product_d.product_tmpl_id.id, 1, self.uom_unit.id, 'normal') + create_bom_lines(bom_d.id, product_c.id, 1, self.uom_kg.id, 'normal') + + # ---------------------------------------- + # Create sale order of 10 Dozen product A. + # ---------------------------------------- + + order = self.SaleOrder.create({ + 'partner_id': self.partner_agrolite.id, + 'date_order': datetime.today(), + }) + self.SaleOrderLine.create({ + 'order_id': order.id, + 'product_id': product_a.id, + 'product_uom_qty': 10, + 'product_uom': self.uom_dozen.id + }) + self.assertTrue(order, "Sale order not created.") + order.action_button_confirm() + + # =============================================================================== + # Sale order of 10 Dozen product A should create production order + # like .. + # =============================================================================== + # Product A 10 Dozen. + # Product C 6 kg + # As product B phantom in bom A, product A will consume product C + # ================================================================ + # For 1 unit product B it will consume 400 gm + # then for 15 unit (Product B 3 unit per 2 Dozen product A) + # product B it will consume [ 6 kg ] product C) + # Product A will consume 6 kg product C. + # + # [15 * 400 gm ( 6 kg product C)] = 6 kg product C + # + # Product C 1502.5 gm. + # [ + # For 2 Dozen product A will consume 300.5 gm product C + # then for 10 Dozen product A will consume 1502.5 gm product C. + # ] + # + # Product C 20 kg + # As product D phantom in bom A, product A will consume product C. + # ================================================================ + # For 1 unit product D will consume 1 kg product C + # then for 20 unit ( Product D 4 unit per 2 Dozen product A) + # product D it will consume [ 20 kg ] product C, + # Product A will consume 20 kg product C. + # + # product D 20 Unit. + # [ + # For 2 dozen product A will consume 4 unit product D + # then for 10 Dozen product A will consume 20 unit of product D. + # ] + # -------------------------------------------------------------------------------- + + # <><><><><><><><><><><><><><><><><><><><> + # Check manufacturing order for product A. + # <><><><><><><><><><><><><><><><><><><><> + + # Run procurement. + # ---------------- + self.ProcurementOrder.run_scheduler() + + mnf_product_a = self.ProcurementOrder.search([('product_id', '=', product_a.id), ('group_id', '=', order.procurement_group_id.id), ('production_id', '!=', False)]).production_id + + # Check quantity, unit of measure and state of manufacturing order. + # ----------------------------------------------------------------- + + self.assertTrue(mnf_product_a, 'Manufacturing order not created.') + self.assertEqual(mnf_product_a.product_qty, 10, 'Wrong product quantity in manufacturing order.') + self.assertEqual(mnf_product_a.product_uom.id, self.uom_dozen.id, 'Wrong unit of measure in manufacturing order.') + self.assertEqual(mnf_product_a.state, 'confirmed', 'Manufacturing order should be confirmed.') + + # ------------------------------------------------------------------------------------------ + # Check 'To consume line' for production order of product A. + # ------------------------------------------------------------------------------------------ + + # Check 'To consume line' with product c and uom kg. + # ------------------------------------------------- + + moves = self.StockMove.search([ + ('raw_material_production_id', '=', mnf_product_a.id), + ('product_id', '=', product_c.id), + ('product_uom', '=', self.uom_kg.id)]) + + # Check total consume line with product c and uom kg. + self.assertEqual(len(moves), 2, 'Production move lines are not generated proper.') + list_qty = [move.product_uom_qty for move in moves] + self.assertEqual(set(list_qty), set([6.0, 20.0]), "Wrong product quantity in 'To consume line' of manufacturing order.") + # Check state of consume line with product c and uom kg. + for move in moves: + self.assertEqual(move.state, 'confirmed', "Wrong state in 'To consume line' of manufacturing order.") + + # Check 'To consume line' with product c and uom gm. + # --------------------------------------------------- + + move = self.StockMove.search([ + ('raw_material_production_id', '=', mnf_product_a.id), + ('product_id', '=', product_c.id), + ('product_uom', '=', self.uom_gm.id)]) + + # Check total consume line of product c with gm. + self.assertEqual(len(move), 1, 'Production move lines are not generated proper.') + # Check quantity should be with 1502.5 ( 2 Dozen product A consume 300.5 gm then 10 Dozen (300.5 * (10/2)). + self.assertEqual(move.product_uom_qty, 1502.5, "Wrong product quantity in 'To consume line' of manufacturing order.") + # Check state of consume line with product c with and uom gm. + self.assertEqual(move.state, 'confirmed', "Wrong state in 'To consume line' of manufacturing order.") + + # Check 'To consume line' with product D. + # --------------------------------------- + + move = self.StockMove.search([ + ('raw_material_production_id', '=', mnf_product_a.id), + ('product_id', '=', product_d.id)]) + + # Check total consume line with product D. + self.assertEqual(len(move), 1, 'Production lines are not generated proper.') + # Check state of consume line with product D. + self.assertEqual(move.state, 'waiting', "Wrong state in 'To consume line' of manufacturing order.") + # Check quantity of consume line with product D. + self.assertEqual(move.product_uom_qty, 20, "Wrong product quantity in 'To consume line' of manufacturing order.") + + # <><><><><><><><><><><><><><><><><><><><><><> + # Manufacturing order for product D (20 unit). + # <><><><><><><><><><><><><><><><><><><><><><> + + procurement_d = self.ProcurementOrder.search([('product_id', '=', product_d.id), ('group_id', '=', order.procurement_group_id.id)]) + # Check total consume line with product c and uom kg. + self.assertEqual(len(procurement_d), 1, 'Procurement order not generated.') + self.assertTrue(procurement_d.production_id, 'Production order not generated from procurement.') + mnf_product_d = procurement_d.production_id + # Check state of production order D. + self.assertEqual(mnf_product_d.state, 'confirmed', 'Manufacturing order should be confirmed.') + + # Check 'To consume line' state, quantity, uom of production order (product D). + # ----------------------------------------------------------------------------- + + move = self.StockMove.search([('raw_material_production_id', '=', mnf_product_d.id), ('product_id', '=', product_c.id)]) + + self.assertEqual(move.product_uom_qty, 20, "Wrong product quantity in 'To consume line' of manufacturing order.") + self.assertEqual(move.product_uom.id, self.uom_kg.id, "Wrong unit of measure in 'To consume line' of manufacturing order.") + self.assertEqual(move.state, 'confirmed', "Wrong state in 'To consume line' of manufacturing order.") + + # ------------------------------- + # Create inventory for product c. + # ------------------------------- + # Need 20 kg product c to produce 20 unit product D. + # -------------------------------------------------- + + inventory = self.Inventory.create({ + 'name': 'Inventory Product KG', + 'product_id': product_c.id, + 'filter': 'product'}) + + inventory.prepare_inventory() + self.assertFalse(inventory.line_ids, "Inventory line should not created.") + self.InventoryLine.create({ + 'inventory_id': inventory.id, + 'product_id': product_c.id, + 'product_uom_id': self.uom_kg.id, + 'product_qty': 20, + 'location_id': self.stock_location.id}) + inventory.action_done() + + # -------------------------------------------------- + # Assign product c to manufacturing order of product D. + # -------------------------------------------------- + + mnf_product_d.action_assign() + self.assertEqual(mnf_product_d.state, 'ready', 'Manufacturing order should be ready.') + self.assertEqual(move.state, 'assigned', "Wrong state in 'To consume line' of manufacturing order.") + + # ------------------ + # produce product D. + # ------------------ + + produce_d = self.ProductProduce.with_context({'active_ids': [mnf_product_d.id], 'active_id': mnf_product_d.id}).create({ + 'mode': 'consume_produce', + 'product_qty': 20}) + lines = produce_d.on_change_qty(mnf_product_d.product_qty, []) + produce_d.write(lines['value']) + produce_d.do_produce() + + # Check state of manufacturing order. + self.assertEqual(mnf_product_d.state, 'done', 'Manufacturing order should be done.') + # Check available quantity of product D. + self.assertEqual(product_d.qty_available, 20, 'Wrong quantity available of product D.') + + # ----------------------------------------------------------------- + # Check product D assigned or not to production order of product A. + # ----------------------------------------------------------------- + + self.assertEqual(mnf_product_a.state, 'confirmed', 'Manufacturing order should be confirmed.') + move = self.StockMove.search([('raw_material_production_id', '=', mnf_product_a.id), ('product_id', '=', product_d.id)]) + self.assertEqual(move.state, 'assigned', "Wrong state in 'To consume line' of manufacturing order.") + + # Create inventry for product C. + # ------------------------------ + # Need product C ( 20 kg + 6 kg + 1502.5 gm = 27.5025 kg) + # ------------------------------------------------------- + inventory = self.Inventory.create({ + 'name': 'Inventory Product C KG', + 'product_id': product_c.id, + 'filter': 'product'}) + + inventory.prepare_inventory() + self.assertFalse(inventory.line_ids, "Inventory line should not created.") + self.InventoryLine.create({ + 'inventory_id': inventory.id, + 'product_id': product_c.id, + 'product_uom_id': self.uom_kg.id, + 'product_qty': 27.5025, + 'location_id': self.stock_location.id}) + inventory.action_done() + + # Assign product to manufacturing order of product A. + # --------------------------------------------------- + + mnf_product_a.action_assign() + self.assertEqual(mnf_product_a.state, 'ready', 'Manufacturing order should be ready.') + moves = self.StockMove.search([('raw_material_production_id', '=', mnf_product_a.id), ('product_id', '=', product_c.id)]) + + # Check product c move line state. + for move in moves: + self.assertEqual(move.state, 'assigned', "Wrong state in 'To consume line' of manufacturing order.") + + # Produce product A. + # ------------------ + produce_a = self.ProductProduce.with_context( + {'active_ids': [mnf_product_a.id], 'active_id': mnf_product_a.id}).create({'mode': 'consume_produce'}) + lines = produce_a.on_change_qty(mnf_product_a.product_qty, []) + produce_a.write(lines['value']) + produce_a.do_produce() + + # Check state of manufacturing order product A. + self.assertEqual(mnf_product_a.state, 'done', 'Manufacturing order should be done.') + # Check product A avaialble quantity should be 120. + self.assertEqual(product_a.qty_available, 120, 'Wrong quantity available of product A.') |
