feat(fusion_accounting_reports): top-level report_viewer OWL component

Made-with: Cursor
This commit is contained in:
gsinghpal
2026-04-19 16:01:12 -04:00
parent 1ffa86b532
commit b33e12e587
4 changed files with 106 additions and 1 deletions

View File

@@ -1,6 +1,6 @@
{
'name': 'Fusion Accounting Reports',
'version': '19.0.1.0.23',
'version': '19.0.1.0.24',
'category': 'Accounting/Accounting',
'summary': 'AI-augmented financial reports (P&L, balance sheet, trial balance, GL).',
'description': """
@@ -43,6 +43,9 @@ menu hides; the engine and AI tools remain available for the chat.
'fusion_accounting_reports/static/src/scss/reports.scss',
'fusion_accounting_reports/static/src/scss/dark_mode.scss',
'fusion_accounting_reports/static/src/services/reports_service.js',
'fusion_accounting_reports/static/src/views/report_viewer/report_viewer.js',
'fusion_accounting_reports/static/src/views/report_viewer/report_viewer.xml',
'fusion_accounting_reports/static/src/views/report_viewer/report_viewer_view.js',
],
},
'installable': True,

View File

@@ -0,0 +1,47 @@
/** @odoo-module **/
import { Component, useState, onWillStart } from "@odoo/owl";
import { useService } from "@web/core/utils/hooks";
import { ReportTable } from "../../components/report_table/report_table";
import { PeriodFilter } from "../../components/period_filter/period_filter";
import { DrillDownDialog } from "../../components/drill_down_dialog/drill_down_dialog";
import { AiCommentaryPanel } from "../../components/ai_commentary_panel/ai_commentary_panel";
import { AnomalyStrip } from "../../components/anomaly_strip/anomaly_strip";
export class ReportViewer extends Component {
static template = "fusion_accounting_reports.ReportViewer";
static props = { "*": true };
static components = {
ReportTable, PeriodFilter, DrillDownDialog,
AiCommentaryPanel, AnomalyStrip,
};
setup() {
this.reports = useService("fusion_reports");
this.state = useState(this.reports.state);
const ctx = this.props.action?.context || {};
const reportType = ctx.default_report_type || 'pnl';
const companyId = this.env.services.user?.context?.allowed_company_ids?.[0];
onWillStart(async () => {
await this.reports.loadAvailableReports(companyId);
const today = new Date();
const year = today.getFullYear();
await this.reports.runReport(
reportType, `${year}-01-01`, `${year}-12-31`, 'none');
});
}
onDrillDown(accountId, label) {
this.reports.drillDown(accountId, label);
}
onCloseDrill() {
this.reports.closeDrillDown();
}
async onGenerateCommentary() {
await this.reports.generateCommentary({ forceRegenerate: false });
}
}

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="fusion_accounting_reports.ReportViewer">
<div class="o_fusion_reports">
<div class="o_fusion_reports_header">
<div>
<h1>
<t t-esc="state.currentResult?.report_name || 'Financial Reports'"/>
</h1>
<div class="text-muted" t-if="state.currentResult">
<t t-esc="state.currentResult.period?.label"/>
</div>
</div>
<div>
<button class="btn_report primary"
t-on-click="onGenerateCommentary"
t-att-disabled="state.isGeneratingCommentary">
<t t-if="state.isGeneratingCommentary">Generating...</t>
<t t-else="">AI Commentary</t>
</button>
</div>
</div>
<PeriodFilter />
<AnomalyStrip t-foreach="state.currentAnomalies" t-as="anomaly"
t-key="anomaly.row_id" anomaly="anomaly"/>
<AiCommentaryPanel t-if="state.currentCommentary" commentary="state.currentCommentary"/>
<ReportTable t-if="state.currentResult" result="state.currentResult"
onDrillDown="onDrillDown.bind(this)"/>
<DrillDownDialog t-if="state.drillDown and state.drillDown.isOpen"
drill="state.drillDown"
onClose="onCloseDrill.bind(this)"/>
</div>
</t>
</templates>

View File

@@ -0,0 +1,14 @@
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { ReportViewer } from "./report_viewer";
export const fusionReportsView = {
type: "fusion_reports",
Controller: ReportViewer,
display_name: "Fusion Financial Reports",
icon: "fa-line-chart",
multiRecord: true,
};
registry.category("views").add("fusion_reports", fusionReportsView);