[FIX] mrp_subcontracting: extra move correctly handle.

Usecase to reproduce:
- Create a receipt of 1 units of a subcontracted product
- Receive 2
- Validate the receipt

-> An extra move for subcontractor of 1 has been validated but a
new move of 2 still in waiting availability and can not be
validated.

It happens due to action_done that will validate existing subcontract
order (with the initial quantity). Then the move is validated and an
extra move is created and merged in the first one. This new merged
move of 2 is then confirmed and validated. That will recreate a
subcontract order of 2 that will not be validated since it was validated
in the picking action_done at the start.

This commit will modify:
- action_done on move in order to validate the subcontract order after
the move validation and the new subcontract order creation too.
- action_confirm in order to create the subcontract order with the
additional quantity and then merge it to the existing moves.
This commit is contained in:
Arnold Moyaux
2019-08-19 14:14:13 +00:00
parent 44507c039e
commit abc8253448
3 changed files with 60 additions and 4 deletions
@@ -22,9 +22,8 @@ class StockMove(models.Model):
return bom
def _action_confirm(self, merge=True, merge_into=False):
res = super(StockMove, self)._action_confirm(merge=merge, merge_into=merge_into)
subcontract_details_per_picking = defaultdict(list)
for move in res:
for move in self:
if not move.picking_id:
continue
if not move.picking_id._is_subcontract():
@@ -38,4 +37,4 @@ class StockMove(models.Model):
subcontract_details_per_picking[move.picking_id].append((move, bom))
for picking, subcontract_details in subcontract_details_per_picking.items():
picking._subcontracted_produce(subcontract_details)
return res
return super(StockMove, self)._action_confirm(merge=merge, merge_into=merge_into)
@@ -53,11 +53,12 @@ class StockPicking(models.Model):
# Action methods
# -------------------------------------------------------------------------
def action_done(self):
res = super(StockPicking, self).action_done()
for picking in self:
subcontracted_productions = picking._get_subcontracted_productions()
for subcontracted_production in subcontracted_productions:
subcontracted_production.button_mark_done()
return super(StockPicking, self).action_done()
return res
def action_view_subcontracted_move_lines(self):
""" Returns a list view with the move lines of the subcontracted products. To find them, we
@@ -408,6 +408,62 @@ class TestSubcontractingFlows(SavepointCase):
self.assertEquals(mo_pick1.bom_id, self.bom)
self.assertEquals(mo_pick2.bom_id, bom2)
def test_flow_5(self):
""" Extra quantity on the move.
"""
# We create a second partner of type subcontractor
main_partner_2 = self.env['res.partner'].create({'name': 'main_partner'})
subcontractor_partner2 = self.env['res.partner'].create({
'name': 'subcontractor_partner',
'type': 'subcontractor',
'parent_id': main_partner_2.id,
})
# We create a different BoM for the same product
comp3 = self.env['product.product'].create({
'name': 'Component3',
'type': 'product',
'categ_id': self.env.ref('product.product_category_all').id,
})
bom_form = Form(self.env['mrp.bom'])
bom_form.type = 'subcontract'
bom_form.product_tmpl_id = self.finished.product_tmpl_id
with bom_form.bom_line_ids.new() as bom_line:
bom_line.product_id = self.comp1
bom_line.product_qty = 1
with bom_form.bom_line_ids.new() as bom_line:
bom_line.product_id = comp3
bom_line.product_qty = 2
bom2 = bom_form.save()
# We assign the second BoM to the new partner
self.bom.write({'subcontractor_ids': [(4, self.subcontractor_partner1.id, None)]})
bom2.write({'subcontractor_ids': [(4, subcontractor_partner2.id, None)]})
# Create a receipt picking from the subcontractor1
picking_form = Form(self.env['stock.picking'])
picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
picking_form.partner_id = subcontractor_partner2
with picking_form.move_ids_without_package.new() as move:
move.product_id = self.finished
move.product_uom_qty = 1
picking_receipt = picking_form.save()
picking_receipt.action_confirm()
picking_receipt.move_lines.quantity_done = 3.0
picking_receipt.action_done()
mo = picking_receipt._get_subcontracted_productions()
move_comp1 = mo.move_raw_ids.filtered(lambda m: m.product_id == self.comp1)
move_comp3 = mo.move_raw_ids.filtered(lambda m: m.product_id == comp3)
self.assertEqual(sum(move_comp1.mapped('product_uom_qty')), 3.0)
self.assertEqual(sum(move_comp3.mapped('product_uom_qty')), 6.0)
self.assertEqual(sum(move_comp1.mapped('quantity_done')), 3.0)
self.assertEqual(sum(move_comp3.mapped('quantity_done')), 6.0)
move_finished = mo.move_finished_ids
self.assertEqual(sum(move_finished.mapped('product_uom_qty')), 3.0)
self.assertEqual(sum(move_finished.mapped('quantity_done')), 3.0)
class TestSubcontractingTracking(TransactionCase):
def setUp(self):