[FIX] mrp: update workcenter with BOM
Before this commit ================= While updating the Bill of Materials (BOM), the work center and operation name remained unchanged in the manufacturing order. When Archiving/Unarchiving the operation doesn't show the "Update BoM" button in the appropriate MO. Steps to Produce ================ - Create a BOM1 with operations - Create a MO with BOM1 and confirm MO - Goto BOM and change the workcenter and operation name - In MO Click on the 'update BoM' button - Now you see the operation name and workcenter are not updated in MO After this commit ================= With this commit the work center and operation name get updated with the update BOM click. For Archiving/Unarchiving the operation results to the display of the "Update BoM" button in the appropriate MO. Directly editing an operation will also cause the "Update BoM" button to appear task-3461985 closes odoo/odoo#138256 X-original-commit: c343ebf0a28f6404f7ad6fc892c4a42edd2bbbe0 Signed-off-by: Tiffany Chang (tic) <tic@odoo.com>
This commit is contained in:
committed by
Tiffany Chang (tic)
parent
75858d3509
commit
8852dc2fb9
@@ -244,22 +244,9 @@ class MrpBom(models.Model):
|
||||
|
||||
def write(self, vals):
|
||||
res = super().write(vals)
|
||||
relevant_fields = ['bom_line_ids', 'byproduct_ids', 'product_tmpl_id', 'product_id', 'product_qty', 'operation_ids']
|
||||
relevant_fields = ['bom_line_ids', 'byproduct_ids', 'product_tmpl_id', 'product_id', 'product_qty']
|
||||
if any(field_name in vals for field_name in relevant_fields):
|
||||
# Searches for MOs using these BoMs to notify them that their BoM has been updated.
|
||||
list_of_domain_by_bom = []
|
||||
for bom in self:
|
||||
domain_by_products = [('product_id', 'in', bom.product_tmpl_id.product_variant_ids.ids)]
|
||||
if bom.product_id:
|
||||
domain_by_products = [('product_id', '=', bom.product_id.id)]
|
||||
domain_for_confirmed_mo = AND([[('state', '=', 'confirmed')], domain_by_products])
|
||||
# Avoid confirmed MOs if the BoM's product was changed.
|
||||
domain_by_states = OR([[('state', '=', 'draft')], domain_for_confirmed_mo])
|
||||
list_of_domain_by_bom.append(AND([[('bom_id', '=', bom.id)], domain_by_states]))
|
||||
domain = OR(list_of_domain_by_bom)
|
||||
productions = self.env['mrp.production'].search(domain)
|
||||
if productions:
|
||||
productions.is_outdated_bom = True
|
||||
self._set_outdated_bom_in_productions()
|
||||
if 'sequence' in vals and self and self[-1].id == self._prefetch_ids[-1]:
|
||||
self.browse(self._prefetch_ids)._check_bom_cycle()
|
||||
return res
|
||||
@@ -428,6 +415,23 @@ class MrpBom(models.Model):
|
||||
'template': '/mrp/static/xls/mrp_bom.xls'
|
||||
}]
|
||||
|
||||
def _set_outdated_bom_in_productions(self):
|
||||
# Searches for MOs using these BoMs to notify them that their BoM has been updated.
|
||||
list_of_domain_by_bom = []
|
||||
for bom in self:
|
||||
domain_by_products = [('product_id', 'in', bom.product_tmpl_id.product_variant_ids.ids)]
|
||||
if bom.product_id:
|
||||
domain_by_products = [('product_id', '=', bom.product_id.id)]
|
||||
domain_for_confirmed_mo = AND([[('state', '=', 'confirmed')], domain_by_products])
|
||||
# Avoid confirmed MOs if the BoM's product was changed.
|
||||
domain_by_states = OR([[('state', '=', 'draft')], domain_for_confirmed_mo])
|
||||
list_of_domain_by_bom.append(AND([[('bom_id', '=', bom.id)], domain_by_states]))
|
||||
if list_of_domain_by_bom:
|
||||
domain = OR(list_of_domain_by_bom)
|
||||
productions = self.env['mrp.production'].search(domain)
|
||||
if productions:
|
||||
productions.is_outdated_bom = True
|
||||
|
||||
|
||||
class MrpBomLine(models.Model):
|
||||
_name = 'mrp.bom.line'
|
||||
|
||||
@@ -2314,6 +2314,13 @@ class MrpProduction(models.Model):
|
||||
break
|
||||
if operation and workorder.operation_id != operation:
|
||||
workorder.operation_id = operation
|
||||
elif operation and workorder.operation_id == operation:
|
||||
if workorder.workcenter_id != operation.workcenter_id:
|
||||
workorder.workcenter_id = operation.workcenter_id
|
||||
if workorder.name != operation.name:
|
||||
workorder.name = operation.name
|
||||
elif workorder.operation_id and workorder.operation_id not in operations_by_id:
|
||||
workorders_to_unlink |= workorder
|
||||
# Creates a workorder for each remaining operation.
|
||||
workorders_values = []
|
||||
for operation in operations_by_id.values():
|
||||
@@ -2403,6 +2410,7 @@ class MrpProduction(models.Model):
|
||||
|
||||
moves_to_unlink._action_cancel()
|
||||
moves_to_unlink.unlink()
|
||||
workorders_to_unlink.unlink()
|
||||
self.bom_id = bom
|
||||
|
||||
@api.model
|
||||
|
||||
@@ -105,10 +105,27 @@ class MrpRoutingWorkcenter(models.Model):
|
||||
if not self._check_m2m_recursion('blocked_by_operation_ids'):
|
||||
raise ValidationError(_("You cannot create cyclic dependency."))
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
res = super().create(vals_list)
|
||||
res.bom_id._set_outdated_bom_in_productions()
|
||||
return res
|
||||
|
||||
def write(self, vals):
|
||||
res = super().write(vals)
|
||||
self.bom_id._set_outdated_bom_in_productions()
|
||||
return res
|
||||
|
||||
def action_archive(self):
|
||||
res = super().action_archive()
|
||||
bom_lines = self.env['mrp.bom.line'].search([('operation_id', 'in', self.ids)])
|
||||
bom_lines.write({'operation_id': False})
|
||||
self.bom_id._set_outdated_bom_in_productions()
|
||||
return res
|
||||
|
||||
def action_unarchive(self):
|
||||
res = super().action_unarchive()
|
||||
self.bom_id._set_outdated_bom_in_productions()
|
||||
return res
|
||||
|
||||
def copy_to_bom(self):
|
||||
|
||||
@@ -1955,3 +1955,47 @@ class TestBoM(TestMrpCommon):
|
||||
# Check that component 1 is set again and component 2 is removed
|
||||
self.assertEqual(mo_form.move_raw_ids._records[0]['product_id'], self.product_1.id)
|
||||
self.assertEqual(len(mo_form.move_raw_ids._records), 1)
|
||||
|
||||
def test_update_operations(self):
|
||||
"""Update the operations in BoM which reflects the changes in Manufacturing Order"""
|
||||
|
||||
mo_form = Form(self.env['mrp.production'].with_user(self.user_mrp_user))
|
||||
mo_form.product_id = self.product_7_1
|
||||
mo_form.product_qty = 1.0
|
||||
mo_form.bom_id = self.bom_2
|
||||
mo = mo_form.save()
|
||||
mo.action_confirm()
|
||||
|
||||
self.bom_2.operation_ids.write({
|
||||
'name': 'Painting',
|
||||
'workcenter_id': self.workcenter_2.id
|
||||
})
|
||||
self.assertTrue(mo.is_outdated_bom)
|
||||
|
||||
mo.action_update_bom()
|
||||
self.assertEqual(self.bom_2.operation_ids.name, mo.workorder_ids.name)
|
||||
self.assertEqual(self.bom_2.operation_ids.workcenter_id, mo.workorder_ids.workcenter_id)
|
||||
|
||||
def test_archive_operations(self):
|
||||
"""Archive the operation in BoM and update the BoM in MO
|
||||
Unarchive the operation which will reflect in BoM and MO"""
|
||||
|
||||
mo_form = Form(self.env['mrp.production'].with_user(self.user_mrp_user))
|
||||
|
||||
mo_form.product_id = self.product_7_1
|
||||
mo_form.product_qty = 1.0
|
||||
mo_form.bom_id = self.bom_2
|
||||
mo_order = mo_form.save()
|
||||
mo_order.action_confirm()
|
||||
|
||||
operation_ids = self.bom_2.operation_ids.ids
|
||||
self.bom_2.operation_ids.action_archive()
|
||||
self.assertTrue(mo_order.is_outdated_bom)
|
||||
|
||||
mo_order.action_update_bom()
|
||||
self.assertEqual(len(mo_order.workorder_ids), 0)
|
||||
|
||||
self.env['mrp.routing.workcenter'].browse(operation_ids).action_unarchive()
|
||||
self.assertTrue(mo_order.is_outdated_bom)
|
||||
mo_order.action_update_bom()
|
||||
self.assertEqual(len(mo_order.workorder_ids), 1)
|
||||
|
||||
Reference in New Issue
Block a user