[FIX] mrp: allow using an unbuilt serial number in manufacturing order

Steps to reproduce the bug:
- Create a storable product “P1”
    - Tracking: by serial number
    - BOM:
        - Component: C1

- Create a storable product “P2”
    - BOM:
        - Component: P1

- Create a MO to produce one unit of P1:
    - serial number: SN1
    - Confirm and mark as done

- Unbuild the manufactured product
- Manufacture the same product using the same serial number again

- Create a new MO to produce one unit of “P2”:
    - Component P1 → select SN1
    - Try to confirm and validate the MO

Problem:
Get User Error: The serial number “SN1” used for component “P1”
has already been consumed

We do a search in the `stock.move.line` to find if the SN has already
been used in a previous MO, but there is no specific condition to get
only those used in an MO so the unbuild order is in the same condition
and therefore the SN is considered as it has already been used
opw-2883450

closes odoo/odoo#95935

X-original-commit: 5ac7f4d6fa5551ba7c6da49a52edf0a7df2d0745
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: Djamel Touati (otd) <otd@odoo.com>
This commit is contained in:
Touati Djamel (otd)
2022-07-14 11:42:57 +02:00
parent f7ba6ce258
commit a4c00c071f
2 changed files with 81 additions and 0 deletions
+1
View File
@@ -2108,6 +2108,7 @@ class MrpProduction(models.Model):
('qty_done', '=', 1),
('state', '=', 'done'),
('location_dest_id.usage', '=', 'production'),
('production_id', '!=', False),
])
if duplicates:
# Maybe some move lines have been compensated by unbuild
+80
View File
@@ -752,3 +752,83 @@ class TestUnbuild(TestMrpCommon):
warehouse = self.env.ref('stock.warehouse0')
self.assertEqual(order.location_id, warehouse.lot_stock_id)
self.assertEqual(order.location_dest_id, warehouse.lot_stock_id)
def test_use_unbuilt_sn_in_mo(self):
"""
use an unbuilt serial number in manufacturing order:
produce a tracked product, unbuild it and then use it as a component with the same SN in a mo.
"""
product_1 = self.env['product.product'].create({
'name': 'Product tracked by sn',
'type': 'product',
'tracking': 'serial',
})
product_1_sn = self.env['stock.lot'].create({
'name': 'sn1',
'product_id': product_1.id,
'company_id': self.env.company.id
})
component = self.env['product.product'].create({
'name': 'Product component',
'type': 'product',
})
bom_1 = self.env['mrp.bom'].create({
'product_id': product_1.id,
'product_tmpl_id': product_1.product_tmpl_id.id,
'product_uom_id': self.env.ref('uom.product_uom_unit').id,
'product_qty': 1.0,
'type': 'normal',
'bom_line_ids': [
(0, 0, {'product_id': component.id, 'product_qty': 1}),
],
})
product_2 = self.env['product.product'].create({
'name': 'finished Product',
'type': 'product',
})
self.env['mrp.bom'].create({
'product_id': product_2.id,
'product_tmpl_id': product_2.product_tmpl_id.id,
'product_uom_id': self.env.ref('uom.product_uom_unit').id,
'product_qty': 1.0,
'type': 'normal',
'bom_line_ids': [
(0, 0, {'product_id': product_1.id, 'product_qty': 1}),
],
})
# mo1
mo_form = Form(self.env['mrp.production'])
mo_form.product_id = product_1
mo_form.bom_id = bom_1
mo_form.product_qty = 1.0
mo = mo_form.save()
mo.action_confirm()
mo_form = Form(mo)
mo_form.qty_producing = 1.0
mo_form.lot_producing_id = product_1_sn
mo = mo_form.save()
mo.button_mark_done()
self.assertEqual(mo.state, 'done', "Production order should be in done state.")
#unbuild order
unbuild_form = Form(self.env['mrp.unbuild'])
unbuild_form.mo_id = mo
unbuild_form.lot_id = product_1_sn
unbuild_form.save().action_unbuild()
#mo2
mo_form = Form(self.env['mrp.production'])
mo_form.product_id = product_2
mo2 = mo_form.save()
mo2.action_confirm()
details_operation_form = Form(mo2.move_raw_ids[0], view=self.env.ref('stock.view_stock_move_operations'))
with details_operation_form.move_line_ids.new() as ml:
ml.lot_id = product_1_sn
ml.qty_done = 1
details_operation_form.save()
mo_form = Form(mo2)
mo_form.qty_producing = 1
mo2 = mo_form.save()
mo2.button_mark_done()
self.assertEqual(mo2.state, 'done', "Production order should be in done state.")