summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOdoo's Mergebot <xmo+roboto@odoo.com>2020-05-28 07:13:56 +0200
committerGitHub <noreply@github.com>2020-05-28 07:13:56 +0200
commit41bf013e04db0d03ca3648b70329df2c47087ef2 (patch)
tree24fbdd78ed852c2f0b97b54476dea5bd736b3425
parent7b8d12e6dc47f1d519f9fc077b073e4ea6a24d71 (diff)
parent6db2a81ea2578615ccc17199dfc488745b2fc596 (diff)
[MERGE] base: make ir.property private
Only system users can access ir.property records. This PR is part of the long-term task id 8203 that plans to remove all access to ir.* models "Official" methods to interact with `ir.property`: - `_set_default(name, model, value, company=False)` - `_set_multi(name, model, values, default_value=None)` - `_get(name, model, res_id=False)` - `_get_multi(name, model, ids)` Done in this PR: - remove ACL on ir.property (only system users can access directly) - make all getter/setters private with sudo - use these methods everywhere instead of CRUD calls - add sudo where needed closes odoo/odoo#51658 Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
-rw-r--r--addons/account/models/account_account.py7
-rw-r--r--addons/account/models/account_payment_term.py5
-rw-r--r--addons/account/models/chart_template.py46
-rw-r--r--addons/account/tests/common.py10
-rw-r--r--addons/hr/security/ir.model.access.csv1
-rw-r--r--addons/hr_expense/models/hr_expense.py4
-rw-r--r--addons/mrp_subcontracting/models/res_company.py16
-rw-r--r--addons/point_of_sale/tests/test_frontend.py18
-rw-r--r--addons/pos_restaurant/tests/test_frontend.py2
-rw-r--r--addons/product/models/product_pricelist.py4
-rw-r--r--addons/product/models/res_company.py4
-rw-r--r--addons/product/models/res_partner.py4
-rw-r--r--addons/sale/security/ir.model.access.csv1
-rw-r--r--addons/stock/models/res_company.py35
-rw-r--r--addons/stock/security/ir.model.access.csv1
-rw-r--r--addons/stock_account/__init__.py9
-rw-r--r--addons/stock_account/models/account_chart_template.py37
-rw-r--r--addons/stock_account/tests/common.py4
-rw-r--r--addons/stock_landed_costs/models/stock_landed_cost.py7
-rw-r--r--addons/test_website_slides_full/tests/test_ui_wslides.py4
-rw-r--r--addons/website_sale/tests/test_website_sale_pricelist.py16
-rw-r--r--odoo/addons/base/models/ir_property.py35
-rw-r--r--odoo/addons/base/security/ir.model.access.csv4
-rw-r--r--odoo/addons/base/tests/test_orm.py15
-rw-r--r--odoo/addons/test_main_flows/tests/test_flow.py10
-rw-r--r--odoo/addons/test_new_api/tests/test_new_fields.py6
-rw-r--r--odoo/addons/test_performance/tests/test_performance.py13
-rw-r--r--odoo/fields.py6
-rw-r--r--odoo/models.py2
29 files changed, 131 insertions, 195 deletions
diff --git a/addons/account/models/account_account.py b/addons/account/models/account_account.py
index c9d2de963bd..d4def8834aa 100644
--- a/addons/account/models/account_account.py
+++ b/addons/account/models/account_account.py
@@ -432,9 +432,12 @@ class AccountAccount(models.Model):
raise UserError(_('You cannot perform this action on an account that contains journal items.'))
#Checking whether the account is set as a property to any Partner or not
values = ['account.account,%s' % (account_id,) for account_id in self.ids]
- partner_prop_acc = self.env['ir.property'].search([('value_reference', 'in', values)], limit=1)
+ partner_prop_acc = self.env['ir.property'].sudo().search([('value_reference', 'in', values)], limit=1)
if partner_prop_acc:
- raise UserError(_('You cannot remove/deactivate an account which is set on a customer or vendor.'))
+ account_name = partner_prop_acc.get_by_record().display_name
+ raise UserError(
+ _('You cannot remove/deactivate the account %s which is set on a customer or vendor.') % account_name
+ )
return super(AccountAccount, self).unlink()
def action_read_account(self):
diff --git a/addons/account/models/account_payment_term.py b/addons/account/models/account_payment_term.py
index bb918807168..c7d8dd8d734 100644
--- a/addons/account/models/account_payment_term.py
+++ b/addons/account/models/account_payment_term.py
@@ -71,8 +71,9 @@ class AccountPaymentTerm(models.Model):
for terms in self:
if self.env['account.move'].search([('invoice_payment_term_id', 'in', terms.ids)]):
raise UserError(_('You can not delete payment terms as other records still reference it. However, you can archive it.'))
- property_recs = self.env['ir.property'].search([('value_reference', 'in', ['account.payment.term,%s'%payment_term.id for payment_term in terms])])
- property_recs.unlink()
+ self.env['ir.property'].sudo().search(
+ [('value_reference', 'in', ['account.payment.term,%s'%payment_term.id for payment_term in terms])]
+ ).unlink()
return super(AccountPaymentTerm, self).unlink()
diff --git a/addons/account/models/chart_template.py b/addons/account/models/chart_template.py
index 202aa38b291..6f12b955724 100644
--- a/addons/account/models/chart_template.py
+++ b/addons/account/models/chart_template.py
@@ -207,9 +207,9 @@ class AccountChartTemplate(models.Model):
existing_journals = self.env['account.journal'].search([('company_id', '=', company.id)])
if existing_journals:
prop_values.extend(['account.journal,%s' % (journal_id,) for journal_id in existing_journals.ids])
- accounting_props = self.env['ir.property'].search([('value_reference', 'in', prop_values)])
- if accounting_props:
- accounting_props.sudo().unlink()
+ self.env['ir.property'].sudo().search(
+ [('value_reference', 'in', prop_values)]
+ ).unlink()
# delete account, journal, tax, fiscal position and reconciliation model
models_to_delete = ['account.reconcile.model', 'account.fiscal.position', 'account.tax', 'account.move', 'account.journal', 'account.group']
@@ -463,34 +463,22 @@ class AccountChartTemplate(models.Model):
self.ensure_one()
PropertyObj = self.env['ir.property']
todo_list = [
- ('property_account_receivable_id', 'res.partner', 'account.account'),
- ('property_account_payable_id', 'res.partner', 'account.account'),
- ('property_account_expense_categ_id', 'product.category', 'account.account'),
- ('property_account_income_categ_id', 'product.category', 'account.account'),
- ('property_account_expense_id', 'product.template', 'account.account'),
- ('property_account_income_id', 'product.template', 'account.account'),
- ('property_tax_payable_account_id', 'account.tax.group', 'account.account'),
- ('property_tax_receivable_account_id', 'account.tax.group', 'account.account'),
- ('property_advance_tax_payment_account_id', 'account.tax.group', 'account.account'),
+ ('property_account_receivable_id', 'res.partner'),
+ ('property_account_payable_id', 'res.partner'),
+ ('property_account_expense_categ_id', 'product.category'),
+ ('property_account_income_categ_id', 'product.category'),
+ ('property_account_expense_id', 'product.template'),
+ ('property_account_income_id', 'product.template'),
+ ('property_tax_payable_account_id', 'account.tax.group'),
+ ('property_tax_receivable_account_id', 'account.tax.group'),
+ ('property_advance_tax_payment_account_id', 'account.tax.group'),
]
- for record in todo_list:
- account = getattr(self, record[0])
- value = account and 'account.account,' + str(acc_template_ref[account.id]) or False
+ for field, model in todo_list:
+ account = self[field]
+ value = acc_template_ref[account.id] if account else False
if value:
- field = self.env['ir.model.fields'].search([('name', '=', record[0]), ('model', '=', record[1]), ('relation', '=', record[2])], limit=1)
- vals = {
- 'name': record[0],
- 'company_id': company.id,
- 'fields_id': field.id,
- 'value': value,
- }
- properties = PropertyObj.search([('name', '=', record[0]), ('company_id', '=', company.id)])
- if properties:
- #the property exist: modify it
- properties.write(vals)
- else:
- #create the property
- PropertyObj.create(vals)
+ PropertyObj._set_default(field, model, value, company=company)
+
stock_properties = [
'property_stock_account_input_categ_id',
'property_stock_account_output_categ_id',
diff --git a/addons/account/tests/common.py b/addons/account/tests/common.py
index b46ca6f93c4..5c665ef1092 100644
--- a/addons/account/tests/common.py
+++ b/addons/account/tests/common.py
@@ -213,11 +213,11 @@ class AccountTestCommon(SavepointCase):
# Properties: Product income and expense accounts, default parameters
Property = cls.env['ir.property']
- Property.set_default('property_account_receivable_id', 'res.partner', cls.a_recv, cls.company)
- Property.set_default('property_account_payable_id', 'res.partner', cls.a_pay, cls.company)
- Property.set_default('property_account_position_id', 'res.partner', False, cls.company)
- Property.set_default('property_account_expense_categ_id', 'product.category', cls.a_expense, cls.company)
- Property.set_default('property_account_income_categ_id', 'product.category', cls.a_sale, cls.company)
+ Property._set_default('property_account_receivable_id', 'res.partner', cls.a_recv, cls.company)
+ Property._set_default('property_account_payable_id', 'res.partner', cls.a_pay, cls.company)
+ Property._set_default('property_account_position_id', 'res.partner', False, cls.company)
+ Property._set_default('property_account_expense_categ_id', 'product.category', cls.a_expense, cls.company)
+ Property._set_default('property_account_income_categ_id', 'product.category', cls.a_sale, cls.company)
# Bank Accounts
cls.bank_account = cls.env['res.partner.bank'].create({
diff --git a/addons/hr/security/ir.model.access.csv b/addons/hr/security/ir.model.access.csv
index 906cef3ee87..5f5fbd458c9 100644
--- a/addons/hr/security/ir.model.access.csv
+++ b/addons/hr/security/ir.model.access.csv
@@ -8,7 +8,6 @@ access_hr_employee_resource_user,resource.resource.user,resource.model_resource_
access_hr_department_user,hr.department.user,model_hr_department,group_hr_user,1,1,1,1
access_hr_department_employee,hr.department.employee,model_hr_department,base.group_user,1,0,0,0
access_hr_job_user,hr.job user,model_hr_job,group_hr_user,1,1,1,1
-access_ir_property_hr_user,ir_property hr_user,base.model_ir_property,group_hr_user,1,1,1,0
access_hr_plan_activity_type_employee,access_hr_plan_activity_type,model_hr_plan_activity_type,base.group_user,1,0,0,0
access_hr_plan_employee,access_hr_plan_employee,model_hr_plan,base.group_user,1,0,0,0
access_hr_plan_activity_type_hr_user,access_hr_plan_activity_type,model_hr_plan_activity_type,group_hr_user,1,1,1,1
diff --git a/addons/hr_expense/models/hr_expense.py b/addons/hr_expense/models/hr_expense.py
index fe9e0bddc60..7c1c6734234 100644
--- a/addons/hr_expense/models/hr_expense.py
+++ b/addons/hr_expense/models/hr_expense.py
@@ -26,7 +26,7 @@ class HrExpense(models.Model):
@api.model
def _default_account_id(self):
- return self.env['ir.property'].get('property_account_expense_categ_id', 'product.category')
+ return self.env['ir.property']._get('property_account_expense_categ_id', 'product.category')
@api.model
def _get_employee_id_domain(self):
@@ -365,7 +365,7 @@ class HrExpense(models.Model):
raise UserError(
_("No Expense account found for the product %s (or for its category), please configure one.") % (self.product_id.name))
else:
- account = self.env['ir.property'].with_company(self.company_id).get('property_account_expense_categ_id', 'product.category')
+ account = self.env['ir.property'].with_company(self.company_id)._get('property_account_expense_categ_id', 'product.category')
if not account:
raise UserError(_('Please configure Default Expense account for Product expense: `property_account_expense_categ_id`.'))
return account
diff --git a/addons/mrp_subcontracting/models/res_company.py b/addons/mrp_subcontracting/models/res_company.py
index 14a7955e98f..583d2413916 100644
--- a/addons/mrp_subcontracting/models/res_company.py
+++ b/addons/mrp_subcontracting/models/res_company.py
@@ -21,10 +21,6 @@ class ResCompany(models.Model):
def _create_subcontracting_location(self):
parent_location = self.env.ref('stock.stock_location_locations', raise_if_not_found=False)
- property_stock_subcontractor_res_partner_field = self.env['ir.model.fields'].search([
- ('model', '=', 'res.partner'),
- ('name', '=', 'property_stock_subcontractor')
- ])
for company in self:
subcontracting_location = self.env['stock.location'].create({
'name': _('Subcontracting Location'),
@@ -32,10 +28,10 @@ class ResCompany(models.Model):
'location_id': parent_location.id,
'company_id': company.id,
})
- self.env['ir.property'].create({
- 'name': 'property_stock_subcontractor_%s' % company.name,
- 'fields_id': property_stock_subcontractor_res_partner_field.id,
- 'company_id': company.id,
- 'value': 'stock.location,%d' % subcontracting_location.id,
- })
+ self.env['ir.property']._set_default(
+ "property_stock_subcontractor",
+ "res.partner",
+ subcontracting_location,
+ company,
+ )
company.subcontracting_location_id = subcontracting_location
diff --git a/addons/point_of_sale/tests/test_frontend.py b/addons/point_of_sale/tests/test_frontend.py
index 63807196588..9fe59733ba1 100644
--- a/addons/point_of_sale/tests/test_frontend.py
+++ b/addons/point_of_sale/tests/test_frontend.py
@@ -30,12 +30,7 @@ class TestPointOfSaleHttpCommon(odoo.tests.HttpCase):
'reconcile': True})
self.env.company.account_default_pos_receivable_account_id = account_receivable
- self.env['ir.property'].set_default(
- 'property_account_receivable_id',
- 'res.partner',
- account_receivable,
- main_company,
- )
+ self.env['ir.property']._set_default('property_account_receivable_id', 'res.partner', account_receivable, main_company)
cash_journal = journal_obj.create({
'name': 'Cash Test',
@@ -400,12 +395,11 @@ class TestPointOfSaleHttpCommon(odoo.tests.HttpCase):
# Change the default sale pricelist of customers,
# so the js tests can expect deterministically this pricelist when selecting a customer.
- field = env['ir.model.fields']._get('res.partner', 'property_product_pricelist')
- env['ir.property'].search([
- ('name', '=', 'property_product_pricelist'),
- ('fields_id', '=', field.id),
- ('res_id', '=', False)
- ]).write({'value_reference': 'product.pricelist,%s' % public_pricelist.id})
+ env['ir.property']._set_default(
+ "property_product_pricelist",
+ "res.partner",
+ public_pricelist,
+ )
@odoo.tests.tagged('post_install', '-at_install')
diff --git a/addons/pos_restaurant/tests/test_frontend.py b/addons/pos_restaurant/tests/test_frontend.py
index 44ae56444c2..28d023f294e 100644
--- a/addons/pos_restaurant/tests/test_frontend.py
+++ b/addons/pos_restaurant/tests/test_frontend.py
@@ -86,7 +86,7 @@ class TestFrontend(odoo.tests.HttpCase):
'user_type_id': self.env.ref('account.data_account_type_receivable').id,
'reconcile': True})
- self.env['ir.property'].set_default(
+ self.env['ir.property']._set_default(
'property_account_receivable_id',
'res.partner',
account_receivable,
diff --git a/addons/product/models/product_pricelist.py b/addons/product/models/product_pricelist.py
index 4938c9c313b..680ed729cf9 100644
--- a/addons/product/models/product_pricelist.py
+++ b/addons/product/models/product_pricelist.py
@@ -340,7 +340,7 @@ class Pricelist(models.Model):
pl_domain = self._get_partner_pricelist_multi_search_domain_hook(company_id)
# if no specific property, try to find a fitting pricelist
- result = Property.get_multi('property_product_pricelist', Partner._name, partner_ids)
+ result = Property._get_multi('property_product_pricelist', Partner._name, partner_ids)
remaining_partner_ids = [pid for pid, val in result.items() if not val or
not val._get_partner_pricelist_multi_filter_hook()]
@@ -348,7 +348,7 @@ class Pricelist(models.Model):
# get fallback pricelist when no pricelist for a given country
pl_fallback = (
Pricelist.search(pl_domain + [('country_group_ids', '=', False)], limit=1) or
- Property.get('property_product_pricelist', 'res.partner') or
+ Property._get('property_product_pricelist', 'res.partner') or
Pricelist.search(pl_domain, limit=1)
)
# group partners by country, and find a pricelist for each country
diff --git a/addons/product/models/res_company.py b/addons/product/models/res_company.py
index 94e053eda23..5a44de1afc1 100644
--- a/addons/product/models/res_company.py
+++ b/addons/product/models/res_company.py
@@ -18,7 +18,7 @@ class ResCompany(models.Model):
'name': _("Default %(currency)s pricelist") % params,
'currency_id': new_company.currency_id.id,
})
- self.env['ir.property'].sudo().set_default(
+ self.env['ir.property']._set_default(
'property_product_pricelist',
'res.partner',
pricelist,
@@ -54,7 +54,7 @@ class ResCompany(models.Model):
'name': _("Default %(currency)s pricelist") % params,
'currency_id': currency_id,
})
- self.env['ir.property'].sudo().set_default(
+ self.env['ir.property']._set_default(
'property_product_pricelist',
'res.partner',
pricelist,
diff --git a/addons/product/models/res_partner.py b/addons/product/models/res_partner.py
index 786923ef5a4..5b641d5f811 100644
--- a/addons/product/models/res_partner.py
+++ b/addons/product/models/res_partner.py
@@ -29,11 +29,11 @@ class Partner(models.Model):
limit=1
)
default_for_country = pls and pls[0]
- actual = self.env['ir.property'].get('property_product_pricelist', 'res.partner', 'res.partner,%s' % partner.id)
+ actual = self.env['ir.property']._get('property_product_pricelist', 'res.partner', 'res.partner,%s' % partner.id)
# update at each change country, and so erase old pricelist
if partner.property_product_pricelist or (actual and default_for_country and default_for_country.id != actual.id):
# keep the company of the current user before sudo
- self.env['ir.property'].sudo().set_multi(
+ self.env['ir.property']._set_multi(
'property_product_pricelist',
partner._name,
{partner.id: partner.property_product_pricelist or default_for_country.id},
diff --git a/addons/sale/security/ir.model.access.csv b/addons/sale/security/ir.model.access.csv
index c09cd3a62ff..e380e0d77a1 100644
--- a/addons/sale/security/ir.model.access.csv
+++ b/addons/sale/security/ir.model.access.csv
@@ -19,7 +19,6 @@ access_sale_order_readonly,sale.order.accountant,model_sale_order,account.group_
access_sale_order_accountant,sale.order.accountant,model_sale_order,account.group_account_user,1,1,0,0
access_sale_report_salesman,sale.report,model_sale_report,sales_team.group_sale_salesman,1,1,1,0
access_sale_report_manager,sale.report,model_sale_report,sales_team.group_sale_manager,1,1,1,1
-access_ir_property_sales,ir.property.sales,base.model_ir_property,sales_team.group_sale_salesman,1,1,1,1
access_sale_account_journal,account.journal sale order.user,account.model_account_journal,sales_team.group_sale_salesman,1,0,0,0
access_res_partner_sale_user,res.partner.sale.user,base.model_res_partner,sales_team.group_sale_salesman,1,0,0,0
access_res_partner_sale_manager,res.partner.sale.manager,base.model_res_partner,sales_team.group_sale_manager,1,1,1,0
diff --git a/addons/stock/models/res_company.py b/addons/stock/models/res_company.py
index 2e7c5bd474c..4ae579ebaeb 100644
--- a/addons/stock/models/res_company.py
+++ b/addons/stock/models/res_company.py
@@ -47,7 +47,6 @@ class Company(models.Model):
def _create_inventory_loss_location(self):
parent_location = self.env.ref('stock.stock_location_locations_virtual', raise_if_not_found=False)
- inventory_loss_product_template_field = self.env['ir.model.fields'].search([('model','=','product.template'),('name','=','property_stock_inventory')])
for company in self:
inventory_loss_location = self.env['stock.location'].create({
'name': 'Inventory adjustment',
@@ -55,16 +54,15 @@ class Company(models.Model):
'location_id': parent_location.id,
'company_id': company.id,
})
- self.env['ir.property'].create({
- 'name': 'property_stock_inventory_%s' % company.name,
- 'fields_id': inventory_loss_product_template_field.id,
- 'company_id': company.id,
- 'value': 'stock.location,%d' % inventory_loss_location.id,
- })
+ self.env['ir.property']._set_default(
+ "property_stock_inventory",
+ "product.template",
+ inventory_loss_location,
+ company.id,
+ )
def _create_production_location(self):
parent_location = self.env.ref('stock.stock_location_locations_virtual', raise_if_not_found=False)
- production_product_template_field = self.env['ir.model.fields'].search([('model','=','product.template'),('name','=','property_stock_production')])
for company in self:
production_location = self.env['stock.location'].create({
'name': 'Production',
@@ -72,12 +70,13 @@ class Company(models.Model):
'location_id': parent_location.id,
'company_id': company.id,
})
- self.env['ir.property'].create({
- 'name': 'property_stock_inventory_%s' % company.name,
- 'fields_id': production_product_template_field.id,
- 'company_id': company.id,
- 'value': 'stock.location,%d' % production_location.id,
- })
+ self.env['ir.property']._set_default(
+ "property_stock_production",
+ "product.template",
+ production_location,
+ company.id,
+ )
+
def _create_scrap_location(self):
parent_location = self.env.ref('stock.stock_location_locations_virtual', raise_if_not_found=False)
@@ -129,16 +128,16 @@ class Company(models.Model):
@api.model
def create_missing_inventory_loss_location(self):
company_ids = self.env['res.company'].search([])
- inventory_loss_product_template_field = self.env['ir.model.fields'].search([('model','=','product.template'),('name','=','property_stock_inventory')])
- companies_having_property = self.env['ir.property'].search([('fields_id', '=', inventory_loss_product_template_field.id)]).mapped('company_id')
+ inventory_loss_product_template_field = self.env['ir.model.fields']._get('product.template', 'property_stock_inventory')
+ companies_having_property = self.env['ir.property'].sudo().search([('fields_id', '=', inventory_loss_product_template_field.id)]).mapped('company_id')
company_without_property = company_ids - companies_having_property
company_without_property._create_inventory_loss_location()
@api.model
def create_missing_production_location(self):
company_ids = self.env['res.company'].search([])
- production_product_template_field = self.env['ir.model.fields'].search([('model','=','product.template'),('name','=','property_stock_production')])
- companies_having_property = self.env['ir.property'].search([('fields_id', '=', production_product_template_field.id)]).mapped('company_id')
+ production_product_template_field = self.env['ir.model.fields']._get('product.template', 'property_stock_production')
+ companies_having_property = self.env['ir.property'].sudo().search([('fields_id', '=', production_product_template_field.id)]).mapped('company_id')
company_without_property = company_ids - companies_having_property
company_without_property._create_production_location()
diff --git a/addons/stock/security/ir.model.access.csv b/addons/stock/security/ir.model.access.csv
index ea20a1f51c5..3ad0386e7d6 100644
--- a/addons/stock/security/ir.model.access.csv
+++ b/addons/stock/security/ir.model.access.csv
@@ -27,7 +27,6 @@ access_product_product_stock_manager,product.product stock_manager,product.model
access_product_packaging_stock_manager,product.packaging stock_manager,product.model_product_packaging,stock.group_stock_manager,1,1,1,1
access_product_supplierinfo_stock_manager,product.supplierinfo stock_manager,product.model_product_supplierinfo,stock.group_stock_manager,1,1,1,1
access_product_pricelist_stock_manager,product.pricelist stock_manager,product.model_product_pricelist,stock.group_stock_manager,1,1,1,1
-access_ir_property_group_stock_manager,ir_property group_stock_manager,base.model_ir_property,stock.group_stock_manager,1,1,1,1
access_product_group_res_partner_stock_manager,res_partner group_stock_manager,base.model_res_partner,stock.group_stock_manager,1,1,1,0
access_product_pricelist_item_stock_manager,product.pricelist.item stock_manager,product.model_product_pricelist_item,stock.group_stock_manager,1,1,1,1
access_stock_warehouse_orderpoint,stock.warehouse.orderpoint,model_stock_warehouse_orderpoint,stock.group_stock_user,1,0,0,0
diff --git a/addons/stock_account/__init__.py b/addons/stock_account/__init__.py
index e0fb76fd2d7..d4786823b49 100644
--- a/addons/stock_account/__init__.py
+++ b/addons/stock_account/__init__.py
@@ -16,8 +16,9 @@ def _configure_journals(cr, registry):
for company_id in company_ids:
# Check if property exists for stock account journal exists
- properties = env['ir.property'].search([
- ('name', '=', 'property_stock_journal'),
+ field = env['ir.model.fields']._get("product.category", "property_stock_journal")
+ properties = env['ir.property'].sudo().search([
+ ('fields_id', '=', field.id),
('company_id', '=', company_id.id)])
# If not, check if you can find a journal that is already there with the same name, otherwise create one
@@ -34,7 +35,7 @@ def _configure_journals(cr, registry):
'company_id': company_id.id,
'show_on_dashboard': False
}).id
- env['ir.property'].set_default(
+ env['ir.property']._set_default(
'property_stock_journal',
'product.category',
journal_id,
@@ -51,7 +52,7 @@ def _configure_journals(cr, registry):
for name in todo_list:
account = getattr(company_id, name)
if account:
- env['ir.property'].set_default(
+ env['ir.property']._set_default(
name,
'product.category',
account,
diff --git a/addons/stock_account/models/account_chart_template.py b/addons/stock_account/models/account_chart_template.py
index 16796b947c5..8f6105d09bb 100644
--- a/addons/stock_account/models/account_chart_template.py
+++ b/addons/stock_account/models/account_chart_template.py
@@ -20,43 +20,16 @@ class AccountChartTemplate(models.Model):
PropertyObj = self.env['ir.property'] # Property Stock Journal
value = self.env['account.journal'].search([('company_id', '=', company.id), ('code', '=', 'STJ'), ('type', '=', 'general')], limit=1)
if value:
- field = self.env['ir.model.fields'].search([('name', '=', 'property_stock_journal'), ('model', '=', 'product.category'), ('relation', '=', 'account.journal')], limit=1)
- vals = {
- 'name': 'property_stock_journal',
- 'company_id': company.id,
- 'fields_id': field.id,
- 'value': 'account.journal,%s' % value.id,
- }
- properties = PropertyObj.search([('name', '=', 'property_stock_journal'), ('company_id', '=', company.id)])
- if properties:
- # the property exist: modify it
- properties.write(vals)
- else:
- # create the property
- PropertyObj.create(vals)
+ PropertyObj._set_default("property_stock_journal", "product.category", value, company)
todo_list = [ # Property Stock Accounts
'property_stock_account_input_categ_id',
'property_stock_account_output_categ_id',
'property_stock_valuation_account_id',
]
- for record in todo_list:
- account = getattr(self, record)
- value = account and 'account.account,' + str(acc_template_ref[account.id]) or False
- if value:
- field = self.env['ir.model.fields'].search([('name', '=', record), ('model', '=', 'product.category'), ('relation', '=', 'account.account')], limit=1)
- vals = {
- 'name': record,
- 'company_id': company.id,
- 'fields_id': field.id,
- 'value': value,
- }
- properties = PropertyObj.search([('name', '=', record), ('company_id', '=', company.id)], limit=1)
- if not properties:
- # create the property
- PropertyObj.create(vals)
- elif not properties.value_reference:
- # update the property if False
- properties.write(vals)
+ for field in todo_list:
+ account = self[field]
+ value = acc_template_ref[account.id] if account else False
+ PropertyObj._set_default(field, "product.category", value, company)
return res
diff --git a/addons/stock_account/tests/common.py b/addons/stock_account/tests/common.py
index 68d79a1b8d9..6eec8bce93c 100644
--- a/addons/stock_account/tests/common.py
+++ b/addons/stock_account/tests/common.py
@@ -11,13 +11,13 @@ class StockAccountTestCommon(AccountTestCommon):
super(StockAccountTestCommon, cls).setUpClass()
# Properties: Stock valuation account and journal
- cls.env['ir.property'].set_default(
+ cls.env['ir.property']._set_default(
'property_stock_valuation_account_id',
'product.category',
cls.stk,
cls.env.company,
)
- cls.env['ir.property'].set_default(
+ cls.env['ir.property']._set_default(
'property_stock_journal',
'product.category',
cls.miscellaneous_journal,
diff --git a/addons/stock_landed_costs/models/stock_landed_cost.py b/addons/stock_landed_costs/models/stock_landed_cost.py
index 66f5a6e9a45..63222bc1385 100644
--- a/addons/stock_landed_costs/models/stock_landed_cost.py
+++ b/addons/stock_landed_costs/models/stock_landed_cost.py
@@ -28,12 +28,7 @@ class StockLandedCost(models.Model):
if self.env.company.lc_journal_id:
lc_journal = self.env.company.lc_journal_id
else:
- ir_property = self.env['ir.property'].search([
- ('name', '=', 'property_stock_journal'),
- ('company_id', '=', self.env.company.id)
- ], limit=1)
- if ir_property:
- lc_journal = ir_property.get_by_record()
+ lc_journal = self.env['ir.property']._get("property_stock_journal", "product.category")
return lc_journal
name = fields.Char(
diff --git a/addons/test_website_slides_full/tests/test_ui_wslides.py b/addons/test_website_slides_full/tests/test_ui_wslides.py
index e8b45d55d7e..c3e999db7a8 100644
--- a/addons/test_website_slides_full/tests/test_ui_wslides.py
+++ b/addons/test_website_slides_full/tests/test_ui_wslides.py
@@ -41,8 +41,8 @@ class TestUi(TestUICommon):
})
Property = self.env['ir.property']
- Property.set_default('property_account_receivable_id', 'res.partner', a_recv, self.env.company)
- Property.set_default('property_account_payable_id', 'res.partner', a_pay, self.env.company)
+ Property._set_default('property_account_receivable_id', 'res.partner', a_recv, self.env.company)
+ Property._set_default('property_account_payable_id', 'res.partner', a_pay, self.env.company)
product_course_channel_6 = self.env['product.product'].create({
'name': 'DIY Furniture Course',
diff --git a/addons/website_sale/tests/test_website_sale_pricelist.py b/addons/website_sale/tests/test_website_sale_pricelist.py
index 04306b9b263..01d5e58049d 100644
--- a/addons/website_sale/tests/test_website_sale_pricelist.py
+++ b/addons/website_sale/tests/test_website_sale_pricelist.py
@@ -432,19 +432,9 @@ class TestWebsitePriceListMultiCompany(TransactionCaseWithUserDemo):
# Ensure everything was done correctly
self.assertEqual(self.demo_user.partner_id.with_company(self.company1.id).property_product_pricelist, self.c1_pl)
self.assertEqual(self.demo_user.partner_id.with_company(self.company2.id).property_product_pricelist, self.c2_pl)
- irp1 = self.env['ir.property'].search([
- ('name', '=', 'property_product_pricelist'),
- ('company_id', '=', self.company1.id),
- ('res_id', '=', 'res.partner,%s' % self.demo_user.partner_id.id),
- ('value_reference', '=', 'product.pricelist,%s' % self.c1_pl.id),
- ])
- irp2 = self.env['ir.property'].search([
- ('name', '=', 'property_product_pricelist'),
- ('company_id', '=', self.company2.id),
- ('res_id', '=', 'res.partner,%s' % self.demo_user.partner_id.id),
- ('value_reference', '=', 'product.pricelist,%s' % self.c2_pl.id),
- ])
- self.assertEqual(len(irp1 + irp2), 2, "Ensure there is an `ir.property` for demo partner for every company, and that the pricelist is the company specific one.")
+ irp1 = self.env['ir.property'].with_company(self.company1)._get("property_product_pricelist", "res.partner", self.demo_user.partner_id.id)
+ irp2 = self.env['ir.property'].with_company(self.company2)._get("property_product_pricelist", "res.partner", self.demo_user.partner_id.id)
+ self.assertEqual((irp1, irp2), (self.c1_pl, self.c2_pl), "Ensure there is an `ir.property` for demo partner for every company, and that the pricelist is the company specific one.")
simulate_frontend_context(self)
# ---------------------------------- IR.PROPERTY -------------------------------------
# id | name | res_id | company_id | value_reference
diff --git a/odoo/addons/base/models/ir_property.py b/odoo/addons/base/models/ir_property.py
index f554f013ac5..aa9a6c04535 100644
--- a/odoo/addons/base/models/ir_property.py
+++ b/odoo/addons/base/models/ir_property.py
@@ -176,7 +176,7 @@ class Property(models.Model):
return False
@api.model
- def set_default(self, name, model, value, company=False):
+ def _set_default(self, name, model, value, company=False):
""" Set the given field's generic value for the given company.
:param name: the field's name
@@ -186,7 +186,7 @@ class Property(models.Model):
"""
field_id = self.env['ir.model.fields']._get(model, name).id
company_id = int(company) if company else False
- prop = self.search([
+ prop = self.sudo().search([
('fields_id', '=', field_id),
('company_id', '=', company_id),
('res_id', '=', False),
@@ -194,7 +194,7 @@ class Property(models.Model):
if prop:
prop.write({'value': value})
else:
- self.create({
+ prop.create({
'fields_id': field_id,
'company_id': company_id,
'res_id': False,
@@ -204,7 +204,14 @@ class Property(models.Model):
})
@api.model
- def get(self, name, model, res_id=False):
+ def _get(self, name, model, res_id=False):
+ """ Get the given field's generic value for the record.
+
+ :param name: the field's name
+ :param model: the field's model name
+ :param res_id: optional resource, format: "<id>" (int) or
+ "<model>,<id>" (str)
+ """
if not res_id:
t, v = self._get_default_property(name, model)
if not v or t != 'many2one':
@@ -216,7 +223,7 @@ class Property(models.Model):
return p.get_by_record()
return False
- # only cache Property.get(res_id=False) as that's
+ # only cache Property._get(res_id=False) as that's
# sub-optimally.
COMPANY_KEY = "self.env.company.id"
@ormcache(COMPANY_KEY, 'name', 'model')
@@ -232,10 +239,12 @@ class Property(models.Model):
def _get_property(self, name, model, res_id):
domain = self._get_domain(name, model)
if domain is not None:
+ if res_id and isinstance(res_id, int):
+ res_id = "%s,%s" % (model, res_id)
domain = [('res_id', '=', res_id)] + domain
#make the search with company_id asc to make sure that properties specific to a company are given first
- return self.search(domain, limit=1, order='company_id')
- return self.browse(())
+ return self.sudo().search(domain, limit=1, order='company_id')
+ return self.sudo().browse(())
def _get_domain(self, prop_name, model):
self._cr.execute("SELECT id FROM ir_model_fields WHERE name=%s AND model=%s", (prop_name, model))
@@ -246,7 +255,7 @@ class Property(models.Model):
return [('fields_id', '=', res[0]), ('company_id', 'in', [company_id, False])]
@api.model
- def get_multi(self, name, model, ids):
+ def _get_multi(self, name, model, ids):
""" Read the property field `name` for the records of model `model` with
the given `ids`, and return a dictionary mapping `ids` to their
corresponding value.
@@ -310,7 +319,7 @@ class Property(models.Model):
}
@api.model
- def set_multi(self, name, model, values, default_value=None):
+ def _set_multi(self, name, model, values, default_value=None):
""" Assign the property field `name` for the records of model `model`
with `values` (dictionary mapping record ids to their value).
If the value for a given record is the same as the default
@@ -331,14 +340,14 @@ class Property(models.Model):
if domain is None:
raise Exception()
# retrieve the default value for the field
- default_value = clean(self.get(name, model))
+ default_value = clean(self._get(name, model))
# retrieve the properties corresponding to the given record ids
self._cr.execute("SELECT id FROM ir_model_fields WHERE name=%s AND model=%s", (name, model))
field_id = self._cr.fetchone()[0]
company_id = self.env.company.id
refs = {('%s,%s' % (model, id)): id for id in values}
- props = self.search([
+ props = self.sudo().search([
('fields_id', '=', field_id),
('company_id', '=', company_id),
('res_id', 'in', list(refs)),
@@ -351,8 +360,6 @@ class Property(models.Model):
if value == default_value:
# avoid prop.unlink(), as it clears the record cache that can
# contain the value of other properties to set on record!
- prop.check_access_rights('unlink')
- prop.check_access_rule('unlink')
self._cr.execute("DELETE FROM ir_property WHERE id=%s", [prop.id])
elif value != clean(prop.get_by_record()):
prop.write({'value': value})
@@ -370,7 +377,7 @@ class Property(models.Model):
'value': value,
'type': self.env[model]._fields[name].type,
})
- self.create(vals_list)
+ self.sudo().create(vals_list)
@api.model
def search_multi(self, name, model, operator, value):
diff --git a/odoo/addons/base/security/ir.model.access.csv b/odoo/addons/base/security/ir.model.access.csv
index 328d36cc421..0a0abc9d090 100644
--- a/odoo/addons/base/security/ir.model.access.csv
+++ b/odoo/addons/base/security/ir.model.access.csv
@@ -20,8 +20,8 @@
"access_ir_module_module_group_user","ir_module_module group_user","model_ir_module_module","group_system",1,1,1,1
"access_ir_module_module_dependency_group_system","ir_module_module_dependency group_system","model_ir_module_module_dependency","group_system",1,1,1,1
"access_ir_module_module_exclusion_group_system","ir_module_module_exclusion group_system","model_ir_module_module_exclusion","group_system",1,1,1,1
-"access_ir_property_group_user","ir_property group_user","model_ir_property",,1,0,0,0
-"access_ir_property_group_user_manager","ir_property group_manager","model_ir_property","base.group_partner_manager",1,1,1,0
+"access_ir_property_group_user","ir_property group_user","model_ir_property",,0,0,0,0
+"access_ir_property_group_system","ir_property group_system","model_ir_property","base.group_system",1,1,1,0
"access_ir_rule_group_erp_manager","ir_rule group_erp_manager","model_ir_rule","group_erp_manager",1,1,1,1
"access_ir_sequence_group_user","ir_sequence group_user","model_ir_sequence","group_user",1,0,0,0
"access_ir_sequence_group_system","ir_sequence group_system","model_ir_sequence","group_system",1,1,1,1
diff --git a/odoo/addons/base/tests/test_orm.py b/odoo/addons/base/tests/test_orm.py
index 2e0406e6b5b..285e4b67290 100644
--- a/odoo/addons/base/tests/test_orm.py
+++ b/odoo/addons/base/tests/test_orm.py
@@ -235,21 +235,18 @@ class TestORM(TransactionCase):
'groups_id': [(6, 0, [self.ref('base.group_partner_manager')])],
})
p1 = self.env['res.partner'].with_user(user).create({'name': 'Zorro'})
- p1_prop = self.env['ir.property'].with_user(user).create({
- 'name': 'Slip en laine',
- 'res_id': 'res.partner,{}'.format(p1.id),
- 'fields_id': self.env['ir.model.fields'].search([
- ('model', '=', 'res.partner'), ('name', '=', 'ref')], limit=1).id,
- 'value_text': 'Nain poilu',
- 'type': 'char',
- })
+ self.env['ir.property'].with_user(user)._set_multi("ref", "res.partner", {p1.id: "Nain poilu"})
+ p1_prop = self.env['ir.property'].with_user(user)._get("ref", "res.partner", res_id=p1.id)
+ self.assertEqual(
+ p1_prop, "Nain poilu", 'p1_prop should have been created')
# Unlink with unprivileged user
p1.unlink()
# ir.property is deleted
+ p1_prop = self.env['ir.property'].with_user(user)._get("ref", "res.partner", res_id=p1.id)
self.assertEqual(
- p1_prop.exists(), self.env['ir.property'], 'p1_prop should have been deleted')
+ p1_prop, False, 'p1_prop should have been deleted')
def test_create_multi(self):
""" create for multiple records """
diff --git a/odoo/addons/test_main_flows/tests/test_flow.py b/odoo/addons/test_main_flows/tests/test_flow.py
index 4aaca90ed4d..6d2cfab311b 100644
--- a/odoo/addons/test_main_flows/tests/test_flow.py
+++ b/odoo/addons/test_main_flows/tests/test_flow.py
@@ -37,11 +37,11 @@ class BaseTestUi(odoo.tests.HttpCase):
})
Property = self.env['ir.property']
- Property.set_default('property_account_receivable_id', 'res.partner', a_recv, self.env.company)
- Property.set_default('property_account_payable_id', 'res.partner', a_pay, self.env.company)
- Property.set_default('property_account_position_id', 'res.partner', False, self.env.company)
- Property.set_default('property_account_expense_categ_id', 'product.category', a_expense, self.env.company)
- Property.set_default('property_account_income_categ_id', 'product.category', a_sale, self.env.company)
+ Property._set_default('property_account_receivable_id', 'res.partner', a_recv, self.env.company)
+ Property._set_default('property_account_payable_id', 'res.partner', a_pay, self.env.company)
+ Property._set_default('property_account_position_id', 'res.partner', False, self.env.company)
+ Property._set_default('property_account_expense_categ_id', 'product.category', a_expense, self.env.company)
+ Property._set_default('property_account_income_categ_id', 'product.category', a_sale, self.env.company)
self.expenses_journal = self.env['account.journal'].create({
'name': 'Vendor Bills - Test',
diff --git a/odoo/addons/test_new_api/tests/test_new_fields.py b/odoo/addons/test_new_api/tests/test_new_fields.py
index 6df342aaf94..44a1fe695bf 100644
--- a/odoo/addons/test_new_api/tests/test_new_fields.py
+++ b/odoo/addons/test_new_api/tests/test_new_fields.py
@@ -1071,9 +1071,9 @@ class TestFields(TransactionCaseWithUserDemo):
tag2 = self.env['test_new_api.multi.tag'].create({'name': 'Quuz'})
# create default values for the company-dependent fields
- self.env['ir.property'].set_default('foo', 'test_new_api.company', 'default')
- self.env['ir.property'].set_default('foo', 'test_new_api.company', 'default1', company1)
- self.env['ir.property'].set_default('tag_id', 'test_new_api.company', tag0)
+ self.env['ir.property']._set_default('foo', 'test_new_api.company', 'default')
+ self.env['ir.property']._set_default('foo', 'test_new_api.company', 'default1', company1)
+ self.env['ir.property']._set_default('tag_id', 'test_new_api.company', tag0)
# assumption: users don't have access to 'ir.property'
accesses = self.env['ir.model.access'].search([('model_id.model', '=', 'ir.property')])
diff --git a/odoo/addons/test_performance/tests/test_performance.py b/odoo/addons/test_performance/tests/test_performance.py
index d77ef7c1a21..01bab7187e2 100644
--- a/odoo/addons/test_performance/tests/test_performance.py
+++ b/odoo/addons/test_performance/tests/test_performance.py
@@ -459,7 +459,7 @@ class TestIrPropertyOptimizations(TransactionCase):
self.Eggs = self.env['test_performance.eggs']
def test_with_falsy_default(self):
- self.assertFalse(self.env['ir.property'].get('property_eggs', 'test_performance.bacon'))
+ self.assertFalse(self.env['ir.property']._get('property_eggs', 'test_performance.bacon'))
# warmup
eggs = self.Eggs.create({})
@@ -485,14 +485,9 @@ class TestIrPropertyOptimizations(TransactionCase):
def test_with_truthy_default(self):
eggs = self.Eggs.create({})
- field = self.env['ir.model.fields']._get('test_performance.bacon', 'property_eggs')
- self.env['ir.property'].create({
- 'name': 'property_eggs_with_bacon',
- 'fields_id': field.id,
- 'value': eggs,
- })
-
- self.assertEqual(eggs, self.env['ir.property'].get('property_eggs', 'test_performance.bacon'))
+ self.env['ir.property']._set_default("property_eggs", "test_performance.bacon", eggs)
+
+ self.assertEqual(eggs, self.env['ir.property']._get('property_eggs', 'test_performance.bacon'))
# warmup
self.Bacon.create({})
diff --git a/odoo/fields.py b/odoo/fields.py
index d64555e0025..56f58364809 100644
--- a/odoo/fields.py
+++ b/odoo/fields.py
@@ -571,12 +571,12 @@ class Field(MetaField('DummyField', (object,), {})):
#
def _default_company_dependent(self, model):
- return model.env['ir.property'].get(self.name, self.model_name)
+ return model.env['ir.property']._get(self.name, self.model_name)
def _compute_company_dependent(self, records):
# read property as superuser, as the current user may not have access
Property = records.env['ir.property'].sudo()
- values = Property.get_multi(self.name, self.model_name, records.ids)
+ values = Property._get_multi(self.name, self.model_name, records.ids)
for record in records:
record[self.name] = values.get(record.id)
@@ -587,7 +587,7 @@ class Field(MetaField('DummyField', (object,), {})):
record.id: self.convert_to_write(record[self.name], record)
for record in records
}
- Property.set_multi(self.name, self.model_name, values)
+ Property._set_multi(self.name, self.model_name, values)
def _search_company_dependent(self, records, operator, value):
Property = records.env['ir.property']
diff --git a/odoo/models.py b/odoo/models.py
index 8af30b89bb5..f88bcce1dca 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -3705,7 +3705,7 @@ Record ids: %(records)s
if not field:
raise ValueError("Invalid field %r on model %r" % (key, self._name))
if field.company_dependent:
- irprop_def = self.env['ir.property'].get(key, self._name)
+ irprop_def = self.env['ir.property']._get(key, self._name)
cached_def = field.convert_to_cache(irprop_def, self)
cached_val = field.convert_to_cache(val, self)
if cached_val == cached_def: