From 10cb1beead2787eacc060db1e2055e5b928bceac Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 22 Aug 2017 10:34:58 +0200 Subject: [PATCH] [REM] base: remove model `ir.values` --- addons/calendar/models/ir_values.py | 22 - addons/web/controllers/main.py | 4 - odoo/addons/base/__manifest__.py | 1 - odoo/addons/base/ir/__init__.py | 1 - odoo/addons/base/ir/ir_actions.py | 6 - odoo/addons/base/ir/ir_values.py | 431 ------------------ odoo/addons/base/ir/ir_values_view.xml | 126 ----- odoo/addons/base/res/res_users.py | 6 - odoo/addons/base/security/base_security.xml | 7 - odoo/addons/base/security/ir.model.access.csv | 1 - odoo/addons/base/tests/__init__.py | 1 - odoo/addons/base/tests/test_ir_values.py | 129 ------ odoo/models.py | 9 - 13 files changed, 744 deletions(-) delete mode 100644 addons/calendar/models/ir_values.py delete mode 100644 odoo/addons/base/ir/ir_values.py delete mode 100644 odoo/addons/base/ir/ir_values_view.xml delete mode 100644 odoo/addons/base/tests/test_ir_values.py 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))