Files
Odoo-Modules/fusion_accounting_reports/tests/test_reports_controller.py
gsinghpal 7d7bd93345 feat(fusion_accounting_reports): XLSX export wizard
Adds a TransientModel wizard fusion.xlsx.export.wizard that lets users
pick a report type, date range, and comparison mode, then runs the
engine and produces an XLSX via xlsxwriter (in-memory).

The wizard exposes a download field that becomes available after export
finishes. Works on P&L, Balance Sheet, Trial Balance, and General Ledger.
Comparison columns are written when the engine returns a comparison_period
in the result.

Also wires the controller's /fusion/reports/export_xlsx endpoint to drive
the wizard and return base64-encoded XLSX bytes (replaces the not_implemented
placeholder).

Tests: 2 new (test_xlsx_export.py) + 1 controller test updated. Manifest
declares xlsxwriter as an external_dependency.

Made-with: Cursor
2026-04-19 16:16:36 -04:00

127 lines
4.2 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_returns_pdf(self):
result = self._jsonrpc('export_pdf', {
'report_type': 'pnl',
'date_from': '2026-01-01',
'date_to': '2026-12-31',
})
self.assertEqual(result.get('status'), 'ok')
self.assertIn('pdf_base64', result)
self.assertTrue(result.get('filename', '').endswith('.pdf'))
def test_export_xlsx_returns_xlsx(self):
try:
import xlsxwriter # noqa: F401
except ImportError:
self.skipTest("xlsxwriter not installed")
result = self._jsonrpc('export_xlsx', {
'report_type': 'pnl',
'date_from': '2026-01-01',
'date_to': '2026-12-31',
})
self.assertEqual(result.get('status'), 'ok')
self.assertTrue(result.get('xlsx_base64'))
self.assertTrue(result.get('filename', '').endswith('.xlsx'))