From 4d7a9eea13a0efd5b70147ce53d3e10c71a29a03 Mon Sep 17 00:00:00 2001 From: gawa-odoo Date: Wed, 19 Oct 2022 11:17:02 +0000 Subject: [PATCH] [FIX] analytic: field None should not validate model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If an aml has no product, it should not trigger a model that has a product. So, we now define the fields that have to be checked on the model, instead of just being the ones given as parameters. The way the field `company_id` impacts the model has also been changed. The idea is that a model with a company specified should be better than a model without one. But we also want that a model with 1 valid rule and no company is better than one with only a good selected company. closes odoo/odoo#107165 X-original-commit: feff1a8a056f1fbbc852f7cf164e73abf83c4cc9 Signed-off-by: William André (wan) --- .../account_analytic_distribution_model.py | 9 ---- .../models/analytic_distribution_model.py | 47 ++++++++++++------- .../analytic/tests/test_analytic_account.py | 46 ++++++++++++++++++ 3 files changed, 76 insertions(+), 26 deletions(-) diff --git a/addons/account/models/account_analytic_distribution_model.py b/addons/account/models/account_analytic_distribution_model.py index bdddfcd174e..757fc861dc5 100644 --- a/addons/account/models/account_analytic_distribution_model.py +++ b/addons/account/models/account_analytic_distribution_model.py @@ -26,12 +26,3 @@ class AccountAnalyticDistributionModel(models.Model): def _create_domain(self, fname, value): if not fname == 'account_prefix': return super()._create_domain(fname, value) - - def _check_score(self, key, value): - if key == 'account_prefix': - if value.startswith(self.account_prefix): - return 1 - else: - return -1 - else: - return super()._check_score(key, value) diff --git a/addons/analytic/models/analytic_distribution_model.py b/addons/analytic/models/analytic_distribution_model.py index 8df27564fd0..ed639e13ca2 100644 --- a/addons/analytic/models/analytic_distribution_model.py +++ b/addons/analytic/models/analytic_distribution_model.py @@ -5,6 +5,10 @@ from odoo import api, fields, models, _ from odoo.exceptions import UserError +class NonMatchingDistribution(Exception): + pass + + class AccountAnalyticDistributionModel(models.Model): _name = 'account.analytic.distribution.model' _inherit = 'analytic.mixin' @@ -57,29 +61,38 @@ class AccountAnalyticDistributionModel(models.Model): domain += self._create_domain(fname, value) or [] best_score = 0 res = {} + fnames = set(self._get_fields_to_check()) for rec in self.search(domain): - score = 0 - for key, value in vals.items(): - if value and rec[key]: - if rec._check_score(key, value) == 1: - score += 1 - else: - score = -1 - break - if score > best_score: - res = rec.analytic_distribution - best_score = score + try: + score = sum(rec._check_score(key, vals.get(key)) for key in fnames) + if score > best_score: + res = rec.analytic_distribution + best_score = score + except NonMatchingDistribution: + continue return res + def _get_fields_to_check(self): + return ( + set(self.env['account.analytic.distribution.model']._fields) + - set(self.env['analytic.mixin']._fields) + - set(models.MAGIC_COLUMNS) - {'display_name', '__last_update'} + ) + def _check_score(self, key, value): self.ensure_one() - if key == 'partner_category_id': - if self[key].id in value: - return 1 - if value == self[key].id: + if key == 'company_id': + if not self.company_id or value == self.company_id.id: + return 1 if self.company_id else 0.5 + raise NonMatchingDistribution + if not self[key]: + return 0 + if value and ((self[key].id in value) if isinstance(value, (list, tuple)) + else (value.startswith(self[key])) if key.endswith('_prefix') + else (value == self[key].id) + ): return 1 - else: - return -1 + raise NonMatchingDistribution def _create_domain(self, fname, value): if not value: diff --git a/addons/analytic/tests/test_analytic_account.py b/addons/analytic/tests/test_analytic_account.py index 507772451d1..dbb15093f5e 100644 --- a/addons/analytic/tests/test_analytic_account.py +++ b/addons/analytic/tests/test_analytic_account.py @@ -2,6 +2,7 @@ from odoo.tests import tagged from odoo.tests.common import TransactionCase +from odoo import Command @tagged('post_install', '-at_install') @@ -113,9 +114,54 @@ class TestAnalyticAccount(TransactionCase): self.assertEqual(distribution_json, {}, "No distribution should be given") distribution_json = self.env['account.analytic.distribution.model']._get_distribution({ "partner_id": self.partner_a.id, + "company_id": self.company_data.id, }) self.assertEqual(distribution_json, {str(self.analytic_account_3.id): 100}, "Distribution 1 should be given") distribution_json = self.env['account.analytic.distribution.model']._get_distribution({ "partner_id": self.partner_b.id, + "company_id": self.company_data.id, }) self.assertEqual(distribution_json, {str(self.analytic_account_2.id): 100}, "Distribution 2 should be given") + + def test_order_analytic_distribution_model(self): + """ Test the distribution returned with company field""" + distribution_3 = self.env['account.analytic.distribution.model'].create({ + 'partner_id': self.partner_a.id, + 'analytic_distribution': {self.analytic_account_1.id: 100}, + 'company_id': self.company_data.id, + }) + distribution_json = self.env['account.analytic.distribution.model']._get_distribution({}) + self.assertEqual(distribution_json, {}, "No distribution should be given") + + distribution_json = self.env['account.analytic.distribution.model']._get_distribution({ + "partner_id": self.partner_a.id, + "company_id": self.company_data.id, + }) + self.assertEqual(distribution_json, distribution_3.analytic_distribution, + "Distribution 3 should be given, as the company is specified in the model") + + distribution_json = self.env['account.analytic.distribution.model']._get_distribution({ + "partner_id": self.partner_b.id, + "company_id": self.company_data.id, + }) + self.assertEqual(distribution_json, {str(self.analytic_account_2.id): 100}, + "Distribution 2 should be given, for the partner") + + partner_category = self.env['res.partner.category'].create({'name': 'partner_categ'}) + self.partner_a.write({ + 'category_id': [Command.set([partner_category.id])] + }) + + distribution_4 = self.env['account.analytic.distribution.model'].create({ + 'partner_id': self.partner_a.id, + 'analytic_distribution': {self.analytic_account_1.id: 100, self.analytic_account_2.id: 100}, + 'partner_category_id': partner_category.id, + }) + + distribution_json = self.env['account.analytic.distribution.model']._get_distribution({ + "partner_id": self.partner_a.id, + "company_id": self.company_data.id, + "partner_category_id": partner_category.ids, + }) + self.assertEqual(distribution_json, distribution_4.analytic_distribution, + "Distribution 4 should be given, as the partner_category_id is better than the company_id")