[FIX] mrp: modify linked move remove quantity done

- create product comp1
- create product finished1
- created bom: 1 comp1 for 1 finished1
- activate PBM
- 100 units of comp1 in stock
- create an MO for 5
- on the pbm, deliver 3 and no backorder
- on the mo, check availability, produce 3
- on the pbm, unlock, change delivered qty from 3 to 5

On the mo, the raw move is reserved to 5 units but the 3 units
used in the first produce are removed.

It happens because editing the quantity or initial on a move
will try to reserve the next moves. In order to reserved,
_do_unreserve will destroy the stock.move.line and _action_assign
(call just after) will recreate them in order to regenerate the
reservation. In the process the qty_done on the stock.move.line will
be loss. We want to avoid this behavior in mrp so we call
_decrease_reserved_quantity from mrp that will keep stock.move.line
with quantity done.

opw-2206472

closes odoo/odoo#47617

X-original-commit: c6cf5841015c87163f8ea16dd75232e5cb855df6
Signed-off-by: Arnold Moyaux <amoyaux@users.noreply.github.com>
This commit is contained in:
Arnold Moyaux
2020-03-13 15:25:19 +00:00
parent 522c2c6fab
commit 343e46d97f
2 changed files with 66 additions and 1 deletions
-1
View File
@@ -685,7 +685,6 @@ class MrpProduction(models.Model):
move = self.move_raw_ids.filtered(lambda x: x.bom_line_id.id == bom_line.id and x.state not in ('done', 'cancel'))
if move:
old_qty = move[0].product_uom_qty
remaining_qty = move[0].raw_material_production_id.product_qty - move[0].raw_material_production_id.qty_produced
if quantity > 0:
move[0].write({'product_uom_qty': quantity})
move[0]._action_assign()
+66
View File
@@ -137,6 +137,72 @@ class TestProcurement(TestMrpCommon):
production_product_4 = production_form.save()
production_product_4.action_confirm()
def test_procurement_3(self):
warehouse = self.env['stock.warehouse'].search([], limit=1)
warehouse.write({'reception_steps': 'three_steps'})
self.env['stock.location']._parent_store_compute()
warehouse.reception_route_id.rule_ids.filtered(
lambda p: p.location_src_id == warehouse.wh_input_stock_loc_id and
p.location_id == warehouse.wh_qc_stock_loc_id).write({
'procure_method': 'make_to_stock'
})
finished_product = self.env['product.product'].create({
'name': 'Finished Product',
'type': 'product',
})
component = self.env['product.product'].create({
'name': 'Component',
'type': 'product',
'route_ids': [(4, warehouse.mto_pull_id.route_id.id)]
})
self.env['stock.quant']._update_available_quantity(component, warehouse.wh_input_stock_loc_id, 100)
bom = self.env['mrp.bom'].create({
'product_id': finished_product.id,
'product_tmpl_id': finished_product.product_tmpl_id.id,
'product_uom_id': self.uom_unit.id,
'product_qty': 1.0,
'type': 'normal',
'bom_line_ids': [
(0, 0, {'product_id': component.id, 'product_qty': 1.0})
]})
mo_form = Form(self.env['mrp.production'])
mo_form.product_id = finished_product
mo_form.bom_id = bom
mo_form.product_qty = 5
mo_form.product_uom_id = finished_product.uom_id
mo_form.location_src_id = warehouse.lot_stock_id
mo = mo_form.save()
mo.action_confirm()
pickings = self.env['stock.picking'].search([('product_id', '=', component.id)])
self.assertEqual(len(pickings), 2.0)
picking_input_to_qc = pickings.filtered(lambda p: p.location_id == warehouse.wh_input_stock_loc_id)
picking_qc_to_stock = pickings - picking_input_to_qc
self.assertTrue(picking_input_to_qc)
self.assertTrue(picking_qc_to_stock)
picking_input_to_qc.action_assign()
self.assertEqual(picking_input_to_qc.state, 'assigned')
picking_input_to_qc.move_line_ids.write({'qty_done': 5.0})
picking_input_to_qc._action_done()
picking_qc_to_stock.action_assign()
self.assertEqual(picking_qc_to_stock.state, 'assigned')
picking_qc_to_stock.move_line_ids.write({'qty_done': 3.0})
picking_qc_to_stock.with_context(skip_backorder=True, picking_ids_not_to_backorder=picking_qc_to_stock.ids).button_validate()
self.assertEqual(picking_qc_to_stock.state, 'done')
mo.action_assign()
self.assertEqual(mo.move_raw_ids.reserved_availability, 3.0)
produce_form = Form(self.env['mrp.product.produce'].with_context({
'active_id': mo.id,
'active_ids': [mo.id],
}))
produce_form.qty_producing = 3.0
produce_wizard = produce_form.save()
produce_wizard.do_produce()
self.assertEqual(mo.move_raw_ids.quantity_done, 3.0)
picking_qc_to_stock.move_line_ids.qty_done = 5.0
self.assertEqual(mo.move_raw_ids.reserved_availability, 5.0)
self.assertEqual(mo.move_raw_ids.quantity_done, 3.0)
def test_date_propagation(self):
""" Check propagation of shedule date for manufaturing route."""