[FIX] mrp : replacing tracked part in repair fails uniqueness

Issue: When replacing a tracked part while doing a repair, we
are changing the tracking number, but when checking for uniqueness,
we don't take that change into consideration

Steps to reproduce :
 1) Manufacture product A with SN "A1" out of product B with SN "B2"
 2) Make Repair Order for "A1" to replace "B2" with Product B (SN "B1").
 3) Create Manufacturing Order product A (A2), select product B with SN
  "B2" as one of the components.
 4) Mark as done
 -> Bug : "The serial number <B2> used for component <B> has already
 been consumed".

Why is that a bug:
 When checking for uniqueness we should take into consideration the
 parts being replaced

opw-2625687

closes odoo/odoo#78407

X-original-commit: 79c673f9d15185be540dd535d7ebe10c8f138bf1
Signed-off-by: William Henrotin <Whenrow@users.noreply.github.com>
This commit is contained in:
Nathan Marotte (nama)
2021-10-18 11:36:58 +00:00
committed by Adrien Widart
parent 433f0c15bf
commit 04bb7005b7
3 changed files with 92 additions and 2 deletions
+14 -2
View File
@@ -1804,7 +1804,13 @@ class MrpProduction(models.Model):
duplicates_unbuild = self.env['stock.move.line'].search_count(domain_unbuild + [
('move_id.unbuild_id', '!=', False)
])
if not (duplicates_unbuild and duplicates - duplicates_unbuild == 0):
removed = self.env['stock.move.line'].search_count([
('lot_id', '=', move_line.lot_id.id),
('state', '=', 'done'),
('location_dest_id.scrap_location', '=', True)
])
# Either removed or unbuild
if not ((duplicates_unbuild or removed) and duplicates - duplicates_unbuild - removed == 0):
raise UserError(message)
# Check presence of same sn in current production
duplicates = co_prod_move_lines.filtered(lambda ml: ml.qty_done and ml.lot_id == move_line.lot_id) - move_line
@@ -1840,7 +1846,13 @@ class MrpProduction(models.Model):
duplicates_unbuild = self.env['stock.move.line'].search_count(domain_unbuild + [
('move_id.unbuild_id', '!=', False)
])
if not (duplicates_unbuild and duplicates - duplicates_unbuild == 0):
removed = self.env['stock.move.line'].search_count([
('lot_id', '=', move_line.lot_id.id),
('state', '=', 'done'),
('location_dest_id.scrap_location', '=', True)
])
# Either removed or unbuild
if not ((duplicates_unbuild or removed) and duplicates - duplicates_unbuild - removed == 0):
raise UserError(message)
# Check presence of same sn in current production
duplicates = co_prod_move_lines.filtered(lambda ml: ml.qty_done and ml.lot_id == move_line.lot_id) - move_line
+4
View File
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_tracability
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.tests import Form, tagged
from odoo.addons.mrp.tests.common import TestMrpCommon
@tagged('post_install', '-at_install')
class TestRepairTraceability(TestMrpCommon):
def test_tracking_repair_production(self):
"""
Test that removing a tracked component with a repair does not block the flow of using that component in another
bom
"""
product_to_repair = self.env['product.product'].create({
'name': 'product first serial to act repair',
'tracking': 'serial',
})
ptrepair_lot = self.env['stock.production.lot'].create({
'name': 'A1',
'product_id': product_to_repair.id,
'company_id': self.env.user.company_id.id
})
product_to_remove = self.env['product.product'].create({
'name': 'other first serial to remove with repair',
'tracking': 'serial',
})
ptremove_lot = self.env['stock.production.lot'].create({
'name': 'B2',
'product_id': product_to_remove.id,
'company_id': self.env.user.company_id.id
})
# Create a manufacturing order with product (with SN A1)
mo_form = Form(self.env['mrp.production'])
mo_form.product_id = product_to_repair
with mo_form.move_raw_ids.new() as move:
move.product_id = product_to_remove
move.product_uom_qty = 1
move.move_line_ids.lot_id = ptremove_lot # Set component serial to B2
mo = mo_form.save()
mo.action_confirm()
# Set serial to A1
mo.lot_producing_id = ptrepair_lot
mo.button_mark_done()
with Form(self.env['repair.order']) as ro_form:
ro_form.product_id = product_to_repair
ro_form.lot_id = ptrepair_lot # Repair product Serial A1
with ro_form.operations.new() as operation:
operation.type = 'remove'
operation.product_id = product_to_remove
operation.lot_id = ptremove_lot # Remove product Serial B2 from the product
ro = ro_form.save()
ro.action_validate()
ro.action_repair_start()
ro.action_repair_end()
# Create a manufacturing order with product (with SN A2)
mo2_form = Form(self.env['mrp.production'])
mo2_form.product_id = product_to_repair
with mo2_form.move_raw_ids.new() as move:
move.product_id = product_to_remove
move.product_uom_qty = 1
move.move_line_ids.lot_id = ptremove_lot # Set component serial to B2 again, it is possible
mo2 = mo2_form.save()
mo2.action_confirm()
# Set serial to A2
mo2.lot_producing_id = self.env['stock.production.lot'].create({
'name': 'A2',
'product_id': product_to_repair.id,
'company_id': self.env.user.company_id.id
})
# We are not forbidden to use that serial number, so nothing raised here
mo2.button_mark_done()