diff --git a/bi_sql_editor/README.rst b/bi_sql_editor/README.rst index 323987f2..b753e56f 100644 --- a/bi_sql_editor/README.rst +++ b/bi_sql_editor/README.rst @@ -1,4 +1,4 @@ -.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 diff --git a/bi_sql_editor/__manifest__.py b/bi_sql_editor/__manifest__.py index 1df8d34a..9920f737 100644 --- a/bi_sql_editor/__manifest__.py +++ b/bi_sql_editor/__manifest__.py @@ -5,13 +5,14 @@ { 'name': 'BI SQL Editor', - 'summary': "BI Views builder, based on Materialized or Normal SQL Views", + 'summary': 'BI Views builder, based on Materialized or Normal SQL Views', 'version': '10.0.1.0.0', 'license': 'AGPL-3', 'category': 'Reporting', 'author': 'GRAP,Odoo Community Association (OCA)', - 'website': 'https://www.odoo-community.org', + 'website': 'https://github.com/OCA/reporting-engine', 'depends': [ + 'base', 'sql_request_abstract', ], 'data': [ diff --git a/bi_sql_editor/models/bi_sql_view.py b/bi_sql_editor/models/bi_sql_view.py index 3a62d357..60b937d3 100644 --- a/bi_sql_editor/models/bi_sql_view.py +++ b/bi_sql_editor/models/bi_sql_view.py @@ -13,6 +13,22 @@ from odoo.exceptions import UserError _logger = logging.getLogger(__name__) +class BaseModel(models.AbstractModel): + _inherit = 'base' + + @api.model_cr_context + def _auto_init(self): + if self._name.startswith(BiSQLView._model_prefix): + self._auto = False + return super(BaseModel, self)._auto_init() + + @api.model_cr_context + def _auto_end(self): + if self._name.startswith(BiSQLView._model_prefix): + self._foreign_keys = set() + return super(BaseModel, self)._auto_end() + + class BiSQLView(models.Model): _name = 'bi.sql.view' _inherit = ['sql.request.mixin'] @@ -161,10 +177,7 @@ class BiSQLView(models.Model): # Overload Section @api.multi def unlink(self): - non_draft_views = self.search([ - ('id', 'in', self.ids), - ('state', 'not in', ('draft', 'sql_valid'))]) - if non_draft_views: + if any(view.state not in ('draft', 'sql_valid') for view in self): raise UserError(_("You can only unlink draft views")) return super(BiSQLView, self).unlink() @@ -201,6 +214,15 @@ class BiSQLView(models.Model): @api.multi def button_set_draft(self): for sql_view in self: + sql_view.menu_id.unlink() + sql_view.action_id.unlink() + sql_view.tree_view_id.unlink() + sql_view.graph_view_id.unlink() + sql_view.pivot_view_id.unlink() + sql_view.search_view_id.unlink() + if sql_view.cron_id: + sql_view.cron_id.unlink() + if sql_view.state in ('model_valid', 'ui_valid'): # Drop SQL View (and indexes by cascade) if sql_view.is_materialized: @@ -209,14 +231,6 @@ class BiSQLView(models.Model): # Drop ORM sql_view._drop_model_and_fields() - sql_view.tree_view_id.unlink() - sql_view.graph_view_id.unlink() - sql_view.pivot_view_id.unlink() - sql_view.search_view_id.unlink() - sql_view.action_id.unlink() - sql_view.menu_id.unlink() - if sql_view.cron_id: - sql_view.cron_id.unlink() sql_view.write({'state': 'draft', 'has_group_changed': False}) @api.multi @@ -293,7 +307,8 @@ class BiSQLView(models.Model): 'name': _('Refresh Materialized View %s') % (self.view_name), 'user_id': SUPERUSER_ID, 'model': 'bi.sql.view', - 'function': 'button_refresh_materialized_view', + 'function': '_refresh_materialized_view_cron', + 'numbercall': -1, 'args': repr(([self.id],)) } @@ -447,7 +462,7 @@ class BiSQLView(models.Model): self._prepare_rule()).id # Drop table, created by the ORM req = "DROP TABLE %s" % (sql_view.view_name) - self.env.cr.execute(req) + self._log_execute(req) @api.multi def _create_model_access(self): @@ -467,7 +482,7 @@ class BiSQLView(models.Model): if sql_view.rule_id: sql_view.rule_id.unlink() if sql_view.model_id: - sql_view.model_id.unlink() + sql_view.model_id.with_context(_force_unlink=True).unlink() @api.multi def _hook_executed_request(self): @@ -481,7 +496,7 @@ class BiSQLView(models.Model): AND NOT attisdropped AND attnum > 0 ORDER BY attnum;""" % (self.view_name) - self.env.cr.execute(req) + self._log_execute(req) return self.env.cr.fetchall() @api.multi @@ -548,6 +563,11 @@ class BiSQLView(models.Model): return columns + @api.model + def _refresh_materialized_view_cron(self, view_ids): + sql_views = self.browse(view_ids) + return sql_views._refresh_materialized_view() + @api.multi def _refresh_materialized_view(self): for sql_view in self: @@ -568,7 +588,7 @@ class BiSQLView(models.Model): for sql_view in self: req = "SELECT pg_size_pretty(pg_total_relation_size('%s'));" % ( sql_view.view_name) - self.env.cr.execute(req) + self._log_execute(req) sql_view.size = self.env.cr.fetchone()[0] @api.multi diff --git a/bi_sql_editor/tests/test_bi_sql_view.py b/bi_sql_editor/tests/test_bi_sql_view.py index 1ab6878c..13fda724 100644 --- a/bi_sql_editor/tests/test_bi_sql_view.py +++ b/bi_sql_editor/tests/test_bi_sql_view.py @@ -2,56 +2,68 @@ # Copyright 2017 Onestein () # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo.tests.common import TransactionCase, at_install, post_install -from odoo.exceptions import AccessError +from odoo.tests.common import SingleTransactionCase, at_install, post_install +from odoo.exceptions import AccessError, UserError -class TestBiSqlViewEditor(TransactionCase): +@at_install(False) +@post_install(True) +class TestBiSqlViewEditor(SingleTransactionCase): - def setUp(self): - super(TestBiSqlViewEditor, self).setUp() - self.res_partner = self.env['res.partner'] - self.res_users = self.env['res.users'] - self.bi_sql_view = self.env['bi.sql.view'] - self.group_bi_user = self.env.ref( + @classmethod + def setUpClass(cls): + super(TestBiSqlViewEditor, cls).setUpClass() + + cls.res_partner = cls.env['res.partner'] + cls.res_users = cls.env['res.users'] + cls.bi_sql_view = cls.env['bi.sql.view'] + cls.group_bi_user = cls.env.ref( 'sql_request_abstract.group_sql_request_manager') - self.group_user = self.env.ref( + cls.group_user = cls.env.ref( 'base.group_user') - self.view = self.bi_sql_view.create({ + cls.view = cls.bi_sql_view.create({ 'name': 'Partners View 2', - 'is_materialized': False, + 'is_materialized': True, 'technical_name': 'partners_view_2', 'query': "SELECT name as x_name, street as x_street," "company_id as x_company_id FROM res_partner " "ORDER BY name" }) - self.company = self.env.ref('base.main_company') + cls.company = cls.env.ref('base.main_company') # Create bi user - self.bi_user = self._create_user('bi_user', [self.group_bi_user], - self.company) - self.no_bi_user = self._create_user('no_bi_user', [self.group_user], - self.company) + cls.bi_user = cls._create_user('bi_user', cls.group_bi_user, + cls.company) + cls.no_bi_user = cls._create_user('no_bi_user', cls.group_user, + cls.company) - def _create_user(self, login, groups, company): + @classmethod + def _create_user(cls, login, groups, company): """Create a user.""" - group_ids = [group.id for group in groups] - user = self.res_users.create({ + user = cls.res_users.create({ 'name': 'Test BI User', 'login': login, 'password': 'demo', 'email': 'example@yourcompany.com', + 'notify_email': 'none', 'company_id': company.id, - 'groups_id': [(6, 0, group_ids)] + 'groups_id': [(6, 0, groups.ids)] }) return user - @at_install(False) - @post_install(True) def test_process_view(self): view = self.view self.assertEqual(view.state, 'draft', 'state not draft') view.button_validate_sql_expression() self.assertEqual(view.state, 'sql_valid', 'state not sql_valid') + view.button_create_sql_view_and_model() + self.assertEqual(view.state, 'model_valid', 'state not model_valid') + view.button_create_ui() + self.assertEqual(view.state, 'ui_valid', 'state not ui_valid') + view.button_update_model_access() + self.assertEqual(view.has_group_changed, False, + 'has_group_changed not False') + cron_res = view.cron_id.method_direct_trigger() + self.assertEqual(cron_res, True, 'something went wrong with the cron') def test_copy(self): copy_view = self.view.copy() @@ -68,8 +80,10 @@ class TestBiSqlViewEditor(TransactionCase): 'bi %s' % self.view.name) def test_unlink(self): - self.assertEqual(self.view.state, 'draft', 'state not draft') - self.view.button_validate_sql_expression() + self.assertEqual(self.view.state, 'ui_valid', 'state not ui_valid') + with self.assertRaises(UserError): + self.view.unlink() + self.view.button_set_draft() self.view.unlink() res = self.bi_sql_view.search([('name', '=', 'Partners View 2')]) self.assertEqual(len(res), 0, 'View not deleted') diff --git a/bi_sql_editor/views/view_bi_sql_view.xml b/bi_sql_editor/views/view_bi_sql_view.xml index 9b7a4d04..8c76cdd7 100644 --- a/bi_sql_editor/views/view_bi_sql_view.xml +++ b/bi_sql_editor/views/view_bi_sql_view.xml @@ -10,7 +10,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). bi.sql.view - + @@ -29,7 +29,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).