[ADD] base: model ir.default to store user-defined defaults

This commit is contained in:
Raphael Collet
2017-08-28 09:53:23 +02:00
parent b6305b7201
commit 60d9f6fef9
23 changed files with 408 additions and 64 deletions
+7 -9
View File
@@ -684,15 +684,13 @@ class AccountTax(models.Model):
@api.multi
def unlink(self):
company_id = self.env.user.company_id.id
ir_values = self.env['ir.values']
supplier_taxes_id = set(ir_values.get_default('product.template', 'supplier_taxes_id', company_id=company_id) or [])
deleted_sup_tax = self.filtered(lambda tax: tax.id in supplier_taxes_id)
if deleted_sup_tax:
ir_values.sudo().set_default('product.template', "supplier_taxes_id", list(supplier_taxes_id - set(deleted_sup_tax.ids)), for_all_users=True, company_id=company_id)
taxes_id = set(self.env['ir.values'].get_default('product.template', 'taxes_id', company_id=company_id) or [])
deleted_tax = self.filtered(lambda tax: tax.id in taxes_id)
if deleted_tax:
ir_values.sudo().set_default('product.template', "taxes_id", list(taxes_id - set(deleted_tax.ids)), for_all_users=True, company_id=company_id)
IrDefault = self.env['ir.default']
taxes = self.browse(IrDefault.get('product.template', 'taxes_id', company_id=company_id) or [])
if self & taxes:
IrDefault.sudo().set('product.template', 'taxes_id', (taxes - self).ids, company_id=company_id)
taxes = self.browse(IrDefault.get('product.template', 'supplier_taxes_id', company_id=company_id) or [])
if self & taxes:
IrDefault.sudo().set('product.template', 'supplier_taxes_id', (taxes - self).ids, company_id=company_id)
return super(AccountTax, self).unlink()
@api.one
@@ -82,9 +82,9 @@ class AccountConfigSettings(models.TransientModel):
if self.group_multi_currency:
self.env.ref('base.group_user').write({'implied_ids': [(4, self.env.ref('product.group_sale_pricelist').id)]})
""" Set the product taxes if they have changed """
ir_values_obj = self.env['ir.values']
ir_values_obj.sudo().set_default('product.template', "taxes_id", [self.default_sale_tax_id.id] if self.default_sale_tax_id else False, for_all_users=True, company_id=self.company_id.id)
ir_values_obj.sudo().set_default('product.template', "supplier_taxes_id", [self.default_purchase_tax_id.id] if self.default_purchase_tax_id else False, for_all_users=True, company_id=self.company_id.id)
IrDefault = self.env['ir.default'].sudo()
IrDefault.set('product.template', "taxes_id", self.default_sale_tax_id.ids, company_id=self.company_id.id)
IrDefault.set('product.template', "supplier_taxes_id", self.default_purchase_tax_id.ids, company_id=self.company_id.id)
""" install a chart of accounts for the given company (if required) """
if self.chart_template_id and self.chart_template_id != self.company_id.chart_template_id:
wizard = self.env['wizard.multi.charts.accounts'].create({
+3 -3
View File
@@ -876,7 +876,6 @@ class WizardMultiChartsAccounts(models.TransientModel):
res.unlink()
existing_accounts.unlink()
ir_values_obj = self.env['ir.values']
company = self.company_id
self.company_id.write({'currency_id': self.currency_id.id,
'accounts_code_digits': self.code_digits,
@@ -903,10 +902,11 @@ class WizardMultiChartsAccounts(models.TransientModel):
acc_template_ref, taxes_ref = self.chart_template_id._install_template(company, code_digits=self.code_digits, transfer_account_id=self.transfer_account_id)
# write values of default taxes for product as super user
IrDefault = self.env['ir.default']
if self.sale_tax_id and taxes_ref:
ir_values_obj.sudo().set_default('product.template', "taxes_id", [taxes_ref[self.sale_tax_id.id]], for_all_users=True, company_id=company.id)
IrDefault.sudo().set('product.template', "taxes_id", [taxes_ref[self.sale_tax_id.id]], company_id=company.id)
if self.purchase_tax_id and taxes_ref:
ir_values_obj.sudo().set_default('product.template', "supplier_taxes_id", [taxes_ref[self.purchase_tax_id.id]], for_all_users=True, company_id=company.id)
IrDefault.sudo().set('product.template', "supplier_taxes_id", [taxes_ref[self.purchase_tax_id.id]], company_id=company.id)
# Create Bank journals
self._create_bank_journals_from_o2m(company, acc_template_ref)
+1 -1
View File
@@ -199,7 +199,7 @@ class IrHttp(models.AbstractModel):
@classmethod
def _get_default_lang(cls):
lang_code = request.env['ir.values'].sudo().get_default('res.partner', 'lang')
lang_code = request.env['ir.default'].sudo().get('res.partner', 'lang')
if lang_code:
return request.env['res.lang'].search([('code', '=', lang_code)], limit=1)
return request.env['res.lang'].search([], limit=1)
@@ -540,14 +540,6 @@ http://kjs.mof.gov.cn/zhengwuxinxi/zhengcefabu/201111/t20111107_605525.html
<field name="expense_currency_exchange_account_id" ref="small_business_chart5712"/>
</record>
<record id="l10n_chart_china_small_business_value" model="ir.values">
<field name="name">小企业会计科目表(财会[2011]17号《小企业会计准则》)</field>
<field name="model">account.chart.template</field>
<field name="key">default</field>
<field name="res_id" ref="l10n_chart_china_small_business"/>
<field name="value" ref="base.CNY"/>
</record>
<!-- Account Tax Tags-->
<record id="tax_tag1" model="account.account.tag">
<field name="name">增值税17%销项税</field>
@@ -10,12 +10,5 @@
<field name="income_currency_exchange_account_id" ref="account_6061" />
<field name="expense_currency_exchange_account_id" ref="account_6061" />
</record>
<record id="l10n_chart_china_standard_business_value" model="ir.values">
<field name="name">中国会计科目表 (财会[2006]3号《企业会计准则》)</field>
<field name="model">account.chart.template</field>
<field name="key">default</field>
<field name="res_id" ref="l10n_chart_china_standard_business" />
<field name="value" ref="base.CNY" />
</record>
</data>
</odoo>
+1 -1
View File
@@ -31,7 +31,7 @@ class WebsitePayment(http.Controller):
# Try default one then fallback on first
acquirer_id = acquirer_id and int(acquirer_id) or \
env['ir.values'].get_default('payment.transaction', 'acquirer_id', company_id=user.company_id.id) or \
env['ir.default'].get('payment.transaction', 'acquirer_id', company_id=user.company_id.id) or \
env['payment.acquirer'].search([('website_published', '=', True), ('company_id', '=', user.company_id.id)])[0].id
acquirer = env['payment.acquirer'].with_context(submit_class='btn btn-primary pull-right',
@@ -3,7 +3,7 @@
<data noupdate="1">
<function id="purchase_default_set"
model="ir.values" name="set_default"
model="ir.default" name="set"
eval="('purchase.requisition', 'warehouse_id', ref('stock.warehouse0'))"/>
<record id="type_single" model="purchase.requisition.type">
+1 -1
View File
@@ -38,7 +38,7 @@ class Website(models.Model):
return self.env['res.lang'].search([]).ids
def _default_language(self):
lang_code = self.env['ir.values'].get_default('res.partner', 'lang')
lang_code = self.env['ir.default'].get('res.partner', 'lang')
def_lang = self.env['res.lang'].search([('code', '=', lang_code)], limit=1)
return def_lang.id if def_lang else self._active_languages()[0]
+2 -2
View File
@@ -10,8 +10,8 @@ class Website(models.Model):
values = super(Website, self)._prepare_sale_order_values(partner, pricelist)
if values['company_id']:
warehouse_id = (
self.env['ir.values'].get_default('sale.order', 'warehouse_id', company_id=values.get('company_id')) or
self.env['ir.values'].get_default('sale.order', 'warehouse_id') or
self.env['ir.default'].get('sale.order', 'warehouse_id', company_id=values.get('company_id')) or
self.env['ir.default'].get('sale.order', 'warehouse_id') or
self.env['stock.warehouse'].sudo().search([('company_id', '=', values['company_id'])], limit=1).id
)
if warehouse_id:
@@ -18,14 +18,14 @@ class WebsiteConfigSettings(models.TransientModel):
@api.multi
def set_values(self):
super(WebsiteConfigSettings, self).set_values()
self.env['ir.values'].sudo().set_default('product.template', 'inventory_availability', self.inventory_availability)
self.env['ir.values'].sudo().set_default('product.template', 'available_threshold', self.available_threshold if self.inventory_availability == 'threshold' else None)
IrDefault = self.env['ir.default'].sudo()
IrDefault.set('product.template', 'inventory_availability', self.inventory_availability)
IrDefault.set('product.template', 'available_threshold', self.available_threshold if self.inventory_availability == 'threshold' else None)
@api.model
def get_values(self):
res = super(WebsiteConfigSettings, self).get_values()
param = self.env['ir.values'].sudo()
res.update(inventory_availability=param.get_default('product.template', 'inventory_availability') or 'never',
available_threshold=param.get_default('product.template', 'available_threshold') or 5.0
)
IrDefault = self.env['ir.default'].sudo()
res.update(inventory_availability=IrDefault.get('product.template', 'inventory_availability') or 'never',
available_threshold=IrDefault.get('product.template', 'available_threshold') or 5.0)
return res
+1
View File
@@ -33,6 +33,7 @@ The kernel of Odoo, needed for all installation.
'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',
'ir/report_ir_model.xml',
+1
View File
@@ -11,6 +11,7 @@ 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
from . import ir_rule
+170
View File
@@ -0,0 +1,170 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import json
from odoo import api, fields, models, tools, _
from odoo.exceptions import ValidationError
class IrDefault(models.Model):
""" User-defined default values for fields. """
_name = 'ir.default'
_rec_name = 'field_id'
field_id = fields.Many2one('ir.model.fields', string="Field", required=True,
ondelete='cascade', index=True)
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")
condition = fields.Char('Condition', help="If set, applies the default upon condition.")
json_value = fields.Char('Default Value (JSON format)', required=True)
@api.model
def create(self, vals):
self.clear_caches()
return super(IrDefault, self).create(vals)
@api.multi
def write(self, vals):
if self:
self.clear_caches()
return super(IrDefault, self).write(vals)
@api.multi
def unlink(self):
if self:
self.clear_caches()
return super(IrDefault, self).unlink()
@api.model
def set(self, model_name, field_name, value, user_id=False, company_id=False, condition=False):
""" Defines a default value for the given field. Any entry for the same
scope (field, user, company) will be replaced. The value is encoded
in JSON to be stored to the database.
:param user_id: may be ``False`` for all users, ``True`` for the
current user, or any user id
:param company_id: may be ``False`` for all companies, ``True`` for
the current user's company, or any company id
:param condition: optional condition that restricts the
applicability of the default value; this is an
opaque string, but the client typically uses
single-field conditions in the form ``'key=val'``.
"""
if user_id is True:
user_id = self.env.uid
if company_id is True:
company_id = self.env.user.company_id.id
# check consistency of model_name, field_name, and value
try:
model = self.env[model_name]
field = model._fields[field_name]
field.convert_to_cache(value, model)
json_value = json.dumps(value, ensure_ascii=False)
except KeyError:
raise ValidationError(_("Invalid field %s.%s") % (model_name, field_name))
except Exception:
raise ValidationError(_("Invalid value for %s.%s: %s") % (model_name, field_name, value))
# update existing default for the same scope, or create one
field = self.env['ir.model.fields']._get(model_name, field_name)
default = self.search([
('field_id', '=', field.id),
('user_id', '=', user_id),
('company_id', '=', company_id),
('condition', '=', condition),
])
if default:
default.write({'json_value': json_value})
else:
self.create({
'field_id': field.id,
'user_id': user_id,
'company_id': company_id,
'condition': condition,
'json_value': json_value,
})
return True
@api.model
def get(self, model_name, field_name, user_id=False, company_id=False, condition=False):
""" Return the default value for the given field, user and company, or
``None`` if no default is available.
:param user_id: may be ``False`` for all users, ``True`` for the
current user, or any user id
:param company_id: may be ``False`` for all companies, ``True`` for
the current user's company, or any company id
:param condition: optional condition that restricts the
applicability of the default value; this is an
opaque string, but the client typically uses
single-field conditions in the form ``'key=val'``.
"""
if user_id is True:
user_id = self.env.uid
if company_id is True:
company_id = self.env.user.company_id.id
field = self.env['ir.model.fields']._get(model_name, field_name)
default = self.search([
('field_id', '=', field.id),
('user_id', '=', user_id),
('company_id', '=', company_id),
('condition', '=', condition),
], limit=1)
return json.loads(default.json_value) if default else None
@api.model
@tools.ormcache('self.env.uid', 'model_name', 'condition')
# Note about ormcache invalidation: it is not needed when deleting a field,
# a user, or a company, as the corresponding defaults will no longer be
# requested. It must only be done when a user's company is modified.
def get_model_defaults(self, model_name, condition=False):
""" Return the available default values for the given model (for the
current user), as a dict mapping field names to values.
"""
cr = self.env.cr
query = """ SELECT f.name, d.json_value FROM ir_default d
JOIN ir_model_fields f ON d.field_id=f.id
JOIN res_users u ON u.id=%s
WHERE f.model=%s
AND (d.user_id IS NULL OR d.user_id=u.id)
AND (d.company_id IS NULL OR d.company_id=u.company_id)
AND {}
ORDER BY d.user_id, d.company_id, d.id
"""
params = [self.env.uid, model_name]
if condition:
query = query.format("d.condition=%s")
params.append(condition)
else:
query = query.format("d.condition IS NULL")
cr.execute(query, params)
result = {}
for row in cr.fetchall():
# keep the highest priority default for each field
if row[0] not in result:
result[row[0]] = json.loads(row[1])
return result
@api.model
def discard_records(self, records):
""" Discard all the defaults of many2one fields using any of the given
records.
"""
json_vals = [json.dumps(id) for id in records.ids]
domain = [('field_id.ttype', '=', 'many2one'),
('field_id.relation', '=', records._name),
('json_value', 'in', json_vals)]
return self.search(domain).unlink()
@api.model
def discard_values(self, model_name, field_name, values):
""" Discard all the defaults for any of the given values. """
field = self.env['ir.model.fields']._get(model_name, field_name)
json_vals = [json.dumps(value, ensure_ascii=False) for value in values]
domain = [('field_id', '=', field.id), ('json_value', 'in', json_vals)]
return self.search(domain).unlink()
+62
View File
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="ir_default_form_view" model="ir.ui.view">
<field name="name">ir.default form view</field>
<field name="model">ir.default</field>
<field name="arch" type="xml">
<form string="User-defined Defaults">
<group>
<group>
<field name="field_id"/>
<field name="json_value"/>
</group>
<group>
<field name="user_id"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
</group>
</form>
</field>
</record>
<record id="ir_default_tree_view" model="ir.ui.view">
<field name="name">ir.default tree view</field>
<field name="model">ir.default</field>
<field name="arch" type="xml">
<tree string="User-defined Defaults">
<field name="field_id"/>
<field name="json_value"/>
<field name="user_id"/>
<field name="company_id" groups="base.group_multi_company"/>
</tree>
</field>
</record>
<record id="ir_default_search_view" model="ir.ui.view">
<field name="name">ir.default search view</field>
<field name="model">ir.default</field>
<field name="arch" type="xml">
<search string="User-defined Defaults">
<field name="field_id"/>
<field name="user_id"/>
<field name="company_id" groups="base.group_multi_company"/>
<group expand="0" string="Group By">
<filter string="User" domain="[]" context="{'group_by':'user_id'}"/>
<filter string="Company" domain="[]" context="{'group_by':'company_id'}"/>
</group>
</search>
</field>
</record>
<record id="ir_default_menu_action" model="ir.actions.act_window">
<field name="name">User-defined Defaults</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">ir.default</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="search_view_id" ref="ir_default_search_view"/>
</record>
<menuitem action="ir_default_menu_action" id="ir_default_menu" parent="next_id_6"/>
</odoo>
+4 -4
View File
@@ -469,14 +469,14 @@ class ResConfigSettings(models.TransientModel, ResConfigModuleInstallationMixin)
@api.model
def default_get(self, fields):
IrValues = self.env['ir.values']
IrDefault = self.env['ir.default']
classified = self._get_classified_fields()
res = super(ResConfigSettings, self).default_get(fields)
# defaults: take the corresponding default value they set
for name, model, field in classified['default']:
value = IrValues.get_default(model, field)
value = IrDefault.get(model, field)
if value is not None:
res[name] = value
@@ -517,7 +517,7 @@ class ResConfigSettings(models.TransientModel, ResConfigModuleInstallationMixin)
classified = self._get_classified_fields()
# default values fields
IrValues = self.env['ir.values'].sudo()
IrDefault = self.env['ir.default'].sudo()
for name, model, field in classified['default']:
if isinstance(self[name], models.BaseModel):
if self._fields[name].type == 'many2one':
@@ -526,7 +526,7 @@ class ResConfigSettings(models.TransientModel, ResConfigModuleInstallationMixin)
value = self[name].ids
else:
value = self[name]
IrValues.set_default(model, field, value)
IrDefault.set(model, field, value)
# group fields: modify group / implied groups
for name, groups, implied_group in classified['group']:
+6 -11
View File
@@ -163,10 +163,10 @@ class Lang(models.Model):
lang = self.search([('code', '=', lang_code)])
if not lang:
self.load_lang(lang_code)
IrValues = self.env['ir.values']
default_value = IrValues.get_defaults('res.partner', condition=False)
if not default_value:
IrValues.set_default('res.partner', 'lang', lang_code, condition=False)
IrDefault = self.env['ir.default']
default_value = IrDefault.get('res.partner', 'lang')
if default_value is None:
IrDefault.set('res.partner', 'lang', lang_code)
# set language of main company, created directly by db bootstrap SQL
partner = self.env.user.company_id.partner_id
if not partner.lang:
@@ -219,13 +219,8 @@ class Lang(models.Model):
if vals.get('active') == False:
if self.env['res.users'].search([('lang', 'in', lang_codes)]):
raise UserError(_("Cannot unactivate a language that is currently used by users."))
# delete linked ir.value specifying default partner's language
default_lang = self.env['ir.values'].search([
('key', '=', 'default'),
('name', '=', 'lang'),
('model', '=', 'res.partner')])
if default_lang and default_lang.value_unpickle in lang_codes:
default_lang.unlink()
# delete linked ir.default specifying default partner's language
self.env['ir.default'].discard_values('res.partner', 'lang', lang_codes)
res = super(Lang, self).write(vals)
self.clear_caches()
+1 -1
View File
@@ -355,7 +355,7 @@ class Users(models.Model):
if user.partner_id.company_id and user.partner_id.company_id.id != values['company_id']:
user.partner_id.write({'company_id': user.company_id.id})
# clear default ir values when company changes
self.env['ir.values'].get_defaults_dict.clear_cache(self.env['ir.values'])
self.env['ir.default'].clear_caches()
# clear caches linked to the users
if 'groups_id' in values:
@@ -111,6 +111,22 @@
<field name="perm_read" eval="False"/>
</record>
<record model="ir.rule" id="ir_default_user_rule">
<field name="name">Defaults: alter personal defaults</field>
<field name="model_id" ref="model_ir_default"/>
<field name="domain_force">[('user_id','=',user.id)]</field>
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
<field name="perm_read" eval="False"/>
</record>
<record model="ir.rule" id="ir_default_system_rule">
<field name="name">Defaults: alter all defaults</field>
<field name="model_id" ref="model_ir_default"/>
<field name="domain_force">[(1,'=',1)]</field>
<field name="groups" eval="[(4, ref('base.group_system'))]"/>
<field name="perm_read" eval="False"/>
</record>
<!-- Used for dashboard customizations, users should only be able to edit their own dashboards -->
<record model="ir.rule" id="ir_ui_view_custom_personal">
<field name="name">ir.ui.view_custom rule</field>
@@ -33,6 +33,9 @@
"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
"access_res_company_group_erp_manager","res_company group_erp_manager","model_res_company","group_erp_manager",1,1,1,1
"access_res_company_group_user","res_company group_user","model_res_company",,1,0,0,0
"access_res_country_group_all","res_country group_user_all","model_res_country",,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
33 access_ir_ui_view_group_system ir_ui_view group_system model_ir_ui_view group_system 1 1 1 1
34 access_ir_ui_view_custom_group_user ir_ui_view_custom_group_user model_ir_ui_view_custom 1 1 1 1
35 access_ir_values_group_all ir_values group_all model_ir_values 1 1 1 1
36 access_ir_default_all ir_default all model_ir_default 1 0 0 0
37 access_ir_default_group_user ir_default group_user model_ir_default group_user 1 1 1 1
38 access_ir_default_group_system ir_default group_system model_ir_default group_system 1 1 1 1
39 access_res_company_group_erp_manager res_company group_erp_manager model_res_company group_erp_manager 1 1 1 1
40 access_res_company_group_user res_company group_user model_res_company 1 0 0 0
41 access_res_country_group_all res_country group_user_all model_res_country 1 0 0 0
+1
View File
@@ -13,6 +13,7 @@ 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
from . import test_mimetypes
+108
View File
@@ -0,0 +1,108 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.exceptions import ValidationError
from odoo.tests.common import TransactionCase
class TestIrDefault(TransactionCase):
def test_defaults(self):
""" check the mechanism of user-defined defaults """
companyA = self.env.user.company_id
companyB = companyA.create({'name': 'CompanyB'})
user1 = self.env.user
user2 = user1.create({'name': 'u2', 'login': 'u2'})
user3 = user1.create({'name': 'u3', 'login': 'u3',
'company_id': companyB.id,
'company_ids': companyB.ids})
# create some default value for some model
IrDefault1 = self.env['ir.default']
IrDefault2 = IrDefault1.sudo(user2)
IrDefault3 = IrDefault1.sudo(user3)
# set a default value for all users
IrDefault1.search([('field_id.model', '=', 'res.partner')]).unlink()
IrDefault1.set('res.partner', 'ref', 'GLOBAL', user_id=False, company_id=False)
self.assertEqual(IrDefault1.get_model_defaults('res.partner'), {'ref': 'GLOBAL'},
"Can't retrieve the created default value for all users.")
self.assertEqual(IrDefault2.get_model_defaults('res.partner'), {'ref': 'GLOBAL'},
"Can't retrieve the created default value for all users.")
self.assertEqual(IrDefault3.get_model_defaults('res.partner'), {'ref': 'GLOBAL'},
"Can't retrieve the created default value for all users.")
# set a default value for current company (behavior of 'set default' from debug mode)
IrDefault1.set('res.partner', 'ref', 'COMPANY', user_id=False, company_id=True)
self.assertEqual(IrDefault1.get_model_defaults('res.partner'), {'ref': 'COMPANY'},
"Can't retrieve the created default value for company.")
self.assertEqual(IrDefault2.get_model_defaults('res.partner'), {'ref': 'COMPANY'},
"Can't retrieve the created default value for company.")
self.assertEqual(IrDefault3.get_model_defaults('res.partner'), {'ref': 'GLOBAL'},
"Unexpected default value for company.")
# set a default value for current user (behavior of 'set default' from debug mode)
IrDefault2.set('res.partner', 'ref', 'USER', user_id=True, company_id=True)
self.assertEqual(IrDefault1.get_model_defaults('res.partner'), {'ref': 'COMPANY'},
"Can't retrieve the created default value for user.")
self.assertEqual(IrDefault2.get_model_defaults('res.partner'), {'ref': 'USER'},
"Unexpected default value for user.")
self.assertEqual(IrDefault3.get_model_defaults('res.partner'), {'ref': 'GLOBAL'},
"Unexpected default value for company.")
# check default values on partners
default1 = IrDefault1.env['res.partner'].default_get(['ref']).get('ref')
self.assertEqual(default1, 'COMPANY', "Wrong default value.")
default2 = IrDefault2.env['res.partner'].default_get(['ref']).get('ref')
self.assertEqual(default2, 'USER', "Wrong default value.")
default3 = IrDefault3.env['res.partner'].default_get(['ref']).get('ref')
self.assertEqual(default3, 'GLOBAL', "Wrong default value.")
def test_conditions(self):
""" check user-defined defaults with condition """
IrDefault = self.env['ir.default']
# default without condition
IrDefault.search([('field_id.model', '=', 'res.partner')]).unlink()
IrDefault.set('res.partner', 'ref', 'X')
self.assertEqual(IrDefault.get_model_defaults('res.partner'),
{'ref': 'X'})
self.assertEqual(IrDefault.get_model_defaults('res.partner', condition='name=Agrolait'),
{})
# default with a condition
IrDefault.search([('field_id.model', '=', 'res.partner.title')]).unlink()
IrDefault.set('res.partner.title', 'shortcut', 'X')
IrDefault.set('res.partner.title', 'shortcut', 'Mr', condition='name=Mister')
self.assertEqual(IrDefault.get_model_defaults('res.partner.title'),
{'shortcut': 'X'})
self.assertEqual(IrDefault.get_model_defaults('res.partner.title', condition='name=Miss'),
{})
self.assertEqual(IrDefault.get_model_defaults('res.partner.title', condition='name=Mister'),
{'shortcut': 'Mr'})
def test_invalid(self):
""" check error cases with 'ir.default' """
IrDefault = self.env['ir.default']
with self.assertRaises(ValidationError):
IrDefault.set('unknown_model', 'unknown_field', 42)
with self.assertRaises(ValidationError):
IrDefault.set('res.partner', 'unknown_field', 42)
with self.assertRaises(ValidationError):
IrDefault.set('res.partner', 'lang', 'some_LANG')
with self.assertRaises(ValidationError):
IrDefault.set('res.partner', 'credit_limit', 'foo')
def test_removal(self):
""" check defaults for many2one with their value being removed """
IrDefault = self.env['ir.default']
IrDefault.search([('field_id.model', '=', 'res.partner')]).unlink()
# set a record as a default value
title = self.env['res.partner.title'].create({'name': 'President'})
IrDefault.set('res.partner', 'title', title.id)
self.assertEqual(IrDefault.get_model_defaults('res.partner'), {'title': title.id})
# delete the record, and check the presence of the default value
title.unlink()
self.assertEqual(IrDefault.get_model_defaults('res.partner'), {})
+10 -6
View File
@@ -975,6 +975,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
defaults = {}
parent_fields = defaultdict(list)
ir_defaults = self.env['ir.default'].get_model_defaults(self._name)
for name in fields_list:
# 1. look up context
@@ -983,11 +984,9 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
defaults[name] = self._context[key]
continue
# 2. look up ir_values
# Note: performance is good, because get_defaults_dict is cached!
ir_values_dict = self.env['ir.values'].get_defaults_dict(self._name)
if name in ir_values_dict:
defaults[name] = ir_values_dict[name]
# 2. look up ir.default
if name in ir_defaults:
defaults[name] = ir_defaults[name]
continue
field = self._fields.get(name)
@@ -2045,7 +2044,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
def _init_column(self, column_name):
""" Initialize the value of the given column for existing rows. """
# get the default value; ideally, we should use default_get(), but it
# fails due to ir.values not being ready
# fails due to ir.default not being ready
field = self._fields[column_name]
if field.default:
value = field.default(self)
@@ -2842,6 +2841,7 @@ 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']
for sub_ids in cr.split_for_in_conditions(self.ids):
@@ -2867,6 +2867,10 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
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))
# For the same reason, remove the relevant records in ir_attachment
# (the search is performed with sql as the search method of
# ir_attachment is overridden to hide attachments of deleted