[FIX] stock,mrp: change procure method at cancellation

Usecase : sell a mto/manufacture product. Confirm the sale order.
Cancel the delivery and the production then
duplicate the delivery.
    - if the delivery was cancelled before the production, another
    production is created.
    - if the delivery was cancelled after the production, no other
    production is created.

In the second case, the production cancellation will reset the procure
method of the delivery. The duplication will not trigger the mto
procurement.

This commit will override the procure method of each cancelled moves and
set it to `make_to_stock'. This way, we have the same behavior independently of the flow.

Task : 2212125

closes odoo/odoo#48366

Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>
This commit is contained in:
William Henrotin
2020-03-26 13:00:26 +00:00
parent a6d38439d5
commit b6c629922d
2 changed files with 115 additions and 2 deletions
+108
View File
@@ -1539,3 +1539,111 @@ class TestSaleMrpFlow(AccountTestCommon):
mo = self.env['mrp.production'].search([('product_id', '=', finished_product.id)])
self.assertTrue(mo, 'Manufacturing order created.')
def test_cancel_flow_1(self):
""" Sell a MTO/manufacture product.
Cancel the delivery and the production order. Then duplicate
the delivery. Another production order should be created."""
route_manufacture = self.warehouse.manufacture_pull_id.route_id.id
route_mto = self.warehouse.mto_pull_id.route_id.id
self.uom_unit = self.env.ref('uom.product_uom_unit')
# Create finished product
finished_product = self.env['product.product'].create({
'name': 'Geyser',
'type': 'product',
'route_ids': [(4, route_mto), (4, route_manufacture)],
})
product_raw = self.env['product.product'].create({
'name': 'raw Geyser',
'type': 'product',
})
# Create bom for finish product
bom = self.env['mrp.bom'].create({
'product_id': finished_product.id,
'product_tmpl_id': finished_product.product_tmpl_id.id,
'product_uom_id': self.env.ref('uom.product_uom_unit').id,
'product_qty': 1.0,
'type': 'normal',
'bom_line_ids': [(5, 0), (0, 0, {'product_id': product_raw.id})]
})
# Create sale order
sale_form = Form(self.env['sale.order'])
sale_form.partner_id = self.env['res.partner'].create({'name': 'My Test Partner'})
with sale_form.order_line.new() as line:
line.name = finished_product.name
line.product_id = finished_product
line.product_uom_qty = 1.0
line.product_uom = self.uom_unit
line.price_unit = 10.0
sale_order = sale_form.save()
sale_order.action_confirm()
mo = self.env['mrp.production'].search([('product_id', '=', finished_product.id)])
delivery = sale_order.picking_ids
delivery.action_cancel()
mo.action_cancel()
copied_delivery = delivery.copy()
copied_delivery.action_confirm()
mos = self.env['mrp.production'].search([('product_id', '=', finished_product.id)])
self.assertEqual(len(mos), 1)
self.assertEqual(mos.state, 'cancel')
def test_cancel_flow_2(self):
""" Sell a MTO/manufacture product.
Cancel the production order and the delivery. Then duplicate
the delivery. Another production order should be created."""
route_manufacture = self.warehouse.manufacture_pull_id.route_id.id
route_mto = self.warehouse.mto_pull_id.route_id.id
self.uom_unit = self.env.ref('uom.product_uom_unit')
# Create finished product
finished_product = self.env['product.product'].create({
'name': 'Geyser',
'type': 'product',
'route_ids': [(4, route_mto), (4, route_manufacture)],
})
product_raw = self.env['product.product'].create({
'name': 'raw Geyser',
'type': 'product',
})
# Create bom for finish product
bom = self.env['mrp.bom'].create({
'product_id': finished_product.id,
'product_tmpl_id': finished_product.product_tmpl_id.id,
'product_uom_id': self.env.ref('uom.product_uom_unit').id,
'product_qty': 1.0,
'type': 'normal',
'bom_line_ids': [(5, 0), (0, 0, {'product_id': product_raw.id})]
})
# Create sale order
sale_form = Form(self.env['sale.order'])
sale_form.partner_id = self.env['res.partner'].create({'name': 'My Test Partner'})
with sale_form.order_line.new() as line:
line.name = finished_product.name
line.product_id = finished_product
line.product_uom_qty = 1.0
line.product_uom = self.uom_unit
line.price_unit = 10.0
sale_order = sale_form.save()
sale_order.action_confirm()
mo = self.env['mrp.production'].search([('product_id', '=', finished_product.id)])
delivery = sale_order.picking_ids
mo.action_cancel()
delivery.action_cancel()
copied_delivery = delivery.copy()
copied_delivery.action_confirm()
mos = self.env['mrp.production'].search([('product_id', '=', finished_product.id)])
self.assertEqual(len(mos), 1)
self.assertEqual(mos.state, 'cancel')
+7 -2
View File
@@ -541,7 +541,7 @@ class StockMove(models.Model):
self.ensure_one()
picking_type_id = self.picking_type_id or self.picking_id.picking_type_id
# If "show suggestions" is not checked on the picking type, we have to filter out the
# reserved move lines. We do this by displaying `move_line_nosuggest_ids`. We use
# different views to display one field or another so that the webclient doesn't have to
@@ -1291,7 +1291,12 @@ class StockMove(models.Model):
if all(state in ('done', 'cancel') for state in siblings_states):
move.move_dest_ids.write({'procure_method': 'make_to_stock'})
move.move_dest_ids.write({'move_orig_ids': [(3, move.id, 0)]})
self.write({'state': 'cancel', 'move_orig_ids': [(5, 0, 0)], 'delay_alert_date': False})
self.write({
'state': 'cancel',
'move_orig_ids': [(5, 0, 0)],
'delay_alert_date': False,
'procure_method': 'make_to_stock',
})
return True
def _prepare_extra_move_vals(self, qty):