[FIX] analytic: plan's applicability don't work without companies
If you create an applicability and remove the company field, they are never used. An applicability like this should be valid for all companies. We put a 0.5 value for the company field so an applicability so it has a lesser priority than other fields. Same idea as the distribution models. opw-3847415 closes odoo/odoo#162152 Signed-off-by: Olivier Colson (oco) <oco@odoo.com>
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user