[FIX] mrp: use the fastest workcenter

Steps to reproduce the bug:
- Create the workcenter_1:
    - Time Efficiency: 100%
    - Capacity: 2
    - Setup Time: 1
    - Cleanup Time: 1

- Create the workcenter_2:
    - Time Efficiency: 100%
     - Capacity: 4
    - Setup Time: 10
    - Cleanup Time: 5
    - Alternative Work centers: workcenter_1

- Create a storable product “P1” with BOM:
    - Add any product as component
    - Add operation:
        - Duration: 60
        - Work center: Workcenter_2

- Create a MO:
    - select “P1” as Product
    - Qty to produce: 4
    - Confirm and Plan

Problem:
The workcenter_1 is chosen while work_center_2 is faster it can manufacture the 4 units at the same time
while workcenter_1 must do two cycles

As the Time Efficiency = 100%, so:
Total duration = (Setup Time + Cleanup Time) + duration_by_unit * nb_cycle
Work_center_1 = (1 + 1) + 60 * 2 = 122
Work_center_2 = (10 + 5) + 60 = 75

The calculation is bad because we use the number of cycles necessary for the work_center defined in the BOM
in the calculation for the alternative work center

opw-2821749

closes odoo/odoo#88945

X-original-commit: deb87a6abf8b8ccc4328eaac21430eedc2536361
Signed-off-by: Arnold Moyaux <arm@odoo.com>
Signed-off-by: Djamel Touati (otd) <otd@odoo.com>
This commit is contained in:
Touati Djamel (otd)
2022-04-19 09:48:02 +02:00
parent 510965b4fb
commit 4f750d8ac9
2 changed files with 79 additions and 1 deletions
+2 -1
View File
@@ -728,7 +728,8 @@ class MrpWorkorder(models.Model):
duration_expected_working = (self.duration_expected - self.workcenter_id.time_start - self.workcenter_id.time_stop) * self.workcenter_id.time_efficiency / (100.0 * cycle_number)
if duration_expected_working < 0:
duration_expected_working = 0
return alternative_workcenter.time_start + alternative_workcenter.time_stop + cycle_number * duration_expected_working * 100.0 / alternative_workcenter.time_efficiency
alternative_wc_cycle_nb = float_round(qty_production / alternative_workcenter.capacity, precision_digits=0, rounding_method='UP')
return alternative_workcenter.time_start + alternative_workcenter.time_stop + alternative_wc_cycle_nb * duration_expected_working * 100.0 / alternative_workcenter.time_efficiency
time_cycle = self.operation_id.time_cycle
return self.workcenter_id.time_start + self.workcenter_id.time_stop + cycle_number * time_cycle * 100.0 / self.workcenter_id.time_efficiency
+77
View File
@@ -2651,3 +2651,80 @@ class TestMrpOrder(TestMrpCommon):
self.assertEqual(mo_3.state, 'to_close')
mo_3.button_mark_done()
self.assertEqual(mo_3.state, 'done')
def test_planning_workorder(self):
"""
Check that the fastest work center is used when planning the workorder.
- create two work centers with similar production capacity
but the work_center_2 with a longer start and stop time.
1:/ produce 2 units > work_center_1 faster because
it does not need much time to start and to finish the production.
2/ - update the production capacity of the work_center_2 to 4
- produce 4 units > work_center_2 faster because
it must do a single cycle while the work_center_1 have to do two cycles.
"""
workcenter_1 = self.env['mrp.workcenter'].create({
'name': 'wc1',
'capacity': 2,
'time_start': 1,
'time_stop': 1,
'time_efficiency': 100,
})
workcenter_2 = self.env['mrp.workcenter'].create({
'name': 'wc2',
'capacity': 2,
'time_start': 10,
'time_stop': 5,
'time_efficiency': 100,
'alternative_workcenter_ids': [workcenter_1.id]
})
product_to_build = self.env['product.product'].create({
'name': 'final product',
'type': 'product',
})
product_to_use = self.env['product.product'].create({
'name': 'component',
'type': 'product',
})
bom = self.env['mrp.bom'].create({
'product_id': product_to_build.id,
'product_tmpl_id': product_to_build.product_tmpl_id.id,
'product_uom_id': self.uom_unit.id,
'product_qty': 1.0,
'type': 'normal',
'consumption': 'flexible',
'operation_ids': [
(0, 0, {'name': 'Test', 'workcenter_id': workcenter_2.id, 'time_cycle': 60, 'sequence': 1}),
],
'bom_line_ids': [
(0, 0, {'product_id': product_to_use.id, 'product_qty': 1}),
]})
#MO_1
mo_form = Form(self.env['mrp.production'])
mo_form.product_id = product_to_build
mo_form.bom_id = bom
mo_form.product_qty = 2
mo = mo_form.save()
mo.action_confirm()
mo.button_plan()
self.assertEqual(mo.workorder_ids[0].workcenter_id.id, workcenter_1.id, 'workcenter_1 is faster than workcenter_2 to manufacture 2 units')
# Unplan the mo to prevent the first workcenter from being busy
mo.button_unplan()
# Update the production capcity
workcenter_2.capacity = 4
#MO_2
mo_form = Form(self.env['mrp.production'])
mo_form.product_id = product_to_build
mo_form.bom_id = bom
mo_form.product_qty = 4
mo_2 = mo_form.save()
mo_2.action_confirm()
mo_2.button_plan()
self.assertEqual(mo_2.workorder_ids[0].workcenter_id.id, workcenter_2.id, 'workcenter_2 is faster than workcenter_1 to manufacture 4 units')