diff --git a/addons/calendar/models/ir_values.py b/addons/calendar/models/ir_values.py
deleted file mode 100644
index 4bc0bc3a4a0..00000000000
--- a/addons/calendar/models/ir_values.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from odoo import api, models, tools
-from odoo.addons.calendar.models.calendar import calendar_id2real_id
-
-class IrValues(models.Model):
- _inherit = 'ir.values'
-
- @api.model
- @api.returns('self', lambda value: value.id)
- def set_action(self, name, action_slot, model, action, res_id=False):
- if res_id:
- res_id = calendar_id2real_id(res_id)
- return super(IrValues, self).set_action(name, action_slot, model, action, res_id=res_id)
-
- @api.model
- @tools.ormcache_context('self._uid', 'action_slot', 'model', 'res_id', keys=('lang',))
- def get_actions(self, action_slot, model, res_id=False):
- if res_id:
- res_id = calendar_id2real_id(res_id)
- return super(IrValues, self).get_actions(action_slot, model, res_id=res_id)
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index f0a6650f3a6..7a032b59bef 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -299,10 +299,6 @@ def set_cookie_and_redirect(redirect_url):
redirect.autocorrect_location_header = False
return redirect
-def load_actions_from_ir_values(action_slot, model, res_id):
- actions = request.env['ir.values'].get_actions(action_slot, model, res_id)
- return [(id, name, clean_action(action)) for id, name, action in actions]
-
def clean_action(action):
action.setdefault('flags', {})
action_type = action.setdefault('type', 'ir.actions.act_window_close')
diff --git a/odoo/addons/base/__manifest__.py b/odoo/addons/base/__manifest__.py
index 493f9f37c2a..68cc520ba4f 100644
--- a/odoo/addons/base/__manifest__.py
+++ b/odoo/addons/base/__manifest__.py
@@ -32,7 +32,6 @@ The kernel of Odoo, needed for all installation.
'ir/ir_translation_view.xml',
'ir/ir_ui_menu_view.xml',
'ir/ir_ui_view_view.xml',
- 'ir/ir_values_view.xml',
'ir/ir_default_view.xml',
'ir/ir_autovacuum.xml',
'ir/ir_model_report.xml',
diff --git a/odoo/addons/base/ir/__init__.py b/odoo/addons/base/ir/__init__.py
index 194da2c4c2f..6f09b5dd6b4 100644
--- a/odoo/addons/base/ir/__init__.py
+++ b/odoo/addons/base/ir/__init__.py
@@ -10,7 +10,6 @@ from . import ir_actions_report
from . import ir_attachment
from . import ir_cron
from . import ir_filters
-from . import ir_values
from . import ir_default
from . import ir_translation
from . import ir_exports
diff --git a/odoo/addons/base/ir/ir_actions.py b/odoo/addons/base/ir/ir_actions.py
index a3cbe9d5d79..aa4e2055afe 100644
--- a/odoo/addons/base/ir/ir_actions.py
+++ b/odoo/addons/base/ir/ir_actions.py
@@ -46,8 +46,6 @@ class IrActions(models.Model):
res = super(IrActions, self).create(vals)
# self.get_bindings() depends on action records
self.clear_caches()
- # ir_values.get_actions() depends on action records
- self.env['ir.values'].clear_caches()
return res
@api.multi
@@ -55,8 +53,6 @@ class IrActions(models.Model):
res = super(IrActions, self).write(vals)
# self.get_bindings() depends on action records
self.clear_caches()
- # ir_values.get_actions() depends on action records
- self.env['ir.values'].clear_caches()
return res
@api.multi
@@ -68,8 +64,6 @@ class IrActions(models.Model):
res = super(IrActions, self).unlink()
# self.get_bindings() depends on action records
self.clear_caches()
- # ir_values.get_actions() depends on action records
- self.env['ir.values'].clear_caches()
return res
@api.model
diff --git a/odoo/addons/base/ir/ir_values.py b/odoo/addons/base/ir/ir_values.py
deleted file mode 100644
index 851c4705738..00000000000
--- a/odoo/addons/base/ir/ir_values.py
+++ /dev/null
@@ -1,431 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from ast import literal_eval
-
-from odoo import api, fields, models, tools, _
-from odoo.exceptions import AccessError, MissingError, ValidationError
-from odoo.tools import pickle, pycompat
-
-import logging
-_logger = logging.getLogger(__name__)
-
-#: Possible slots to bind an action to with :meth:`~.set_action`
-ACTION_SLOTS = [
- "client_action_multi", # sidebar wizard action
- "client_print_multi", # sidebar report printing button
- "client_action_relate", # sidebar related link
- "tree_but_open", # double-click on item in tree view
- "tree_but_action", # deprecated: same as tree_but_open
-]
-
-
-class IrValues(models.Model):
- """Holds internal model-specific action bindings and user-defined default
- field values. definitions. This is a legacy internal model, mixing
- two different concepts, and will likely be updated or replaced in a
- future version by cleaner, separate models. You should not depend
- explicitly on it.
-
- The purpose of each ``ir.values`` entry depends on its type, defined
- by the ``key`` column:
-
- * 'default': user-defined default values, used when creating new
- records of this model:
- * 'action': binding of an action to a particular *action slot* of
- this model, making the action easily available in the user
- interface for this model.
-
- The ``key2`` column acts as a qualifier, further refining the type
- of the entry. The possible values are:
-
- * for 'default' entries: an optional condition restricting the
- cases where this particular default value will be applicable,
- or ``False`` for no condition
- * for 'action' entries: the ``key2`` qualifier is one of the available
- action slots, defining how this action can be invoked:
-
- * ``'client_print_multi'`` for report printing actions that will
- be available on views displaying items from this model
- * ``'client_action_multi'`` for assistants (wizards) actions
- that will be available in views displaying objects of this model
- * ``'client_action_relate'`` for links towards related documents
- that should be available in views displaying objects of this model
- * ``'tree_but_open'`` for actions that will be triggered when
- double-clicking an item from this model in a hierarchical tree view
-
- Each entry is specific to a model (``model`` column), and for ``'actions'``
- type, may even be made specific to a given record of that model when the
- ``res_id`` column contains a record ID (``False`` means it's global for
- all records).
-
- The content of the entry is defined by the ``value`` column, which may either
- contain an arbitrary value, or a reference string defining the action that
- should be executed.
-
- .. rubric:: Usage: default values
-
- The ``'default'`` entries are usually defined manually by the
- users, and set by their UI clients calling :meth:`~.set_default`.
- These default values are then automatically used by the
- ORM every time a new record is about to be created, i.e. when
- :meth:`~odoo.models.Model.default_get`
- or :meth:`~odoo.models.Model.create` are called.
-
- .. rubric:: Usage: action bindings
-
- Business applications will usually bind their actions during
- installation, and Odoo UI clients will apply them as defined,
- based on the list of actions included in the result of
- :meth:`~odoo.models.Model.fields_view_get`,
- or directly returned by explicit calls to :meth:`~.get_actions`.
- """
- _name = 'ir.values'
-
- name = fields.Char(required=True)
- model = fields.Char(string='Model Name', index=True, required=True,
- help="Model to which this entry applies")
-
- # TODO: model_id and action_id should be read-write function fields
- model_id = fields.Many2one('ir.model', string='Model (change only)',
- help="Model to which this entry applies - "
- "helper field for setting a model, will "
- "automatically set the correct model name")
- action_id = fields.Many2one('ir.actions.actions', string='Action (change only)',
- help="Action bound to this entry - "
- "helper field for binding an action, will "
- "automatically set the correct reference")
-
- value = fields.Binary(help="Default value (pickled) or reference to an action")
- value_unpickle = fields.Binary(string='Default value or action reference',
- compute='_value_unpickle', inverse='_value_pickle')
- key = fields.Selection([('action', 'Action'), ('default', 'Default')],
- string='Type', index=True, required=True, default='action',
- help="- Action: an action attached to one slot of the given model\n"
- "- Default: a default value for a model field")
- key2 = fields.Char(string='Qualifier', index=True, default='tree_but_open',
- help="For actions, one of the possible action slots: \n"
- " - client_action_multi\n"
- " - client_print_multi\n"
- " - client_action_relate\n"
- " - tree_but_open\n"
- "For defaults, an optional condition")
- res_id = fields.Integer(string='Record ID', index=True,
- help="Database identifier of the record to which this applies. "
- "0 = for all records")
- user_id = fields.Many2one('res.users', string='User', ondelete='cascade', index=True,
- help="If set, action binding only applies for this user.")
- company_id = fields.Many2one('res.company', string='Company', ondelete='cascade', index=True,
- help="If set, action binding only applies for this company")
-
- @api.depends('key', 'value')
- def _value_unpickle(self):
- for record in self:
- value = record.value
- if record.key == 'default' and value:
- # default values are pickled on the fly
- with tools.ignore(Exception):
- value = str(pickle.loads(value))
- record.value_unpickle = value
-
- def _value_pickle(self):
- context = dict(self._context)
- context.pop(self.CONCURRENCY_CHECK_FIELD, None)
- for record in self.with_context(context):
- value = record.value_unpickle
- # Only char-like fields should be written directly. Other types should be converted to
- # their appropriate type first.
- if record.model in self.env and record.name in self.env[record.model]._fields:
- field = self.env[record.model]._fields[record.name]
- if field.type not in ['char', 'text', 'html', 'selection']:
- value = literal_eval(value)
- if record.key == 'default':
- value = pickle.dumps(value)
- record.value = value
-
- @api.onchange('model_id')
- def onchange_object_id(self):
- if self.model_id:
- self.model = self.model_id.model
-
- @api.onchange('action_id')
- def onchange_action_id(self):
- if self.action_id:
- self.value_unpickle = self.action_id
-
- @api.model_cr_context
- def _auto_init(self):
- res = super(IrValues, self)._auto_init()
- tools.create_index(self._cr, 'ir_values_key_model_key2_res_id_user_id_idx',
- self._table, ['key', 'model', 'key2', 'res_id', 'user_id'])
- return res
-
- @api.model
- def create(self, vals):
- self.clear_caches()
- return super(IrValues, self).create(vals)
-
- @api.multi
- def write(self, vals):
- self.clear_caches()
- return super(IrValues, self).write(vals)
-
- @api.multi
- def unlink(self):
- self.clear_caches()
- return super(IrValues, self).unlink()
-
- @api.model
- @api.returns('self', lambda value: value.id)
- def set_default(self, model, field_name, value, for_all_users=True, company_id=False, condition=False):
- """Defines a default value for the given model and field_name. Any previous
- default for the same scope (model, field_name, value, for_all_users, company_id, condition)
- will be replaced and lost in the process.
-
- Defaults can be later retrieved via :meth:`~.get_defaults`, which will return
- the highest priority default for any given field. Defaults that are more specific
- have a higher priority, in the following order (highest to lowest):
-
- * specific to user and company
- * specific to user only
- * specific to company only
- * global to everyone
-
- :param string model: model name
- :param string field_name: field name to which the default applies
- :param value: the default field value to set
- :type value: any serializable Python value
- :param bool for_all_users: whether the default should apply to everybody or only
- the user calling the method
- :param int company_id: optional ID of the company to which the default should
- apply. If omitted, the default will be global. If True
- is passed, the current user's company will be used.
- :param string condition: optional condition specification that can be used to
- restrict the applicability of the default values
- (e.g. based on another field's value). This is an
- opaque string as far as the API is concerned, but client
- stacks typically use single-field conditions in the
- form ``'key=stringified_value'``.
- (Currently, the condition is trimmed to 200 characters,
- so values that share the same first 200 characters always
- match)
- :return: the newly created ir.values entry
- """
- if isinstance(value, pycompat.string_types):
- value = pycompat.to_native(value)
- if company_id is True:
- # should be company-specific, need to get company id
- company_id = self.env.user.company_id.id
-
- # check consistency of model, field_name and value
- try:
- field = self.env[model]._fields[field_name]
- field.convert_to_cache(value, self.browse())
- except KeyError:
- _logger.warning("Invalid field %s.%s", model, field_name)
- except Exception:
- raise ValidationError(_("Invalid value for %s.%s: %s") % (model, field_name, value))
-
- # remove existing defaults for the same scope
- search_criteria = [
- ('key', '=', 'default'),
- ('key2', '=', condition and condition[:200]),
- ('model', '=', model),
- ('name', '=', field_name),
- ('user_id', '=', False if for_all_users else self._uid),
- ('company_id', '=', company_id)
- ]
- self.search(search_criteria).unlink()
-
- return self.create({
- 'name': field_name,
- 'value': pickle.dumps(value),
- 'model': model,
- 'key': 'default',
- 'key2': condition and condition[:200],
- 'user_id': False if for_all_users else self._uid,
- 'company_id': company_id,
- })
-
- @api.model
- def get_default(self, model, field_name, for_all_users=True, company_id=False, condition=False):
- """ Return the default value defined for model, field_name, users, company and condition.
- Return ``None`` if no such default exists.
- """
- search_criteria = [
- ('key', '=', 'default'),
- ('key2', '=', condition and condition[:200]),
- ('model', '=', model),
- ('name', '=', field_name),
- ('user_id', '=', False if for_all_users else self._uid),
- ('company_id', '=', company_id)
- ]
- defaults = self.search(search_criteria)
- return pickle.loads(defaults.value) if defaults else None
-
- @api.model
- def get_defaults(self, model, condition=False):
- """Returns any default values that are defined for the current model and user,
- (and match ``condition``, if specified), previously registered via
- :meth:`~.set_default`.
-
- Defaults are global to a model, not field-specific, but an optional
- ``condition`` can be provided to restrict matching default values
- to those that were defined for the same condition (usually based
- on another field's value).
-
- Default values also have priorities depending on whom they apply
- to: only the highest priority value will be returned for any
- field. See :meth:`~.set_default` for more details.
-
- :param string model: model name
- :param string condition: optional condition specification that can be used to
- restrict the applicability of the default values
- (e.g. based on another field's value). This is an
- opaque string as far as the API is concerned, but client
- stacks typically use single-field conditions in the
- form ``'key=stringified_value'``.
- (Currently, the condition is trimmed to 200 characters,
- so values that share the same first 200 characters always
- match)
- :return: list of default values tuples of the form ``(id, field_name, value)``
- (``id`` is the ID of the default entry, usually irrelevant)
- """
- # use a direct SQL query for performance reasons,
- # this is called very often
- query = """ SELECT v.id, v.name, v.value FROM ir_values v
- LEFT JOIN res_users u ON (v.user_id = u.id)
- WHERE v.key = %%s AND v.model = %%s
- AND (v.user_id = %%s OR v.user_id IS NULL)
- AND (v.company_id IS NULL OR
- v.company_id = (SELECT company_id FROM res_users WHERE id = %%s)
- )
- %s
- ORDER BY v.user_id, v.company_id, v.id"""
- params = ('default', model, self._uid, self._uid)
- if condition:
- query = query % 'AND v.key2 = %s'
- params += (condition[:200],)
- else:
- query = query % 'AND v.key2 IS NULL'
- self._cr.execute(query, params)
-
- # keep only the highest priority default for each field
- defaults = {}
- for row in self._cr.dictfetchall():
- value = pickle.loads(row['value'])
- defaults.setdefault(row['name'], (row['id'], row['name'], value))
- return list(defaults.values())
-
- # use ormcache: this is called a lot by BaseModel.default_get()!
- @api.model
- @tools.ormcache('self._uid', 'model', 'condition')
- def get_defaults_dict(self, model, condition=False):
- """ Returns a dictionary mapping field names with their corresponding
- default value. This method simply improves the returned value of
- :meth:`~.get_defaults`.
- """
- return dict((f, v) for i, f, v in self.get_defaults(model, condition))
-
- @api.model
- @api.returns('self', lambda value: value.id)
- def set_action(self, name, action_slot, model, action, res_id=False):
- """Binds an the given action to the given model's action slot - for later
- retrieval via :meth:`~.get_actions`. Any existing binding of the same action
- to the same slot is first removed, allowing an update of the action's name.
- See the class description for more details about the various action
- slots: :class:`~ir_values`.
-
- :param string name: action label, usually displayed by UI client
- :param string action_slot: the action slot to which the action should be
- bound to - one of ``client_action_multi``,
- ``client_print_multi``, ``client_action_relate``,
- ``tree_but_open``.
- :param string model: model name
- :param string action: action reference, in the form ``'model,id'``
- :param int res_id: optional record id - will bind the action only to a
- specific record of the model, not all records.
- :return: the newly created ir.values entry
- """
- assert isinstance(action, pycompat.string_types) and ',' in action, \
- 'Action definition must be an action reference, e.g. "ir.actions.act_window,42"'
- assert action_slot in ACTION_SLOTS, \
- 'Action slot (%s) must be one of: %r' % (action_slot, ACTION_SLOTS)
-
- action = action.encode('utf-8')
-
- # remove existing action definition of same slot and value
- search_criteria = [
- ('key', '=', 'action'),
- ('key2', '=', action_slot),
- ('model', '=', model),
- ('res_id', '=', res_id or 0), # int field -> NULL == 0
- ('value', '=', action),
- ]
- self.search(search_criteria).unlink()
-
- return self.create({
- 'key': 'action',
- 'key2': action_slot,
- 'model': model,
- 'res_id': res_id,
- 'name': name,
- 'value': action,
- })
-
- @api.model
- @tools.ormcache_context('self._uid', 'action_slot', 'model', 'res_id', keys=('lang',))
- def get_actions(self, action_slot, model, res_id=False):
- """Retrieves the list of actions bound to the given model's action slot.
- See the class description for more details about the various action
- slots: :class:`~.ir_values`.
-
- :param string action_slot: the action slot to which the actions should be
- bound to - one of ``client_action_multi``,
- ``client_print_multi``, ``client_action_relate``,
- ``tree_but_open``.
- :param string model: model name
- :param int res_id: optional record id - will bind the action only to a
- specific record of the model, not all records.
- :return: list of action tuples of the form ``(id, name, action_def)``,
- where ``id`` is the ID of the default entry, ``name`` is the
- action label, and ``action_def`` is a dict containing the
- action definition as obtained by calling
- :meth:`~odoo.models.Model.read` on the action record.
- """
- assert action_slot in ACTION_SLOTS, 'Illegal action slot value: %s' % action_slot
- # use a direct SQL query for performance reasons,
- # this is called very often
- query = """ SELECT v.id, v.name, v.value FROM ir_values v
- WHERE v.key = %s AND v.key2 = %s AND v.model = %s
- AND (v.res_id = %s OR v.res_id IS NULL OR v.res_id = 0)
- ORDER BY v.id """
- self._cr.execute(query, ('action', action_slot, model, res_id or None))
-
- # map values to their corresponding action record
- actions = []
- for id, name, value in self._cr.fetchall():
- if not value:
- continue # skip if undefined
- action_model, action_id = bytes(value).decode('utf-8').split(',')
- if action_model not in self.env:
- continue # unknown model? skip it!
- action = self.env[action_model].browse(int(action_id))
- actions.append((id, name, action))
-
- # process values and their action
- results = {}
- for id, name, action in actions:
- # FIXME: needs cleanup
- try:
- action_def = dict([(k, v.convert_to_read(action[k], action)) for k, v in action._fields.items()])
- if action._name in ('ir.actions.report', 'ir.actions.act_window'):
- if action.groups_id and not action.groups_id & self.env.user.groups_id:
- if name == 'Menuitem':
- raise AccessError(_('You do not have the permission to perform this operation!!!'))
- continue
- # keep only the last action registered for each action name
- results[name] = (id, name, action_def)
- except (AccessError, MissingError):
- continue
- return sorted(results.values())
diff --git a/odoo/addons/base/ir/ir_values_view.xml b/odoo/addons/base/ir/ir_values_view.xml
deleted file mode 100644
index 1f0ae67525e..00000000000
--- a/odoo/addons/base/ir/ir_values_view.xml
+++ /dev/null
@@ -1,126 +0,0 @@
-
-
-
-
- ir.values.form.action
- ir.values
-
-
-
-
-
-
- ir.values.form.defaults
- ir.values
-
-
-
-
-
-
- ir.values.tree.action
- ir.values
-
-
-
-
-
-
-
-
-
-
-
- ir.values.search.action
- ir.values
-
-
-
-
-
-
-
-
-
-
-
-
- Action Bindings
- ir.actions.act_window
- ir.values
- form
- tree,form
-
- [('key','=','action')]
- {'default_key':'action'}
-
-
-
- tree
-
-
-
-
-
- form
-
-
-
-
-
-
- User-defined Defaults
- ir.actions.act_window
- ir.values
- form
- tree,form
-
- [('key','=','default')]
- {'default_key':'default','default_key2':''}
-
-
-
- tree
-
-
-
-
-
- form
-
-
-
-
-
-
diff --git a/odoo/addons/base/res/res_users.py b/odoo/addons/base/res/res_users.py
index 729e8c612f9..2a17198a7de 100644
--- a/odoo/addons/base/res/res_users.py
+++ b/odoo/addons/base/res/res_users.py
@@ -683,8 +683,6 @@ class GroupsView(models.Model):
self._update_user_groups_view()
# actions.get_bindings() depends on action records
self.env['ir.actions.actions'].clear_caches()
- # ir_values.get_actions() depends on action records
- self.env['ir.values'].clear_caches()
return user
@api.multi
@@ -693,8 +691,6 @@ class GroupsView(models.Model):
self._update_user_groups_view()
# actions.get_bindings() depends on action records
self.env['ir.actions.actions'].clear_caches()
- # ir_values.get_actions() depends on action records
- self.env['ir.values'].clear_caches()
return res
@api.multi
@@ -703,8 +699,6 @@ class GroupsView(models.Model):
self._update_user_groups_view()
# actions.get_bindings() depends on action records
self.env['ir.actions.actions'].clear_caches()
- # ir_values.get_actions() depends on action records
- self.env['ir.values'].clear_caches()
return res
@api.model
diff --git a/odoo/addons/base/security/base_security.xml b/odoo/addons/base/security/base_security.xml
index cbfcff5e0a4..6ac1efaac5b 100644
--- a/odoo/addons/base/security/base_security.xml
+++ b/odoo/addons/base/security/base_security.xml
@@ -104,13 +104,6 @@
-
- Defaults: alter personal values only
-
- [('key','=','default'),('user_id','=',user.id)]
-
-
-
Defaults: alter personal defaults
diff --git a/odoo/addons/base/security/ir.model.access.csv b/odoo/addons/base/security/ir.model.access.csv
index 656ba20cbc4..13e07e1aeac 100644
--- a/odoo/addons/base/security/ir.model.access.csv
+++ b/odoo/addons/base/security/ir.model.access.csv
@@ -32,7 +32,6 @@
"access_ir_ui_view_group_user","ir_ui_view group_user","model_ir_ui_view",,1,0,0,0
"access_ir_ui_view_group_system","ir_ui_view group_system","model_ir_ui_view","group_system",1,1,1,1
"access_ir_ui_view_custom_group_user","ir_ui_view_custom_group_user","model_ir_ui_view_custom",,1,1,1,1
-"access_ir_values_group_all","ir_values group_all","model_ir_values",,1,1,1,1
"access_ir_default_all","ir_default all","model_ir_default",,1,0,0,0
"access_ir_default_group_user","ir_default group_user","model_ir_default","group_user",1,1,1,1
"access_ir_default_group_system","ir_default group_system","model_ir_default","group_system",1,1,1,1
diff --git a/odoo/addons/base/tests/__init__.py b/odoo/addons/base/tests/__init__.py
index daba366b3f8..8041e071e9b 100644
--- a/odoo/addons/base/tests/__init__.py
+++ b/odoo/addons/base/tests/__init__.py
@@ -12,7 +12,6 @@ from . import test_ir_http
from . import test_ir_filters
from . import test_ir_sequence
from . import test_ir_sequence_date_range
-from . import test_ir_values
from . import test_ir_default
from . import test_mail
from . import test_menu
diff --git a/odoo/addons/base/tests/test_ir_values.py b/odoo/addons/base/tests/test_ir_values.py
deleted file mode 100644
index a4365f7e0aa..00000000000
--- a/odoo/addons/base/tests/test_ir_values.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from odoo import tools
-from odoo.exceptions import ValidationError
-from odoo.tests.common import TransactionCase
-
-
-class TestIrValues(TransactionCase):
-
- def test_defaults(self):
- # Create some default value for some model, for all users.
- ir_values = self.env['ir.values']
- ir_values.set_default('res.partner', 'ref', 'X11')
- ir_values.set_default('res.partner.title', 'shortcut', 'Mr', condition='name=Mister')
-
- # Retrieve them: ds is a list of triplets (id, name, value)
- ds = ir_values.get_defaults('res.partner')
- d = next((d for d in ds if d[1] == 'ref'), None)
- self.assertTrue(d, "At least one value should be retrieved for this model.")
- self.assertEqual(d[2], 'X11', "Can't retrieve the created default value.")
-
- ds = ir_values.get_defaults('res.partner.title')
- d = next((d for d in ds if d[1] == 'shortcut'), None)
- self.assertFalse(d, "No value should be retrieved, the condition is not met.")
-
- ds = ir_values.get_defaults('res.partner.title', condition="name=Miss")
- d = next((d for d in ds if d[1] == 'shortcut'), None)
- self.assertFalse(d, "No value should be retrieved, the condition is not met.")
-
- ds = ir_values.get_defaults('res.partner.title', condition="name=Mister")
- d = next((d for d in ds if d[1] == 'shortcut'), None)
- self.assertTrue(d, "At least one value should be retrieved.")
- self.assertEqual(d[2], 'Mr', "Can't retrieve the created default value.")
-
- # Do it again but for a specific user.
- ir_values.set_default('res.partner', 'ref', '007', for_all_users=False)
-
- # Retrieve it and check it is the one for the current user.
- ds = ir_values.get_defaults('res.partner')
- d = next((d for d in ds if d[1] == 'ref'), None)
- self.assertTrue(d, "At least one value should be retrieved for this model.")
- self.assertEqual(d[2], '007', "Can't retrieve the created default value.")
-
- # create valid but unusable defaults, a ValidationError should not be thrown
- with tools.mute_logger('odoo.addons.base.ir.ir_values'):
- ir_values.set_default('unknown_model', 'unknown_field', 42)
- ir_values.set_default('res.partner', 'unknown_field', 42)
-
- # create invalid defaults
- with self.assertRaises(ValidationError):
- ir_values.set_default('res.partner', 'lang', 'some_LANG')
- with self.assertRaises(ValidationError):
- ir_values.set_default('res.partner', 'credit_limit', 'foo')
-
- def test_actions(self):
- # Create some action bindings for a model.
- act_id_1 = self.ref('base.act_values_form_action')
- act_id_2 = self.ref('base.act_values_form_defaults')
- act_id_3 = self.ref('base.action_res_company_form')
- ir_values = self.env['ir.values']
- ir_values.set_action('OnDblClick Action', action_slot='tree_but_open', model='res.partner', action='ir.actions.act_window,%d' % act_id_1, res_id=False)
- ir_values.set_action('OnDblClick Action 2', action_slot='tree_but_open', model='res.partner', action='ir.actions.act_window,%d' % act_id_2, res_id=False)
- ir_values.set_action('Side Wizard', action_slot='client_action_multi', model='res.partner', action='ir.actions.act_window,%d' % act_id_3, res_id=False)
-
- reports = self.env['ir.actions.report'].search([])
- report_id = next(report.id for report in reports if not report.groups_id)
- ir_values.set_action('Nice Report', action_slot='client_print_multi', model='res.partner', action='ir.actions.report,%d' % report_id, res_id=False)
-
- # Replace one action binding to set a new name.
- ir_values.set_action('OnDblClick Action New', action_slot='tree_but_open', model='res.partner', action='ir.actions.act_window,%d' % act_id_1, res_id=False)
-
- # Retrieve the action bindings and check they're correct
- actions = ir_values.get_actions(action_slot='tree_but_open', model='res.partner', res_id=False)
- self.assertEqual(len(actions), 2, "Mismatching number of bound actions")
- # first action
- self.assertEqual(len(actions[0]), 3, "Malformed action definition")
- self.assertEqual(actions[0][1], 'OnDblClick Action 2', 'Bound action does not match definition')
- self.assertTrue(isinstance(actions[0][2], dict) and actions[0][2]['id'] == act_id_2,
- 'Bound action does not match definition')
- # second action - this ones comes last because it was re-created with a different name
- self.assertEqual(len(actions[1]), 3, "Malformed action definition")
- self.assertEqual(actions[1][1], 'OnDblClick Action New', 'Re-Registering an action should replace it')
- self.assertTrue(isinstance(actions[1][2], dict) and actions[1][2]['id'] == act_id_1,
- 'Bound action does not match definition')
-
- actions = ir_values.get_actions(action_slot='client_action_multi', model='res.partner', res_id=False)
- self.assertEqual(len(actions), 1, "Mismatching number of bound actions")
- self.assertEqual(len(actions[0]), 3, "Malformed action definition")
- self.assertEqual(actions[0][1], 'Side Wizard', 'Bound action does not match definition')
- self.assertTrue(isinstance(actions[0][2], dict) and actions[0][2]['id'] == act_id_3,
- 'Bound action does not match definition')
-
- actions = ir_values.get_actions(action_slot='client_print_multi', model='res.partner', res_id=False)
- self.assertEqual(len(actions), 1, "Mismatching number of bound actions")
- self.assertEqual(len(actions[0]), 3, "Malformed action definition")
- self.assertEqual(actions[0][1], 'Nice Report', 'Bound action does not match definition')
- self.assertTrue(isinstance(actions[0][2], dict) and actions[0][2]['id'] == report_id,
- 'Bound action does not match definition')
-
- def test_orders(self):
- ir_values = self.env['ir.values']
-
- # create a global rule for all
- ir_values.set_default(
- 'res.partner', 'ref', 'value_global',
- for_all_users=True, company_id=False, condition=False)
- self.assertEqual(
- ir_values.get_defaults_dict('res.partner')['ref'],
- 'value_global',
- "Can't retrieve the created default value for all.")
-
- # set a default value for current company (behavior of 'set default' from debug mode)
- ir_values.set_default(
- 'res.partner', 'ref', 'value_company',
- for_all_users=True, company_id=True, condition=False)
- self.assertEqual(
- ir_values.get_defaults_dict('res.partner')['ref'],
- 'value_company',
- "Can't retrieve the created default value for company.")
-
- # set a default value for current user (behavior of 'set default' from debug mode)
- ir_values.set_default(
- 'res.partner', 'ref', 'value_user',
- for_all_users=False, company_id=True, condition=False)
- self.assertEqual(
- ir_values.get_defaults_dict('res.partner')['ref'],
- 'value_user',
- "Can't retrieve the created default value for user.")
diff --git a/odoo/models.py b/odoo/models.py
index 6604e0ea222..c589d4805fd 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -2832,7 +2832,6 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
cr = self._cr
Data = self.env['ir.model.data'].sudo().with_context({})
- Values = self.env['ir.values']
Defaults = self.env['ir.default'].sudo()
Attachment = self.env['ir.attachment']
@@ -2851,14 +2850,6 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
if data:
data.unlink()
- # For the same reason, remove the relevant records in ir_values
- refs = ['%s,%s' % (self._name, i) for i in sub_ids]
- values = Values.search(['|', ('value', 'in', refs),
- '&', ('model', '=', self._name),
- ('res_id', 'in', sub_ids)])
- if values:
- values.unlink()
-
# For the same reason, remove the defaults having some of the
# records as value
Defaults.discard_records(self.browse(sub_ids))