diff options
| author | Pierre Masereel <pim@odoo.com> | 2019-11-15 15:38:48 +0000 |
|---|---|---|
| committer | Raphael Collet <rco@odoo.com> | 2019-11-22 12:34:43 +0000 |
| commit | e85faf398659a5beb0b1570a06af64dcf78dc1c8 (patch) | |
| tree | 2726de4e47cb5f61bfd748416f85f3fadfb6bf7d /addons | |
| parent | 8821f0e9176e3b976828f088ce5b7f5c6517b0c7 (diff) | |
[IMP] base: add unique constraint on ir.property
There is no unique constraint on the properties to avoid having two
properties for the same field, company and res_id.
Having two properties for the same field, company and res_id, leads to
inconsistencies through the code, as reading a company-dependent field
nondeterministically returns one of the available property value.
So now, before creating a property, we have to check that there is not
already a value for the field, company and res_id and write or create
depending on if it is already exists.
The properties of specific records already satisfy the constraint thanks
to the implementation of company-dependent fields that use the method
`set_multi`. We added a method `set_default` to set generic properties,
and its implementation does the right thing. It also simplifies the
code to set such properties, by the way.
closes odoo/odoo#40473
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Co-authored-by: Raphael Collet <rco@odoo.com>
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/account/tests/common.py | 32 | ||||
| -rw-r--r-- | addons/point_of_sale/tests/test_frontend.py | 12 | ||||
| -rw-r--r-- | addons/pos_restaurant/tests/test_frontend.py | 13 | ||||
| -rw-r--r-- | addons/product/models/res_company.py | 28 | ||||
| -rw-r--r-- | addons/stock_account/__init__.py | 65 | ||||
| -rw-r--r-- | addons/stock_account/tests/common.py | 23 | ||||
| -rw-r--r-- | addons/test_website_slides_full/tests/test_ui_wslides.py | 17 |
7 files changed, 66 insertions, 124 deletions
diff --git a/addons/account/tests/common.py b/addons/account/tests/common.py index c2ea7307021..b3362bf9c43 100644 --- a/addons/account/tests/common.py +++ b/addons/account/tests/common.py @@ -206,32 +206,12 @@ class AccountTestCommon(SavepointCase): }) # Properties: Product income and expense accounts, default parameters - cls.env['ir.property'].create([{ - 'name': 'property_account_receivable_id', - 'fields_id': cls.env['ir.model.fields'].search([('model', '=', 'res.partner'), ('name', '=', 'property_account_receivable_id')], limit=1).id, - 'value': 'account.account,%s' % (cls.a_recv.id), - 'company_id': cls.company.id, - }, { - 'name': 'property_account_payable_id', - 'fields_id': cls.env['ir.model.fields'].search([('model', '=', 'res.partner'), ('name', '=', 'property_account_payable_id')], limit=1).id, - 'value': 'account.account,%s' % (cls.a_pay.id), - 'company_id': cls.company.id, - }, { - 'name': 'property_account_position_id', - 'fields_id': cls.env['ir.model.fields'].search([('model', '=', 'res.partner'), ('name', '=', 'property_account_position_id')], limit=1).id, - 'value': False, - 'company_id': cls.company.id, - }, { - 'name': 'property_account_expense_categ_id', - 'fields_id': cls.env['ir.model.fields'].search([('model', '=', 'product.category'), ('name', '=', 'property_account_expense_categ_id')], limit=1).id, - 'value': 'account.account,%s' % (cls.a_expense.id), - 'company_id': cls.company.id, - }, { - 'name': 'property_account_income_categ_id', - 'fields_id': cls.env['ir.model.fields'].search([('model', '=', 'product.category'), ('name', '=', 'property_account_income_categ_id')], limit=1).id, - 'value': 'account.account,%s' % (cls.a_sale.id), - 'company_id': cls.company.id, - }]) + 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) # Bank Accounts cls.bank_account = cls.env['res.partner.bank'].create({ diff --git a/addons/point_of_sale/tests/test_frontend.py b/addons/point_of_sale/tests/test_frontend.py index 1b323572ff4..02447e04ab4 100644 --- a/addons/point_of_sale/tests/test_frontend.py +++ b/addons/point_of_sale/tests/test_frontend.py @@ -29,11 +29,13 @@ class TestPointOfSaleHttpCommon(odoo.tests.HttpCase): 'user_type_id': env.ref('account.data_account_type_receivable').id, 'reconcile': True}) self.env.company.account_default_pos_receivable_account_id = account_receivable - field = env['ir.model.fields']._get('res.partner', 'property_account_receivable_id') - env['ir.property'].create({'name': 'property_account_receivable_id', - 'company_id': main_company.id, - 'fields_id': field.id, - 'value': 'account.account,' + str(account_receivable.id)}) + + self.env['ir.property'].set_default( + 'property_account_receivable_id', + 'res.partner', + account_receivable, + main_company, + ) cash_journal = journal_obj.create({ 'name': 'Cash Test', diff --git a/addons/pos_restaurant/tests/test_frontend.py b/addons/pos_restaurant/tests/test_frontend.py index b4d5a8b3ed8..03120b757c6 100644 --- a/addons/pos_restaurant/tests/test_frontend.py +++ b/addons/pos_restaurant/tests/test_frontend.py @@ -56,11 +56,14 @@ class TestFrontend(odoo.tests.HttpCase): 'name': 'Account Receivable - Test', 'user_type_id': env.ref('account.data_account_type_receivable').id, 'reconcile': True}) - field = env['ir.model.fields']._get('res.partner', 'property_account_receivable_id') - env['ir.property'].create({'name': 'property_account_receivable_id', - 'company_id': main_company.id, - 'fields_id': field.id, - 'value': 'account.account,' + str(account_receivable.id)}) + + self.env['ir.property'].set_default( + 'property_account_receivable_id', + 'res.partner', + account_receivable, + main_company, + ) + test_sale_journal = env['account.journal'].create({ 'name': 'Sales Journal - Test', 'code': 'TSJ', diff --git a/addons/product/models/res_company.py b/addons/product/models/res_company.py index 5de5704aed4..94e053eda23 100644 --- a/addons/product/models/res_company.py +++ b/addons/product/models/res_company.py @@ -18,13 +18,12 @@ class ResCompany(models.Model): 'name': _("Default %(currency)s pricelist") % params, 'currency_id': new_company.currency_id.id, }) - field = self.env['ir.model.fields']._get('res.partner', 'property_product_pricelist') - self.env['ir.property'].sudo().create({ - 'name': 'property_product_pricelist', - 'value_reference': 'product.pricelist,%s' % pricelist.id, - 'fields_id': field.id, - 'company_id': new_company.id, - }) + self.env['ir.property'].sudo().set_default( + 'property_product_pricelist', + 'res.partner', + pricelist, + new_company, + ) return new_company def write(self, values): @@ -38,7 +37,7 @@ class ResCompany(models.Model): nb_companies = self.search_count([]) for company in self: existing_pricelist = ProductPricelist.search( - [('company_id', 'in', (False, company.id)), + [('company_id', 'in', (False, company.id)), ('currency_id', '=', currency_id)]) if existing_pricelist: continue @@ -55,11 +54,10 @@ class ResCompany(models.Model): 'name': _("Default %(currency)s pricelist") % params, 'currency_id': currency_id, }) - field = self.env['ir.model.fields'].search([('model', '=', 'res.partner'), ('name', '=', 'property_product_pricelist')]) - self.env['ir.property'].sudo().create({ - 'name': 'property_product_pricelist', - 'company_id': company.id, - 'value_reference': 'product.pricelist,%s' % pricelist.id, - 'fields_id': field.id - }) + self.env['ir.property'].sudo().set_default( + 'property_product_pricelist', + 'res.partner', + pricelist, + company, + ) return super(ResCompany, self).write(values) diff --git a/addons/stock_account/__init__.py b/addons/stock_account/__init__.py index 74f33e2e2b7..e0fb76fd2d7 100644 --- a/addons/stock_account/__init__.py +++ b/addons/stock_account/__init__.py @@ -34,16 +34,12 @@ def _configure_journals(cr, registry): 'company_id': company_id.id, 'show_on_dashboard': False }).id - vals = { - 'name': 'property_stock_journal', - 'fields_id': env['ir.model.fields'].search([ - ('name', '=', 'property_stock_journal'), - ('model', '=', 'product.category'), - ('relation', '=', 'account.journal')], limit=1).id, - 'company_id': company_id.id, - 'value': 'account.journal,' + str(journal_id) - } - env['ir.property'].create(vals) + env['ir.property'].set_default( + 'property_stock_journal', + 'product.category', + journal_id, + company_id, + ) # Property Stock Accounts todo_list = [ @@ -52,43 +48,12 @@ def _configure_journals(cr, registry): 'property_stock_valuation_account_id', ] - for record in todo_list: - account = getattr(company_id, record) - value = account and 'account.account,' + str(account.id) or False - if value: - field_id = env['ir.model.fields'].search([ - ('name', '=', record), - ('model', '=', 'product.category'), - ('relation', '=', 'account.account') - ], limit=1).id - vals = { - 'name': record, - 'company_id': company_id.id, - 'fields_id': field_id, - 'value': value, - } - properties = env['ir.property'].search([ - ('name', '=', record), - ('company_id', '=', company_id.id), - ]) - if properties: - properties.write(vals) - else: - # create the property - env['ir.property'].create(vals) - - stock_account = env.ref('account.demo_stock_account', False) - if stock_account: - account_id = env['account.account'].search([('tag_ids', '=', stock_account.id)], limit=1).id - fields_id = env['ir.model.fields'].search([('model', '=', 'product.category'), ('name', '=', 'property_stock_valuation_account_id')], limit=1).id - if not account_id: - account_id = env['account.account'].search([('user_type_id', '=', env.ref('account.data_account_type_current_assets').id)], limit=1).id - if account_id: - xml_id = 'stock_account.property_stock_valuation_account_id' - vals = { - 'name': 'property_stock_valuation_account_id', - 'fields_id': fields_id, - 'value': 'account.account,'+str(account_id), - 'company_id': env.ref('base.main_company').id, - } - env['ir.property']._load_records([dict(xml_id=xml_id, values=vals, noupdate=True)]) + for name in todo_list: + account = getattr(company_id, name) + if account: + env['ir.property'].set_default( + name, + 'product.category', + account, + company_id, + ) diff --git a/addons/stock_account/tests/common.py b/addons/stock_account/tests/common.py index ae153a77cb1..68d79a1b8d9 100644 --- a/addons/stock_account/tests/common.py +++ b/addons/stock_account/tests/common.py @@ -11,14 +11,15 @@ class StockAccountTestCommon(AccountTestCommon): super(StockAccountTestCommon, cls).setUpClass() # Properties: Stock valuation account and journal - cls.env['ir.property'].create([{ - 'name': 'property_stock_valuation_account_id', - 'fields_id': cls.env['ir.model.fields'].search([('model', '=', 'product.category'), ('name', '=', 'property_stock_valuation_account_id')], limit=1).id, - 'value': 'account.account,%s' % (cls.stk.id), - 'company_id': cls.env.company.id, - }, { - 'name': 'property_stock_valuation_journal', - 'fields_id': cls.env['ir.model.fields'].search([('model', '=', 'product.category'), ('name', '=', 'property_stock_journal')], limit=1).id, - 'value': 'account.journal,%s' % (cls.miscellaneous_journal.id), - 'company_id': cls.env.company.id, - }]) + cls.env['ir.property'].set_default( + 'property_stock_valuation_account_id', + 'product.category', + cls.stk, + cls.env.company, + ) + cls.env['ir.property'].set_default( + 'property_stock_journal', + 'product.category', + cls.miscellaneous_journal, + cls.env.company, + ) 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 39ff909e2b5..d0785e059dd 100644 --- a/addons/test_website_slides_full/tests/test_ui_wslides.py +++ b/addons/test_website_slides_full/tests/test_ui_wslides.py @@ -24,7 +24,7 @@ class TestUi(TestUICommon): 'email': 'admin@yourcompany.example.com', }) - # Specify Accounting Data + # Specify Accounting Data cash_journal = self.env['account.journal'].create({'name': 'Cash - Test', 'type': 'cash', 'code': 'CASH - Test'}) self.env['payment.acquirer'].search([('journal_id', '=', False)]).journal_id = cash_journal a_recv = self.env['account.account'].create({ @@ -39,17 +39,10 @@ class TestUi(TestUICommon): 'user_type_id': self.env.ref('account.data_account_type_payable').id, 'reconcile': True, }) - self.env['ir.property'].create([{ - 'name': 'property_account_receivable_id', - 'fields_id': self.env['ir.model.fields'].search([('model', '=', 'res.partner'), ('name', '=', 'property_account_receivable_id')], limit=1).id, - 'value': 'account.account,%s' % (a_recv.id), - 'company_id': self.env.company.id, - }, { - 'name': 'property_account_payable_id', - 'fields_id': self.env['ir.model.fields'].search([('model', '=', 'res.partner'), ('name', '=', 'property_account_payable_id')], limit=1).id, - 'value': 'account.account,%s' % (a_pay.id), - 'company_id': self.env.company.id, - }]) + + 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) product_course_channel_6 = self.env['product.product'].create({ 'name': 'DIY Furniture Course', |
