[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:
@@ -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()
|
||||
|
||||
@@ -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."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user