Fix several issues
Fix error '... is not a table or foreign table' Fix view (colors + oe_highlight) Fix tests Fix README + manifest Fix back to draft Fix cron call + default values Use Postgres version 9.6 for travis buildspull/557/head
parent
4a2fba7f34
commit
d09e4677f5
|
@ -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
|
||||
|
||||
|
|
|
@ -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': [
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2,56 +2,68 @@
|
|||
# Copyright 2017 Onestein (<http://www.onestein.eu>)
|
||||
# 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')
|
||||
|
|
|
@ -10,7 +10,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|||
<record id="view_bi_sql_view_tree" model="ir.ui.view">
|
||||
<field name="model">bi.sql.view</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree colors="blue:state=='draft'; brown:state in ('sql_valid', 'model_valid')">
|
||||
<tree decoration-info="state=='draft'" decoration-warning="state in ('sql_valid', 'model_valid')">
|
||||
<field name="name"/>
|
||||
<field name="technical_name"/>
|
||||
<field name="size"/>
|
||||
|
@ -29,7 +29,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|||
<button name="button_set_draft" type="object" states="sql_valid,model_valid,ui_valid"
|
||||
string="Set to Draft" groups="sql_request_abstract.group_sql_request_manager"
|
||||
confirm="Are you sure you want to set to draft this SQL View. It will delete the materialized view, and all the previous mapping realized with the columns"/>
|
||||
<button name="button_preview_sql_expression" type="object" states="draft" string="Preview SQL Expression" class="oe_highlight"/>
|
||||
<button name="button_preview_sql_expression" type="object" states="draft" string="Preview SQL Expression" />
|
||||
<button name="button_create_sql_view_and_model" type="object" states="sql_valid"
|
||||
string="Create SQL View, Indexes and Models" class="oe_highlight"
|
||||
help="This will try to create an SQL View, based on the SQL request and the according Transient Model and fields, based on settings"/>
|
||||
|
@ -70,7 +70,7 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|||
</page>
|
||||
<page string="SQL Fields" attrs="{'invisible': [('state', '=', 'draft')]}">
|
||||
<field name="bi_sql_view_field_ids" nolabel="1" colspan="4" attrs="{'readonly': [('state', '!=', 'sql_valid')]}">
|
||||
<tree editable="bottom" colors="blue:field_description==False">
|
||||
<tree editable="bottom" decoration-info="field_description==False">
|
||||
<field name="sequence"/>
|
||||
<field name="name"/>
|
||||
<field name="sql_type"/>
|
||||
|
|
Loading…
Reference in New Issue