From 3c5f311f8444cd7e0ecbf4eb6075b83d4af855b8 Mon Sep 17 00:00:00 2001 From: AaronHForgeFlow Date: Mon, 6 May 2024 18:39:40 +0200 Subject: [PATCH] [FIX] rma_scrap: minor lint error [FIX] rma_scrap: ensure scrapping serials will scrap just 1 unit & ensure scrapped quantity is always positve [FIX] rma_scrap: scrap quantity should consider the quantity in the stock moves not the product_uom_qty [IMP] rma_scrap: test serial case --- rma_scrap/models/rma_operation.py | 3 +- rma_scrap/models/rma_order_line.py | 2 +- rma_scrap/tests/test_rma_scrap.py | 93 ++++++++++++++++++++++++++++- rma_scrap/wizards/rma_make_scrap.py | 8 ++- 4 files changed, 101 insertions(+), 5 deletions(-) diff --git a/rma_scrap/models/rma_operation.py b/rma_scrap/models/rma_operation.py index 3e070e4d1..47f5e745e 100644 --- a/rma_scrap/models/rma_operation.py +++ b/rma_scrap/models/rma_operation.py @@ -19,5 +19,6 @@ class RmaOperation(models.Model): scrap_location_id = fields.Many2one( comodel_name="stock.location", string="Scrap Destination Location", - domain="[('scrap_location', '=', True), ('company_id', 'in', [company_id, False])]", + domain="[('scrap_location', '=', True)," + "('company_id', 'in', [company_id, False])]", ) diff --git a/rma_scrap/models/rma_order_line.py b/rma_scrap/models/rma_order_line.py index 4dcd62288..939dd014b 100644 --- a/rma_scrap/models/rma_order_line.py +++ b/rma_scrap/models/rma_order_line.py @@ -49,7 +49,7 @@ def _compute_qty_scrap(self): for move in rec.move_ids.filtered( lambda m: m.state in ["done"] and m.is_rma_scrap ): - qty += product_obj._compute_quantity(move.product_uom_qty, rec.uom_id) + qty += product_obj._compute_quantity(move.quantity, rec.uom_id) rec.qty_scrap = qty def _compute_scrap_count(self): diff --git a/rma_scrap/tests/test_rma_scrap.py b/rma_scrap/tests/test_rma_scrap.py index 0187547b5..e7f3656ee 100644 --- a/rma_scrap/tests/test_rma_scrap.py +++ b/rma_scrap/tests/test_rma_scrap.py @@ -1,3 +1,4 @@ +from odoo.exceptions import ValidationError from odoo.tests import common @@ -32,7 +33,14 @@ def setUpClass(cls): "tracking": "lot", } ) - + cls.product_3 = cls.product_obj.create( + { + "name": "Test Product 3", + "type": "product", + "list_price": 150.0, + "tracking": "serial", + } + ) cls.lot = cls.env["stock.lot"].create( { "name": "Lot for tests", @@ -40,6 +48,13 @@ def setUpClass(cls): "company_id": cls.env.ref("base.main_company").id, } ) + cls.serial_p3 = cls.env["stock.lot"].create( + { + "name": "Serial for tests", + "product_id": cls.product_3.id, + "company_id": cls.env.ref("base.main_company").id, + } + ) cls.wh = cls.env.ref("stock.warehouse0") cls.stock_rma_location = cls.wh.lot_rma_id cls.scrap_loc = cls.env["stock.location"].create( @@ -77,6 +92,14 @@ def setUpClass(cls): "out_route_id": cls.rma_route_cust.id, } ) + # add somne qty or we cannot scrap + cls.env["stock.quant"].create( + { + "product_id": cls.product_1.id, + "location_id": cls.stock_rma_location.id, + "inventory_quantity": 1, + } + ).action_apply_inventory() def test_01_rma_scrap_received(self): rma = self.rma_line_obj.create( @@ -184,12 +207,78 @@ def test_02_rma_scrap_ordered(self): ], } ).create({}) + wizard.item_ids[0].qty_to_scrap = 1 action = wizard.action_create_scrap() scrap = self.env["stock.scrap"].browse([action["res_id"]]) self.assertEqual(scrap.location_id.id, self.stock_rma_location.id) self.assertEqual(scrap.move_ids.id, False) self.assertEqual(rma.qty_in_scrap, 1.00) res = scrap.action_validate() - scrap.do_scrap() self.assertTrue(res) self.assertEqual(rma.qty_scrap, 1.00) + + def test_03_rma_scrap_lot(self): + rma = self.rma_line_obj.create( + { + "partner_id": self.customer1.id, + "product_id": self.product_3.id, + "operation_id": self.operation_1.id, + "uom_id": self.product_1.uom_id.id, + "in_route_id": self.operation_1.in_route_id.id, + "out_route_id": self.operation_1.out_route_id.id, + "in_warehouse_id": self.operation_1.in_warehouse_id.id, + "out_warehouse_id": self.operation_1.out_warehouse_id.id, + "location_id": self.stock_rma_location.id, + } + ) + rma._onchange_operation_id() + rma.action_rma_to_approve() + wizard = self.rma_make_picking.with_context( + **{ + "active_ids": rma.id, + "active_model": "rma.order.line", + "picking_type": "incoming", + "active_id": 1, + } + ).create({}) + + self.assertEqual(rma.qty_to_receive, 1.00) + self.assertFalse(rma.qty_to_scrap) + + action_picking = wizard.action_create_picking() + picking = self.env["stock.picking"].browse([action_picking["res_id"]]) + picking.move_line_ids[0].quantity = rma.qty_to_receive + picking.move_line_ids[0].lot_id = self.serial_p3 + + picking.button_validate() + rma._compute_qty_to_scrap() + + self.assertFalse(rma.qty_to_receive) + self.assertEqual(rma.qty_received, 1.00) + self.assertEqual(rma.qty_to_scrap, 1.00) + wizard = self.rma_make_scrap_wiz.with_context( + **{ + "active_ids": rma.id, + "active_model": "rma.order.line", + "item_ids": [ + 0, + 0, + { + "line_id": rma.id, + "product_id": rma.product_id.id, + "product_qty": rma.product_qty, + "location_id": rma.location_id, + "qty_to_scrap": rma.qty_to_scrap, + "uom_id": rma.uom_id.id, + }, + ], + } + ).create({}) + with self.assertRaises(ValidationError): + wizard.item_ids[0].qty_to_scrap = 0 + action = wizard.action_create_scrap() + # now try to put more qty and check it is scrapped 1 anyway + wizard.item_ids[0].qty_to_scrap = 2 + action = wizard.action_create_scrap() + scrap = self.env["stock.scrap"].browse([action["res_id"]]) + self.assertEqual(scrap.scrap_qty, 1) diff --git a/rma_scrap/wizards/rma_make_scrap.py b/rma_scrap/wizards/rma_make_scrap.py index 747efc45c..62936c0be 100644 --- a/rma_scrap/wizards/rma_make_scrap.py +++ b/rma_scrap/wizards/rma_make_scrap.py @@ -53,6 +53,8 @@ def default_get(self, fields_list): def _create_scrap(self): scraps = [] for item in self.item_ids: + if item.qty_to_scrap <= 0: + raise ValidationError(_("Quantity to scrap must be positive")) line = item.line_id if line.state != "approved": raise ValidationError(_("RMA %s is not approved") % line.name) @@ -68,12 +70,16 @@ def action_create_scrap(self): @api.model def _prepare_scrap(self, item): line = item.line_id + if item.line_id.product_id.tracking == "serial": + scrap_qty = 1 + else: + scrap_qty = item.qty_to_scrap scrap = self.env["stock.scrap"].create( { "name": line.rma_id.id and line.rma_id.name or line.name, "origin": line.name, "product_id": item.line_id.product_id.id, - "scrap_qty": item.qty_to_scrap, + "scrap_qty": scrap_qty, "product_uom_id": item.line_id.product_id.product_tmpl_id.uom_id.id, "location_id": item.location_id.id, "scrap_location_id": item.scrap_location_id.id,