[IMP] mrp: can delete active MO

Before this commit, you can delete only canceled MO.
Now, if you want to delete a non-canceled MO, it will try to cancel it
then to unlink it.

Task #1969034

closes odoo/odoo#34026

Signed-off-by: Arnold Moyaux <amoyaux@users.noreply.github.com>
This commit is contained in:
svs-odoo
2019-07-31 12:37:39 +00:00
parent 3d4c0f92af
commit b499c3308c
5 changed files with 51 additions and 6 deletions
+11 -2
View File
@@ -468,8 +468,17 @@ class MrpProduction(models.Model):
return super(MrpProduction, self).create(values)
def unlink(self):
if any(production.state != 'cancel' for production in self):
raise UserError(_('Cannot delete a manufacturing order not in cancel state'))
if any(production.state == 'done' for production in self):
raise UserError(_('Cannot delete a manufacturing order in done state.'))
self.action_cancel()
not_cancel = self.filtered(lambda m: m.state != 'cancel')
if not_cancel:
productions_name = ', '.join([prod.display_name for prod in not_cancel])
raise UserError(_('%s cannot be deleted. Try to cancel them before.') % productions_name)
workorders_to_delete = self.workorder_ids.filtered(lambda wo: wo.state != 'done')
if workorders_to_delete:
workorders_to_delete.unlink()
return super(MrpProduction, self).unlink()
def action_toggle_is_locked(self):
+9 -2
View File
@@ -202,6 +202,11 @@ class MrpWorkorder(models.Model):
def name_get(self):
return [(wo.id, "%s - %s - %s" % (wo.production_id.name, wo.product_id.name, wo.name)) for wo in self]
def unlink(self):
# Removes references to workorder to avoid Validation Error
(self.mapped('move_raw_ids') | self.mapped('move_finished_ids')).write({'workorder_id': False})
return super(MrpWorkorder, self).unlink()
@api.depends('production_id.product_qty', 'qty_produced')
def _compute_is_produced(self):
for order in self:
@@ -563,8 +568,10 @@ class MrpWorkorderLine(models.Model):
_inherit = ["mrp.abstract.workorder.line"]
_description = "Workorder move line"
raw_workorder_id = fields.Many2one('mrp.workorder', 'Component for Workorder')
finished_workorder_id = fields.Many2one('mrp.workorder', 'Finished Product for Workorder')
raw_workorder_id = fields.Many2one('mrp.workorder', 'Component for Workorder',
ondelete='cascade')
finished_workorder_id = fields.Many2one('mrp.workorder', 'Finished Product for Workorder',
ondelete='cascade')
@api.model
def _get_raw_workorder_inverse_name(self):
+27
View File
@@ -115,3 +115,30 @@ class TestMrpCancelMO(TestMrpCommon):
"Due to 'post_inventory', a move finished must stay in done state")
self.assertEqual(manufacturing_order.move_finished_ids[1].state, 'cancel',
"The other move finished is cancelled like its MO.")
def test_unlink_mo(self):
""" Try to unlink a Manufacturing Order, and check it's possible or not
depending of the MO state (must be in cancel state to be unlinked, but
the unlink method will try to cancel MO before unlink them).
"""
# Case #1: Create MO, do nothing and try to unlink it (can be deleted)
manufacturing_order = self.generate_mo()[0]
self.assertEqual(manufacturing_order.exists().state, 'confirmed')
manufacturing_order.unlink()
# Check the MO is deleted.
self.assertEqual(manufacturing_order.exists().state, False)
# Case #2: Create MO, make and post some production, then try to unlink
# it (cannot be deleted)
manufacturing_order = self.generate_mo()[0]
# Produce some quantity (not all to avoid to done the MO when post inventory)
produce_form = Form(self.env['mrp.product.produce'].with_context(active_id=manufacturing_order.id))
produce_form.qty_producing = 2
produce = produce_form.save()
produce.do_produce()
# Post Inventory
manufacturing_order.post_inventory()
# Unlink the MO must raises an UserError since it cannot be really cancelled
self.assertEqual(manufacturing_order.exists().state, 'progress')
with self.assertRaises(UserError):
manufacturing_order.unlink()
+2 -2
View File
@@ -10,8 +10,8 @@ class ChangeProductionQty(models.TransientModel):
_name = 'change.production.qty'
_description = 'Change Production Qty'
# TDE FIXME: add production_id field
mo_id = fields.Many2one('mrp.production', 'Manufacturing Order', required=True)
mo_id = fields.Many2one('mrp.production', 'Manufacturing Order',
required=True, ondelete='cascade')
product_qty = fields.Float(
'Quantity To Produce',
digits='Product Unit of Measure', required=True)
+2
View File
@@ -50,6 +50,8 @@ class MrpProductProduce(models.TransientModel):
'raw_product_produce_id', string='Components')
finished_workorder_line_ids = fields.One2many('mrp.product.produce.line',
'finished_product_produce_id', string='By-products')
production_id = fields.Many2one('mrp.production', 'Manufacturing Order',
required=True, ondelete='cascade')
@api.depends('qty_producing')
def _compute_pending_production(self):