From 3a4574d67fbc2a3dc8b36f44ccacc8dca85b8c7b Mon Sep 17 00:00:00 2001 From: Djamel Touati Date: Thu, 28 Sep 2023 08:55:42 +0000 Subject: [PATCH] [FIX] stock: avoid error when editing quant with duplicated sn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The error is caused by this commit: https://github.com/odoo/odoo/commit/e21c17fae8a29c8ee04883b27d761b8ce13cf5b7 Steps to reproduce the bug: - Enable Storage location in inventory setting - Create a storable product “P1”: - Tracked: SN - Create a purchase order with 1 unit of P1 - Receive product: - location: WH/stock/shelf 1 - SN: S1 - Valide the delivery - Go to the product form - update the quantity: - new quant: - Location: WH/stock/shelf 2 - SN: use the same as shelf 1 (S1) - You will receive a warning informing you that S1 is already used in another location (this is expected), but the quant is still created with this SN. - Now try to clear the quant or refresh the page. Problem: You will always get a user error: "Quant's editing is restricted, you can't do this operation." This occurs because the field "sn_duplicated" is computed, and the write function is called to set it as True. However, since this field is not included in the allowed fields, the user error will always be triggered. opw-3511463 closes odoo/odoo#137206 X-original-commit: 3a7b781dc1fad41ca0120c48f7587edb6d7adafe Signed-off-by: William Henrotin (whe) Signed-off-by: Djamel Touati (otd) Co-authored-by: William Henrotin (whe) --- addons/stock/models/stock_move_line.py | 2 ++ addons/stock/models/stock_quant.py | 12 ++++++++---- addons/stock/tests/test_quant.py | 22 ++++++++++++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/addons/stock/models/stock_move_line.py b/addons/stock/models/stock_move_line.py index cea0b0ae1fe..77332513df7 100644 --- a/addons/stock/models/stock_move_line.py +++ b/addons/stock/models/stock_move_line.py @@ -1000,6 +1000,8 @@ class StockMoveLine(models.Model): def action_revert_inventory(self): move_vals = [] + # remove inventory mode + self = self.with_context(inventory_mode=False) processed_move_line = self.env['stock.move.line'] for move_line in self: if move_line.is_inventory and not float_is_zero(move_line.qty_done, precision_digits=move_line.product_uom_id.rounding): diff --git a/addons/stock/models/stock_quant.py b/addons/stock/models/stock_quant.py index 832eabc8ff0..5432317de7d 100644 --- a/addons/stock/models/stock_quant.py +++ b/addons/stock/models/stock_quant.py @@ -316,16 +316,20 @@ class StockQuant(models.Model): 'template': '/stock/static/xlsx/stock_quant.xlsx' }] + @api.model + def _get_forbidden_fields_write(self): + """ Returns a list of fields user can't edit when he want to edit a quant in `inventory_mode`.""" + return ['product_id', 'location_id', 'lot_id', 'package_id', 'owner_id'] + def write(self, vals): """ Override to handle the "inventory mode" and create the inventory move. """ - allowed_fields = self._get_inventory_fields_write() - if self._is_inventory_mode() and any(field for field in allowed_fields if field in vals.keys()): + forbidden_fields = self._get_forbidden_fields_write() + if self._is_inventory_mode() and any(field for field in forbidden_fields if field in vals.keys()): if any(quant.location_id.usage == 'inventory' for quant in self): # Do nothing when user tries to modify manually a inventory loss return - if any(field for field in vals.keys() if field not in allowed_fields): - raise UserError(_("Quant's editing is restricted, you can't do this operation.")) self = self.sudo() + raise UserError(_("Quant's editing is restricted, you can't do this operation.")) return super(StockQuant, self).write(vals) @api.ondelete(at_uninstall=False) diff --git a/addons/stock/tests/test_quant.py b/addons/stock/tests/test_quant.py index a6744a4bb62..9354d4ca3e5 100644 --- a/addons/stock/tests/test_quant.py +++ b/addons/stock/tests/test_quant.py @@ -889,6 +889,28 @@ class StockQuant(TransactionCase): self.assertEqual(len(quant), 1) self.assertEqual(quant.lot_id.name, 'Michel') + def test_update_quant_with_forbidden_field(self): + """ + Test that updating a quant with a forbidden field raise an error. + """ + product = self.env['product.product'].create({ + 'name': 'Product', + 'type': 'product', + 'tracking': 'serial', + }) + sn1 = self.env['stock.lot'].create({ + 'name': 'SN1', + 'product_id': product.id, + }) + self.env['stock.quant']._update_available_quantity(product, self.stock_subloc2, 1.0, lot_id=sn1) + self.assertEqual(len(product.stock_quant_ids), 1) + self.env['stock.quant']._update_available_quantity(product, self.stock_subloc3, 1.0, lot_id=sn1) + self.assertEqual(len(product.stock_quant_ids), 2) + quant_2 = product.stock_quant_ids[1] + self.assertEqual(quant_2.with_context(inventory_mode=True).sn_duplicated, True) + with self.assertRaises(UserError): + quant_2.with_context(inventory_mode=True).write({'location_id': self.stock_subloc2}) + def test_relocate(self): """ Test the relocation wizard. """ def _get_relocate_wizard(quant_ids):