diff --git a/addons/account/tests/test_account_analytic.py b/addons/account/tests/test_account_analytic.py index 0ae4a2f07a4..f320022390a 100644 --- a/addons/account/tests/test_account_analytic.py +++ b/addons/account/tests/test_account_analytic.py @@ -264,3 +264,31 @@ class TestAccountAnalyticAccount(AccountTestInvoicingCommon): self.assertEqual(self.analytic_account_a.invoice_count, 1) self.analytic_account_a._compute_vendor_bill_count() self.assertEqual(self.analytic_account_a.vendor_bill_count, 1) + + def test_applicability_score(self): + """ Tests which applicability is chosen if several ones are valid """ + applicability_without_company, applicability_with_company = self.env['account.analytic.applicability'].create([ + { + 'business_domain': 'invoice', + 'product_categ_id': self.product_a.categ_id.id, + 'applicability': 'mandatory', + 'analytic_plan_id': self.default_plan.id, + 'company_id': False, + }, + { + 'business_domain': 'invoice', + 'applicability': 'unavailable', + 'analytic_plan_id': self.default_plan.id, + 'company_id': self.env.company.id, + }, + ]) + + applicability = self.default_plan._get_applicability(business_domain='invoice', company_id=self.env.company.id, product=self.product_a.id) + self.assertEqual(applicability, 'mandatory', "product takes precedence over company") + + # If the model that asks for a validation does not have a company_id, + # the score shouldn't take into account the company of the applicability + score = applicability_without_company._get_score(business_domain='invoice', product=self.product_a.id) + self.assertEqual(score, 2) + score = applicability_with_company._get_score(business_domain='invoice', product=self.product_a.id) + self.assertEqual(score, 1) diff --git a/addons/analytic/models/analytic_plan.py b/addons/analytic/models/analytic_plan.py index 4d25a3fe9a1..04f22d628a0 100644 --- a/addons/analytic/models/analytic_plan.py +++ b/addons/analytic/models/analytic_plan.py @@ -233,7 +233,12 @@ class AccountAnalyticPlan(models.Model): else: score = 0 applicability = self.default_applicability - for applicability_rule in self.applicability_ids.filtered(lambda rule: rule.company_id == self.env.company): + for applicability_rule in self.applicability_ids.filtered( + lambda rule: + not rule.company_id + or not kwargs.get('company_id') + or rule.company_id.id == kwargs.get('company_id') + ): score_rule = applicability_rule._get_score(**kwargs) if score_rule > score: applicability = applicability_rule.applicability @@ -304,7 +309,10 @@ class AccountAnalyticApplicability(models.Model): def _get_score(self, **kwargs): """ Gives the score of an applicability with the parameters of kwargs """ self.ensure_one() + # 0.5 is because company is less important than other fields for an equal number of valid fields + # No company on the applicability and the kwargs together are not considered a more fitting rule + score = 0.5 if self.company_id and kwargs.get('company_id') else 0 if not kwargs.get('business_domain'): - return 0 + return score else: - return 1 if kwargs.get('business_domain') == self.business_domain else -1 + return score + 1 if kwargs.get('business_domain') == self.business_domain else -1 diff --git a/addons/analytic/tests/test_plan_operations.py b/addons/analytic/tests/test_plan_operations.py index 408afd28810..3054d4bef69 100644 --- a/addons/analytic/tests/test_plan_operations.py +++ b/addons/analytic/tests/test_plan_operations.py @@ -72,23 +72,29 @@ class TestAnalyticPlanOperations(TransactionCase): company_2 = self.env['res.company'].create({ 'name': 'company_2', }) - mandatory_plan = self.env['account.analytic.plan'].create([{ - 'name': 'Mandatory Plan', + plan = self.env['account.analytic.plan'].create([{ + 'name': 'Plan', 'default_applicability': 'optional', }]) - mandatory_plan.with_company(company_2).write({'default_applicability': 'mandatory'}) - self.env['account.analytic.applicability'].create({ + applicability = self.env['account.analytic.applicability'].create({ 'business_domain': 'general', - 'analytic_plan_id': mandatory_plan.id, + 'analytic_plan_id': plan.id, 'applicability': 'mandatory', 'company_id': company_2.id, }) self.env['account.analytic.account'].create([{ 'name': 'Mandatory Account', 'code': 'manda', - 'plan_id': mandatory_plan.id, + 'plan_id': plan.id, }]) distribution_model = self.env['account.analytic.distribution.model'].create({}).with_context(validate_analytic=True) - # only mandatory applicability is in company_2, should not raise - distribution_model._validate_distribution(business_domain='general') + # mandatory applicability is only in company_2, should not raise for company_1 + distribution_model._validate_distribution(business_domain='general', company_id=self.env.company.id) + + applicability.company_id = False + # It should apply for all companies now + with self.assertRaisesRegex(UserError, r'require a 100% analytic distribution'): + distribution_model._validate_distribution(business_domain='general', company_id=self.env.company.id) + with self.assertRaisesRegex(UserError, r'require a 100% analytic distribution'): + distribution_model._validate_distribution(business_domain='general')