From c1bb8bfc404036127e23b333b90ad2d47c61d765 Mon Sep 17 00:00:00 2001 From: Geraldo Lopez Date: Mon, 22 Sep 2025 09:26:58 +0200 Subject: [PATCH] [FIX] mis_builder: account.account has company_ids in Odoo 18 Limit display to 3 companies plus ellipsis. Fixes ``` File "/home/odoo/mis-builder/mis_builder/models/kpimatrix.py", line 478, in _get_account_name result = f"{result} [{account.company_id.name}]" ^^^^^^^^^^^^^^^^^^ AttributeError: 'account.account' object has no attribute 'company_id' ``` Co-authored-by: Stefan Rijnhart --- mis_builder/models/kpimatrix.py | 7 +- mis_builder/tests/__init__.py | 1 + .../tests/test_kpimatrix_account_names.py | 126 ++++++++++++++++++ 3 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 mis_builder/tests/test_kpimatrix_account_names.py diff --git a/mis_builder/models/kpimatrix.py b/mis_builder/models/kpimatrix.py index dc23b12a7..2de4c5be9 100644 --- a/mis_builder/models/kpimatrix.py +++ b/mis_builder/models/kpimatrix.py @@ -469,7 +469,12 @@ def _load_account_names(self): def _get_account_name(self, account): result = f"{account.code} {account.name}" if self._multi_company: - result = f"{result} [{account.company_id.name}]" + company_names = ", ".join( + [c.name for c in account.company_ids[:3]] + ) # Limit to first 3 companies + if len(account.company_ids) > 3: + company_names += ", ..." + result = f"{result} [{company_names}]" return result def get_account_name(self, account_id): diff --git a/mis_builder/tests/__init__.py b/mis_builder/tests/__init__.py index 3a0cafe11..c7c3a17d0 100644 --- a/mis_builder/tests/__init__.py +++ b/mis_builder/tests/__init__.py @@ -7,6 +7,7 @@ from . import test_aggregate from . import test_data_sources from . import test_kpi_data +from . import test_kpimatrix_account_names from . import test_mis_report_instance from . import test_mis_safe_eval from . import test_period_dates diff --git a/mis_builder/tests/test_kpimatrix_account_names.py b/mis_builder/tests/test_kpimatrix_account_names.py new file mode 100644 index 000000000..8cee85a12 --- /dev/null +++ b/mis_builder/tests/test_kpimatrix_account_names.py @@ -0,0 +1,126 @@ +# Copyright 2025 Geraldo Lopez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from unittest.mock import MagicMock, Mock + +from odoo.tests import common + +from ..models.kpimatrix import KpiMatrix + + +class TestKPIMatrixAccountNames(common.TransactionCase): + """Unit tests for KpiMatrix._get_account_name() method enhancements""" + + @classmethod + def setUpClass(cls): + super().setUpClass() + + # Create a proper mock environment for KpiMatrix + mock_env = MagicMock() + + # Mock the required models and services + mock_lang_model = Mock() + mock_lang_model._lang_get.return_value = Mock() + mock_env.__getitem__.side_effect = lambda key: { + "res.lang": mock_lang_model, + "mis.report.style": Mock(), + "account.account": Mock(), + }.get(key, Mock()) + + # Mock user with language + mock_env.user.lang = "en_US" + + # Create KpiMatrix with mock environment + cls.kpi_matrix = KpiMatrix(mock_env, multi_company=True) + + def _create_mock_account( + self, + code="100", + name="Test Account", + company_ids=None, + ): + """Helper to create mock account objects""" + account = Mock() + account.code = code + account.name = name + + account.company_ids = company_ids or [] + + return account + + def _create_mock_company(self, name): + """Helper to create mock company objects""" + company = Mock() + company.name = name + return company + + def test_get_account_name_single_company_mode(self): + """Test account name without company info in single company mode""" + # Create a separate KpiMatrix for single company mode + mock_env = MagicMock() + mock_lang_model = Mock() + mock_lang_model._lang_get.return_value = Mock() + mock_env.__getitem__.side_effect = lambda key: { + "res.lang": mock_lang_model, + "mis.report.style": Mock(), + "account.account": Mock(), + }.get(key, Mock()) + mock_env.user.lang = "en_US" + + single_company_matrix = KpiMatrix(mock_env, multi_company=False) + + account = self._create_mock_account(code="100", name="Cash") + + result = single_company_matrix._get_account_name(account) + + self.assertEqual(result, "100 Cash") + + def test_get_account_name_with_company_ids_single(self): + """Test account name with company_ids field containing one company""" + company = self._create_mock_company("Company B") + account = self._create_mock_account( + code="200", + name="Bank", + company_ids=[company], + ) + + result = self.kpi_matrix._get_account_name(account) + self.assertEqual(result, "200 Bank [Company B]") + + def test_get_account_name_with_company_ids_multiple(self): + """Test account name with company_ids field containing multiple + companies (≤3)""" + companies = [ + self._create_mock_company("Company A"), + self._create_mock_company("Company B"), + self._create_mock_company("Company C"), + ] + + account = self._create_mock_account( + code="300", + name="Receivables", + company_ids=companies, + ) + + result = self.kpi_matrix._get_account_name(account) + self.assertEqual(result, "300 Receivables [Company A, Company B, Company C]") + + def test_get_account_name_with_company_ids_many(self): + """Test account name with company_ids field containing >3 companies + (should truncate)""" + companies = [ + self._create_mock_company("Company A"), + self._create_mock_company("Company B"), + self._create_mock_company("Company C"), + self._create_mock_company("Company D"), + self._create_mock_company("Company E"), + ] + + account = self._create_mock_account( + code="400", + name="Payables", + company_ids=companies, + ) + + result = self.kpi_matrix._get_account_name(account) + self.assertEqual(result, "400 Payables [Company A, Company B, Company C, ...]")