summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThibault Delavallée <tde@openerp.com>2016-06-29 11:33:59 +0200
committerThibault Delavallée <tde@openerp.com>2016-07-04 16:22:37 +0200
commit53fe7e9fa60c287f4bf8c6d4b70a054038bb8aac (patch)
treec94df33d9f14d49c4b09076ce6d177155c50a208
parent2ddc35a5300e89981c0572ae6749aee946f34e9d (diff)
[TESTS] mrp and various: updating tests
-rw-r--r--addons/mrp/tests/__init__.py5
-rw-r--r--addons/mrp/tests/common.py85
-rw-r--r--addons/mrp/tests/test_bom.py141
-rw-r--r--addons/mrp/tests/test_order.py338
-rw-r--r--addons/mrp/tests/test_order_process.py140
-rw-r--r--addons/mrp/tests/test_procurement.py107
-rw-r--r--addons/mrp/tests/test_stock.py101
-rw-r--r--addons/mrp/tests/test_workorder_operation.py337
-rw-r--r--addons/mrp_byproduct/tests/test_mrp_byproduct.py89
-rw-r--r--addons/product/tests/common.py101
-rw-r--r--addons/sale_mrp/tests/__init__.py2
-rw-r--r--addons/sale_mrp/tests/test_move_explode.py21
-rw-r--r--addons/sale_mrp/tests/test_sale_mrp_flow.py3
-rw-r--r--addons/stock/tests/common2.py3
-rw-r--r--addons/stock/tests/test_warehouse.py4
15 files changed, 1044 insertions, 433 deletions
diff --git a/addons/mrp/tests/__init__.py b/addons/mrp/tests/__init__.py
index 44dc0c6b4ce..dfa765c7f49 100644
--- a/addons/mrp/tests/__init__.py
+++ b/addons/mrp/tests/__init__.py
@@ -2,5 +2,6 @@
import test_bom
import test_order
-import test_order_process
-import test_workorder_operation \ No newline at end of file
+import test_stock
+import test_workorder_operation
+import test_procurement \ No newline at end of file
diff --git a/addons/mrp/tests/common.py b/addons/mrp/tests/common.py
index 90869b123e5..5f2fc1e2451 100644
--- a/addons/mrp/tests/common.py
+++ b/addons/mrp/tests/common.py
@@ -13,7 +13,12 @@ class TestMrpCommon(common2.TestStockCommon):
user_group_mrp_user = cls.env.ref('mrp.group_mrp_user')
user_group_mrp_manager = cls.env.ref('mrp.group_mrp_manager')
- # User Data: stock user and stock manager
+ # Update demo products
+ (cls.product_2 | cls.product_3 | cls.product_4 | cls.product_5 | cls.product_6 | cls.product_7 | cls.product_8).write({
+ 'type': 'product',
+ })
+
+ # User Data: mrp user and mrp manager
Users = cls.env['res.users'].with_context({'no_reset_password': True, 'mail_create_nosubscribe': True})
cls.user_mrp_user = Users.create({
'name': 'Hilda Ferachwal',
@@ -28,21 +33,73 @@ class TestMrpCommon(common2.TestStockCommon):
'notify_email': 'none',
'groups_id': [(6, 0, [user_group_mrp_manager.id])]})
+ cls.workcenter_1 = cls.env['mrp.workcenter'].create({
+ 'name': 'Nuclear Workcenter',
+ 'capacity': 2,
+ 'time_start': 10,
+ 'time_stop': 5,
+ 'time_efficiency': 80,
+ })
+ cls.routing_1 = cls.env['mrp.routing'].create({
+ 'name': 'Simple Line',
+ })
+ cls.routing_2 = cls.env['mrp.routing'].create({
+ 'name': 'Complicated Line',
+ })
+ cls.operation_1 = cls.env['mrp.routing.workcenter'].create({
+ 'name': 'Gift Wrap Maching',
+ 'workcenter_id': cls.workcenter_1.id,
+ 'routing_id': cls.routing_1.id,
+ 'time_cycle': 15,
+ 'sequence': 1,
+ })
+ cls.operation_2 = cls.env['mrp.routing.workcenter'].create({
+ 'name': 'Cutting Machine',
+ 'workcenter_id': cls.workcenter_1.id,
+ 'routing_id': cls.routing_2.id,
+ 'time_cycle': 12,
+ 'sequence': 1,
+ })
+ cls.operation_3 = cls.env['mrp.routing.workcenter'].create({
+ 'name': 'Weld Machine',
+ 'workcenter_id': cls.workcenter_1.id,
+ 'routing_id': cls.routing_2.id,
+ 'time_cycle': 18,
+ 'sequence': 2,
+ })
+
cls.bom_1 = cls.env['mrp.bom'].create({
- 'product_id': cls.product_1.id,
- 'product_tmpl_id': cls.product_1.product_tmpl_id.id,
- 'product_uom_id': cls.product_1.uom_id.id,
- 'product_qty': 1.0,
+ 'product_id': cls.product_4.id,
+ 'product_tmpl_id': cls.product_4.product_tmpl_id.id,
+ 'product_uom_id': cls.uom_unit.id,
+ 'product_qty': 4.0,
+ 'routing_id': cls.routing_2.id,
'type': 'normal',
'bom_line_ids': [
- (0, 0, {'product_id': cls.product_2.id}),
- (0, 0, {'product_id': cls.product_3.id})
+ (0, 0, {'product_id': cls.product_2.id, 'product_qty': 2}),
+ (0, 0, {'product_id': cls.product_1.id, 'product_qty': 4})
]})
-
- cls.production_1 = cls.env['mrp.production'].create({
- 'name': 'MO-Test',
- 'product_id': cls.product_1.id,
+ cls.bom_2 = cls.env['mrp.bom'].create({
+ 'product_id': cls.product_5.id,
+ 'product_tmpl_id': cls.product_5.product_tmpl_id.id,
+ 'product_uom_id': cls.product_5.uom_id.id,
'product_qty': 1.0,
- 'bom_id': cls.bom_1.id,
- 'product_uom_id': cls.product_1.uom_id.id,
- })
+ 'routing_id': cls.routing_1.id,
+ 'type': 'phantom',
+ 'sequence': 2,
+ 'bom_line_ids': [
+ (0, 0, {'product_id': cls.product_4.id, 'product_qty': 2}),
+ (0, 0, {'product_id': cls.product_3.id, 'product_qty': 3})
+ ]})
+ cls.bom_3 = cls.env['mrp.bom'].create({
+ 'product_id': cls.product_6.id,
+ 'product_tmpl_id': cls.product_6.product_tmpl_id.id,
+ 'product_uom_id': cls.uom_dozen.id,
+ 'product_qty': 2.0,
+ 'routing_id': cls.routing_2.id,
+ 'type': 'normal',
+ 'bom_line_ids': [
+ (0, 0, {'product_id': cls.product_5.id, 'product_qty': 2}),
+ (0, 0, {'product_id': cls.product_4.id, 'product_qty': 8}),
+ (0, 0, {'product_id': cls.product_2.id, 'product_qty': 12})
+ ]})
diff --git a/addons/mrp/tests/test_bom.py b/addons/mrp/tests/test_bom.py
index 7f9d30f9133..4d54f23df0a 100644
--- a/addons/mrp/tests/test_bom.py
+++ b/addons/mrp/tests/test_bom.py
@@ -1,34 +1,137 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from odoo import exceptions
from odoo.addons.mrp.tests.common import TestMrpCommon
class TestBoM(TestMrpCommon):
- def test_basic(self):
- # make the production order
- production = self.production_1
+ def test_explode(self):
+ boms, lines = self.bom_1.explode(self.product_4, 3)
+ self.assertEqual(set([bom[0].id for bom in boms]), set(self.bom_1.ids))
+ self.assertEqual(set([line[0].id for line in lines]), set(self.bom_1.bom_line_ids.ids))
- # # compute production order data
- # production.action_compute()
+ boms, lines = self.bom_3.explode(self.product_6, 3)
+ self.assertEqual(set([bom[0].id for bom in boms]), set((self.bom_2 | self.bom_3).ids))
+ self.assertEqual(
+ set([line[0].id for line in lines]),
+ set((self.bom_2 | self.bom_3).mapped('bom_line_ids').filtered(lambda line: not line.child_bom_id or line.child_bom_id.type != 'phantom').ids))
- # # confirm production
- # production.signal_workflow('button_confirm')
- self.assertEqual(production.state, 'confirmed')
+ def test_variants(self):
+ test_bom = self.env['mrp.bom'].create({
+ 'product_id': self.product_7.id,
+ 'product_tmpl_id': self.product_7.product_tmpl_id.id,
+ 'product_uom_id': self.uom_unit.id,
+ 'product_qty': 4.0,
+ 'routing_id': self.routing_2.id,
+ 'type': 'normal',
+ })
+ test_bom_l1 = self.env['mrp.bom.line'].create({
+ 'bom_id': test_bom.id,
+ 'product_id': self.product_2.id,
+ 'product_qty': 2,
+ })
+ test_bom_l2 = self.env['mrp.bom.line'].create({
+ 'bom_id': test_bom.id,
+ 'product_id': self.product_3.id,
+ 'product_qty': 2,
+ 'attribute_value_ids': [(4, self.prod_attr1_v1.id)],
+ })
+ test_bom_l3 = self.env['mrp.bom.line'].create({
+ 'bom_id': test_bom.id,
+ 'product_id': self.product_4.id,
+ 'product_qty': 2,
+ 'attribute_value_ids': [(4, self.prod_attr1_v2.id)],
+ })
+ boms, lines = test_bom.explode(self.product_7, 4)
+ self.assertIn(test_bom, [b[0]for b in boms])
+ self.assertIn(test_bom_l1, [l[0] for l in lines])
+ self.assertNotIn(test_bom_l2, [l[0] for l in lines])
+ self.assertNotIn(test_bom_l3, [l[0] for l in lines])
- # reserve product
- # production.force_production()
+ boms, lines = test_bom.explode(self.product_7_1, 4)
+ self.assertIn(test_bom, [b[0]for b in boms])
+ self.assertIn(test_bom_l1, [l[0] for l in lines])
+ self.assertIn(test_bom_l2, [l[0] for l in lines])
+ self.assertNotIn(test_bom_l3, [l[0] for l in lines])
- # produce product
- produce_wizard = self.env['mrp.product.produce'].with_context({
- 'active_id': production.id,
- 'active_ids': [production.id],
- }).create({
+ boms, lines = test_bom.explode(self.product_7_2, 4)
+ self.assertIn(test_bom, [b[0]for b in boms])
+ self.assertIn(test_bom_l1, [l[0] for l in lines])
+ self.assertNotIn(test_bom_l2, [l[0] for l in lines])
+ self.assertIn(test_bom_l3, [l[0] for l in lines])
+
+ def test_multi_level_variants(self):
+ 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,
+ })
+ test_bom_1 = self.env['mrp.bom'].create({
+ 'product_tmpl_id': self.product_5.product_tmpl_id.id,
+ 'product_uom_id': self.product_5.uom_id.id,
'product_qty': 1.0,
+ 'routing_id': self.routing_1.id,
+ 'type': 'phantom'
+ })
+ test_bom_1_l1 = self.env['mrp.bom.line'].create({
+ 'bom_id': test_bom_1.id,
+ 'product_id': self.product_3.id,
+ 'product_qty': 3,
+ })
+
+ test_bom_2 = self.env['mrp.bom'].create({
+ 'product_id': self.product_7.id,
+ 'product_tmpl_id': self.product_7.product_tmpl_id.id,
+ 'product_uom_id': self.uom_unit.id,
+ 'product_qty': 4.0,
+ 'routing_id': self.routing_2.id,
+ 'type': 'normal',
+ })
+ test_bom_2_l1 = self.env['mrp.bom.line'].create({
+ 'bom_id': test_bom_2.id,
+ 'product_id': self.product_2.id,
+ 'product_qty': 2,
+ })
+ test_bom_2_l2 = self.env['mrp.bom.line'].create({
+ 'bom_id': test_bom_2.id,
+ 'product_id': self.product_5.id,
+ 'product_qty': 2,
+ 'attribute_value_ids': [(4, self.prod_attr1_v1.id)],
+ })
+ test_bom_2_l3 = self.env['mrp.bom.line'].create({
+ 'bom_id': test_bom_2.id,
+ 'product_id': self.product_5.id,
+ 'product_qty': 2,
+ 'attribute_value_ids': [(4, self.prod_attr1_v2.id)],
})
- # produce_wizard.on_change_qty()
- produce_wizard.do_produce()
+ test_bom_2_l4 = self.env['mrp.bom.line'].create({
+ 'bom_id': test_bom_2.id,
+ 'product_id': self.product_4.id,
+ 'product_qty': 2,
+ })
+
+ # check product > product_tmpl
+ boms, lines = test_bom_2.explode(self.product_7_1, 4)
+ self.assertEqual(set((test_bom_2 | self.bom_2).ids), set([b[0].id for b in boms]))
+ self.assertEqual(set((test_bom_2_l1 | test_bom_2_l4 | self.bom_2.bom_line_ids).ids), set([l[0].id for l in lines]))
+
+ # check sequence priority
+ test_bom_1.write({'sequence': 1})
+ boms, lines = test_bom_2.explode(self.product_7_1, 4)
+ self.assertEqual(set((test_bom_2 | test_bom_1).ids), set([b[0].id for b in boms]))
+ self.assertEqual(set((test_bom_2_l1 | test_bom_2_l4 | test_bom_1.bom_line_ids).ids), set([l[0].id for l in lines]))
+
+ # check with another picking_type
+ test_bom_1.write({'picking_type_id': self.warehouse_1.manu_type_id.id})
+ self.bom_2.write({'picking_type_id': tmp_picking_type.id})
+ test_bom_2.write({'picking_type_id': tmp_picking_type.id})
+ boms, lines = test_bom_2.explode(self.product_7_1, 4)
+ self.assertEqual(set((test_bom_2 | self.bom_2).ids), set([b[0].id for b in boms]))
+ self.assertEqual(set((test_bom_2_l1 | test_bom_2_l4 | self.bom_2.bom_line_ids).ids), set([l[0].id for l in lines]))
- # check production
- # self.assertEqual(production.state, 'done')
+ # check recursion
+ test_bom_2_l3.write({'attribute_value_ids': [(6, 0, [self.prod_attr1_v1.id])]})
+ with self.assertRaises(exceptions.UserError):
+ test_bom_2.explode(self.product_7_1, 4)
diff --git a/addons/mrp/tests/test_order.py b/addons/mrp/tests/test_order.py
index 5b534e5d560..172078ae656 100644
--- a/addons/mrp/tests/test_order.py
+++ b/addons/mrp/tests/test_order.py
@@ -1,27 +1,333 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from datetime import datetime, timedelta
+
+from odoo.fields import Datetime as Dt
from odoo.addons.mrp.tests.common import TestMrpCommon
class TestMrpOrder(TestMrpCommon):
def test_access_rights_manager(self):
- production = self.production_1.sudo(self.user_mrp_manager)
- # production.action_compute()
- # production.signal_workflow('button_confirm')
- production.action_cancel()
- self.assertEqual(production.state, 'cancel')
- production.unlink()
+ man_order = self.env['mrp.production'].sudo(self.user_mrp_manager).create({
+ 'name': 'Stick-0',
+ 'product_id': self.product_4.id,
+ 'product_uom_id': self.product_4.uom_id.id,
+ 'product_qty': 5.0,
+ 'bom_id': self.bom_1.id,
+ 'location_src_id': self.location_1.id,
+ 'location_dest_id': self.warehouse_1.wh_output_stock_loc_id.id,
+ })
+ man_order.action_cancel()
+ self.assertEqual(man_order.state, 'cancel', "Production order should be in cancel state.")
+ man_order.unlink()
def test_access_rights_user(self):
- production = self.production_1.sudo(self.user_mrp_user)
- # production.action_compute()
- # production.signal_workflow('button_confirm')
- production.action_cancel()
- self.assertEqual(production.state, 'cancel')
- production.unlink()
-
- def test_flow(self):
- production = self.production_1.sudo(self.user_mrp_user)
- # production.action_compute()
+ man_order = self.env['mrp.production'].sudo(self.user_mrp_user).create({
+ 'name': 'Stick-0',
+ 'product_id': self.product_4.id,
+ 'product_uom_id': self.product_4.uom_id.id,
+ 'product_qty': 5.0,
+ 'bom_id': self.bom_1.id,
+ 'location_src_id': self.location_1.id,
+ 'location_dest_id': self.warehouse_1.wh_output_stock_loc_id.id,
+ })
+ man_order.action_cancel()
+ self.assertEqual(man_order.state, 'cancel', "Production order should be in cancel state.")
+ man_order.unlink()
+
+ def test_basic(self):
+ """ Basic order test: no routing (thus no workorders), no lot """
+ inventory = self.env['stock.inventory'].create({
+ 'name': 'Initial inventory',
+ 'filter': 'partial',
+ 'line_ids': [(0, 0, {
+ 'product_id': self.product_1.id,
+ 'product_uom_id': self.product_1.uom_id.id,
+ 'product_qty': 500,
+ 'location_id': self.warehouse_1.lot_stock_id.id
+ }), (0, 0, {
+ 'product_id': self.product_2.id,
+ 'product_uom_id': self.product_2.uom_id.id,
+ 'product_qty': 500,
+ 'location_id': self.warehouse_1.lot_stock_id.id
+ })]
+ })
+ inventory.action_done()
+
+ test_date_planned = datetime.now() - timedelta(days=1)
+ test_quantity = 2.0
+ self.bom_1.routing_id = False
+ man_order = self.env['mrp.production'].sudo(self.user_mrp_user).create({
+ 'name': 'Stick-0',
+ 'product_id': self.product_4.id,
+ 'product_uom_id': self.product_4.uom_id.id,
+ 'product_qty': test_quantity,
+ 'bom_id': self.bom_1.id,
+ 'date_planned_start': test_date_planned,
+ 'location_src_id': self.location_1.id,
+ 'location_dest_id': self.warehouse_1.wh_output_stock_loc_id.id,
+ })
+ self.assertEqual(man_order.state, 'confirmed', "Production order should be in confirmed state.")
+
+ # check production move
+ production_move = man_order.move_finished_ids
+ self.assertEqual(production_move.date, Dt.to_string(test_date_planned))
+ self.assertEqual(production_move.product_id, self.product_4)
+ self.assertEqual(production_move.product_uom, man_order.product_uom_id)
+ self.assertEqual(production_move.product_qty, man_order.product_qty)
+ self.assertEqual(production_move.location_id, self.product_4.property_stock_production)
+ self.assertEqual(production_move.location_dest_id, man_order.location_dest_id)
+
+ # check consumption moves
+ for move in man_order.move_raw_ids:
+ self.assertEqual(move.date, Dt.to_string(test_date_planned))
+ first_move = man_order.move_raw_ids.filtered(lambda move: move.product_id == self.product_2)
+ self.assertEqual(first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 2)
+ first_move = man_order.move_raw_ids.filtered(lambda move: move.product_id == self.product_1)
+ self.assertEqual(first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 4)
+
+ # waste some material, create a scrap
+ # scrap = self.env['stock.scrap'].with_context(
+ # active_model='mrp.production', active_id=man_order.id
+ # ).create({})
+ # scrap = self.env['stock.scrap'].create({
+ # 'production_id': man_order.id,
+ # 'product_id': first_move.product_id.id,
+ # 'product_uom_id': first_move.product_uom.id,
+ # 'scrap_qty': 5.0,
+ # })
+ # check created scrap
+
+
+ # procurements = self.env['procurement.order'].search([('move_dest_id', 'in', man_order.move_raw_ids.ids)])
+ # print procurements
+ # procurements = self.env['procurement.order'].search([('production_id', '=', man_order.id)])
+ # print procurements
+ # for proc in self.env['procurement.order'].browse(procurements):
+ # date_planned = self.mrp_production_test1.date_planned
+ # if proc.product_id.type not in ('product', 'consu'):
+ # continue
+ # if proc.product_id.id == order_line.product_id.id:
+ # self.assertEqual(proc.date_planned, date_planned, "Planned date does not correspond")
+ # # procurement state should be `confirmed` at this stage, except if procurement_jit is installed, in which
+ # # case it could already be in `running` or `exception` state (not enough stock)
+ # expected_states = ('confirmed', 'running', 'exception')
+ # self.assertEqual(proc.state in expected_states, 'Procurement state is `%s` for %s, expected one of %s' % (proc.state, proc.product_id.name, expected_states))
+
+ # Change production quantity
+ qty_wizard = self.env['change.production.qty'].create({
+ 'mo_id': man_order.id,
+ 'product_qty': 3.0,
+ })
+ # qty_wizard.change_prod_qty()
+
+ # # I check qty after changed in production order.
+ # #self.assertEqual(self.mrp_production_test1.product_qty, 3, "Qty is not changed in order.")
+ # move = self.mrp_production_test1.move_finished_ids[0]
+ # self.assertEqual(move.product_qty, self.mrp_production_test1.product_qty, "Qty is not changed in move line.")
+
+ # # I run scheduler.
+ # self.env['procurement.order'].run_scheduler()
+
+ # # The production order is Waiting Goods, will force production which should set consume lines as available
+ # self.mrp_production_test1.button_plan()
+ # # I check that production order in ready state after forcing production.
+
+ # #self.assertEqual(self.mrp_production_test1.availability, 'assigned', 'Production order availability should be set as available')
+
+ # produce product
+ produce_wizard = self.env['mrp.product.produce'].sudo(self.user_mrp_user).with_context({
+ 'active_id': man_order.id,
+ 'active_ids': [man_order.id],
+ }).create({
+ 'product_qty': 1.0,
+ })
+ produce_wizard.do_produce()
+
+ # man_order.button_mark_done()
+ man_order.button_mark_done()
+ self.assertEqual(man_order.state, 'done', "Production order should be in done state.")
+
+ def test_explode_from_order(self):
+ #
+ # bom3 produces 2 Dozen of Doors (p6), aka 24
+ # To produce 24 Units of Doors (p6)
+ # - 2 Units of Tools (p5) -> need 4
+ # - 8 Dozen of Sticks (p4) -> need 16
+ # - 12 Units of Wood (p2) -> need 24
+ # bom2 produces 1 Unit of Sticks (p4)
+ # To produce 1 Unit of Sticks (p4)
+ # - 2 Dozen of Sticks (p4) -> need 8
+ # - 3 Dozen of Stones (p3) -> need 12
+
+ # Update capacity, start time, stop time, and time efficiency.
+ # ------------------------------------------------------------
+ self.workcenter_1.write({'capacity': 1, 'time_start': 0, 'time_stop': 0, 'time_efficiency': 100})
+
+ # Set manual time cycle 20 and 10.
+ # --------------------------------
+ self.operation_1.write({'time_cycle_manual': 20})
+ (self.operation_2 | self.operation_3).write({'time_cycle_manual': 10})
+
+ man_order = self.env['mrp.production'].create({
+ 'name': 'MO-Test',
+ 'product_id': self.product_6.id,
+ 'product_uom_id': self.product_6.uom_id.id,
+ 'product_qty': 48,
+ 'bom_id': self.bom_3.id,
+ })
+
+ # reset quantities
+ self.env['stock.change.product.qty'].create({
+ 'product_id': self.product_1.id,
+ 'new_quantity': 0.0,
+ 'location_id': self.warehouse_1.lot_stock_id.id,
+ }).change_product_qty()
+
+ (self.product_2 | self.product_4).write({
+ 'tracking': 'lot',
+ })
+ # assign consume material
+ man_order.action_assign()
+ self.assertEqual(man_order.availability, 'waiting', "Production order should be in waiting state.")
+
+ # check consume materials of manufacturing order
+ self.assertEqual(len(man_order.move_raw_ids), 4, "Consume material lines are not generated proper.")
+ product_2_consume_moves = man_order.move_raw_ids.filtered(lambda x: x.product_id == self.product_2)
+ product_3_consume_moves = man_order.move_raw_ids.filtered(lambda x: x.product_id == self.product_3)
+ product_4_consume_moves = man_order.move_raw_ids.filtered(lambda x: x.product_id == self.product_4)
+ product_5_consume_moves = man_order.move_raw_ids.filtered(lambda x: x.product_id == self.product_5)
+ consume_qty_2 = product_2_consume_moves.product_uom_qty
+ self.assertEqual(consume_qty_2, 24.0, "Consume material quantity of Wood should be 24 instead of %s" % str(consume_qty_2))
+ consume_qty_3 = product_3_consume_moves.product_uom_qty
+ self.assertEqual(consume_qty_3, 12.0, "Consume material quantity of Stone should be 12 instead of %s" % str(consume_qty_3))
+ self.assertEqual(len(product_4_consume_moves), 2, "Consume move are not generated proper.")
+ for consume_moves in product_4_consume_moves:
+ consume_qty_4 = consume_moves.product_uom_qty
+ self.assertIn(consume_qty_4, [8.0, 16.0], "Consume material quantity of Stick should be 8 or 16 instead of %s" % str(consume_qty_4))
+ self.assertFalse(product_5_consume_moves, "Move should not create for phantom bom")
+
+ # create required lots
+ lot_product_2 = self.env['stock.production.lot'].create({'product_id': self.product_2.id})
+ lot_product_4 = self.env['stock.production.lot'].create({'product_id': self.product_4.id})
+
+ # refuel stock
+ inventory = self.env['stock.inventory'].create({
+ 'name': 'Inventory For Product C',
+ 'filter': 'partial',
+ 'line_ids': [(0, 0, {
+ 'product_id': self.product_2.id,
+ 'product_uom_id': self.product_2.uom_id.id,
+ 'product_qty': 30,
+ 'prod_lot_id': lot_product_2.id,
+ 'location_id': self.ref('stock.stock_location_14')
+ }), (0, 0, {
+ 'product_id': self.product_3.id,
+ 'product_uom_id': self.product_3.uom_id.id,
+ 'product_qty': 60,
+ 'location_id': self.ref('stock.stock_location_14')
+ }), (0, 0, {
+ 'product_id': self.product_4.id,
+ 'product_uom_id': self.product_4.uom_id.id,
+ 'product_qty': 60,
+ 'prod_lot_id': lot_product_4.id,
+ 'location_id': self.ref('stock.stock_location_14')
+ })]
+ })
+ inventory.prepare_inventory()
+ inventory.action_done()
+
+ # re-assign consume material
+ man_order.action_assign()
+
+ # Check production order status after assign.
+ self.assertEqual(man_order.availability, 'assigned', "Production order should be in assigned state.")
+ # Plan production order.
+ man_order.button_plan()
+
+ # check workorders
+ # - main bom: Door: 2 operations
+ # operation 1: Cutting
+ # operation 2: Welding, waiting for the previous one
+ # - kit bom: Stone Tool: 1 operation
+ # operation 1: Gift Wrapping
+ workorders = man_order.workorder_ids
+ kit_wo = man_order.workorder_ids.filtered(lambda wo: wo.operation_id == self.operation_1)
+ door_wo_1 = man_order.workorder_ids.filtered(lambda wo: wo.operation_id == self.operation_2)
+ door_wo_2 = man_order.workorder_ids.filtered(lambda wo: wo.operation_id == self.operation_3)
+ for workorder in workorders:
+ self.assertEqual(workorder.workcenter_id, self.workcenter_1, "Workcenter does not match.")
+ self.assertEqual(kit_wo.state, 'ready', "Workorder should be in ready state.")
+ self.assertEqual(door_wo_1.state, 'ready', "Workorder should be in ready state.")
+ self.assertEqual(door_wo_2.state, 'pending', "Workorder should be in pending state.")
+ self.assertEqual(kit_wo.duration_expected, 80, "Workorder duration should be 80 instead of %s." % str(kit_wo.duration_expected))
+ self.assertEqual(door_wo_1.duration_expected, 20, "Workorder duration should be 20 instead of %s." % str(door_wo_1.duration_expected))
+ self.assertEqual(door_wo_2.duration_expected, 20, "Workorder duration should be 20 instead of %s." % str(door_wo_2.duration_expected))
+
+ # subbom: kit for stone tools
+ kit_wo.button_start()
+ finished_lot = self.env['stock.production.lot'].create({'product_id': man_order.product_id.id})
+ kit_wo.write({
+ 'final_lot_id': finished_lot.id,
+ 'qty_producing': 48
+ })
+ kit_wo.record_production()
+
+ self.assertEqual(kit_wo.state, 'done', "Workorder should be in done state.")
+
+ # first operation of main bom
+ finished_lot = self.env['stock.production.lot'].create({'product_id': man_order.product_id.id})
+ door_wo_1.write({
+ 'final_lot_id': finished_lot.id,
+ 'qty_producing': 48
+ })
+ door_wo_1.record_production()
+ self.assertEqual(door_wo_1.state, 'done', "Workorder should be in done state.")
+
+ # second operation of main bom
+ self.assertEqual(door_wo_2.state, 'ready', "Workorder should be in ready state.")
+ door_wo_2.record_production()
+ self.assertEqual(door_wo_2.state, 'done', "Workorder should be in done state.")
+
+ def test_production_avialability(self):
+ """
+ Test availability of production order.
+ """
+ self.bom_3.bom_line_ids.filtered(lambda x: x.product_id == self.product_5).unlink()
+ self.bom_3.bom_line_ids.filtered(lambda x: x.product_id == self.product_4).unlink()
+
+ production_2 = self.env['mrp.production'].create({
+ 'name': 'MO-Test001',
+ 'product_id': self.product_6.id,
+ 'product_qty': 5.0,
+ 'bom_id': self.bom_3.id,
+ 'product_uom_id': self.product_6.uom_id.id,
+ })
+ production_2.action_assign()
+
+ # check sub product availability state is waiting
+ self.assertEqual(production_2.availability, 'waiting', 'Production order should be availability for waiting state')
+
+ # Update Inventory
+ inventory_wizard = self.env['stock.change.product.qty'].create({
+ 'product_id': self.product_2.id,
+ 'new_quantity': 2.0,
+ })
+ inventory_wizard.change_product_qty()
+
+ production_2.action_assign()
+ # check sub product availability state is partially available
+ self.assertEqual(production_2.availability, 'partially_available', 'Production order should be availability for partially available state')
+
+ # Update Inventory
+ inventory_wizard = self.env['stock.change.product.qty'].create({
+ 'product_id': self.product_2.id,
+ 'new_quantity': 5.0,
+ })
+ inventory_wizard.change_product_qty()
+
+ production_2.action_assign()
+ # check sub product availability state is assigned
+ self.assertEqual(production_2.availability, 'assigned', 'Production order should be availability for assigned state')
diff --git a/addons/mrp/tests/test_order_process.py b/addons/mrp/tests/test_order_process.py
deleted file mode 100644
index 5c7c95a849f..00000000000
--- a/addons/mrp/tests/test_order_process.py
+++ /dev/null
@@ -1,140 +0,0 @@
-
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from openerp.tests import common
-
-
-class TestOrderProcess(common.TransactionCase):
-
- def test_00_order_process(self):
- self.res_users_mrp_manager = self.env.ref('mrp.group_mrp_manager')
- # self.group_account_user = self.env.ref('account.group_account_user')
- self.main_company = self.env.ref('base.main_company')
- self.group_mrp_user = self.env.ref('mrp.group_mrp_user')
-
- self.res_users_mrp_manager = self.env['res.users'].create({
- 'company_id': self.main_company.id,
- 'name': 'MRP Manager',
- 'login': 'mam',
- 'password': 'mam',
- 'email': 'mrp_manager@yourcompany.com',
- 'groups_id': [(6, 0, [self.res_users_mrp_manager.id])] # self.group_account_user.id
- })
-
- # Create a user as 'MRP User'
- # I added groups for MRP User.
- self.res_users_mrp_user = self.env['res.users'].create({
- 'company_id': self.main_company.id,
- 'name': 'MRP User',
- 'login': 'mau',
- 'password': 'mau',
- 'email': 'mrp_user@yourcompany.com',
- 'groups_id': [(6, 0, [self.group_mrp_user.id])]
- })
-
- self.mrp_production_test1 = self.env['mrp.production'].sudo(self.res_users_mrp_user.id).create({
- 'product_id': self.env.ref('product.product_product_3').id,
- 'product_qty': 5.0,
- 'product_uom_id': self.env.ref('product.product_product_3').uom_id.id,
- 'location_src_id': self.env.ref('stock.stock_location_14').id,
- 'location_dest_id': self.env.ref('stock.stock_location_output').id,
- 'bom_id': self.env.ref('mrp.mrp_bom_kit').id,
- 'routing_id': self.env.ref('mrp.mrp_routing_1').id
- })
-
- # I compute the production order.
- # self.mrp_production_test1.action_compute()
-
- # I check production lines after compute.
- # self.assertEqual(len(self.mrp_production_test1.product_lines), 7)
-
- # Now I check workcenter lines.
- from openerp.tools import float_compare
-
- def assert_equals(value1, value2, msg, float_compare=float_compare):
- assert float_compare(value1, value2, precision_digits=2) == 0, msg
- # self.assertTrue(len(self.mrp_production_test1.workcenter_lines))
-
-
- # I check details of Produce Move of Production Order to trace Final Product.
-
- self.assertEqual(self.mrp_production_test1.state, 'confirmed', "Production order should be confirmed.")
- self.assertTrue(self.mrp_production_test1.move_finished_ids, "Trace Record is not created for Final Product.")
- move = self.mrp_production_test1.move_finished_ids[0]
- source_location_id = self.mrp_production_test1.product_id.property_stock_production.id
- self.assertEqual(move.date, self.mrp_production_test1.date_planned, "Planned date is not correspond.")
- self.assertEqual(move.product_id.id, self.mrp_production_test1.product_id.id, "Product does not correspond.")
- self.assertEqual(move.product_uom.id, self.mrp_production_test1.product_uom_id.id, "UOM does not correspond.")
- self.assertEqual(move.product_qty, self.mrp_production_test1.product_qty, "Qty does not correspond.")
- self.assertEqual(move.location_id.id, source_location_id, "Source Location does not correspond.")
- self.assertEqual(move.location_dest_id.id, self.mrp_production_test1.location_dest_id.id, "Destination Location does not correspond.")
- routing_loc = None
- if self.mrp_production_test1.bom_id.routing_id and self.mrp_production_test1.bom_id.routing_id.location_id:
- routing_loc = self.mrp_production_test1.routing_id.location_id.id
- date_planned = self.mrp_production_test1.date_planned
- for move_line in self.mrp_production_test1.move_raw_ids:
- self.assertEqual(move_line.date, date_planned, "Planned date does not correspond in 'To consume line'.")
- # I consume raw materials and put one material in scrap location due to waste it.
- for move in self.mrp_production_test1.move_raw_ids:
- if move.product_id.id == self.env.ref("product.product_product_6").id:
- self.env['stock.scrap'].with_context(active_model='mrp.production', active_id=self.mrp_production_test1.id).create({'product_id': move.product_id.id, 'scrap_qty': 5.0, 'product_uom_id': move.product_uom.id})
-
- # I check procurements have been generated for every consume line
-
- # order = self.env["mrp.production"].browse(self.env.ref("mrp_production_test1"))
- move_line_ids = [x.id for x in self.mrp_production_test1.move_raw_ids]
- procurements = self.env['procurement.order'].search([('move_dest_id', 'in', move_line_ids)])
- for proc in self.env['procurement.order'].browse(procurements):
- date_planned = self.mrp_production_test1.date_planned
- if proc.product_id.type not in ('product', 'consu'):
- continue
- if proc.product_id.id == order_line.product_id.id:
- self.assertEqual(proc.date_planned, date_planned, "Planned date does not correspond")
- # procurement state should be `confirmed` at this stage, except if procurement_jit is installed, in which
- # case it could already be in `running` or `exception` state (not enough stock)
- expected_states = ('confirmed', 'running', 'exception')
- self.assertEqual(proc.state in expected_states, 'Procurement state is `%s` for %s, expected one of %s' % (proc.state, proc.product_id.name, expected_states))
-
- # I change production qty with 3 PC Assemble SC349.
- ctx = dict(self.env.context)
- ctx.update({'active_id': self.mrp_production_test1.id})
-
-
- #TODO: fix change production qty
- #self.mrp_production_qty = self.env['change.production.qty'].with_context(ctx).create({
- # 'product_qty': 3.0
- #})
-
- #self.mrp_production_qty.change_prod_qty()
-
- # I check qty after changed in production order.
- #self.assertEqual(self.mrp_production_test1.product_qty, 3, "Qty is not changed in order.")
- move = self.mrp_production_test1.move_finished_ids[0]
- self.assertEqual(move.product_qty, self.mrp_production_test1.product_qty, "Qty is not changed in move line.")
-
- # I run scheduler.
- self.env['procurement.order'].run_scheduler()
-
- # The production order is Waiting Goods, will force production which should set consume lines as available
- self.mrp_production_test1.button_plan()
- # I check that production order in ready state after forcing production.
-
- #self.assertEqual(self.mrp_production_test1.availability, 'assigned', 'Production order availability should be set as available')
-
- # I produce product.
- ctx.update({'active_id': self.mrp_production_test1.id})
-
- self.mrp_product_produce1 = self.env['mrp.product.produce'].with_context(ctx).create({})
-
- qty = self.mrp_product_produce1.product_qty
- self.mrp_product_produce1.do_produce()
-
- # I check production order after produced.
- # self.assertEqual(self.mrp_production_test1.state, 'planned', "Production order should be in planned state.")
-
- def rounding(f, r):
- import math
- if not r:
- return f
- return math.ceil(f / r) * r
diff --git a/addons/mrp/tests/test_procurement.py b/addons/mrp/tests/test_procurement.py
new file mode 100644
index 00000000000..bc212050db5
--- /dev/null
+++ b/addons/mrp/tests/test_procurement.py
@@ -0,0 +1,107 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo.addons.mrp.tests.common import TestMrpCommon
+
+
+class TestProcurement(TestMrpCommon):
+
+ def test_procurement(self):
+ """This test case when create production order check procurement is create"""
+ # Update BOM
+ self.bom_3.bom_line_ids.filtered(lambda x: x.product_id == self.product_5).unlink()
+ self.bom_1.bom_line_ids.filtered(lambda x: x.product_id == self.product_1).unlink()
+
+ # Update route
+ self.warehouse = self.env.ref('stock.warehouse0')
+ route_manufacture = self.warehouse.manufacture_pull_id.route_id.id
+ route_mto = self.warehouse.mto_pull_id.route_id.id
+ self.product_4.write({'route_ids': [(6, 0, [route_manufacture, route_mto])]})
+
+ # Create production order
+ # -------------------------
+ # Product6 Unit 24
+ # Product4 8 Dozen
+ # Product2 12 Unit
+ # -----------------------
+
+ production_product_6 = self.env['mrp.production'].create({
+ 'name': 'MO/Test-00002',
+ 'product_id': self.product_6.id,
+ 'product_qty': 24,
+ 'bom_id': self.bom_3.id,
+ 'product_uom_id': self.product_6.uom_id.id,
+ })
+ production_product_6.action_assign()
+
+ # check production state is Confirmed
+ self.assertEqual(production_product_6.state, 'confirmed', 'Production order should be for Confirmed state')
+
+ # Check procurement for product 4 created or not.
+ procurement = self.env['procurement.order'].search([('group_id', '=', production_product_6.procurement_group_id.id), ('product_id', '=', self.product_4.id)])
+ self.assertTrue(procurement, 'No procurement are created !')
+ self.assertEqual(procurement.state, 'running', 'Procurement order should be in state running')
+
+ produce_product_4 = procurement.production_id
+ # produce product
+ self.assertEqual(produce_product_4.availability, 'waiting', "Consume material not available")
+
+ # Create production order
+ # -------------------------
+ # Product 4 96 Unit
+ # Product2 48 Unit
+ # ---------------------
+ # Update Inventory
+ inventory_wizard = self.env['stock.change.product.qty'].create({
+ 'product_id': self.product_2.id,
+ 'new_quantity': 48,
+ })
+ inventory_wizard.change_product_qty()
+ produce_product_4.action_assign()
+ self.assertEqual(produce_product_4.product_qty, 8, "Wrong quantity of finish product.")
+ self.assertEqual(produce_product_4.product_uom_id, self.uom_dozen, "Wrong quantity of finish product.")
+ self.assertEqual(produce_product_4.availability, 'assigned', "Consume material not available")
+
+ # produce product4
+ # ---------------
+
+ produce_wizard = self.env['mrp.product.produce'].with_context({
+ 'active_id': produce_product_4.id,
+ 'active_ids': [produce_product_4.id],
+ }).create({
+ 'product_qty': produce_product_4.product_qty,
+ })
+ produce_wizard.do_produce()
+ produce_product_4.post_inventory()
+ # Check procurement and Production state for product 4.
+ produce_product_4.button_mark_done()
+ self.assertEqual(produce_product_4.state, 'done', 'Production order should be in state done')
+ self.assertEqual(procurement.state, 'done', 'Procurement order should be in state done')
+
+ # Produce product 6
+ # ------------------
+
+ # Update Inventory
+ inventory_wizard = self.env['stock.change.product.qty'].create({
+ 'product_id': self.product_2.id,
+ 'new_quantity': 12,
+ })
+ inventory_wizard.change_product_qty()
+ production_product_6.action_assign()
+
+ # ------------------------------------
+
+ self.assertEqual(production_product_6.availability, 'assigned', "Consume material not available")
+ produce_wizard = self.env['mrp.product.produce'].with_context({
+ 'active_id': production_product_6.id,
+ 'active_ids': [production_product_6.id],
+ }).create({
+ 'product_qty': production_product_6.product_qty,
+ })
+ produce_wizard.do_produce()
+
+ production_product_6.post_inventory()
+ # Check procurement and Production state for product 6.
+ production_product_6.button_mark_done()
+ self.assertEqual(production_product_6.state, 'done', 'Production order should be in state done')
+ self.assertEqual(self.product_6.qty_available, 24, 'Wrong quantity available of finished product.')
diff --git a/addons/mrp/tests/test_stock.py b/addons/mrp/tests/test_stock.py
new file mode 100644
index 00000000000..ddd4deb4341
--- /dev/null
+++ b/addons/mrp/tests/test_stock.py
@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import common
+from odoo.exceptions import except_orm
+
+
+class TestWarehouse(common.TestMrpCommon):
+
+ def test_manufacturing_route(self):
+ warehouse_1_stock_manager = self.warehouse_1.sudo(self.user_stock_manager)
+ manu_rule = self.env['procurement.rule'].search([
+ ('action', '=', 'manufacture'),
+ ('warehouse_id', '=', self.warehouse_1.id)])
+ self.assertEqual(self.warehouse_1.manufacture_pull_id, manu_rule)
+ manu_route = manu_rule.route_id
+ self.assertIn(manu_route, warehouse_1_stock_manager._get_all_routes())
+ warehouse_1_stock_manager.write({
+ 'manufacture_to_resupply': False
+ })
+ self.assertFalse(self.warehouse_1.manufacture_pull_id)
+ 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({
+ 'manufacture_to_resupply': True
+ })
+ manu_rule = self.env['procurement.rule'].search([
+ ('action', '=', 'manufacture'),
+ ('warehouse_id', '=', self.warehouse_1.id)])
+ self.assertEqual(self.warehouse_1.manufacture_pull_id, manu_rule)
+ self.assertTrue(self.warehouse_1.manu_type_id.active)
+ self.assertIn(manu_route, warehouse_1_stock_manager._get_all_routes())
+
+ def test_manufacturing_scrap(self):
+ """
+ Testing to do a scrap of consumed material.
+ """
+
+ # Update demo products
+ (self.product_4 | self.product_2).write({
+ 'tracking': 'lot',
+ })
+
+ # Update Bill Of Material to remove product with phantom bom.
+ self.bom_3.bom_line_ids.filtered(lambda x: x.product_id == self.product_5).unlink()
+
+ # Create Inventory Adjustment For Stick and Stone Tools with lot.
+ lot_product_4 = self.env['stock.production.lot'].create({
+ 'name': '0000000000001',
+ 'product_id': self.product_4.id,
+ })
+ lot_product_2 = self.env['stock.production.lot'].create({
+ 'name': '0000000000002',
+ 'product_id': self.product_2.id,
+ })
+
+ stock_inv_product_4 = self.env['stock.inventory'].create({
+ 'name': 'Stock Inventory for Stick',
+ 'filter': 'product',
+ 'product_id': self.product_4.id,
+ 'line_ids': [
+ (0, 0, {'product_id': self.product_4.id, 'product_uom_id': self.product_4.uom_id.id, 'product_qty': 8, 'prod_lot_id': lot_product_4.id, 'location_id': self.ref('stock.stock_location_14')}),
+ ]})
+
+ stock_inv_product_2 = self.env['stock.inventory'].create({
+ 'name': 'Stock Inventory for Stone Tools',
+ 'filter': 'product',
+ 'product_id': self.product_2.id,
+ 'line_ids': [
+ (0, 0, {'product_id': self.product_2.id, 'product_uom_id': self.product_2.uom_id.id, 'product_qty': 12, 'prod_lot_id': lot_product_2.id, 'location_id': self.ref('stock.stock_location_14')})
+ ]})
+ (stock_inv_product_4 | stock_inv_product_2).prepare_inventory()
+ (stock_inv_product_4 | stock_inv_product_2).action_done()
+
+ #Create Manufacturing order.
+ production_3 = self.env['mrp.production'].create({
+ 'name': 'MO-Test003',
+ 'product_id': self.product_6.id,
+ 'product_qty': 12,
+ 'bom_id': self.bom_3.id,
+ 'product_uom_id': self.product_6.uom_id.id,
+ })
+ production_3.action_assign()
+
+ # Check Manufacturing order's availability.
+ self.assertEqual(production_3.availability, 'assigned', "Production order's availability should be Available.")
+
+ location_id = production_3.move_raw_ids.filtered(lambda x: x.state not in ('done', 'cancel')) and production_3.location_src_id.id or production_3.location_dest_id.id,
+
+ # Scrap Product Wood without lot to check assert raise ?.
+ with self.assertRaises(except_orm):
+ self.env['stock.scrap'].with_context(active_model='mrp.production', active_id=production_3.id).create({'product_id': self.product_2.id, 'scrap_qty': 1.0, 'product_uom_id': self.product_2.uom_id.id, 'location_id': location_id, 'production_id': production_3.id})
+
+ # Scrap Product Wood with lot.
+ self.env['stock.scrap'].with_context(active_model='mrp.production', active_id=production_3.id).create({'product_id': self.product_2.id, 'scrap_qty': 1.0, 'product_uom_id': self.product_2.uom_id.id, 'location_id': location_id, 'lot_id': lot_product_2.id, 'production_id': production_3.id})
+
+ #Check scrap move is created for this production order.
+ #TODO: should check with scrap objects link in between
+
+# scrap_move = production_3.move_raw_ids.filtered(lambda x: x.product_id == self.product_2 and x.scrapped)
+# self.assertTrue(scrap_move, "There are no any scrap move created for production order.")
diff --git a/addons/mrp/tests/test_workorder_operation.py b/addons/mrp/tests/test_workorder_operation.py
index 10bc62dd4a9..b773f1fcca7 100644
--- a/addons/mrp/tests/test_workorder_operation.py
+++ b/addons/mrp/tests/test_workorder_operation.py
@@ -6,42 +6,9 @@ class TestWorkOrderProcess(common.TransactionCase):
def setUp(self):
super(TestWorkOrderProcess, self).setUp()
- self.MrpProductProduce = self.env['mrp.product.produce']
- self.Product = self.env['product.product']
- self.Lot = self.env['stock.production.lot']
- self.StockMoveLot = self.env['stock.move.lots']
- self.MrpBom = self.env['mrp.bom']
- self.MrpBomLine = self.env['mrp.bom.line']
- self.Inventory = self.env['stock.inventory']
- self.InventoryLine = self.env['stock.inventory.line']
self.source_location_id = self.ref('stock.stock_location_14')
self.warehouse = self.env.ref('stock.warehouse0')
- def create_product(self, name, uom_id, route_ids=None):
- return self.Product.create({
- 'name': name,
- 'type': 'product',
- 'tracking': 'lot',
- 'uom_id': uom_id,
- 'uom_po_id': uom_id,
- 'route_ids': route_ids})
-
- def create_bom_lines(self, bom_id, product_id, qty, uom_id):
- self.MrpBomLine.create({
- 'product_id': product_id,
- 'product_qty': qty,
- 'bom_id': bom_id,
- 'product_uom_id': uom_id})
-
- def create_inventory_line(self, inventory, product, qty, lot_id=False):
- self.InventoryLine.create({
- 'inventory_id': inventory.id,
- 'product_id': product.id,
- 'product_uom_id': product.uom_id.id,
- 'product_qty': qty,
- 'prod_lot_id': lot_id,
- 'location_id': self.source_location_id})
-
def test_00_workorder_process(self):
""" Testing consume quants and produced quants with workorder """
dining_table = self.env.ref("mrp.product_product_computer_desk")
@@ -53,7 +20,8 @@ class TestWorkOrderProcess(common.TransactionCase):
'product_id': dining_table.id,
'product_qty': 1.0,
'product_uom_id': dining_table.uom_id.id,
- 'bom_id': self.ref("mrp.mrp_bom_desk")})
+ 'bom_id': self.ref("mrp.mrp_bom_desk")
+ })
# Set tracking lot on finish and consume products.
dining_table.tracking = 'lot'
@@ -62,26 +30,41 @@ class TestWorkOrderProcess(common.TransactionCase):
product_bolt.tracking = "lot"
# Initial inventory of product sheet, lags and bolt
- lot_sheet = self.Lot.create({'product_id': product_table_sheet.id})
- lot_leg = self.Lot.create({'product_id': product_table_leg.id})
- lot_bolt = self.Lot.create({'product_id': product_bolt.id})
+ lot_sheet = self.env['stock.production.lot'].create({'product_id': product_table_sheet.id})
+ lot_leg = self.env['stock.production.lot'].create({'product_id': product_table_leg.id})
+ lot_bolt = self.env['stock.production.lot'].create({'product_id': product_bolt.id})
# Initialize inventory
# --------------------
- inventory = self.Inventory.create({
+ inventory = self.env['stock.inventory'].create({
'name': 'Inventory Product Table',
- 'filter': 'partial'})
- inventory.prepare_inventory()
- self.assertFalse(inventory.line_ids, "Inventory line should not created.")
- self.create_inventory_line(inventory, product_table_sheet, 20, lot_sheet.id)
- self.create_inventory_line(inventory, product_table_leg, 20, lot_leg.id)
- self.create_inventory_line(inventory, product_bolt, 20, lot_bolt.id)
+ 'filter': 'partial',
+ 'line_ids': [(0, 0, {
+ 'product_id': product_table_sheet.id,
+ 'product_uom_id': product_table_sheet.uom_id.id,
+ 'product_qty': 20,
+ 'prod_lot_id': lot_sheet.id,
+ 'location_id': self.source_location_id
+ }), (0, 0, {
+ 'product_id': product_table_leg.id,
+ 'product_uom_id': product_table_leg.uom_id.id,
+ 'product_qty': 20,
+ 'prod_lot_id': lot_leg.id,
+ 'location_id': self.source_location_id
+ }), (0, 0, {
+ 'product_id': product_bolt.id,
+ 'product_uom_id': product_bolt.uom_id.id,
+ 'product_qty': 20,
+ 'prod_lot_id': lot_bolt.id,
+ 'location_id': self.source_location_id
+ })]
+ })
inventory.action_done()
# Create work order
production_table.button_plan()
# Check Work order created or not
- self.assertEqual(len(production_table.workorder_ids), 3, "Workorder should be created 3 instead of %s"%(len(production_table.workorder_ids)))
+ self.assertEqual(len(production_table.workorder_ids), 3)
# ---------------------------------------------------------
# Process all workorder and check it state.
@@ -89,8 +72,8 @@ class TestWorkOrderProcess(common.TransactionCase):
workorders = production_table.workorder_ids
self.assertEqual(workorders[0].state, 'ready', "First workorder state should be ready.")
- self.assertEqual(workorders[1].state, 'pending', "Workorder state should be pending.")
- self.assertEqual(workorders[2].state, 'pending', "Workorder state should be pending.")
+ self.assertEqual(workorders[1].state, 'pending')
+ self.assertEqual(workorders[2].state, 'pending')
# --------------------------------------------------------------
# Process cutting operation...
@@ -100,11 +83,11 @@ class TestWorkOrderProcess(common.TransactionCase):
workorders[0].write({'final_lot_id': finished_lot.id})
workorders[0].button_start()
workorders[0].active_move_lot_ids[0].write({'lot_id': lot_sheet.id, 'quantity_done': 1})
- self.assertEqual(workorders[0].state, 'progress', "First workorder state should be Inprogress.")
+ self.assertEqual(workorders[0].state, 'progress')
workorders[0].record_production()
- self.assertEqual(workorders[0].state, 'done', "Cutting process should be done.")
+ self.assertEqual(workorders[0].state, 'done')
move_table_sheet = production_table.move_raw_ids.filtered(lambda x : x.product_id == product_table_sheet)
- self.assertEqual(move_table_sheet.quantity_done, 1, "Wrong consumed quantity of raw materials.")
+ self.assertEqual(move_table_sheet.quantity_done, 1)
# --------------------------------------------------------------
# Process drilling operation ...
@@ -114,8 +97,8 @@ class TestWorkOrderProcess(common.TransactionCase):
workorders[1].active_move_lot_ids[0].write({'lot_id': lot_leg.id, 'quantity_done': 4})
workorders[1].record_production()
move_leg = production_table.move_raw_ids.filtered(lambda x : x.product_id == product_table_leg)
- self.assertEqual(workorders[1].state, 'done', "Drilling process should be done.")
- self.assertEqual(move_leg.quantity_done, 4, "Wrong consumed quantity of raw materials.")
+ self.assertEqual(workorders[1].state, 'done')
+ self.assertEqual(move_leg.quantity_done, 4)
# --------------------------------------------------------------
# Process fitting operation ...
@@ -128,8 +111,8 @@ class TestWorkOrderProcess(common.TransactionCase):
move_lot.write({'lot_id': lot_bolt.id, 'quantity_done': 4})
move_table_bolt = production_table.move_raw_ids.filtered(lambda x : x.product_id.id == product_bolt.id)
workorders[2].record_production()
- self.assertEqual(workorders[2].state, 'done', "Fitting process should done.")
- self.assertEqual(move_table_bolt.quantity_done, 4, "Wrong consumed quantity of raw materials.")
+ self.assertEqual(workorders[2].state, 'done')
+ self.assertEqual(move_table_bolt.quantity_done, 4)
# -----------------------------------------
# Post inventory of manufacturing order
@@ -141,20 +124,20 @@ class TestWorkOrderProcess(common.TransactionCase):
# ----------------------------------------
# Check consume quants and produce quants.
# ----------------------------------------
- self.assertEqual(sum(move_table_sheet.quant_ids.mapped('qty')) , 1, "Wrong quantity of consumed product %s"% move_table_sheet.product_id.name)
- self.assertEqual(sum(move_leg.quant_ids.mapped('qty')), 4, "Wrong quantity of consumed product %s"% move_leg.product_id.name)
- self.assertEqual(sum(move_table_bolt.quant_ids.mapped('qty')), 4, "Wrong quantity of consumed product %s"% move_table_bolt.product_id.name)
+ self.assertEqual(sum(move_table_sheet.quant_ids.mapped('qty')), 1, "Wrong quantity of consumed product %s" % move_table_sheet.product_id.name)
+ self.assertEqual(sum(move_leg.quant_ids.mapped('qty')), 4, "Wrong quantity of consumed product %s" % move_leg.product_id.name)
+ self.assertEqual(sum(move_table_bolt.quant_ids.mapped('qty')), 4, "Wrong quantity of consumed product %s" % move_table_bolt.product_id.name)
consume_quants = move_table_sheet.quant_ids + move_leg.quant_ids + move_table_bolt.quant_ids
# Check for produced quant correctly linked with consumed quants or not.
- finish_move = production_table.move_finished_ids.filtered(lambda x : x.product_id.id == dining_table.id)
+ finish_move = production_table.move_finished_ids.filtered(lambda x: x.product_id.id == dining_table.id)
finished_quant = finish_move.quant_ids[0]
for quant in consume_quants:
- self.assertEqual(len(quant.produced_quant_ids), 1, "Wrong produced quants on consumed quant.")
- self.assertEqual(quant.produced_quant_ids[0].lot_id.id, finished_lot.id, "Wrong produced quant lot on consumed quant.")
- self.assertEqual(quant.produced_quant_ids[0].id, finished_quant.id, "Wrong produced quants of consume material.")
+ self.assertEqual(len(quant.produced_quant_ids), 1)
+ self.assertEqual(quant.produced_quant_ids[0].lot_id.id, finished_lot.id)
+ self.assertEqual(quant.produced_quant_ids[0].id, finished_quant.id)
# ------------------------------------------
# Check finished quants with consumed quant.
@@ -170,17 +153,35 @@ class TestWorkOrderProcess(common.TransactionCase):
# Create new product charger and keybord
# --------------------------------------
- product_charger = self.create_product('Charger', unit)
- product_keybord = self.create_product('Usb Keybord', unit)
+ product_charger = self.env['product.product'].create({
+ 'name': 'Charger',
+ 'type': 'product',
+ 'tracking': 'lot',
+ 'uom_id': unit,
+ 'uom_po_id': unit})
+ product_keybord = self.env['product.product'].create({
+ 'name': 'Usb Keybord',
+ 'type': 'product',
+ 'tracking': 'lot',
+ 'uom_id': unit,
+ 'uom_po_id': unit})
# Create bill of material for customized laptop.
- bom_custom_laptop = self.MrpBom.create({
- 'product_tmpl_id': custom_laptop.product_tmpl_id.id,
- 'product_qty': 10,
- 'product_uom_id': unit})
- self.create_bom_lines(bom_custom_laptop.id, product_charger.id, 20, unit)
- self.create_bom_lines(bom_custom_laptop.id, product_keybord.id, 20, unit)
+ bom_custom_laptop = self.env['mrp.bom'].create({
+ 'product_tmpl_id': custom_laptop.product_tmpl_id.id,
+ 'product_qty': 10,
+ 'product_uom_id': unit,
+ 'bom_line_ids': [(0, 0, {
+ 'product_id': product_charger.id,
+ 'product_qty': 20,
+ 'product_uom_id': unit
+ }), (0, 0, {
+ 'product_id': product_keybord.id,
+ 'product_qty': 20,
+ 'product_uom_id': unit
+ })]
+ })
# Create production order for customize laptop.
@@ -195,34 +196,45 @@ class TestWorkOrderProcess(common.TransactionCase):
# Check production order status of availablity
- self.assertEqual(mo_custom_laptop.availability, 'waiting', "Production order should be in waiting state.")
+ self.assertEqual(mo_custom_laptop.availability, 'waiting')
# --------------------------------------------------
# Set inventory for rawmaterial charger and keybord
# --------------------------------------------------
- lot_charger = self.Lot.create({'product_id': product_charger.id})
- lot_keybord = self.Lot.create({'product_id': product_keybord.id})
+ lot_charger = self.env['stock.production.lot'].create({'product_id': product_charger.id})
+ lot_keybord = self.env['stock.production.lot'].create({'product_id': product_keybord.id})
# Initialize Inventory
# --------------------
- inventory = self.Inventory.create({
+ inventory = self.env['stock.inventory'].create({
'name': 'Inventory Product Table',
- 'filter': 'partial'})
- inventory.prepare_inventory()
- self.assertFalse(inventory.line_ids, "Inventory line should not created.")
- self.create_inventory_line(inventory, product_charger, 20, lot_charger.id)
- self.create_inventory_line(inventory, product_keybord, 20, lot_keybord.id)
+ 'filter': 'partial',
+ 'line_ids': [(0, 0, {
+ 'product_id': product_charger.id,
+ 'product_uom_id': product_charger.uom_id.id,
+ 'product_qty': 20,
+ 'prod_lot_id': lot_charger.id,
+ 'location_id': self.source_location_id
+ }), (0, 0, {
+ 'product_id': product_keybord.id,
+ 'product_uom_id': product_keybord.uom_id.id,
+ 'product_qty': 20,
+ 'prod_lot_id': lot_keybord.id,
+ 'location_id': self.source_location_id
+ })]
+ })
+ # inventory.prepare_inventory()
inventory.action_done()
# Check consumed move status
mo_custom_laptop.action_assign()
- self.assertEqual( mo_custom_laptop.availability, 'assigned', "Production order should be in assigned state.")
+ self.assertEqual( mo_custom_laptop.availability, 'assigned')
# Check current status of raw materials.
for move in mo_custom_laptop.move_raw_ids:
- self.assertEqual(move.product_uom_qty, 20, "Wrong consume quantity of raw material %s"% (move.product_id.name))
- self.assertEqual(move.quantity_done, 0, "Wrong produced quantity on raw material %s"% (move.product_id.name))
+ self.assertEqual(move.product_uom_qty, 20, "Wrong consume quantity of raw material %s: %s instead of %s" % (move.product_id.name, move.product_uom_qty, 20))
+ self.assertEqual(move.quantity_done, 0, "Wrong produced quantity on raw material %s: %s instead of %s" % (move.product_id.name, move.quantity_done, 0))
# -----------------
# Start production
@@ -231,41 +243,41 @@ class TestWorkOrderProcess(common.TransactionCase):
# Produce 6 Unit of custom laptop will consume ( 12 Unit of keybord and 12 Unit of charger)
context = {"active_ids": [mo_custom_laptop.id], "active_id": mo_custom_laptop.id}
- product_consume = self.MrpProductProduce.with_context(context).create({'product_qty': 6.00})
- laptop_lot_001 = self.Lot.create({'product_id': custom_laptop.id})
+ product_consume = self.env['mrp.product.produce'].with_context(context).create({'product_qty': 6.00})
+ laptop_lot_001 = self.env['stock.production.lot'].create({'product_id': custom_laptop.id})
product_consume.lot_id = laptop_lot_001.id
product_consume.consume_line_ids.write({'quantity_done': 12})
product_consume.do_produce()
# Check consumed move after produce 6 quantity of customized laptop.
for move in mo_custom_laptop.move_raw_ids:
- self.assertEqual(move.quantity_done, 12, "Wrong produced quantity on raw material %s"% (move.product_id.name))
- self.assertEqual(len(mo_custom_laptop.move_raw_ids), 2, "Wrong raw material moves of production order.")
+ self.assertEqual(move.quantity_done, 12, "Wrong produced quantity on raw material %s" % (move.product_id.name))
+ self.assertEqual(len(mo_custom_laptop.move_raw_ids), 2)
mo_custom_laptop.post_inventory()
- self.assertEqual(len(mo_custom_laptop.move_raw_ids), 4, "Wrong raw material moves of production order.")
+ self.assertEqual(len(mo_custom_laptop.move_raw_ids), 4)
# Check done move and confirmed move quantity.
- charger_done_move = mo_custom_laptop.move_raw_ids.filtered(lambda x : x.product_id.id == product_charger.id and x.state == 'done')
- keybord_done_move = mo_custom_laptop.move_raw_ids.filtered(lambda x : x.product_id.id == product_keybord.id and x.state == 'done')
- self.assertEquals(charger_done_move.product_uom_qty, 12, "Wrong consumed raw material charger.")
- self.assertEquals(keybord_done_move.product_uom_qty, 12, "Wrong consumed raw material keybord")
+ charger_done_move = mo_custom_laptop.move_raw_ids.filtered(lambda x: x.product_id.id == product_charger.id and x.state == 'done')
+ keybord_done_move = mo_custom_laptop.move_raw_ids.filtered(lambda x: x.product_id.id == product_keybord.id and x.state == 'done')
+ self.assertEquals(charger_done_move.product_uom_qty, 12)
+ self.assertEquals(keybord_done_move.product_uom_qty, 12)
# Produce remaining 4 quantity
# ----------------------------
# Produce 4 Unit of custom laptop will consume ( 8 Unit of keybord and 8 Unit of charger).
context = {"active_ids": [mo_custom_laptop.id], "active_id": mo_custom_laptop.id}
- product_consume = self.MrpProductProduce.with_context(context).create({'product_qty': 4.00})
- laptop_lot_002 = self.Lot.create({'product_id': custom_laptop.id})
+ product_consume = self.env['mrp.product.produce'].with_context(context).create({'product_qty': 4.00})
+ laptop_lot_002 = self.env['stock.production.lot'].create({'product_id': custom_laptop.id})
product_consume.lot_id = laptop_lot_002.id
- self.assertEquals(len(product_consume.consume_line_ids), 2, "Wrong lots linked with move.")
+ self.assertEquals(len(product_consume.consume_line_ids), 2)
product_consume.consume_line_ids.write({'quantity_done': 8})
product_consume.do_produce()
- charger_move = mo_custom_laptop.move_raw_ids.filtered(lambda x : x.product_id.id == product_charger.id and x.state != 'done')
- keybord_move = mo_custom_laptop.move_raw_ids.filtered(lambda x : x.product_id.id == product_keybord.id and x.state !='done')
- self.assertEquals(charger_move.quantity_done, 8, "Wrong consumed quantity of %s"% charger_move.product_id.name)
- self.assertEquals(keybord_move.quantity_done, 8, "Wrong consumed quantity of %s"% keybord_move.product_id.name)
+ charger_move = mo_custom_laptop.move_raw_ids.filtered(lambda x: x.product_id.id == product_charger.id and x.state != 'done')
+ keybord_move = mo_custom_laptop.move_raw_ids.filtered(lambda x: x.product_id.id == product_keybord.id and x.state !='done')
+ self.assertEquals(charger_move.quantity_done, 8, "Wrong consumed quantity of %s" % charger_move.product_id.name)
+ self.assertEquals(keybord_move.quantity_done, 8, "Wrong consumed quantity of %s" % keybord_move.product_id.name)
# Post Inventory of production order.
mo_custom_laptop.post_inventory()
@@ -277,8 +289,8 @@ class TestWorkOrderProcess(common.TransactionCase):
# Finished move quants of production order
- finshed_quant_lot_001 = mo_custom_laptop.move_finished_ids.filtered(lambda x : x.product_id.id == custom_laptop.id and x.product_uom_qty==6).mapped('quant_ids')
- finshed_quant_lot_002 = mo_custom_laptop.move_finished_ids.filtered(lambda x : x.product_id.id == custom_laptop.id and x.product_uom_qty==4).mapped('quant_ids')
+ finshed_quant_lot_001 = mo_custom_laptop.move_finished_ids.filtered(lambda x: x.product_id.id == custom_laptop.id and x.product_uom_qty==6).mapped('quant_ids')
+ finshed_quant_lot_002 = mo_custom_laptop.move_finished_ids.filtered(lambda x: x.product_id.id == custom_laptop.id and x.product_uom_qty==4).mapped('quant_ids')
# --------------------------------
# Check consume and produce quants
@@ -286,34 +298,31 @@ class TestWorkOrderProcess(common.TransactionCase):
# Check consumed quants of lot1
for consume_quant in finshed_quant_lot_001[0].consumed_quant_ids:
- self.assertEqual(consume_quant.qty, 12, "Wrong quantity of quants of consume quants")
- self.assertEqual(consume_quant.produced_quant_ids[0].lot_id.id , finshed_quant_lot_001[0].lot_id.id , "Wrong produced quant lot on consume quants")
- self.assertEqual(consume_quant.produced_quant_ids[0].id , finshed_quant_lot_001[0].id , "Wrong produced quant on consume quants")
+ self.assertEqual(consume_quant.qty, 12)
+ self.assertEqual(consume_quant.produced_quant_ids[0].lot_id.id, finshed_quant_lot_001[0].lot_id.id)
+ self.assertEqual(consume_quant.produced_quant_ids[0].id, finshed_quant_lot_001[0].id)
- self.assertEqual(len(finshed_quant_lot_001[0].consumed_quant_ids), 2, "Wrong consumed quant linked with produced quant for lot %s "%laptop_lot_001.name)
+ self.assertEqual(len(finshed_quant_lot_001[0].consumed_quant_ids), 2, "Wrong consumed quant linked with produced quant for lot %s " % laptop_lot_001.name)
# Check total no of quants linked with produced quants.
- self.assertEqual(len(finshed_quant_lot_002[0].consumed_quant_ids), 2, "Wrong consumed quant linked with produced quant for lot %s "%laptop_lot_002.name)
+ self.assertEqual(len(finshed_quant_lot_002[0].consumed_quant_ids), 2, "Wrong consumed quant linked with produced quant for lot %s " % laptop_lot_002.name)
# Check consumed quants of lot2
for consume_quant in finshed_quant_lot_002[0].consumed_quant_ids:
- self.assertEqual(consume_quant.qty, 8, "Wrong quantity of quants of consume quants")
- self.assertEqual(consume_quant.produced_quant_ids[0].lot_id.id , finshed_quant_lot_002[0].lot_id.id , "Wrong produced quant lot on consume quants")
- self.assertEqual(consume_quant.produced_quant_ids[0].id , finshed_quant_lot_002[0].id , "Wrong produced quant on consume quants")
+ self.assertEqual(consume_quant.qty, 8)
+ self.assertEqual(consume_quant.produced_quant_ids[0].lot_id.id, finshed_quant_lot_002[0].lot_id.id)
+ self.assertEqual(consume_quant.produced_quant_ids[0].id, finshed_quant_lot_002[0].id)
# Check total quantity consumed of charger, keybord
# --------------------------------------------------
- charger_quants = mo_custom_laptop.move_raw_ids.filtered(lambda x : x.product_id.id == product_charger.id and x.state == 'done').mapped('quant_ids')
- keybord_moves = mo_custom_laptop.move_raw_ids.filtered(lambda x : x.product_id.id == product_keybord.id and x.state == 'done').mapped('quant_ids')
- self.assertEqual(sum(charger_quants.mapped('qty')) , 20 , "Wrong consumed quants quantity of charger.")
- self.assertEqual(sum(keybord_moves.mapped('qty')) , 20 , "Wrong consumed quants quantity of keybord.")
+ charger_quants = mo_custom_laptop.move_raw_ids.filtered(lambda x: x.product_id.id == product_charger.id and x.state == 'done').mapped('quant_ids')
+ keybord_moves = mo_custom_laptop.move_raw_ids.filtered(lambda x: x.product_id.id == product_keybord.id and x.state == 'done').mapped('quant_ids')
+ self.assertEqual(sum(charger_quants.mapped('qty')), 20)
+ self.assertEqual(sum(keybord_moves.mapped('qty')), 20)
def test_02_different_uom_on_bomlines(self):
""" Testing bill of material 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
unit = self.ref("product.product_uom_unit")
@@ -321,9 +330,25 @@ class TestWorkOrderProcess(common.TransactionCase):
kg = self.ref("product.product_uom_kgm")
gm = self.ref("product.product_uom_gram")
# Create Product A, B, C
- product_A = self.create_product('Product A', dozen, [(6, 0, [route_manufacture, route_mto])])
- product_B = self.create_product('Product B', dozen)
- product_C = self.create_product('Product C', kg)
+ product_A = self.env['product.product'].create({
+ 'name': 'Product A',
+ 'type': 'product',
+ 'tracking': 'lot',
+ 'uom_id': dozen,
+ 'uom_po_id': dozen,
+ 'route_ids': [(6, 0, [route_manufacture, route_mto])]})
+ product_B = self.env['product.product'].create({
+ 'name': 'Product B',
+ 'type': 'product',
+ 'tracking': 'lot',
+ 'uom_id': dozen,
+ 'uom_po_id': dozen})
+ product_C = self.env['product.product'].create({
+ 'name': 'Product C',
+ 'type': 'product',
+ 'tracking': 'lot',
+ 'uom_id': kg,
+ 'uom_po_id': kg})
# Bill of materials
# -----------------
@@ -334,13 +359,20 @@ class TestWorkOrderProcess(common.TransactionCase):
# Product C 600 gram
# -----------------------------------
- bom_a = self.MrpBom.create({
- 'product_tmpl_id': product_A.product_tmpl_id.id,
- 'product_qty': 2,
- 'product_uom_id': unit})
- self.create_bom_lines(bom_a.id, product_B.id, 4, unit)
- self.create_bom_lines(bom_a.id, product_C.id, 600, gm)
- #create_bom_lines(bom_a.id, product_d.id, 4, self.uom_unit.id, 'make_to_order')
+ bom_a = self.env['mrp.bom'].create({
+ 'product_tmpl_id': product_A.product_tmpl_id.id,
+ 'product_qty': 2,
+ 'product_uom_id': unit,
+ 'bom_line_ids': [(0, 0, {
+ 'product_id': product_B.id,
+ 'product_qty': 4,
+ 'product_uom_id': unit
+ }), (0, 0, {
+ 'product_id': product_C.id,
+ 'product_qty': 600,
+ 'product_uom_id': gm
+ })]
+ })
# Create production order with product A 10 Unit.
# -----------------------------------------------
@@ -351,30 +383,41 @@ class TestWorkOrderProcess(common.TransactionCase):
'product_uom_id': unit,
'bom_id': bom_a.id})
- move_product_b = mo_custom_product.move_raw_ids.filtered(lambda x : x.product_id == product_B)
- move_product_c = mo_custom_product.move_raw_ids.filtered(lambda x : x.product_id == product_C)
+ move_product_b = mo_custom_product.move_raw_ids.filtered(lambda x: x.product_id == product_B)
+ move_product_c = mo_custom_product.move_raw_ids.filtered(lambda x: x.product_id == product_C)
# Check move correctly created or not.
- self.assertEqual(move_product_b.product_uom_qty, 20 , "Wrong consume quantity of raw materials.")
- self.assertEqual(move_product_b.product_uom.id, unit, "Wrong unit of measure in rawmaterial.")
- self.assertEqual(move_product_c.product_uom_qty, 3000, "Wrong consume quantity of raw materials.")
- self.assertEqual(move_product_c.product_uom.id, gm, "Wrong unit of measure in rawmaterial.")
+ self.assertEqual(move_product_b.product_uom_qty, 20)
+ self.assertEqual(move_product_b.product_uom.id, unit)
+ self.assertEqual(move_product_c.product_uom_qty, 3000)
+ self.assertEqual(move_product_c.product_uom.id, gm)
# Lot create for product B and product C
# ---------------------------------------
- lot_a = self.Lot.create({'product_id': product_A.id})
- lot_b = self.Lot.create({'product_id': product_B.id})
- lot_c = self.Lot.create({'product_id': product_C.id})
+ lot_a = self.env['stock.production.lot'].create({'product_id': product_A.id})
+ lot_b = self.env['stock.production.lot'].create({'product_id': product_B.id})
+ lot_c = self.env['stock.production.lot'].create({'product_id': product_C.id})
# Inventory Update
# ----------------
- inventory = self.Inventory.create({
+ inventory = self.env['stock.inventory'].create({
'name': 'Inventory Product B and C',
- 'filter': 'partial'})
- inventory.prepare_inventory()
- self.assertFalse(inventory.line_ids, "Inventory line should not created.")
- self.create_inventory_line(inventory, product_B, 3, lot_b.id)
- self.create_inventory_line(inventory, product_C, 3, lot_c.id)
+ 'filter': 'partial',
+ 'line_ids': [(0, 0, {
+ 'product_id': product_B.id,
+ 'product_uom_id': product_B.uom_id.id,
+ 'product_qty': 3,
+ 'prod_lot_id': lot_b.id,
+ 'location_id': self.source_location_id
+ }), (0, 0, {
+ 'product_id': product_C.id,
+ 'product_uom_id': product_C.uom_id.id,
+ 'product_qty': 3,
+ 'prod_lot_id': lot_c.id,
+ 'location_id': self.source_location_id
+ })]
+ })
+ # inventory.prepare_inventory()
inventory.action_done()
# Start Production ...
@@ -382,10 +425,10 @@ class TestWorkOrderProcess(common.TransactionCase):
mo_custom_product.action_assign()
context = {"active_ids": [mo_custom_product.id], "active_id": mo_custom_product.id}
- product_consume = self.MrpProductProduce.with_context(context).create({'product_qty': 10})
- # laptop_lot_002 = self.Lot.create({'product_id': custom_laptop.id})
+ product_consume = self.env['mrp.product.produce'].with_context(context).create({'product_qty': 10})
+ # laptop_lot_002 = self.env['stock.production.lot'].create({'product_id': custom_laptop.id})
product_consume.lot_id = lot_a.id
- self.assertEquals(len(product_consume.consume_line_ids), 2, "Wrong move lot linked to produce wizard.")
+ self.assertEquals(len(product_consume.consume_line_ids), 2)
product_consume.consume_line_ids.filtered(lambda x : x.product_id == product_C).write({'quantity_done': 3000})
product_consume.consume_line_ids.filtered(lambda x : x.product_id == product_B).write({'quantity_done': 20})
product_consume.do_produce()
@@ -393,8 +436,8 @@ class TestWorkOrderProcess(common.TransactionCase):
# Check correct quant linked with move or not
# -------------------------------------------
- self.assertEqual(len(move_product_b.quant_ids), 1, "Wrong quants on move of product B")
- self.assertEqual(len(move_product_c.quant_ids), 1, "Wrong quants on move of product C")
- self.assertEqual(move_product_b.quant_ids.qty, move_product_b.product_qty , "Wrong quantity on quants of product B")
- self.assertEqual(move_product_c.quant_ids.qty, 3 , "Wrong quantity on quants of product B")
- self.assertEqual(move_product_c.quant_ids.product_uom_id.id, kg , "Wrong quantity on quants of product B")
+ self.assertEqual(len(move_product_b.quant_ids), 1)
+ self.assertEqual(len(move_product_c.quant_ids), 1)
+ self.assertEqual(move_product_b.quant_ids.qty, move_product_b.product_qty)
+ self.assertEqual(move_product_c.quant_ids.qty, 3)
+ self.assertEqual(move_product_c.quant_ids.product_uom_id.id, kg)
diff --git a/addons/mrp_byproduct/tests/test_mrp_byproduct.py b/addons/mrp_byproduct/tests/test_mrp_byproduct.py
index e9dc45b07c3..457dc719dd2 100644
--- a/addons/mrp_byproduct/tests/test_mrp_byproduct.py
+++ b/addons/mrp_byproduct/tests/test_mrp_byproduct.py
@@ -8,52 +8,79 @@ class TestMrpByProduct(common.TransactionCase):
def setUp(self):
super(TestMrpByProduct, self).setUp()
- self.product_28 = self.env.ref('product.product_delivery_02')
- self.product_33 = self.env.ref('product.product_delivery_01')
- self.product_uom = self.env.ref('product.product_uom_unit')
- self.location_src = self.env.ref('stock.stock_location_stock')
- self.mrp_action = self.env.ref('mrp.menu_mrp_production_action')
+ self.MrpBom = self.env['mrp.bom']
+ self.warehouse = self.env.ref('stock.warehouse0')
+ route_manufacture = self.warehouse.manufacture_pull_id.route_id.id
+ route_mto = self.warehouse.mto_pull_id.route_id.id
+ self.uom_unit_id = self.ref('product.product_uom_unit')
+ def create_product(name, route_ids=[]):
+ return self.env['product.product'].create({
+ 'name': name,
+ 'type': 'product',
+ 'route_ids': route_ids})
+
+ # Create product A, B, C.
+ # --------------------------
+ self.product_a = create_product('Product A', route_ids=[(6, 0, [route_manufacture, route_mto])])
+ self.product_b = create_product('Product B', route_ids=[(6, 0, [route_manufacture, route_mto])])
+ self.product_c_id = create_product('Product C', route_ids=[]).id
def test_00_mrp_byproduct(self):
- # I add a sub product in Bill of material for product External Hard Disk.
- bom_hardisk = self.env['mrp.bom'].create({'product_tmpl_id': self.product_28.product_tmpl_id.id,
- 'product_uom_id': self.product_uom.id,
- 'sub_products': [(0, 0, {'product_id': self.product_33.id,
- 'product_uom_id': self.product_uom.id,
- 'product_qty': 2.0})]})
- # I create a production order for External Hard Disk
- mnf_hardisk = self.env['mrp.production'].create({'product_id': self.product_28.id,
- 'product_qty': 2.0,
- 'product_uom_id': self.product_uom.id,
- 'bom_id': bom_hardisk.id,
- 'location_src_id': self.location_src.id})
+ """ Test by product with production order."""
+ # Create BOM for product B
+ # ------------------------
+ bom_product_b = self.MrpBom.create({
+ 'product_tmpl_id': self.product_b.product_tmpl_id.id,
+ 'product_qty': 1.0,
+ 'type': 'normal',
+ 'product_uom_id': self.uom_unit_id,
+ 'bom_line_ids': [(0, 0, {'product_id': self.product_c_id, 'product_uom_id': self.uom_unit_id, 'product_qty': 2})]
+ })
- # I compute the data of production order
- context = {"active_ids": [mnf_hardisk.id], "active_id": mnf_hardisk.id}
- # mnf_hardisk.with_context(context).action_compute()
+ # Create BOM for product A and set byproduct product B
+ bom_product_a = self.MrpBom.create({
+ 'product_tmpl_id': self.product_a.product_tmpl_id.id,
+ 'product_qty': 1.0,
+ 'type': 'normal',
+ 'product_uom_id': self.uom_unit_id,
+ 'bom_line_ids': [(0, 0, {'product_id': self.product_c_id, 'product_uom_id': self.uom_unit_id, 'product_qty': 2})],
+ 'sub_products': [(0, 0, {'product_id': self.product_b.id, 'product_uom_id': self.uom_unit_id, 'product_qty': 1})]
+ })
- # I confirm the production order.
- # mnf_hardisk.signal_workflow('button_confirm')
+ # Create production order for product A
+ # -------------------------------------
+
+ mnf_product_a = self.env['mrp.production'].create({
+ 'product_id': self.product_a.id,
+ 'product_qty': 2.0,
+ 'product_uom_id': self.uom_unit_id,
+ 'bom_id': bom_product_a.id,
+ })
+
+ # I compute the data of production order
+ context = {"active_model": "mrp.production", "active_ids": [mnf_product_a.id], "active_id": mnf_product_a.id}
# I confirm the production order.
- self.assertEqual(mnf_hardisk.state, 'confirmed', 'Production order should be in state confirmed')
+ self.assertEqual(mnf_product_a.state, 'confirmed', 'Production order should be in state confirmed')
# Now I check the stock moves for the byproduct I created in the bill of material.
# This move is created automatically when I confirmed the production order.
- moves = self.env['stock.move'].search([('product_id', '=', self.product_33.id)])
+ moves = mnf_product_a.move_raw_ids | mnf_product_a.move_finished_ids
self.assertTrue(moves, 'No moves are created !')
# I consume and produce the production of products.
# I create record for selecting mode and quantity of products to produce.
product_consume = self.env['mrp.product.produce'].with_context(context).create({'product_qty': 2.00})
# I finish the production order.
- context = {"active_model": "mrp.production", "active_ids": [mnf_hardisk.id], "active_id": mnf_hardisk.id}
+ self.assertEqual(len(mnf_product_a.move_raw_ids), 1, "Wrong consume move on production order.")
product_consume.do_produce()
- mnf_hardisk.post_inventory()
+ consume_move_c = mnf_product_a.move_raw_ids
+ by_product_move = mnf_product_a.move_finished_ids.filtered(lambda x: x.product_id.id == self.product_b.id)
+ # Check sub production produced quantity...
+ self.assertEqual(consume_move_c.product_uom_qty, 4, "Wrong consumed quantity of product c.")
+ self.assertEqual(by_product_move.product_uom_qty, 2, "Wrong produced quantity of sub product.")
+
+ mnf_product_a.post_inventory()
# I see that stock moves of External Hard Disk including Headset USB are done now.
- #moves = self.Move.search([('origin', '=', mnf_hardisk.name), ('product_id', 'in', [self.product_28.id, self.product_33.id])])
- #for move in moves:
- # self.assertEqual(move.state, 'done', 'Moves are not done!')
-
- \ No newline at end of file
+ self.assertFalse(any(move.state != 'done' for move in moves), 'Moves are not done!')
diff --git a/addons/product/tests/common.py b/addons/product/tests/common.py
index fac4c1dba74..007caf4d6bd 100644
--- a/addons/product/tests/common.py
+++ b/addons/product/tests/common.py
@@ -17,51 +17,76 @@ class TestProductCommon(common.SavepointCase):
# Product environment related data
Uom = cls.env['product.uom']
- categ_unit = cls.env.ref('product.product_uom_categ_unit')
- weight_unit = cls.env.ref('product.product_uom_categ_kgm')
- cls.uom_unit = Uom.create({
- 'name': 'TestUnit',
- 'category_id': categ_unit.id,
- 'factor_inv': 1.0,
- 'factor': 1.0,
- 'uom_type': 'reference',
- 'rounding': 0.000001})
- cls.uom_kunit = Uom.create({
- 'name': 'KTestUnit',
- 'category_id': categ_unit.id,
- 'factor_inv': 1000.0,
- 'factor': 0.001,
- 'uom_type': 'bigger',
- 'rounding': 0.001})
- cls.uom_munit = Uom.create({
- 'name': 'mTestUnit',
- 'category_id': categ_unit.id,
- 'factor_inv': 0.001,
- 'factor': 1000.0,
+ cls.uom_unit = cls.env.ref('product.product_uom_unit')
+ cls.uom_dozen = cls.env.ref('product.product_uom_dozen')
+ cls.uom_dunit = Uom.create({
+ 'name': 'DeciUnit',
+ 'category_id': cls.uom_unit.category_id.id,
+ 'factor_inv': 0.1,
+ 'factor': 10.0,
'uom_type': 'smaller',
'rounding': 0.001})
- cls.uom_weight = Uom.create({
- 'name': 'TestWeight',
- 'category_id': weight_unit.id,
- 'factor_inv': 1.0,
- 'factor': 1.0,
- 'uom_type': 'reference',
- 'rounding': 0.000001
- })
+ cls.uom_weight = cls.env.ref('product.product_uom_kgm')
Product = cls.env['product.product']
- cls.product_1 = Product.create({
- 'name': 'TestProduct 1',
+ cls.product_0 = Product.create({
+ 'name': 'Work',
+ 'type': 'service',
'uom_id': cls.uom_unit.id,
'uom_po_id': cls.uom_unit.id})
+ cls.product_1 = Product.create({
+ 'name': 'Courage',
+ 'type': 'consu',
+ 'uom_id': cls.uom_dunit.id,
+ 'uom_po_id': cls.uom_dunit.id})
+
cls.product_2 = Product.create({
- 'name': 'TestProduct 2',
+ 'name': 'Wood',
'uom_id': cls.uom_unit.id,
'uom_po_id': cls.uom_unit.id})
cls.product_3 = Product.create({
- 'name': 'TestProduct 3 (KTestUnit)',
- 'uom_id': cls.uom_kunit.id,
- 'uom_po_id': cls.uom_kunit.id})
+ 'name': 'Stone',
+ 'uom_id': cls.uom_dozen.id,
+ 'uom_po_id': cls.uom_dozen.id})
+
cls.product_4 = Product.create({
- 'name': 'TestProduct 4 (mTestUnit)',
- 'uom_id': cls.uom_munit.id,
- 'uom_po_id': cls.uom_munit.id})
+ 'name': 'Stick',
+ 'uom_id': cls.uom_dozen.id,
+ 'uom_po_id': cls.uom_dozen.id})
+ cls.product_5 = Product.create({
+ 'name': 'Stone Tools',
+ 'uom_id': cls.uom_unit.id,
+ 'uom_po_id': cls.uom_unit.id})
+
+ cls.product_6 = Product.create({
+ 'name': 'Door',
+ 'uom_id': cls.uom_unit.id,
+ 'uom_po_id': cls.uom_unit.id})
+
+ cls.prod_att_1 = cls.env['product.attribute'].create({'name': 'Color'})
+ cls.prod_attr1_v1 = cls.env['product.attribute.value'].create({'name': 'red', 'attribute_id': cls.prod_att_1.id})
+ cls.prod_attr1_v2 = cls.env['product.attribute.value'].create({'name': 'blue', 'attribute_id': cls.prod_att_1.id})
+
+ cls.product_7_template = cls.env['product.template'].create({
+ 'name': 'Sofa',
+ 'uom_id': cls.uom_unit.id,
+ 'uom_po_id': cls.uom_unit.id,
+ 'attribute_line_ids': [(0, 0, {
+ 'attribute_id': cls.prod_att_1.id,
+ })]
+ })
+ cls.product_7 = Product.create({
+ 'product_tmpl_id': cls.product_7_template.id,
+ })
+ cls.product_7_1 = Product.create({
+ 'product_tmpl_id': cls.product_7_template.id,
+ 'attribute_value_ids': [(6, 0, [cls.prod_attr1_v1.id])],
+ })
+ cls.product_7_2 = Product.create({
+ 'product_tmpl_id': cls.product_7_template.id,
+ 'attribute_value_ids': [(6, 0, [cls.prod_attr1_v2.id])],
+ })
+
+ cls.product_8 = Product.create({
+ 'name': 'House',
+ 'uom_id': cls.uom_unit.id,
+ 'uom_po_id': cls.uom_unit.id})
diff --git a/addons/sale_mrp/tests/__init__.py b/addons/sale_mrp/tests/__init__.py
index 5441d7d9b8d..1b510b23429 100644
--- a/addons/sale_mrp/tests/__init__.py
+++ b/addons/sale_mrp/tests/__init__.py
@@ -2,4 +2,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_move_explode
-# from . import test_sale_mrp_flow
+from . import test_sale_mrp_flow
diff --git a/addons/sale_mrp/tests/test_move_explode.py b/addons/sale_mrp/tests/test_move_explode.py
index b24f19ed329..14e947bb971 100644
--- a/addons/sale_mrp/tests/test_move_explode.py
+++ b/addons/sale_mrp/tests/test_move_explode.py
@@ -56,24 +56,3 @@ class TestMoveExplode(common.TransactionCase):
#self.assertEqual(len(move_ids), len(bom_component_length[0]))
# We should have same amount of move as the component in the phatom bom
#self.assertEqual(len(move_ids), 5)
-
- # def test_00_bom_find(self):
- # """Check that _bom_find searches the bom corresponding to the properties passed or takes the bom with the smallest
- # sequence."""
- # bom = self.MrpBom._bom_find(product_tmpl_id=self.template.id, product_id=None, properties=[self.mrp_property.id])
- # self.assertEqual(bom, self.bom_prop)
-
- # def test_00_bom_find(self):
- # """Check that _bom_find searches the bom corresponding to the properties passed or takes the bom with the smallest
- # sequence."""
- # res = self.MrpBom._bom_find(product_tmpl=self.template)
- # self.assertEqual(res.id, self.bom_prop.id)
-
-
- # def test_00_explode(self):
- # """Check that explode only takes the lines with the right properties."""
- # bom = self.bom_prop_line
- # product = self.product_bom_prop
- # res = bom.explode_data(product, 1, properties=self.mrp_property)
- # res = set([p['product_id'] for p in res[0]])
- # self.assertEqual(res, set([self.product_A.id, self.product_B.id]))
diff --git a/addons/sale_mrp/tests/test_sale_mrp_flow.py b/addons/sale_mrp/tests/test_sale_mrp_flow.py
index 9fd80c67bb7..74d1da1e8f8 100644
--- a/addons/sale_mrp/tests/test_sale_mrp_flow.py
+++ b/addons/sale_mrp/tests/test_sale_mrp_flow.py
@@ -340,7 +340,8 @@ class TestSaleMrpFlow(common.TransactionCase):
""" Test delivered quantity on SO based on delivered quantity in pickings."""
# intial so
self.partner = self.env.ref('base.res_partner_1')
- self.product = self.env.ref('product.product_product_5')
+ self.product = self.env.ref('mrp.product_product_build_kit')
+ self.product.invoice_policy = 'delivery'
so_vals = {
'partner_id': self.partner.id,
'partner_invoice_id': self.partner.id,
diff --git a/addons/stock/tests/common2.py b/addons/stock/tests/common2.py
index b12774f7840..c6654dec903 100644
--- a/addons/stock/tests/common2.py
+++ b/addons/stock/tests/common2.py
@@ -80,7 +80,8 @@ class TestStockCommon(common.TestProductCommon):
'name': 'TestLocation1',
'posx': 3,
'location_id': cls.warehouse_1.lot_stock_id.id,
- })
+ })
+
# Existing data
cls.existing_inventories = cls.env['stock.inventory'].search([])
cls.existing_quants = cls.env['stock.quant'].search([])
diff --git a/addons/stock/tests/test_warehouse.py b/addons/stock/tests/test_warehouse.py
index 048392f5085..6e71ec74276 100644
--- a/addons/stock/tests/test_warehouse.py
+++ b/addons/stock/tests/test_warehouse.py
@@ -19,7 +19,7 @@ class TestInventory(TestStockCommon):
self.assertEqual(len(inventory.line_ids), 1)
self.assertEqual(inventory.line_ids.theoretical_qty, 50.0)
self.assertEqual(inventory.line_ids.product_id, self.product_1)
- self.assertEqual(inventory.line_ids.product_uom_id, self.uom_unit)
+ self.assertEqual(inventory.line_ids.product_uom_id, self.product_1.uom_id)
# Update the line, set to 35
inventory.line_ids.write({'product_qty': 35.0})
@@ -70,7 +70,7 @@ class TestInventory(TestStockCommon):
customer_move = self._create_move(product, self.warehouse_1.lot_stock_id, self.env.ref('stock.stock_location_customers'), product_uom_qty=5)
# test move values
- self.assertEqual(customer_move.product_uom, self.uom_kunit)
+ self.assertEqual(customer_move.product_uom, product.uom_id)
self.assertEqual(customer_move.location_id, self.warehouse_1.lot_stock_id)
self.assertEqual(customer_move.location_dest_id, self.env.ref('stock.stock_location_customers'))