210 lines
7.7 KiB
Python
210 lines
7.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import Command
|
|
from odoo.addons.mrp.tests import common
|
|
from odoo.tests import Form
|
|
|
|
|
|
class TestWorkOrderDependencies(common.TestMrpCommon):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
|
|
cls.wkct1 = cls.env['mrp.workcenter'].create({
|
|
'name': 'Workcenter#1',
|
|
})
|
|
cls.wkct2 = cls.env['mrp.workcenter'].create({
|
|
'name': 'Workcenter#2',
|
|
})
|
|
cls.wkct3 = cls.env['mrp.workcenter'].create({
|
|
'name': 'Workcenter#3',
|
|
})
|
|
cls.finished = cls.env['product.product'].create({
|
|
'name': 'Finished Product',
|
|
'type': 'product',
|
|
})
|
|
cls.component1 = cls.env['product.product'].create({
|
|
'name': 'Component#1',
|
|
'type': 'product',
|
|
})
|
|
cls.component2 = cls.env['product.product'].create({
|
|
'name': 'Component#2',
|
|
'type': 'product',
|
|
})
|
|
cls.bom = cls.env['mrp.bom'].create({
|
|
'product_id': cls.finished.id,
|
|
'product_tmpl_id': cls.finished.product_tmpl_id.id,
|
|
'product_qty': 1.0,
|
|
'bom_line_ids': [
|
|
Command.create({'product_id': cls.component1.id, 'product_qty': 1}),
|
|
Command.create({'product_id': cls.component2.id, 'product_qty': 2})
|
|
],
|
|
'operation_ids': [
|
|
Command.create({'name': 'Operation#A', 'workcenter_id': cls.wkct1.id}),
|
|
Command.create({'name': 'Operation#B', 'workcenter_id': cls.wkct2.id}),
|
|
Command.create({'name': 'Operation#C', 'workcenter_id': cls.wkct3.id}),
|
|
],
|
|
'allow_operation_dependencies': True,
|
|
})
|
|
cls.stock_location = cls.env.ref('stock.stock_location_stock')
|
|
cls.env['stock.quant']._update_available_quantity(cls.component1, cls.stock_location, 100)
|
|
cls.env['stock.quant']._update_available_quantity(cls.component2, cls.stock_location, 100)
|
|
|
|
def test_parallel_workorders(self):
|
|
""" Test parallel workorders: bom allowing operation dependencies without any dependency."""
|
|
|
|
# Make MO
|
|
mo_form = Form(self.env['mrp.production'])
|
|
mo_form.product_id = self.finished
|
|
mo_form.product_qty = 2.0
|
|
mo = mo_form.save()
|
|
mo.action_confirm()
|
|
|
|
# Check workorders initial state
|
|
self.assertEqual(mo.workorder_ids[0].state, 'ready', "All workorders should be ready.")
|
|
self.assertEqual(mo.workorder_ids[1].state, 'ready', "All workorders should be ready.")
|
|
self.assertEqual(mo.workorder_ids[2].state, 'ready', "All workorders should be ready.")
|
|
|
|
def test_stepped_workorders(self):
|
|
""" Test step-by-step workorders: bom operations are interdependent."""
|
|
|
|
# Make 1st workorder depend on 3rd
|
|
self.bom.operation_ids[0].blocked_by_operation_ids = [Command.link(self.bom.operation_ids[2].id)]
|
|
|
|
# Make MO
|
|
mo_form = Form(self.env['mrp.production'])
|
|
mo_form.product_id = self.finished
|
|
mo_form.product_qty = 2.0
|
|
mo = mo_form.save()
|
|
mo.action_confirm()
|
|
wo1, wo2, wo3 = mo.workorder_ids
|
|
# Check workorders initial state
|
|
self.assertEqual(wo1.state, 'pending', "Workorder for Operation-A should be Waiting for another WO (the 3rd).")
|
|
self.assertEqual(wo2.state, 'ready', "Workorder for Operation-B should be ready.")
|
|
self.assertEqual(wo3.state, 'ready', "Workorder for Operation-C should be ready.")
|
|
mo.button_plan()
|
|
# Mark 1st initial WO as done
|
|
wo2.button_start()
|
|
wo2.qty_producing = 2
|
|
wo2.record_production()
|
|
# Check 3rd WO (not dependent on 1st)
|
|
self.assertEqual(wo1.state, 'pending', "Workorder for Operation-A should STILL be Waiting for another WO (the 3rd).")
|
|
# Mark 2nd initial WO as done
|
|
wo3.button_start()
|
|
wo3.qty_producing = 2
|
|
wo3.record_production()
|
|
# Check dependent WO
|
|
self.assertEqual(wo1.state, 'ready', "Workorder for Operation-A can be started, as its predecessors are now done.")
|
|
|
|
def test_propagate_quantity_on_backorders_with_stepped_workorders(self):
|
|
"""Create a MO for a product with several work orders.
|
|
Produce different quantities to test quantity propagation and workorder cancellation.
|
|
-> Reproduce test_propagate_quantity_on_backorders on stepped workorders
|
|
"""
|
|
|
|
# Make 1st workorder depend on 3rd
|
|
self.bom.operation_ids[0].blocked_by_operation_ids = [Command.link(self.bom.operation_ids[2].id)]
|
|
|
|
# Make MO for 20 products
|
|
|
|
mo_form = Form(self.env['mrp.production'])
|
|
mo_form.product_id = self.finished
|
|
mo_form.product_qty = 20
|
|
mo = mo_form.save()
|
|
|
|
self.assertEqual(mo.state, 'draft')
|
|
mo.action_confirm()
|
|
|
|
wo_1, wo_2, wo_3 = mo.workorder_ids
|
|
self.assertEqual(mo.state, 'confirmed')
|
|
self.assertEqual(wo_1.state, 'pending')
|
|
self.assertEqual(wo_2.state, 'ready')
|
|
self.assertEqual(wo_3.state, 'ready')
|
|
|
|
# produce 20 / 10 / 5 on workorders 2 / 3 / 1, mark as done & create backorder
|
|
# mo closed with 5 produced
|
|
# backorder for 15 created with
|
|
# - wo5 'cancel' (fully processed)
|
|
# - wo6 'ready' for 10
|
|
# - wo4 'pending' for 15
|
|
|
|
wo_2.button_start()
|
|
wo_2.qty_producing = 20
|
|
self.assertEqual(mo.state, 'progress')
|
|
wo_2.button_finish()
|
|
|
|
wo_3.button_start()
|
|
wo_3.qty_producing = 10
|
|
wo_3.button_finish()
|
|
|
|
wo_1.button_start()
|
|
wo_1.qty_producing = 5
|
|
wo_1.button_finish()
|
|
|
|
self.assertEqual(mo.state, 'to_close')
|
|
mo.button_mark_done()
|
|
|
|
bo = self.env['mrp.production.backorder'].create({
|
|
"mrp_production_backorder_line_ids": [
|
|
[0, 0, {"mrp_production_id": mo.id, "to_backorder": True}]
|
|
]
|
|
})
|
|
bo.action_backorder()
|
|
|
|
self.assertEqual(mo.state, 'done')
|
|
|
|
mo_2 = mo.procurement_group_id.mrp_production_ids - mo
|
|
wo_4, wo_5, wo_6 = mo_2.workorder_ids
|
|
|
|
self.assertEqual(wo_4.state, 'pending')
|
|
self.assertEqual(wo_5.state, 'cancel')
|
|
self.assertEqual(wo_6.state, 'ready')
|
|
|
|
# produce 10 / 5 on workorders 6 / 4, mark as done & create backorder
|
|
# mo closed with 5 produced
|
|
# backorder for 10 created with
|
|
# - wo8 'cancel' (already fully processed)
|
|
# - wo9 'cancel' (fully processed)
|
|
# - wo7 'ready' for 10
|
|
|
|
wo_6.button_start()
|
|
wo_6.qty_producing = 10
|
|
self.assertEqual(mo_2.state, 'progress')
|
|
wo_6.button_finish()
|
|
|
|
wo_4.button_start()
|
|
wo_4.qty_producing = 5
|
|
wo_4.button_finish()
|
|
|
|
self.assertEqual(mo_2.state, 'to_close')
|
|
mo_2.button_mark_done()
|
|
|
|
bo = self.env['mrp.production.backorder'].create({
|
|
"mrp_production_backorder_line_ids": [
|
|
[0, 0, {"mrp_production_id": mo_2.id, "to_backorder": True}]
|
|
]
|
|
})
|
|
bo.action_backorder()
|
|
|
|
self.assertEqual(mo_2.state, 'done')
|
|
|
|
mo_3 = mo.procurement_group_id.mrp_production_ids - (mo | mo_2)
|
|
wo_7, wo_8, wo_9 = mo_3.workorder_ids
|
|
|
|
self.assertEqual(wo_7.state, 'ready')
|
|
self.assertEqual(wo_8.state, 'cancel')
|
|
self.assertEqual(wo_9.state, 'cancel')
|
|
|
|
# produce 10 on workorder 7 and finish work
|
|
|
|
wo_7.button_start()
|
|
wo_7.qty_producing = 10
|
|
self.assertEqual(mo_3.state, 'progress')
|
|
wo_7.button_finish()
|
|
|
|
self.assertEqual(mo_3.state, 'to_close')
|
|
mo_3.button_mark_done()
|
|
self.assertEqual(mo_3.state, 'done')
|