Adds FusionReportsController exposing: - list_available, run, drill_down - get_anomalies (with optional persistence to fusion.report.anomaly) - get_commentary (LLM cache via fusion.report.commentary, force_regenerate flag) - compare_periods (delegates to run with comparison flag) - export_pdf / export_xlsx (Phase 2 placeholders for Tasks 34/35) All endpoints use V19's type='jsonrpc' and route through fusion.report.engine - no direct ORM aggregation in the controller. 8 new HttpCase tests cover each endpoint. Total: 78 logical tests. Made-with: Cursor
119 lines
3.9 KiB
Python
119 lines
3.9 KiB
Python
"""Controller tests using HttpCase for the 8 JSON-RPC endpoints."""
|
|
|
|
import json
|
|
|
|
from odoo.tests.common import HttpCase, new_test_user, tagged
|
|
|
|
|
|
@tagged('post_install', '-at_install')
|
|
class TestReportsController(HttpCase):
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.user = new_test_user(
|
|
self.env,
|
|
login='reports_test_user',
|
|
groups='base.group_user,account.group_account_invoice',
|
|
)
|
|
|
|
def _jsonrpc(self, endpoint, params):
|
|
self.authenticate('reports_test_user', 'reports_test_user')
|
|
url = f'/fusion/reports/{endpoint}'
|
|
body = {
|
|
'jsonrpc': '2.0',
|
|
'method': 'call',
|
|
'params': params,
|
|
'id': 1,
|
|
}
|
|
response = self.url_open(
|
|
url,
|
|
data=json.dumps(body),
|
|
headers={'Content-Type': 'application/json'},
|
|
)
|
|
self.assertEqual(
|
|
response.status_code, 200,
|
|
f"{endpoint} returned {response.status_code}: {response.text[:300]}",
|
|
)
|
|
result = response.json()
|
|
if 'error' in result:
|
|
self.fail(f"{endpoint} errored: {result['error']}")
|
|
return result.get('result', {})
|
|
|
|
def test_list_available(self):
|
|
result = self._jsonrpc('list_available', {
|
|
'company_id': self.env.company.id,
|
|
})
|
|
self.assertIn('reports', result)
|
|
codes = [r['code'] for r in result['reports']]
|
|
self.assertIn('pnl', codes)
|
|
|
|
def test_run_pnl(self):
|
|
result = self._jsonrpc('run', {
|
|
'report_type': 'pnl',
|
|
'date_from': '2026-01-01',
|
|
'date_to': '2026-12-31',
|
|
'company_id': self.env.company.id,
|
|
})
|
|
self.assertEqual(result.get('report_type'), 'pnl')
|
|
self.assertIn('rows', result)
|
|
|
|
def test_run_balance_sheet(self):
|
|
result = self._jsonrpc('run', {
|
|
'report_type': 'balance_sheet',
|
|
'date_from': '2026-01-01',
|
|
'date_to': '2026-12-31',
|
|
'company_id': self.env.company.id,
|
|
})
|
|
self.assertEqual(result.get('report_type'), 'balance_sheet')
|
|
|
|
def test_drill_down_returns_list(self):
|
|
line = self.env['account.move.line'].search(
|
|
[('parent_state', '=', 'posted')], limit=1,
|
|
)
|
|
if not line:
|
|
self.skipTest("No posted lines in DB")
|
|
result = self._jsonrpc('drill_down', {
|
|
'account_id': line.account_id.id,
|
|
'date_from': str(line.date),
|
|
'date_to': str(line.date),
|
|
'company_id': line.company_id.id,
|
|
})
|
|
self.assertIn('rows', result)
|
|
|
|
def test_get_anomalies_returns_list(self):
|
|
result = self._jsonrpc('get_anomalies', {
|
|
'report_type': 'pnl',
|
|
'date_from': '2026-01-01',
|
|
'date_to': '2026-12-31',
|
|
'comparison': 'previous_year',
|
|
'company_id': self.env.company.id,
|
|
})
|
|
self.assertIn('anomalies', result)
|
|
|
|
def test_get_commentary_returns_dict(self):
|
|
result = self._jsonrpc('get_commentary', {
|
|
'report_type': 'pnl',
|
|
'date_from': '2026-01-01',
|
|
'date_to': '2026-12-31',
|
|
'company_id': self.env.company.id,
|
|
})
|
|
self.assertIn('summary', result)
|
|
self.assertIn('highlights', result)
|
|
self.assertIn('concerns', result)
|
|
|
|
def test_export_pdf_placeholder(self):
|
|
result = self._jsonrpc('export_pdf', {
|
|
'report_type': 'pnl',
|
|
'date_from': '2026-01-01',
|
|
'date_to': '2026-12-31',
|
|
})
|
|
self.assertEqual(result.get('status'), 'not_implemented')
|
|
|
|
def test_export_xlsx_placeholder(self):
|
|
result = self._jsonrpc('export_xlsx', {
|
|
'report_type': 'pnl',
|
|
'date_from': '2026-01-01',
|
|
'date_to': '2026-12-31',
|
|
})
|
|
self.assertEqual(result.get('status'), 'not_implemented')
|