Files
Odoo-Modules/fusion_accounting_ai/services/tools/financial_reports.py
gsinghpal 118f0d9d16
Some checks failed
fusion_accounting CI / test (fusion_accounting_ai) (push) Has been cancelled
fusion_accounting CI / test (fusion_accounting_core) (push) Has been cancelled
fusion_accounting CI / test (fusion_accounting_migration) (push) Has been cancelled
feat(fusion_accounting_ai): 5 new financial reports AI tools
Adds financial_reports.py tools module with 5 fusion-engine-routed
tools registered in TOOL_DISPATCH:

- fusion_run_report
- fusion_get_anomalies
- fusion_generate_commentary
- fusion_drill_down_report_line
- fusion_compare_periods

Each tool guards on 'fusion.report.engine' being in the registry and
otherwise returns a structured error so the chat agent can surface a
clear "module not installed" message.

6 new TransactionCase tests (including a TOOL_DISPATCH registration
sanity check).

Made-with: Cursor
2026-04-19 15:41:10 -04:00

128 lines
4.4 KiB
Python

"""Fusion-engine-routed AI tools for financial reports.
These 5 tools route through ReportsAdapter's Phase-2 methods
(run_fusion_report / get_anomalies / get_commentary), which in turn
call fusion.report.engine when fusion_accounting_reports is installed.
"""
import logging
_logger = logging.getLogger(__name__)
def _company_id(env, params):
raw = params.get('company_id')
return int(raw) if raw else env.company.id
def fusion_run_report(env, params):
"""Run a fusion financial report.
Params: report_type (pnl|balance_sheet|trial_balance|general_ledger),
date_from, date_to, comparison (none|previous_period|previous_year),
optional company_id.
"""
if 'fusion.report.engine' not in env.registry:
return {'error': 'fusion_accounting_reports not installed'}
from ..data_adapters import get_adapter
adapter = get_adapter(env, 'reports')
result = adapter.run_fusion_report(
report_type=params.get('report_type'),
date_from=params.get('date_from'),
date_to=params.get('date_to'),
comparison=params.get('comparison', 'none'),
company_id=_company_id(env, params),
)
rows = result.get('rows', [])
return {
'report_type': params.get('report_type'),
'period': result.get('period'),
'comparison_period': result.get('comparison_period'),
'row_count': len(rows),
'rows': rows,
}
def fusion_get_anomalies(env, params):
"""Detect variance anomalies in a report."""
if 'fusion.report.engine' not in env.registry:
return {'error': 'fusion_accounting_reports not installed'}
from ..data_adapters import get_adapter
adapter = get_adapter(env, 'reports')
result = adapter.get_anomalies(
report_type=params.get('report_type'),
date_from=params.get('date_from'),
date_to=params.get('date_to'),
comparison=params.get('comparison', 'previous_year'),
company_id=_company_id(env, params),
)
anomalies = result.get('anomalies', [])
return {'count': len(anomalies), 'anomalies': anomalies}
def fusion_generate_commentary(env, params):
"""Generate AI commentary for a report."""
if 'fusion.report.engine' not in env.registry:
return {'error': 'fusion_accounting_reports not installed'}
from ..data_adapters import get_adapter
adapter = get_adapter(env, 'reports')
result = adapter.get_commentary(
report_type=params.get('report_type'),
date_from=params.get('date_from'),
date_to=params.get('date_to'),
comparison=params.get('comparison', 'none'),
company_id=_company_id(env, params),
)
return {
'summary': result.get('summary', ''),
'highlights': result.get('highlights', []),
'concerns': result.get('concerns', []),
'next_actions': result.get('next_actions', []),
}
def fusion_drill_down_report_line(env, params):
"""Drill from a report line into the underlying journal items."""
if 'fusion.report.engine' not in env.registry:
return {'error': 'fusion_accounting_reports not installed'}
from datetime import datetime
from odoo.addons.fusion_accounting_reports.services.date_periods import (
Period,
)
date_from = params['date_from']
date_to = params['date_to']
if isinstance(date_from, str):
date_from = datetime.strptime(date_from, '%Y-%m-%d').date()
if isinstance(date_to, str):
date_to = datetime.strptime(date_to, '%Y-%m-%d').date()
period = Period(date_from=date_from, date_to=date_to, label='drill')
engine = env['fusion.report.engine']
rows = engine.drill_down(
account_id=int(params['account_id']),
period=period,
company_id=_company_id(env, params),
)
return {'count': len(rows), 'rows': rows}
def fusion_compare_periods(env, params):
"""Run a report with period comparison side-by-side.
Defaults comparison to 'previous_year' so callers get a comparison
column without specifying it explicitly.
"""
return fusion_run_report(env, {
**params,
'comparison': params.get('comparison', 'previous_year'),
})
TOOLS = {
'fusion_run_report': fusion_run_report,
'fusion_get_anomalies': fusion_get_anomalies,
'fusion_generate_commentary': fusion_generate_commentary,
'fusion_drill_down_report_line': fusion_drill_down_report_line,
'fusion_compare_periods': fusion_compare_periods,
}