[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:
Djamel Touati
2023-12-06 14:07:56 +00:00
parent 392e6d2369
commit fe508c6b2c
4 changed files with 81 additions and 1 deletions
+2
View File
@@ -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