Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
818 changes: 176 additions & 642 deletions mis_builder/i18n/es.po

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions mis_builder/i18n/mis_builder.pot
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-11-26 10:41+0000\n"
"PO-Revision-Date: 2025-11-26 10:41+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
Expand Down Expand Up @@ -1735,6 +1737,12 @@ msgstr ""
msgid "`fld` must have a field name in exression %s"
msgstr ""

#. module: mis_builder
#. odoo-python
#: code:addons/mis_builder/models/kpimatrix.py:0
msgid "and %s more"
msgstr ""

#. module: mis_builder
#. odoo-python
#: code:addons/mis_builder/models/mis_report_instance.py:0
Expand Down
30 changes: 25 additions & 5 deletions mis_builder/models/kpimatrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from .mis_safe_eval import DataError, mis_safe_eval
from .simple_array import SimpleArray

COMPANY_NAMES_DISPLAY_LIMIT = 3

_logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -139,12 +141,15 @@ def __init__(


class KpiMatrix:
def __init__(self, env, multi_company=False, account_model="account.account"):
def __init__(
self, env, multi_company, query_companies, account_model="account.account"
):
# cache language id for faster rendering
lang_model = env["res.lang"]
self.lang = lang_model._lang_get(env.user.lang)
self._style_model = env["mis.report.style"]
self._account_model = env[account_model]
self._ = env._
# data structures
# { kpi: KpiMatrixRow }
self._kpi_rows = OrderedDict()
Expand All @@ -159,6 +164,7 @@ def __init__(self, env, multi_company=False, account_model="account.account"):
# { account_id: account_name }
self._account_names = {}
self._multi_company = multi_company
self._query_companies = query_companies

def declare_kpi(self, kpi):
"""Declare a new kpi (row) in the matrix.
Expand Down Expand Up @@ -467,10 +473,24 @@ def _load_account_names(self):
self._account_names = {a.id: self._get_account_name(a) for a in accounts}

def _get_account_name(self, account):
result = f"{account.code} {account.name}"
if self._multi_company:
result = f"{result} [{account.company_id.name}]"
return result
account_code = account.code
result = f"{account_code} {account.name}"
if not self._multi_company:
return result
# Multi company report
account_companies = account.company_ids.filtered_domain(
[("id", "in", self._query_companies.ids)]
)
# Maybe account belongs to a company that is not the current env company
# and has no visible code, so choose the first one and get the code
if not account_code:
account_code = account.with_company(account_companies[:1]).code
company_names = account_companies.mapped("name")
if len(company_names) > COMPANY_NAMES_DISPLAY_LIMIT:
company_names = company_names[:COMPANY_NAMES_DISPLAY_LIMIT] + [
self._("and %s more", len(company_names) - COMPANY_NAMES_DISPLAY_LIMIT)
]
return f"{account_code} {account.name} [{', '.join(company_names)}]"

def get_account_name(self, account_id):
if account_id not in self._account_names:
Expand Down
6 changes: 4 additions & 2 deletions mis_builder/models/mis_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -532,9 +532,11 @@ def copy(self, default=None):

# TODO: kpi name cannot be start with query name

def prepare_kpi_matrix(self, multi_company=False):
def prepare_kpi_matrix(self, multi_company=False, query_companies=None):
self.ensure_one()
kpi_matrix = KpiMatrix(self.env, multi_company, self.account_model)
kpi_matrix = KpiMatrix(
self.env, multi_company, query_companies, self.account_model
)
for kpi in self.kpi_ids:
kpi_matrix.declare_kpi(kpi)
return kpi_matrix
Expand Down
4 changes: 3 additions & 1 deletion mis_builder/models/mis_report_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,9 @@ def _compute_matrix(self):
self.ensure_one()
aep = self.report_id._prepare_aep(self.query_company_ids, self.currency_id)
multi_company = self.multi_company and len(self.query_company_ids) > 1
kpi_matrix = self.report_id.prepare_kpi_matrix(multi_company)
kpi_matrix = self.report_id.prepare_kpi_matrix(
multi_company=multi_company, query_companies=self.query_company_ids
)
for period in self.period_ids:
description = None
if period.mode == MODE_NONE:
Expand Down
1 change: 1 addition & 0 deletions mis_builder/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
84 changes: 84 additions & 0 deletions mis_builder/tests/test_kpimatrix_account_names.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# 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 COMPANY_NAMES_DISPLAY_LIMIT, KpiMatrix


class TestKPIMatrixAccountNames(common.TransactionCase):
"""Unit tests for KpiMatrix._get_account_name() method enhancements"""

def _create_mock_env_kpimatrix(self, companies):
"""Helper to create KpiMatrix instances"""
# 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"
mock_env._ = self.env._
# Create KpiMatrix instance with chosen companies
return KpiMatrix(
mock_env, multi_company=len(companies) > 1, query_companies=companies
)

def _create_mock_account(self, code, name, company_ids):
"""Helper to create mock account objects"""
account = Mock()
account.code = code
account.name = name
account.company_ids = company_ids or []
return account

def _create_nbr_companies(self, number_of_companies):
"""Helper to create company objects"""
companies = self.env["res.company"]
for name in [f"Company {i + 1}" for i in range(number_of_companies)]:
companies |= self.env["res.company"].create({"name": name})
return companies

def test_get_account_name_single_company(self):
"""Test account name without company info in single company mode"""
company = self._create_nbr_companies(1)
single_company_matrix = self._create_mock_env_kpimatrix(company)
account = self._create_mock_account("100", "Cash", company)
result = single_company_matrix._get_account_name(account)
self.assertEqual(
result,
"100 Cash",
"Account name are not displayed correctly on single company",
)

def test_get_account_name_with_company_ids_multiple(self):
"""Test account name with company_ids field containing multiple
companies (≤ 3)"""
companies = self._create_nbr_companies(COMPANY_NAMES_DISPLAY_LIMIT)
account = self._create_mock_account("300", "Receivables", companies)
kpi_matrix = self._create_mock_env_kpimatrix(companies)
result = kpi_matrix._get_account_name(account)
self.assertEqual(
result,
"300 Receivables [Company 1, Company 2, Company 3]",
"Company names on account name are not displayed correctly",
)

def test_get_account_name_with_company_ids_many(self):
"""Test account name with company_ids field containing > N companies"""
companies = self._create_nbr_companies(COMPANY_NAMES_DISPLAY_LIMIT + 1)
account = self._create_mock_account("400", "Payables", companies)
kpi_matrix = self._create_mock_env_kpimatrix(companies)
result = kpi_matrix._get_account_name(account)
self.assertEqual(
result,
"400 Payables [Company 1, Company 2, Company 3, and 1 more]",
"Company names on account name should be truncated",
)
Loading