[FIX] mrp: validate a MO with manual consumption
Steps to reproduce the bug:
- Create a storable produce P1 with BoM:
- select any component, qty: 1 unit
- Create a MO to produce one unit of P1
- Confirm the MO
- Update the qty of the component to 2
- Validate the MO
Problem:
The quantity of the component is overwritten and reset to 1
Because, when the new qty of the component is set, only the
“manual_consumption” field is updated to “True” thanks to their compute:
https://github.com/odoo/odoo/blob/17.0/addons/mrp/models/stock_move.py#L138-L145
But the field ‘picked’, is not updated
So when we check if we have to set a quantity, the condition is false
and the quantity is reset to the original value:
https://github.com/odoo/odoo/blob/26193fdb707a631d498cbc37d68c08497e32a31d/addons/mrp/models/mrp_production.py#L1201-L1202
opw-3616628
closes odoo/odoo#145157
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
This commit is contained in:
@@ -287,6 +287,8 @@ class StockMove(models.Model):
|
||||
def write(self, vals):
|
||||
if self.env.context.get('force_manual_consumption'):
|
||||
vals['manual_consumption'] = True
|
||||
if vals.get('manual_consumption'):
|
||||
self.picked = True
|
||||
if 'product_uom_qty' in vals and 'move_line_ids' in vals:
|
||||
# first update lines then product_uom_qty as the later will unreserve
|
||||
# so possibly unlink lines
|
||||
|
||||
@@ -23,7 +23,7 @@ export class MrpConsumed extends FloatField {
|
||||
}
|
||||
|
||||
onInput(ev) {
|
||||
return this.props.record.update({ manual_consumption: true });
|
||||
return this.props.record.update({ manual_consumption: true, picked: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,3 +70,37 @@ registry.category("web_tour.tours").add('test_mrp_manual_consumption', {
|
||||
},
|
||||
...stepUtils.saveForm(),
|
||||
]});
|
||||
|
||||
registry.category("web_tour.tours").add('test_mrp_manual_consumption_02', {
|
||||
test: true,
|
||||
steps: () => [
|
||||
{
|
||||
trigger: 'div[name=move_raw_ids] td[name="quantity"]:last:contains("0.00")',
|
||||
run: () => {},
|
||||
},
|
||||
{
|
||||
trigger: 'div[name=move_raw_ids] td[name="quantity"]:last',
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
trigger: 'div[name="quantity"] input',
|
||||
run: 'text 16.0'
|
||||
},
|
||||
{
|
||||
content: "Click Pager",
|
||||
trigger: ".o_pager_value:first()",
|
||||
},
|
||||
{
|
||||
trigger: "input[id='qty_producing_0']",
|
||||
run: 'text 8.0',
|
||||
},
|
||||
{
|
||||
content: "Click Pager",
|
||||
trigger: ".o_pager_value:first()",
|
||||
},
|
||||
{
|
||||
trigger: 'div[name=move_raw_ids] td[name="quantity"]:last:contains("16.00")',
|
||||
run: () => {},
|
||||
},
|
||||
...stepUtils.saveForm(),
|
||||
]});
|
||||
|
||||
@@ -86,6 +86,50 @@ class TestTourManualConsumption(HttpCase):
|
||||
self.assertEqual(move_sn.manual_consumption, True)
|
||||
self.assertEqual(move_lot.manual_consumption, True)
|
||||
|
||||
def test_mrp_manual_consumption_02(self):
|
||||
"""
|
||||
test that when a new quantity is manually set for a component,
|
||||
and the MO is marked as done, the component quantity is not overwritten.
|
||||
"""
|
||||
Product = self.env['product.product']
|
||||
product_finish = Product.create({
|
||||
'name': 'finish',
|
||||
'type': 'product',
|
||||
'tracking': 'none',})
|
||||
product_nt = Product.create({
|
||||
'name': 'No tracking',
|
||||
'type': 'product',
|
||||
'tracking': 'none',})
|
||||
bom = self.env['mrp.bom'].create({
|
||||
'product_id': product_finish.id,
|
||||
'product_tmpl_id': product_finish.product_tmpl_id.id,
|
||||
'product_qty': 1,
|
||||
'type': 'normal',
|
||||
'bom_line_ids': [
|
||||
(0, 0, {'product_id': product_nt.id, 'product_qty': 1}),
|
||||
],
|
||||
})
|
||||
|
||||
mo_form = Form(self.env['mrp.production'])
|
||||
mo_form.product_id = product_finish
|
||||
mo_form.bom_id = bom
|
||||
mo_form.product_qty = 10
|
||||
mo = mo_form.save()
|
||||
mo.action_confirm()
|
||||
|
||||
self.assertEqual(mo.state, 'confirmed')
|
||||
move_nt = mo.move_raw_ids
|
||||
self.assertEqual(move_nt.manual_consumption, False)
|
||||
self.assertEqual(move_nt.quantity, 0)
|
||||
self.assertFalse(move_nt.picked)
|
||||
|
||||
action_id = self.env.ref('mrp.menu_mrp_production_action').action
|
||||
url = "/web#model=mrp.production&view_type=form&action=%s&id=%s" % (str(action_id.id), str(mo.id))
|
||||
self.start_tour(url, "test_mrp_manual_consumption_02", login="admin", timeout=100)
|
||||
|
||||
self.assertEqual(move_nt.manual_consumption, True)
|
||||
self.assertEqual(move_nt.picked, True)
|
||||
self.assertEqual(move_nt.quantity, 16.0)
|
||||
|
||||
class TestManualConsumption(TestMrpCommon):
|
||||
@classmethod
|
||||
|
||||
Reference in New Issue
Block a user