From 5d084bcf889e14fd4fbab9fe18b8afee7d96b976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=20De=20Caluw=C3=A9?= Date: Tue, 18 Oct 2022 12:21:56 +0000 Subject: [PATCH] [FIX] purchase_stock: set qty_received_method to manual on uninstall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After uninstalling the stock module on a database which also has the purchase (and purchase_stock) module installed, the qty_received_method is removed for purchase order lines handling the reception of the products through the stock module (qty_received_method = 'stock_moves'). Because of this, a recompute is triggered on the qty_received, setting it to zero. This leaves the purchase order in an invalid state (the received quantity did not change through the uninstallation of the stock module), additionally the problem cannot be corrected, since the receiving method is not set to manual. Functionally, the uninstallation shouldn't update the purchase orders, instead they should be decoupled from the associated stock moves. To this end, an ondelete handler is added for the stock_moves selection option. Steps to reproduce: - Install Purchases app - Install Inventory app - Create a purchase order with purchase lines and quantity > 0 - Confirm the purchase order - Click on receive products - Click on validate - Uninstall Inventory app - Check that the purchase order lines have the received field set to zero and it is not editable opw-3006951 closes odoo/odoo#121549 X-original-commit: cedd0603a24aa0c0e6716c2e0f49e89c870eae04 Signed-off-by: Nicolas Lempereur (nle) Signed-off-by: De Caluwé Tom (tdc) Co-authored-by: Pedro Manuel Calheiros Lima de Sousa (peso) --- addons/purchase_stock/models/purchase.py | 15 +++++- addons/purchase_stock/tests/__init__.py | 1 + addons/purchase_stock/tests/test_uninstall.py | 53 +++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 addons/purchase_stock/tests/test_uninstall.py diff --git a/addons/purchase_stock/models/purchase.py b/addons/purchase_stock/models/purchase.py index fc909b5cf79..a5c946333e7 100644 --- a/addons/purchase_stock/models/purchase.py +++ b/addons/purchase_stock/models/purchase.py @@ -293,7 +293,20 @@ class PurchaseOrder(models.Model): class PurchaseOrderLine(models.Model): _inherit = 'purchase.order.line' - qty_received_method = fields.Selection(selection_add=[('stock_moves', 'Stock Moves')]) + def _ondelete_stock_moves(self): + modified_fields = ['qty_received_manual', 'qty_received_method'] + self.flush_recordset(fnames=['qty_received', *modified_fields]) + self.invalidate_recordset(fnames=modified_fields, flush=False) + query = f''' + UPDATE {self._table} + SET qty_received_manual = qty_received, qty_received_method = 'manual' + WHERE id IN %(ids)s + ''' + self.env.cr.execute(query, {'ids': self._ids or (None,)}) + self.modified(modified_fields) + + qty_received_method = fields.Selection(selection_add=[('stock_moves', 'Stock Moves')], + ondelete={'stock_moves': _ondelete_stock_moves}) move_ids = fields.One2many('stock.move', 'purchase_line_id', string='Reservation', readonly=True, copy=False) orderpoint_id = fields.Many2one('stock.warehouse.orderpoint', 'Orderpoint', copy=False, index='btree_not_null') diff --git a/addons/purchase_stock/tests/__init__.py b/addons/purchase_stock/tests/__init__.py index a05c295b1d0..15b7c7f0541 100644 --- a/addons/purchase_stock/tests/__init__.py +++ b/addons/purchase_stock/tests/__init__.py @@ -19,3 +19,4 @@ from . import test_move_cancel_propagation from . import test_product_template from . import test_routes from . import test_purchase_stock_accrued_entries +from . import test_uninstall diff --git a/addons/purchase_stock/tests/test_uninstall.py b/addons/purchase_stock/tests/test_uninstall.py new file mode 100644 index 00000000000..742057645a8 --- /dev/null +++ b/addons/purchase_stock/tests/test_uninstall.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +from unittest.mock import patch + +from odoo import fields +from odoo.addons.base.models.ir_model import MODULE_UNINSTALL_FLAG +from odoo.addons.purchase_stock.models.purchase import PurchaseOrderLine +from odoo.tests.common import tagged + +from .common import PurchaseTestCommon + + +@tagged('post_install', '-at_install') +class TestUninstallPurchaseStock(PurchaseTestCommon): + def test_qty_received_method(self): + partner = self.env['res.partner'].create({'name': 'Test Partner'}) + purchase_order = self.env['purchase.order'].create({ + 'partner_id': partner.id, + 'state': 'purchase', + 'order_line': [fields.Command.create({ + 'product_id': self.product_1.id, + })], + }) + order_line = purchase_order.order_line + stock_move = order_line.move_ids + + self.assertEqual(order_line.product_id.detailed_type, 'product') + + stock_move.quantity_done = 1 + stock_move.picking_id.button_validate() + + self.assertEqual(purchase_order.order_line.qty_received, 1) + + stock_moves_option = self.env['ir.model.fields.selection'].search([ + ('field_id.model', '=', 'purchase.order.line'), + ('field_id.name', '=', 'qty_received_method'), + ('value', '=', 'stock_moves'), + ]) + + original_compute = PurchaseOrderLine._compute_qty_received + def _compute_qty_received(records): + records.read() + with self.assertQueryCount(0): + original_compute(records) + records.flush_recordset() + + with patch.object(PurchaseOrderLine, '_compute_qty_received', _compute_qty_received): + stock_moves_option.sudo().with_context(**{ + MODULE_UNINSTALL_FLAG: True + }).unlink() + + self.assertEqual(order_line.qty_received_method, 'manual') + self.assertEqual(order_line.qty_received, 1)