From c4ee25fb7ff6a6213e5d443756a0e7bc81e870e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Theys?= Date: Fri, 28 Dec 2018 13:17:26 +0000 Subject: [PATCH] [FIX] base,*: add MODULE_UNINSTALL_FLAG to cleanup views * website_theme_install This commit will add MODULE_UNINSTALL_FLAG to the cleanup methods of themes and modules. This is necessary to also unlink inherited views of those we try to unlink. Before this commit, an error would be raised when trying to delete a view that still had other inherited views (either created manually by the user, or with just bad luck in the order of which the views are deleted). PR: #29753 --- .../tests/test_website_sale_comparison.py | 18 ++++++++++++++++++ .../models/ir_module_module.py | 8 +++++--- odoo/addons/base/models/ir_module.py | 3 ++- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/addons/website_sale_comparison/tests/test_website_sale_comparison.py b/addons/website_sale_comparison/tests/test_website_sale_comparison.py index 5913b00bb40..91c68c7508a 100644 --- a/addons/website_sale_comparison/tests/test_website_sale_comparison.py +++ b/addons/website_sale_comparison/tests/test_website_sale_comparison.py @@ -18,6 +18,18 @@ class TestWebsiteSaleComparison(odoo.tests.TransactionCase): Website0 = self.env['website'].with_context(website_id=None) Website1 = self.env['website'].with_context(website_id=1) + # Create a generic inherited view, with a key not starting with + # `website_sale_comparison` otherwise the unlink will work just based on + # the key, but we want to test also for `MODULE_UNINSTALL_FLAG`. + product_add_to_compare = Website0.viewref('website_sale_comparison.product_add_to_compare') + test_view_key = 'my_test.my_key' + self.env['ir.ui.view'].with_context(website_id=None).create({ + 'name': 'test inherited view', + 'key': test_view_key, + 'inherit_id': product_add_to_compare.id, + 'arch': '
', + }) + # Retrieve the generic view product = Website0.viewref('website_sale.product') # Trigger COW to create specific views of the whole tree @@ -26,6 +38,7 @@ class TestWebsiteSaleComparison(odoo.tests.TransactionCase): # Verify initial state: the specific views exist self.assertEquals(Website1.viewref('website_sale.product').website_id.id, 1) self.assertEquals(Website1.viewref('website_sale_comparison.product_add_to_compare').website_id.id, 1) + self.assertEquals(Website1.viewref(test_view_key).website_id.id, 1) # Remove the module (use `module_uninstall` because it is enough to test # what we want here, no need/can't use `button_immediate_uninstall` @@ -37,3 +50,8 @@ class TestWebsiteSaleComparison(odoo.tests.TransactionCase): self.assertFalse(Website0.viewref('website_sale_comparison.product_add_to_compare', raise_if_not_found=False)) # Check that the specific view is correctly removed self.assertFalse(Website1.viewref('website_sale_comparison.product_add_to_compare', raise_if_not_found=False)) + + # Check that the generic inherited view is correctly removed + self.assertFalse(Website0.viewref(test_view_key, raise_if_not_found=False)) + # Check that the specific inherited view is correctly removed + self.assertFalse(Website1.viewref(test_view_key, raise_if_not_found=False)) diff --git a/addons/website_theme_install/models/ir_module_module.py b/addons/website_theme_install/models/ir_module_module.py index 85a777efa7c..55f77590c6b 100644 --- a/addons/website_theme_install/models/ir_module_module.py +++ b/addons/website_theme_install/models/ir_module_module.py @@ -6,6 +6,7 @@ import os from collections import OrderedDict from odoo import api, fields, models +from odoo.addons.base.models.ir_model import MODULE_UNINSTALL_FLAG from odoo.exceptions import MissingError from odoo.http import request @@ -206,7 +207,7 @@ class IrModuleModule(models.Model): for model_name in self._theme_model_names: template = self._get_module_data(model_name) - models = template.with_context(active_test=False).mapped('copy_ids').filtered(lambda m: m.website_id == website) + models = template.with_context(**{'active_test': False, MODULE_UNINSTALL_FLAG: True}).mapped('copy_ids').filtered(lambda m: m.website_id == website) models.unlink() self._theme_cleanup(model_name, website) @@ -235,8 +236,9 @@ class IrModuleModule(models.Model): if model_name in ('website.page', 'website.menu'): return model - - orphans = model.with_context(active_test=False).search([ + # use active_test to also unlink archived models + # and use MODULE_UNINSTALL_FLAG to also unlink inherited models + orphans = model.with_context(**{'active_test': False, MODULE_UNINSTALL_FLAG: True}).search([ ('key', '=like', self.name + '.%'), ('website_id', '=', website.id), ('theme_template_id', '=', False), diff --git a/odoo/addons/base/models/ir_module.py b/odoo/addons/base/models/ir_module.py index a270a46dfb1..2d24a06362f 100644 --- a/odoo/addons/base/models/ir_module.py +++ b/odoo/addons/base/models/ir_module.py @@ -24,6 +24,7 @@ import lxml.html import odoo from odoo import api, fields, models, modules, tools, _ +from odoo.addons.base.models.ir_model import MODULE_UNINSTALL_FLAG from odoo.exceptions import AccessDenied, UserError from odoo.osv import expression from odoo.tools.parse_version import parse_version @@ -472,7 +473,7 @@ class Module(models.Model): they rely on data that don't exist anymore if the module is removed. """ domain = expression.OR([[('key', '=like', m.name + '.%')] for m in self]) - orphans = self.env['ir.ui.view'].with_context(active_test=False).search(domain) + orphans = self.env['ir.ui.view'].with_context(**{'active_test': False, MODULE_UNINSTALL_FLAG: True}).search(domain) orphans.unlink() @api.multi