summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Smet <las@odoo.com>2019-12-13 08:01:19 +0000
committerLaurent Smet <las@odoo.com>2019-12-16 13:34:45 +0000
commite4eb845af59d45fdd13f7cc88d083549b890427e (patch)
tree89f95fd6477900f5736355516d6fd374079e7d24
parentb4587e955399f9ee19885b2d44588d119c9492d6 (diff)
[FIX] account: Fix missing constrains about multi-companies.
There is actually nothing preventing changing the company of some records even there is some journal entries/items that are using them. closes odoo/odoo#41945 X-original-commit: b3b66304eb98819cd87d6e4c7a29ca4803ffc3ff Signed-off-by: oco-odoo <oco-odoo@users.noreply.github.com>
-rw-r--r--addons/account/i18n/account.pot30
-rw-r--r--addons/account/models/account.py59
-rw-r--r--addons/account/models/account_analytic_line.py49
-rw-r--r--addons/account/tests/__init__.py4
-rw-r--r--addons/account/tests/test_account_account.py39
-rw-r--r--addons/account/tests/test_account_analytic.py62
-rw-r--r--addons/account/tests/test_account_journal.py30
-rw-r--r--addons/account/tests/test_account_tax.py40
8 files changed, 311 insertions, 2 deletions
diff --git a/addons/account/i18n/account.pot b/addons/account/i18n/account.pot
index 2ce5f729127..ba0010f0906 100644
--- a/addons/account/i18n/account.pot
+++ b/addons/account/i18n/account.pot
@@ -12082,3 +12082,33 @@ msgstr ""
#: model_terms:ir.ui.view,arch_db:account.view_bank_statement_form
msgid "→ Count"
msgstr ""
+
+#. module: account
+#: code:addons/account/models/account.py:0
+#, python-format
+msgid "You can't change the company of your account since there are some journal items linked to it."
+msgstr ""
+
+#. module: account
+#: code:addons/account/models/account.py:0
+#, python-format
+msgid "You can't change the company of your journal since there are some journal entries linked to it."
+msgstr ""
+
+#. module: account
+#: code:addons/account/models/account.py:0
+#, python-format
+msgid "You can't change the company of your tax since there are some journal items linked to it."
+msgstr ""
+
+#. module: account
+#: code:addons/account/models/account_analytic_line.py:0
+#, python-format
+msgid "You can't set a different company on your analytic account since there are some journal items linked to it."
+msgstr ""
+
+#. module: account
+#: code:addons/account/models/account_analytic_line.py:0
+#, python-format
+msgid "You can't set a different company on your analytic tags since there are some journal items linked to it."
+msgstr ""
diff --git a/addons/account/models/account.py b/addons/account/models/account.py
index 524efd3adc6..f335bd66354 100644
--- a/addons/account/models/account.py
+++ b/addons/account/models/account.py
@@ -406,6 +406,22 @@ class AccountAccount(models.Model):
if ids:
raise ValidationError(_('Some journal items already exist with this account but in other journals than the allowed ones.'))
+ @api.constrains('company_id')
+ def _check_company_consistency(self):
+ if not self:
+ return
+
+ self.flush(['company_id'])
+ self._cr.execute('''
+ SELECT line.id
+ FROM account_move_line line
+ JOIN account_account account ON account.id = line.account_id
+ WHERE line.account_id IN %s
+ AND line.company_id != account.company_id
+ ''', [tuple(self.ids)])
+ if self._cr.fetchone():
+ raise UserError(_("You can't change the company of your account since there are some journal items linked to it."))
+
@api.depends('code')
def _compute_account_root(self):
# this computes the first 2 digits of the account.
@@ -1059,6 +1075,22 @@ class AccountJournal(models.Model):
if journal.bank_account_id.partner_id != journal.company_id.partner_id:
raise ValidationError(_('The holder of a journal\'s bank account must be the company (%s).') % journal.company_id.name)
+ @api.constrains('company_id')
+ def _check_company_consistency(self):
+ if not self:
+ return
+
+ self.flush(['company_id'])
+ self._cr.execute('''
+ SELECT move.id
+ FROM account_move move
+ JOIN account_journal journal ON journal.id = move.journal_id
+ WHERE move.journal_id IN %s
+ AND move.company_id != journal.company_id
+ ''', [tuple(self.ids)])
+ if self._cr.fetchone():
+ raise UserError(_("You can't change the company of your journal since there are some journal entries linked to it."))
+
@api.onchange('default_debit_account_id')
def onchange_debit_account_id(self):
if not self.default_credit_account_id:
@@ -1541,7 +1573,32 @@ class AccountTax(models.Model):
if not tax._check_m2m_recursion('children_tax_ids'):
raise ValidationError(_("Recursion found for tax '%s'.") % (tax.name,))
if not all(child.type_tax_use in ('none', tax.type_tax_use) for child in tax.children_tax_ids):
- raise ValidationError(_('The application scope of taxes in a group must be either the same as the group or left empty.'))
+ raise ValidationError(_('The application scope of taxes in a group must be either the same as the group or left empty.'))\
+
+ @api.constrains('company_id')
+ def _check_company_consistency(self):
+ if not self:
+ return
+
+ self.flush(['company_id'])
+ self._cr.execute('''
+ SELECT line.id
+ FROM account_move_line line
+ JOIN account_tax tax ON tax.id = line.tax_line_id
+ WHERE line.tax_line_id IN %s
+ AND line.company_id != tax.company_id
+
+ UNION ALL
+
+ SELECT line.id
+ FROM account_move_line_account_tax_rel tax_rel
+ JOIN account_tax tax ON tax.id = tax_rel.account_tax_id
+ JOIN account_move_line line ON line.id = tax_rel.account_move_line_id
+ WHERE tax_rel.account_tax_id IN %s
+ AND line.company_id != tax.company_id
+ ''', [tuple(self.ids)] * 2)
+ if self._cr.fetchone():
+ raise UserError(_("You can't change the company of your tax since there are some journal items linked to it."))
@api.returns('self', lambda value: value.id)
def copy(self, default=None):
diff --git a/addons/account/models/account_analytic_line.py b/addons/account/models/account_analytic_line.py
index 60e80ab015a..3b02d93e5b2 100644
--- a/addons/account/models/account_analytic_line.py
+++ b/addons/account/models/account_analytic_line.py
@@ -1,7 +1,54 @@
# -*- coding: utf-8 -*-
from odoo import api, fields, models, _
-from math import copysign
+from odoo.exceptions import UserError
+
+
+class AccountAnalyticAccount(models.Model):
+ _inherit = 'account.analytic.account'
+
+ @api.constrains('company_id')
+ def _check_company_consistency(self):
+ analytic_accounts = self.filtered('company_id')
+
+ if not analytic_accounts:
+ return
+
+ self.flush(['company_id'])
+ self._cr.execute('''
+ SELECT line.id
+ FROM account_move_line line
+ JOIN account_analytic_account account ON account.id = line.analytic_account_id
+ WHERE line.analytic_account_id IN %s
+ AND line.company_id != account.company_id
+ ''', [tuple(analytic_accounts.ids)])
+
+ if self._cr.fetchone():
+ raise UserError(_("You can't set a different company on your analytic account since there are some journal items linked to it."))
+
+
+class AccountAnalyticTag(models.Model):
+ _inherit = 'account.analytic.tag'
+
+ @api.constrains('company_id')
+ def _check_company_consistency(self):
+ analytic_tags = self.filtered('company_id')
+
+ if not analytic_tags:
+ return
+
+ self.flush(['company_id'])
+ self._cr.execute('''
+ SELECT line.id
+ FROM account_analytic_tag_account_move_line_rel tag_rel
+ JOIN account_analytic_tag tag ON tag.id = tag_rel.account_analytic_tag_id
+ JOIN account_move_line line ON line.id = tag_rel.account_move_line_id
+ WHERE tag_rel.account_analytic_tag_id IN %s
+ AND line.company_id != tag.company_id
+ ''', [tuple(analytic_tags.ids)])
+
+ if self._cr.fetchone():
+ raise UserError(_("You can't set a different company on your analytic tags since there are some journal items linked to it."))
class AccountAnalyticLine(models.Model):
diff --git a/addons/account/tests/__init__.py b/addons/account/tests/__init__.py
index 4614179269f..f160b87453f 100644
--- a/addons/account/tests/__init__.py
+++ b/addons/account/tests/__init__.py
@@ -5,6 +5,10 @@ from . import test_account_move_out_refund
from . import test_account_move_in_invoice
from . import test_account_move_in_refund
from . import test_account_move_entry
+from . import test_account_journal
+from . import test_account_account
+from . import test_account_tax
+from . import test_account_analytic
from . import test_account_payment
from . import test_account_move_partner_count
from . import test_account_move_rounding
diff --git a/addons/account/tests/test_account_account.py b/addons/account/tests/test_account_account.py
new file mode 100644
index 00000000000..61ed7666cbb
--- /dev/null
+++ b/addons/account/tests/test_account_account.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+from odoo.addons.account.tests.common import AccountTestInvoicingCommon
+from odoo.tests import tagged
+from odoo.exceptions import UserError
+
+
+@tagged('post_install', '-at_install')
+class TestAccountAccount(AccountTestInvoicingCommon):
+
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+
+ # Create another company.
+ cls.company_data_2 = cls.setup_company_data('company_2_data')
+
+ # By default, tests are run with the current user set on the first company.
+ cls.env.user.company_id = cls.company_data['company']
+
+ def test_changing_account_company(self):
+ ''' Ensure you can't change the company of an account.account if there are some journal entries '''
+
+ self.env['account.move'].create({
+ 'type': 'entry',
+ 'date': '2019-01-01',
+ 'line_ids': [
+ (0, 0, {
+ 'name': 'line_debit',
+ 'account_id': self.company_data['default_account_revenue'].id,
+ }),
+ (0, 0, {
+ 'name': 'line_credit',
+ 'account_id': self.company_data['default_account_revenue'].id,
+ }),
+ ],
+ })
+
+ with self.assertRaises(UserError), self.cr.savepoint():
+ self.company_data['default_account_revenue'].company_id = self.company_data_2['company']
diff --git a/addons/account/tests/test_account_analytic.py b/addons/account/tests/test_account_analytic.py
new file mode 100644
index 00000000000..c8251f71838
--- /dev/null
+++ b/addons/account/tests/test_account_analytic.py
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+from odoo.addons.account.tests.common import AccountTestInvoicingCommon
+from odoo.tests import tagged
+from odoo.exceptions import UserError
+
+
+@tagged('post_install', '-at_install')
+class TestAccountAnalyticAccount(AccountTestInvoicingCommon):
+
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+
+ cls.env.user.write({
+ 'groups_id': [
+ (4, cls.env.ref('analytic.group_analytic_accounting').id),
+ (4, cls.env.ref('analytic.group_analytic_tags').id),
+ ],
+ })
+
+ # Create another company.
+ cls.company_data_2 = cls.setup_company_data('company_2_data')
+
+ # By default, tests are run with the current user set on the first company.
+ cls.env.user.company_id = cls.company_data['company']
+
+ cls.test_analytic_account = cls.env['account.analytic.account'].create({'name': 'test_analytic_account'})
+ cls.test_analytic_tag = cls.env['account.analytic.tag'].create({'name': 'test_analytic_tag'})
+
+ def test_changing_analytic_company(self):
+ ''' Ensure you can't change the company of an account.analytic.account if there are some journal entries '''
+
+ self.env['account.move'].create({
+ 'type': 'entry',
+ 'date': '2019-01-01',
+ 'line_ids': [
+ (0, 0, {
+ 'name': 'line_debit',
+ 'account_id': self.company_data['default_account_revenue'].id,
+ 'analytic_account_id': self.test_analytic_account.id,
+ 'analytic_tag_ids': [(6, 0, self.test_analytic_tag.ids)],
+ }),
+ (0, 0, {
+ 'name': 'line_credit',
+ 'account_id': self.company_data['default_account_revenue'].id,
+ }),
+ ],
+ })
+
+ # Set a different company on the analytic account.
+ with self.assertRaises(UserError), self.cr.savepoint():
+ self.test_analytic_account.company_id = self.company_data_2['company']
+
+ # Making the analytic account not company dependent is allowed.
+ self.test_analytic_account.company_id = False
+
+ # Set a different company on the analytic tag.
+ with self.assertRaises(UserError), self.cr.savepoint():
+ self.test_analytic_tag.company_id = self.company_data_2['company']
+
+ # Making the analytic tag not company dependent is allowed.
+ self.test_analytic_tag.company_id = False
diff --git a/addons/account/tests/test_account_journal.py b/addons/account/tests/test_account_journal.py
new file mode 100644
index 00000000000..10d2c58d9e5
--- /dev/null
+++ b/addons/account/tests/test_account_journal.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+from odoo.addons.account.tests.common import AccountTestInvoicingCommon
+from odoo.tests import tagged
+from odoo.exceptions import UserError
+
+
+@tagged('post_install', '-at_install')
+class TestAccountJournal(AccountTestInvoicingCommon):
+
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+
+ # Create another company.
+ cls.company_data_2 = cls.setup_company_data('company_2_data')
+
+ # By default, tests are run with the current user set on the first company.
+ cls.env.user.company_id = cls.company_data['company']
+
+ def test_changing_journal_company(self):
+ ''' Ensure you can't change the company of an account.journal if there are some journal entries '''
+
+ self.env['account.move'].create({
+ 'type': 'entry',
+ 'date': '2019-01-01',
+ 'journal_id': self.company_data['default_journal_sale'].id,
+ })
+
+ with self.assertRaises(UserError), self.cr.savepoint():
+ self.company_data['default_journal_sale'].company_id = self.company_data_2['company']
diff --git a/addons/account/tests/test_account_tax.py b/addons/account/tests/test_account_tax.py
new file mode 100644
index 00000000000..6a81294bcec
--- /dev/null
+++ b/addons/account/tests/test_account_tax.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+from odoo.addons.account.tests.common import AccountTestInvoicingCommon
+from odoo.tests import tagged
+from odoo.exceptions import UserError
+
+
+@tagged('post_install', '-at_install')
+class TestAccountTax(AccountTestInvoicingCommon):
+
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+
+ # Create another company.
+ cls.company_data_2 = cls.setup_company_data('company_2_data')
+
+ # By default, tests are run with the current user set on the first company.
+ cls.env.user.company_id = cls.company_data['company']
+
+ def test_changing_tax_company(self):
+ ''' Ensure you can't change the company of an account.tax if there are some journal entries '''
+
+ # Avoid duplicate key value violates unique constraint "account_tax_name_company_uniq".
+ self.company_data['default_tax_sale'].name = 'test_changing_account_company'
+
+ self.env['account.move'].create({
+ 'type': 'out_invoice',
+ 'date': '2019-01-01',
+ 'invoice_line_ids': [
+ (0, 0, {
+ 'name': 'invoice_line',
+ 'quantity': 1.0,
+ 'price_unit': 100.0,
+ 'tax_ids': [(6, 0, self.company_data['default_tax_sale'].ids)],
+ }),
+ ],
+ })
+
+ with self.assertRaises(UserError), self.cr.savepoint():
+ self.company_data['default_tax_sale'].company_id = self.company_data_2['company']