[IMP] Add test + several fixes
parent
20a1c97409
commit
a2da8473d4
|
@ -78,6 +78,7 @@ To configure this module, you need to:
|
||||||
take a while, if view is materialized)
|
take a while, if view is materialized)
|
||||||
|
|
||||||
* If it's a MATERIALIZED view:
|
* If it's a MATERIALIZED view:
|
||||||
|
|
||||||
* a cron task is created to refresh
|
* a cron task is created to refresh
|
||||||
the view. You can so define the frequency of the refresh.
|
the view. You can so define the frequency of the refresh.
|
||||||
* the size of view (and the indexes is displayed)
|
* the size of view (and the indexes is displayed)
|
||||||
|
@ -93,9 +94,9 @@ Usage
|
||||||
|
|
||||||
To use this module, you need to:
|
To use this module, you need to:
|
||||||
|
|
||||||
* Go to 'Reporting' / 'Custom Reports'
|
#. Go to 'Reporting' / 'Custom Reports'
|
||||||
|
|
||||||
* select the desired report
|
#. Select the desired report
|
||||||
|
|
||||||
.. figure:: /bi_sql_editor/static/description/05_reporting_pivot.png
|
.. figure:: /bi_sql_editor/static/description/05_reporting_pivot.png
|
||||||
:width: 800 px
|
:width: 800 px
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
|
from .hooks import uninstall_hook
|
||||||
|
|
|
@ -21,8 +21,9 @@
|
||||||
'views/menu.xml',
|
'views/menu.xml',
|
||||||
],
|
],
|
||||||
'demo': [
|
'demo': [
|
||||||
'demo/res_groups.xml',
|
'demo/res_groups_demo.xml',
|
||||||
'demo/bi_sql_view.xml',
|
'demo/bi_sql_view_demo.xml',
|
||||||
],
|
],
|
||||||
'installable': True,
|
'installable': True,
|
||||||
|
'uninstall_hook': 'uninstall_hook'
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright (C) 2014 - Today GRAP (http://www.grap.coop)
|
|
||||||
@author Sylvain LE GAL (https://twitter.com/legalsylvain)
|
|
||||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
||||||
-->
|
|
||||||
|
|
||||||
<openerp><data>
|
|
||||||
|
|
||||||
<record id="incorrect_sql_view" model="bi.sql.view">
|
|
||||||
<field name="name">Draft Incorrect SQL View</field>
|
|
||||||
<field name="technical_name">incorrect_view</field>
|
|
||||||
<field name="query"><![CDATA[
|
|
||||||
SELECT *
|
|
||||||
FROM unexisting_table
|
|
||||||
ORDER BY unexisting_field
|
|
||||||
]]>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="partner_sql_view" model="bi.sql.view">
|
|
||||||
<field name="name">Partners View</field>
|
|
||||||
<field name="technical_name">partners_view</field>
|
|
||||||
<field name="query"><![CDATA[
|
|
||||||
SELECT
|
|
||||||
name as x_name,
|
|
||||||
street as x_street,
|
|
||||||
company_id as x_company_id
|
|
||||||
FROM res_partner
|
|
||||||
ORDER BY name
|
|
||||||
]]>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<function model="bi.sql.view" name="button_validate_sql_expression" eval="([ref('partner_sql_view')])"/>
|
|
||||||
|
|
||||||
<record id="module_sql_view" model="bi.sql.view">
|
|
||||||
<field name="name">Modules by Authors</field>
|
|
||||||
<field name="technical_name">modules_view</field>
|
|
||||||
<field name="is_materialized" eval="0" />
|
|
||||||
<field name="query"><![CDATA[
|
|
||||||
SELECT
|
|
||||||
name as x_name,
|
|
||||||
case
|
|
||||||
when author ilike '%OpenERP SA%' THEN 'Odoo SA'
|
|
||||||
when author ilike '%Odoo Community Association (OCA)%' THEN 'OCA'
|
|
||||||
else 'Undefined Author' END as x_author_type
|
|
||||||
FROM ir_module_module
|
|
||||||
]]>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<function model="bi.sql.view" name="button_validate_sql_expression" eval="([ref('module_sql_view')])"/>
|
|
||||||
|
|
||||||
<function model="bi.sql.view" name="button_create_sql_view_and_model" eval="([ref('module_sql_view')])"/>
|
|
||||||
|
|
||||||
<function model="bi.sql.view" name="button_create_ui" eval="([ref('module_sql_view')])"/>
|
|
||||||
|
|
||||||
</data></openerp>
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2014 - Today GRAP (http://www.grap.coop)
|
||||||
|
@author Sylvain LE GAL (https://twitter.com/legalsylvain)
|
||||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
-->
|
||||||
|
|
||||||
|
<odoo>
|
||||||
|
<data noupdate="1">
|
||||||
|
|
||||||
|
<record id="incorrect_sql_view" model="bi.sql.view">
|
||||||
|
<field name="name">Draft Incorrect SQL View</field>
|
||||||
|
<field name="technical_name">incorrect_view</field>
|
||||||
|
<field name="query"><![CDATA[
|
||||||
|
SELECT *
|
||||||
|
FROM unexisting_table
|
||||||
|
ORDER BY unexisting_field
|
||||||
|
]]>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="partner_sql_view" model="bi.sql.view">
|
||||||
|
<field name="name">Partners View</field>
|
||||||
|
<field name="technical_name">partners_view</field>
|
||||||
|
<field name="query"><![CDATA[
|
||||||
|
SELECT
|
||||||
|
name as x_name,
|
||||||
|
street as x_street,
|
||||||
|
company_id as x_company_id
|
||||||
|
FROM res_partner
|
||||||
|
ORDER BY name
|
||||||
|
]]>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="module_sql_view" model="bi.sql.view">
|
||||||
|
<field name="name">Modules by Authors</field>
|
||||||
|
<field name="technical_name">modules_view</field>
|
||||||
|
<field name="is_materialized" eval="0" />
|
||||||
|
<field name="query"><![CDATA[
|
||||||
|
SELECT
|
||||||
|
name as x_name,
|
||||||
|
case
|
||||||
|
when author ilike '%OpenERP SA%' THEN 'Odoo SA'
|
||||||
|
when author ilike '%Odoo Community Association (OCA)%' THEN 'OCA'
|
||||||
|
else 'Undefined Author' END as x_author_type
|
||||||
|
FROM ir_module_module
|
||||||
|
]]>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<function model="bi.sql.view" name="button_validate_sql_expression" eval="([ref('module_sql_view')])"/>
|
||||||
|
|
||||||
|
<function model="bi.sql.view" name="button_create_sql_view_and_model" eval="([ref('module_sql_view')])"/>
|
||||||
|
|
||||||
|
<function model="bi.sql.view" name="button_create_ui" eval="([ref('module_sql_view')])"/>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
|
@ -1,18 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright (C) 2014 - Today GRAP (http://www.grap.coop)
|
|
||||||
@author Sylvain LE GAL (https://twitter.com/legalsylvain)
|
|
||||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
||||||
-->
|
|
||||||
|
|
||||||
<openerp><data>
|
|
||||||
|
|
||||||
<record id="base.group_no_one" model="res.groups">
|
|
||||||
<field name="users" eval="[(4, ref('base.user_root'))]" />
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="sql_request_abstract.group_sql_request_user" model="res.groups">
|
|
||||||
<field name="users" eval="[(4, ref('base.user_demo'))]" />
|
|
||||||
</record>
|
|
||||||
|
|
||||||
</data></openerp>
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2014 - Today GRAP (http://www.grap.coop)
|
||||||
|
@author Sylvain LE GAL (https://twitter.com/legalsylvain)
|
||||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
-->
|
||||||
|
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<record id="base.group_no_one" model="res.groups">
|
||||||
|
<field name="users" eval="[(4, ref('base.user_root'))]" />
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="sql_request_abstract.group_sql_request_user" model="res.groups">
|
||||||
|
<field name="users" eval="[(4, ref('base.user_demo'))]" />
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
|
@ -0,0 +1,12 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright 2015-2017 Onestein (<http://www.onestein.eu>)
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
from openerp import SUPERUSER_ID
|
||||||
|
from openerp.api import Environment
|
||||||
|
|
||||||
|
|
||||||
|
def uninstall_hook(cr, registry):
|
||||||
|
env = Environment(cr, SUPERUSER_ID, {})
|
||||||
|
recs = env['bi.sql.view'].search([])
|
||||||
|
for rec in recs:
|
||||||
|
rec.button_set_draft()
|
|
@ -27,14 +27,14 @@ class BiSQLView(models.Model):
|
||||||
|
|
||||||
_STATE_SQL_EDITOR = [
|
_STATE_SQL_EDITOR = [
|
||||||
('model_valid', 'SQL View and Model Created'),
|
('model_valid', 'SQL View and Model Created'),
|
||||||
('ui_valid', 'Graph, action and Menu Created'),
|
('ui_valid', 'Views, Action and Menu Created'),
|
||||||
]
|
]
|
||||||
|
|
||||||
technical_name = fields.Char(
|
technical_name = fields.Char(
|
||||||
string='Technical Name', required=True,
|
string='Technical Name', required=True,
|
||||||
help="Suffix of the SQL view. (SQL full name will be computed and"
|
help="Suffix of the SQL view. SQL full name will be computed and"
|
||||||
" prefixed by 'x_bi_sql_view_'. Should have correct"
|
" prefixed by 'x_bi_sql_view_'. Syntax should follow: "
|
||||||
"syntax. For more information, see https://www.postgresql.org/"
|
"https://www.postgresql.org/"
|
||||||
"docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS")
|
"docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS")
|
||||||
|
|
||||||
view_name = fields.Char(
|
view_name = fields.Char(
|
||||||
|
@ -59,6 +59,14 @@ class BiSQLView(models.Model):
|
||||||
|
|
||||||
state = fields.Selection(selection_add=_STATE_SQL_EDITOR)
|
state = fields.Selection(selection_add=_STATE_SQL_EDITOR)
|
||||||
|
|
||||||
|
view_order = fields.Char(string='View Order',
|
||||||
|
required=True,
|
||||||
|
readonly=False,
|
||||||
|
states={'ui_valid': [('readonly', True)]},
|
||||||
|
default="pivot,graph,tree",
|
||||||
|
help='Comma-separated text. Possible values:'
|
||||||
|
' "graph", "pivot" or "tree"')
|
||||||
|
|
||||||
query = fields.Text(
|
query = fields.Text(
|
||||||
help="SQL Request that will be inserted as the view. Take care to :\n"
|
help="SQL Request that will be inserted as the view. Take care to :\n"
|
||||||
" * set a name for all your selected fields, specially if you use"
|
" * set a name for all your selected fields, specially if you use"
|
||||||
|
@ -113,6 +121,16 @@ class BiSQLView(models.Model):
|
||||||
rule_id = fields.Many2one(
|
rule_id = fields.Many2one(
|
||||||
string='Odoo Rule', comodel_name='ir.rule', readonly=True)
|
string='Odoo Rule', comodel_name='ir.rule', readonly=True)
|
||||||
|
|
||||||
|
@api.constrains('view_order')
|
||||||
|
@api.multi
|
||||||
|
def _check_view_order(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.view_order:
|
||||||
|
for vtype in rec.view_order.split(','):
|
||||||
|
if vtype not in ('graph', 'pivot', 'tree'):
|
||||||
|
raise UserError(_(
|
||||||
|
'Only graph, pivot or tree views are supported'))
|
||||||
|
|
||||||
# Compute Section
|
# Compute Section
|
||||||
@api.depends('is_materialized')
|
@api.depends('is_materialized')
|
||||||
@api.multi
|
@api.multi
|
||||||
|
@ -148,7 +166,7 @@ class BiSQLView(models.Model):
|
||||||
('state', 'not in', ('draft', 'sql_valid'))])
|
('state', 'not in', ('draft', 'sql_valid'))])
|
||||||
if non_draft_views:
|
if non_draft_views:
|
||||||
raise UserError(_("You can only unlink draft views"))
|
raise UserError(_("You can only unlink draft views"))
|
||||||
return self.unlink()
|
return super(BiSQLView, self).unlink()
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def copy(self, default=None):
|
def copy(self, default=None):
|
||||||
|
@ -185,7 +203,8 @@ class BiSQLView(models.Model):
|
||||||
for sql_view in self:
|
for sql_view in self:
|
||||||
if sql_view.state in ('model_valid', 'ui_valid'):
|
if sql_view.state in ('model_valid', 'ui_valid'):
|
||||||
# Drop SQL View (and indexes by cascade)
|
# Drop SQL View (and indexes by cascade)
|
||||||
sql_view._drop_view()
|
if sql_view.is_materialized:
|
||||||
|
sql_view._drop_view()
|
||||||
|
|
||||||
# Drop ORM
|
# Drop ORM
|
||||||
sql_view._drop_model_and_fields()
|
sql_view._drop_model_and_fields()
|
||||||
|
@ -233,7 +252,7 @@ class BiSQLView(models.Model):
|
||||||
'type': 'ir.actions.act_window',
|
'type': 'ir.actions.act_window',
|
||||||
'res_model': self.model_id.model,
|
'res_model': self.model_id.model,
|
||||||
'search_view_id': self.search_view_id.id,
|
'search_view_id': self.search_view_id.id,
|
||||||
'view_mode': 'graph,pivot,tree',
|
'view_mode': self.action_id.view_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Prepare Function
|
# Prepare Function
|
||||||
|
@ -357,12 +376,20 @@ class BiSQLView(models.Model):
|
||||||
@api.multi
|
@api.multi
|
||||||
def _prepare_action(self):
|
def _prepare_action(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
|
view_mode = self.view_order
|
||||||
|
first_view = view_mode.split(',')[0]
|
||||||
|
if first_view == 'tree':
|
||||||
|
view_id = self.tree_view_id.id
|
||||||
|
elif first_view == 'pivot':
|
||||||
|
view_id = self.pivot_view_id.id
|
||||||
|
else:
|
||||||
|
view_id = self.graph_view_id.id
|
||||||
return {
|
return {
|
||||||
'name': self.name,
|
'name': self.name,
|
||||||
'res_model': self.model_id.model,
|
'res_model': self.model_id.model,
|
||||||
'type': 'ir.actions.act_window',
|
'type': 'ir.actions.act_window',
|
||||||
'view_mode': 'graph,pivot,tree',
|
'view_mode': view_mode,
|
||||||
'view_id': self.graph_view_id.id,
|
'view_id': view_id,
|
||||||
'search_view_id': self.search_view_id.id,
|
'search_view_id': self.search_view_id.id,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,7 +465,8 @@ class BiSQLView(models.Model):
|
||||||
@api.multi
|
@api.multi
|
||||||
def _drop_model_and_fields(self):
|
def _drop_model_and_fields(self):
|
||||||
for sql_view in self:
|
for sql_view in self:
|
||||||
sql_view.model_id.unlink()
|
if sql_view.model_id:
|
||||||
|
sql_view.model_id.unlink()
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _hook_executed_request(self):
|
def _hook_executed_request(self):
|
||||||
|
@ -522,16 +550,17 @@ class BiSQLView(models.Model):
|
||||||
@api.multi
|
@api.multi
|
||||||
def _refresh_materialized_view(self):
|
def _refresh_materialized_view(self):
|
||||||
for sql_view in self:
|
for sql_view in self:
|
||||||
req = "REFRESH %s VIEW %s" % (
|
if sql_view.is_materialized:
|
||||||
sql_view.materialized_text, sql_view.view_name)
|
req = "REFRESH %s VIEW %s" % (
|
||||||
self._log_execute(req)
|
sql_view.materialized_text, sql_view.view_name)
|
||||||
sql_view._refresh_size()
|
self._log_execute(req)
|
||||||
if sql_view.action_id:
|
sql_view._refresh_size()
|
||||||
# Alter name of the action, to display last refresh datetime
|
if sql_view.action_id:
|
||||||
# of the materialized view
|
# Alter name of the action, to display last refresh
|
||||||
sql_view.action_id.name = "%s (%s)" % (
|
# datetime of the materialized view
|
||||||
self.name,
|
sql_view.action_id.name = "%s (%s)" % (
|
||||||
datetime.utcnow().strftime(_("%m/%d/%Y %H:%M:%S UTC")))
|
self.name,
|
||||||
|
datetime.utcnow().strftime(_("%m/%d/%Y %H:%M:%S UTC")))
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _refresh_size(self):
|
def _refresh_size(self):
|
||||||
|
|
|
@ -84,7 +84,7 @@ class BiSQLViewField(models.Model):
|
||||||
|
|
||||||
ttype = fields.Selection(
|
ttype = fields.Selection(
|
||||||
string='Field Type', selection=_TTYPE_SELECTION, help="Type of the"
|
string='Field Type', selection=_TTYPE_SELECTION, help="Type of the"
|
||||||
" Odoo field that will be created. Let empty if you don't want to"
|
" Odoo field that will be created. Keep empty if you don't want to"
|
||||||
" create a new field. If empty, this field will not be displayed"
|
" create a new field. If empty, this field will not be displayed"
|
||||||
" neither available for search or group by function")
|
" neither available for search or group by function")
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ class BiSQLViewField(models.Model):
|
||||||
many2one_model_id = fields.Many2one(
|
many2one_model_id = fields.Many2one(
|
||||||
comodel_name='ir.model', string='Model',
|
comodel_name='ir.model', string='Model',
|
||||||
help="For 'Many2one' Odoo field.\n"
|
help="For 'Many2one' Odoo field.\n"
|
||||||
" Co Model of the field.")
|
" Comodel of the field.")
|
||||||
|
|
||||||
# Compute Section
|
# Compute Section
|
||||||
@api.multi
|
@api.multi
|
||||||
|
@ -174,8 +174,6 @@ class BiSQLViewField(models.Model):
|
||||||
'selection': self.ttype == 'selection' and self.selection or False,
|
'selection': self.ttype == 'selection' and self.selection or False,
|
||||||
'relation': self.ttype == 'many2one' and
|
'relation': self.ttype == 'many2one' and
|
||||||
self.many2one_model_id.model or False,
|
self.many2one_model_id.model or False,
|
||||||
'tree_visibility': self.field_description and
|
|
||||||
'available' or 'unavailable',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
from . import test_bi_sql_view
|
|
@ -0,0 +1,75 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright 2017 Onestein (<http://www.onestein.eu>)
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
from openerp.tests.common import TransactionCase, at_install, post_install
|
||||||
|
from openerp.exceptions import AccessError
|
||||||
|
|
||||||
|
|
||||||
|
class TestBiSqlViewEditor(TransactionCase):
|
||||||
|
|
||||||
|
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(
|
||||||
|
'sql_request_abstract.group_sql_request_manager')
|
||||||
|
self.group_user = self.env.ref(
|
||||||
|
'base.group_user')
|
||||||
|
self.view = self.bi_sql_view.create({
|
||||||
|
'name': 'Partners View 2',
|
||||||
|
'is_materialized': False,
|
||||||
|
'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')
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
def _create_user(self, login, groups, company):
|
||||||
|
"""Create a user."""
|
||||||
|
group_ids = [group.id for group in groups]
|
||||||
|
user = self.res_users.create({
|
||||||
|
'name': 'Test BI User',
|
||||||
|
'login': login,
|
||||||
|
'password': 'demo',
|
||||||
|
'email': 'example@yourcompany.com',
|
||||||
|
'company_id': company.id,
|
||||||
|
'groups_id': [(6, 0, group_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')
|
||||||
|
|
||||||
|
def test_copy(self):
|
||||||
|
copy_view = self.view.copy()
|
||||||
|
self.assertEqual(
|
||||||
|
copy_view.name, 'Partners View 2 (Copy)', 'Wrong name')
|
||||||
|
|
||||||
|
def test_security(self):
|
||||||
|
with self.assertRaises(AccessError):
|
||||||
|
self.bi_sql_view.sudo(self.no_bi_user.id).search(
|
||||||
|
[('name', '=', 'Partners View 2')])
|
||||||
|
bi = self.bi_sql_view.sudo(self.bi_user.id).search(
|
||||||
|
[('name', '=', 'Partners View 2')])
|
||||||
|
self.assertEqual(len(bi), 1, 'Bi user should not have access to '
|
||||||
|
'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.view.unlink()
|
||||||
|
res = self.bi_sql_view.search([('name', '=', 'Partners View 2')])
|
||||||
|
self.assertEqual(len(res), 0, 'View not deleted')
|
|
@ -53,7 +53,8 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<field name="technical_name"/>
|
<field name="technical_name"/>
|
||||||
<field name="view_name" />
|
<field name="view_name"/>
|
||||||
|
<field name="view_order"/>
|
||||||
<field name="is_materialized"/>
|
<field name="is_materialized"/>
|
||||||
<field name="size"
|
<field name="size"
|
||||||
attrs="{'invisible': ['|', ('state', '=', 'draft'), ('is_materialized', '=', False)]}"/>
|
attrs="{'invisible': ['|', ('state', '=', 'draft'), ('is_materialized', '=', False)]}"/>
|
||||||
|
|
Loading…
Reference in New Issue