Browse Source

[IMP] Restrict kanban stages only to supported models

12.0
mreficent 5 years ago
committed by ahenriquez
parent
commit
bfc066470c
  1. 1
      base_kanban_stage/README.rst
  2. 1
      base_kanban_stage/__manifest__.py
  3. 1
      base_kanban_stage/models/__init__.py
  4. 5
      base_kanban_stage/models/base_kanban_stage.py
  5. 49
      base_kanban_stage/models/ir_model.py
  6. 8
      base_kanban_stage/tests/test_base_kanban_stage.py
  7. 30
      base_kanban_stage/views/ir_model_views.xml

1
base_kanban_stage/README.rst

@ -93,6 +93,7 @@ Contributors
* Oleg Bulkin <obulkin@laslabs.com> * Oleg Bulkin <obulkin@laslabs.com>
* Daniel Reis <dreis.pt@hotmail.com> * Daniel Reis <dreis.pt@hotmail.com>
* Alex Comba <alex.comba@agilebg.com> * Alex Comba <alex.comba@agilebg.com>
* Miquel Raïch <miquel.raich@eficent.com>
Maintainer Maintainer
---------- ----------

1
base_kanban_stage/__manifest__.py

@ -16,6 +16,7 @@
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'views/base_kanban_abstract.xml', 'views/base_kanban_abstract.xml',
'views/base_kanban_stage.xml', 'views/base_kanban_stage.xml',
'views/ir_model_views.xml',
], ],
'installable': True, 'installable': True,
'application': False, 'application': False,

1
base_kanban_stage/models/__init__.py

@ -3,3 +3,4 @@
from . import base_kanban_abstract from . import base_kanban_abstract
from . import base_kanban_stage from . import base_kanban_stage
from . import ir_model

5
base_kanban_stage/models/base_kanban_stage.py

@ -69,13 +69,14 @@ class BaseKanbanStage(models.Model):
required=True, required=True,
index=True, index=True,
help='The model that this Kanban stage will be used for', help='The model that this Kanban stage will be used for',
domain=[('transient', '=', False)],
domain=['&', ('is_kanban', '=', True), ('transient', '=', False)],
default=lambda s: s._default_res_model_id(), default=lambda s: s._default_res_model_id(),
ondelete='cascade',
) )
@api.model @api.model
def _default_res_model_id(self): def _default_res_model_id(self):
'''Useful when creating stages from a Kanban view for another model'''
"""Useful when creating stages from a Kanban view for another model"""
action_id = self.env.context.get('params', {}).get('action') action_id = self.env.context.get('params', {}).get('action')
action = self.env['ir.actions.act_window'].browse(action_id) action = self.env['ir.actions.act_window'].browse(action_id)
default_model = action.res_model default_model = action.res_model

49
base_kanban_stage/models/ir_model.py

@ -0,0 +1,49 @@
# Copyright 2019 Eficent Business and IT Consulting Services S.L.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from odoo import _, api, fields, models
from odoo.exceptions import UserError
class IrModel(models.Model):
_inherit = 'ir.model'
is_kanban = fields.Boolean(
string="Kanban", default=False,
help="Whether this model support kanban stages.",
)
@api.multi
def write(self, vals):
if self and 'is_kanban' in vals:
if not all(rec.state == 'manual' for rec in self):
raise UserError(_('Only custom models can be modified.'))
if not all(rec.is_kanban <= vals['is_kanban'] for rec in self):
raise UserError(
_('Field "Kanban" cannot be changed to "False".'))
res = super(IrModel, self).write(vals)
# setup models; this reloads custom models in registry
self.pool.setup_models(self._cr)
# update database schema of models
models = self.pool.descendants(self.mapped('model'), '_inherits')
self.pool.init_models(self._cr, models, dict(
self._context, update_custom_fields=True))
else:
res = super(IrModel, self).write(vals)
return res
def _reflect_model_params(self, model):
vals = super(IrModel, self)._reflect_model_params(model)
vals['is_kanban'] = issubclass(
type(model), self.pool['base.kanban.abstract'])
return vals
@api.model
def _instanciate(self, model_data):
model_class = super(IrModel, self)._instanciate(model_data)
if model_data.get('is_kanban') and \
model_class._name != 'base.kanban.abstract':
parents = model_class._inherit or []
parents = [parents] if isinstance(parents, (str,)) else parents
model_class._inherit = parents + ['base.kanban.abstract']
return model_class

8
base_kanban_stage/tests/test_base_kanban_stage.py

@ -6,7 +6,7 @@ from odoo.tests.common import TransactionCase
class TestBaseKanbanStage(TransactionCase): class TestBaseKanbanStage(TransactionCase):
def test_default_res_model_id_no_params(self): def test_default_res_model_id_no_params(self):
'''It should return empty ir.model Recordset if no params in context'''
"""It should return empty ir.model Recordset if no params in context"""
test_stage = self.env['base.kanban.stage'].with_context({}) test_stage = self.env['base.kanban.stage'].with_context({})
res_model_id = test_stage._default_res_model_id() res_model_id = test_stage._default_res_model_id()
@ -14,7 +14,7 @@ class TestBaseKanbanStage(TransactionCase):
self.assertEqual(res_model_id._name, 'ir.model') self.assertEqual(res_model_id._name, 'ir.model')
def test_default_res_model_id_no_action(self): def test_default_res_model_id_no_action(self):
'''It should return empty ir.model Recordset if no action in params'''
"""It should return empty ir.model Recordset if no action in params"""
test_stage = self.env['base.kanban.stage'].with_context(params={}) test_stage = self.env['base.kanban.stage'].with_context(params={})
res_model_id = test_stage._default_res_model_id() res_model_id = test_stage._default_res_model_id()
@ -22,7 +22,7 @@ class TestBaseKanbanStage(TransactionCase):
self.assertEqual(res_model_id._name, 'ir.model') self.assertEqual(res_model_id._name, 'ir.model')
def test_default_res_model_id_info_in_context(self): def test_default_res_model_id_info_in_context(self):
'''It should return correct ir.model record if info in context'''
"""It should return correct ir.model record if info in context"""
test_action = self.env['ir.actions.act_window'].create({ test_action = self.env['ir.actions.act_window'].create({
'name': 'Test Action', 'name': 'Test Action',
'res_model': 'res.users', 'res_model': 'res.users',
@ -37,7 +37,7 @@ class TestBaseKanbanStage(TransactionCase):
) )
def test_default_res_model_id_ignore_self(self): def test_default_res_model_id_ignore_self(self):
'''It should not return ir.model record corresponding to stage model'''
"""It should not return ir.model record corresponding to stage model"""
test_action = self.env['ir.actions.act_window'].create({ test_action = self.env['ir.actions.act_window'].create({
'name': 'Test Action', 'name': 'Test Action',
'res_model': 'base.kanban.stage', 'res_model': 'base.kanban.stage',

30
base_kanban_stage/views/ir_model_views.xml

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Eficent Business and IT Consulting Services S.L.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
-->
<odoo>
<record id="model_form_view" model="ir.ui.view">
<field name="model">ir.model</field>
<field name="inherit_id" ref="base.view_model_form"/>
<field name="arch" type="xml">
<field name="transient" position="after">
<field name="is_kanban" attrs="{'readonly': [('state','!=', 'manual')]}" groups="base.group_no_one"/>
</field>
</field>
</record>
<record id="model_search_view" model="ir.ui.view">
<field name="model">ir.model</field>
<field name="inherit_id" ref="base.view_model_search"/>
<field name="arch" type="xml">
<filter name="base" position="after">
<filter string="Kanban" name="is_kanban" domain="[('is_kanban', '=', True)]"/>
</filter>
</field>
</record>
</odoo>
Loading…
Cancel
Save