diff --git a/odoo/addons/base/models/ir_module.py b/odoo/addons/base/models/ir_module.py index 1320ed5df79..c9b69a1798a 100644 --- a/odoo/addons/base/models/ir_module.py +++ b/odoo/addons/base/models/ir_module.py @@ -26,7 +26,7 @@ import psycopg2 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.exceptions import AccessDenied, UserError, ValidationError from odoo.osv import expression from odoo.tools.parse_version import parse_version from odoo.tools.misc import topological_sort, get_flag @@ -98,6 +98,12 @@ class ModuleCategory(models.Model): for cat in self: cat.xml_id = xml_ids.get(cat.id, [''])[0] + @api.constrains('parent_id') + def _check_parent_not_circular(self): + if not self._check_recursion(): + raise ValidationError(_("Error ! You cannot create recursive categories.")) + + class MyFilterMessages(Transform): """ Custom docutils transform to remove `system message` for a document and diff --git a/odoo/addons/base/tests/__init__.py b/odoo/addons/base/tests/__init__.py index e57be3c2c5e..314c5e4e602 100644 --- a/odoo/addons/base/tests/__init__.py +++ b/odoo/addons/base/tests/__init__.py @@ -64,3 +64,4 @@ from . import test_profiler from . import test_pdf from . import test_neutralize from . import test_config_parameter +from . import test_ir_module_category diff --git a/odoo/addons/base/tests/test_ir_module_category.py b/odoo/addons/base/tests/test_ir_module_category.py new file mode 100644 index 00000000000..76b14e87c78 --- /dev/null +++ b/odoo/addons/base/tests/test_ir_module_category.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +from odoo.exceptions import ValidationError +from odoo.tests.common import TransactionCase + +class TestModuleCategory(TransactionCase): + + def test_parent_circular_dependencies(self): + Cats = self.env['ir.module.category'] + + def create(name, **kw): + return Cats.create(dict(kw, name=name)) + + category_a = create('A', parent_id=False) + category_b = create('B', parent_id=category_a.id) + category_c = create('C', parent_id=category_b.id) + + with self.assertRaises(ValidationError): + category_a.write({'parent_id': category_c.id}) + with self.assertRaises(ValidationError): + category_b.write({'parent_id': category_b.id})