From c5728f58b504707c72da10f36bb7fdbf26d91c60 Mon Sep 17 00:00:00 2001 From: Ethan Vincent Date: Thu, 1 Feb 2024 13:04:21 +0100 Subject: [PATCH] [FIX] repair: make mltpl ROs when serial tracking **Current behavior:** Confirming a sale order containing an order line associated with >1 products which are tracked via serial number creates a single repair order. **Expected behavior:** A repair order for each individual product in the line is created. **Steps to reproduce:** 0. Create a storable product which is tracked via serial number and has create_repair set to True. Update on hand stock so there are at least two available and assign them each a serial number. 1. Make a new sale order with one order line for that product with the product_uom_quantity equal to the quantity created in step 0 2. Confirm the order and open the newly created repair order 3. Select a serial number for the repair order, start the repair, then end the repair to raise the exception **Cause of the issue:** Multiple products will be associated with one serial number. In stock_quant.py, the check_quantity() method checks the quantity of product_ids associated with a particular lot_id and location_id. In this instance, quantity will now be >1 which results in the ValidationError exception. **Fix:** Make a discrete repair order for each product in the order line when the product has serial tracking. This is more logical than asking a user to select one serial number for many products. opw-3688072 closes odoo/odoo#151041 Signed-off-by: Quentin Wolfs (quwo) --- addons/repair/models/sale_order.py | 20 ++++++++++++++++---- addons/repair/tests/test_repair.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/addons/repair/models/sale_order.py b/addons/repair/models/sale_order.py index 274b2d934ab..ef14078e0fe 100644 --- a/addons/repair/models/sale_order.py +++ b/addons/repair/models/sale_order.py @@ -93,20 +93,32 @@ class SaleOrderLine(models.Model): continue if not line.product_template_id.sudo().create_repair or line.move_ids.sudo().repair_id or float_compare(line.product_uom_qty, 0, precision_rounding=line.product_uom.rounding) <= 0: continue + order = line.order_id - new_repair_vals.append({ + default_repair_vals = { 'state': 'confirmed', 'partner_id': order.partner_id.id, 'sale_order_id': order.id, 'sale_order_line_id': line.id, 'picking_type_id': order.warehouse_id.repair_type_id.id, - }) - if line.product_template_id.type in ('consu', 'product'): - new_repair_vals[-1].update({ + } + if line.product_id.tracking == 'serial': + vals = { + **default_repair_vals, + 'product_id': line.product_id.id, + 'product_qty': 1, + 'product_uom': line.product_uom.id, + } + new_repair_vals.extend([vals] * int(line.product_uom_qty)) + elif line.product_id.type in ('consu', 'product'): + new_repair_vals.append({ + **default_repair_vals, 'product_id': line.product_id.id, 'product_qty': line.product_uom_qty, 'product_uom': line.product_uom.id, }) + else: + new_repair_vals.append(default_repair_vals.copy()) if new_repair_vals: self.env['repair.order'].sudo().create(new_repair_vals) diff --git a/addons/repair/tests/test_repair.py b/addons/repair/tests/test_repair.py index 82e65d2826c..c0500e266c4 100644 --- a/addons/repair/tests/test_repair.py +++ b/addons/repair/tests/test_repair.py @@ -3,6 +3,7 @@ from odoo.exceptions import UserError from odoo.tests import tagged, common, Form from odoo.tools import float_compare, float_is_zero +from odoo import Command @tagged('post_install', '-at_install') @@ -623,3 +624,31 @@ class TestRepair(common.TransactionCase): repair_order.move_ids.quantity = 1 repair_order.action_repair_end() self.assertEqual(repair_order.state, 'done') + + def test_repair_multi_unit_order_with_serial_tracking(self): + """ + Test that a sale order with a single order line with quantity > 1 for a product that creates a repair order and + is tracked via serial number creates multiple repair orders rather than grouping the line into a single RO + """ + product_a = self.env['product.product'].create({ + 'name': 'productA', + 'detailed_type': 'product', + 'tracking': 'serial', + 'create_repair': True, + }) + + sale_order = self.env['sale.order'].create({ + 'partner_id': self.res_partner_1.id, + 'order_line': [Command.create({ + 'product_id': product_a.id, + 'product_uom_qty': 3.0, + })] + }) + sale_order.action_confirm() + + repair_orders = sale_order.repair_order_ids + self.assertRecordValues(repair_orders, [ + {'product_id': product_a.id, 'product_qty': 1.0}, + {'product_id': product_a.id, 'product_qty': 1.0}, + {'product_id': product_a.id, 'product_qty': 1.0}, + ])