fix(fusion_accounting_reports): engine accepts report_code to disambiguate

When multiple fusion.report rows share a report_type (e.g. 4 PnL-typed
reports: pnl, cash_flow, executive_summary, annual_statements), the
engine's _get_report previously returned whichever matched the type
filter first \u2014 so all four reports rendered the canonical P&L
line_specs regardless of which report the user selected.

Adds report_code kwarg to compute_pnl, compute_balance_sheet,
compute_trial_balance, compute_gl. Controller /fusion/reports/run now
accepts and forwards report_code. _get_report has a 3-tier resolution:
1. Exact code match (validates type)
2. Canonical (code == report_type)
3. First by sequence

Two new tests assert distinct line_specs render for distinct codes and
that wrong-type code raises ValidationError.

Verified live on westin-v19: pnl/cash_flow/executive_summary/
annual_statements now return 3/9/7/5 rows respectively (was all
3 before).

Made-with: Cursor
This commit is contained in:
gsinghpal
2026-04-19 23:58:29 -04:00
parent 1ebff01d35
commit 1817f63c67
3 changed files with 136 additions and 23 deletions

View File

@@ -107,6 +107,58 @@ class TestFusionReportEngine(TransactionCase):
):
self.assertIn(key, result['rows'][0])
def test_report_code_disambiguates_same_report_type(self):
"""Multiple reports of report_type='pnl' must each be addressable
by code so the engine returns the requested definition's line_specs
(not whichever was first by company_id)."""
spec_one = [
{'label': 'A', 'account_type_prefix': 'income_', 'sign': 1},
]
spec_two = [
{'label': 'X', 'account_type_prefix': 'income_', 'sign': 1},
{'label': 'Y', 'account_type_prefix': 'expense_', 'sign': -1},
{'label': 'Z', 'account_type_prefix': 'asset_', 'sign': 1},
]
self.env['fusion.report'].create({
'name': 'Variant One', 'code': 'variant_one',
'report_type': 'pnl', 'line_specs': spec_one,
'company_id': self.env.company.id,
})
self.env['fusion.report'].create({
'name': 'Variant Two', 'code': 'variant_two',
'report_type': 'pnl', 'line_specs': spec_two,
'company_id': self.env.company.id,
})
period = Period(date(2026, 1, 1), date(2026, 12, 31), 'Test')
engine = self.env['fusion.report.engine']
r1 = engine.compute_pnl(
period, company_id=self.env.company.id,
report_code='variant_one',
)
r2 = engine.compute_pnl(
period, company_id=self.env.company.id,
report_code='variant_two',
)
self.assertEqual(r1['report_name'], 'Variant One')
self.assertEqual(r2['report_name'], 'Variant Two')
self.assertEqual(len(r1['rows']), 1)
self.assertEqual(len(r2['rows']), 3)
def test_report_code_validates_type_match(self):
"""Asking for a 'pnl' computation but giving a balance_sheet code
should raise ValidationError, not silently mis-render."""
self.env['fusion.report'].create({
'name': 'Wrong Type', 'code': 'wrong_type_test',
'report_type': 'balance_sheet', 'line_specs': [],
'company_id': self.env.company.id,
})
period = Period(date(2026, 1, 1), date(2026, 12, 31), 'Test')
with self.assertRaises(ValidationError):
self.env['fusion.report.engine'].compute_pnl(
period, company_id=self.env.company.id,
report_code='wrong_type_test',
)
def test_no_report_raises_validation_error(self):
period = Period(date(2026, 1, 1), date(2026, 12, 31), 'Test 2026')
# Inactivate any pre-existing GL definitions so the lookup