From 3e48bab087ed609cea5ce17fbc93141aa196284a Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Sun, 19 Apr 2026 12:33:57 -0400 Subject: [PATCH] feat(fusion_accounting_bank_rec): kanban controller + renderer for OWL widget Top-level OWL component (BankRecKanbanController) hosts the bank reconciliation widget. Reads journal_id + company_id from action context, initializes the fusion_bank_reconciliation service, and renders the layout: header (stats), left column (line cards via BankRecLineCard renderer), right column (detail panel with AI suggestions). Custom view type 'fusion_bank_rec_kanban' registered so window actions can use fusion_bank_rec_kanban. Made-with: Cursor --- fusion_accounting_bank_rec/__manifest__.py | 6 +- .../src/views/kanban/bank_rec_kanban.xml | 142 ++++++++++++++++++ .../kanban/bank_rec_kanban_controller.js | 81 ++++++++++ .../views/kanban/bank_rec_kanban_renderer.js | 20 +++ .../src/views/kanban/bank_rec_kanban_view.js | 20 +++ 5 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban.xml create mode 100644 fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_controller.js create mode 100644 fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_renderer.js create mode 100644 fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_view.js diff --git a/fusion_accounting_bank_rec/__manifest__.py b/fusion_accounting_bank_rec/__manifest__.py index 8304451c..80a07454 100644 --- a/fusion_accounting_bank_rec/__manifest__.py +++ b/fusion_accounting_bank_rec/__manifest__.py @@ -1,6 +1,6 @@ { 'name': 'Fusion Accounting — Bank Reconciliation', - 'version': '19.0.1.0.10', + 'version': '19.0.1.0.11', 'category': 'Accounting/Accounting', 'sequence': 28, 'summary': 'Native V19 bank reconciliation widget with AI confidence scoring + behavioural learning.', @@ -39,6 +39,10 @@ Built by Nexa Systems Inc. 'fusion_accounting_bank_rec/static/src/scss/ai_suggestion.scss', 'fusion_accounting_bank_rec/static/src/scss/dark_mode.scss', 'fusion_accounting_bank_rec/static/src/services/bank_reconciliation_service.js', + 'fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_controller.js', + 'fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_renderer.js', + 'fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_view.js', + 'fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban.xml', ], }, 'installable': True, diff --git a/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban.xml b/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban.xml new file mode 100644 index 00000000..3ef618d2 --- /dev/null +++ b/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban.xml @@ -0,0 +1,142 @@ + + + + +
+
+
+

Bank Reconciliation

+
+ Journal # +
+
+
+
+ Unreconciled: + +
+
+ Total pending: + + $ + +
+
+
+ +
+
+
+ Loading… +
+
+ Nothing to reconcile. +
+
+ +
+ +
+
+
+ +
+ + +
Loading detail…
+
+

+ +

+
+ + + $ + + + · + +
+ +
+ +
+
+
AI Suggestions
+
+
+ % +
+
+
+
+
+ +
+
+
+
+
+ +
+ Select a bank line on the left to see details. +
+
+
+
+
+
+ + +
+
+
+ $ +
+
+ +
+
+
+ + + + + + +
+
+ 📎 +
+
+
+ AI Suggestion Available +
+
+
+
+ +
diff --git a/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_controller.js b/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_controller.js new file mode 100644 index 00000000..94ff1c0c --- /dev/null +++ b/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_controller.js @@ -0,0 +1,81 @@ +/** @odoo-module **/ + +/** + * Bank reconciliation kanban controller. + * + * Top-level OWL component for the fusion bank-rec widget. Hosts: + * - Header bar (journal name, unreconciled count, total pending amount) + * - Left column: list of unreconciled bank line cards + * - Right column: detail panel for the selected line + * + * Reads journal_id + company_id from action context. Wires up the + * fusion_bank_reconciliation service for all data + reactivity. + */ + +import { Component, useState, onWillStart } from "@odoo/owl"; +import { useService } from "@web/core/utils/hooks"; +import { BankRecLineCard } from "./bank_rec_kanban_renderer"; + +export class BankRecKanbanController extends Component { + static template = "fusion_accounting_bank_rec.BankRecKanbanController"; + static components = { BankRecLineCard }; + static props = { + action: { type: Object, optional: true }, + actionId: { type: [Number, String], optional: true }, + className: { type: String, optional: true }, + "*": true, + }; + + setup() { + this.bankRec = useService("fusion_bank_reconciliation"); + this.notification = useService("notification"); + this.state = useState(this.bankRec.state); + + const ctx = this.props.action?.context || {}; + const journalId = ctx.default_journal_id || ctx.active_id; + const companyId = ctx.allowed_company_ids?.[0] + || this.env.services.user?.context?.allowed_company_ids?.[0]; + + onWillStart(async () => { + if (journalId && companyId) { + await this.bankRec.initForJournal(journalId, companyId); + } + }); + } + + onSelectLine(lineId) { + this.bankRec.selectLine(lineId); + } + + async onLoadMore() { + await this.bankRec.loadMore(); + } + + async onSuggestForLine(lineId) { + await this.bankRec.suggestMatches([lineId]); + } + + async onAcceptSuggestion(suggestionId) { + await this.bankRec.acceptSuggestion(suggestionId); + } + + async onUnreconcile(partialIds) { + await this.bankRec.unreconcile(partialIds); + } + + formatCurrency(amount) { + return new Intl.NumberFormat(undefined, { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + }).format(amount); + } + + confidenceBandLabel(band) { + return { + high: "High", + medium: "Medium", + low: "Low", + none: "None", + }[band] || "—"; + } +} diff --git a/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_renderer.js b/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_renderer.js new file mode 100644 index 00000000..d385404c --- /dev/null +++ b/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_renderer.js @@ -0,0 +1,20 @@ +/** @odoo-module **/ + +/** + * Bank reconciliation line-card renderer. + * + * Renders one unreconciled bank line as a card in the kanban list. + * Owned by BankRecKanbanController; receives line + selected flag as props. + */ + +import { Component } from "@odoo/owl"; + +export class BankRecLineCard extends Component { + static template = "fusion_accounting_bank_rec.BankRecLineCard"; + static props = { + line: { type: Object }, + selected: { type: Boolean, optional: true }, + onSelect: { type: Function }, + formatCurrency: { type: Function }, + }; +} diff --git a/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_view.js b/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_view.js new file mode 100644 index 00000000..6964fa72 --- /dev/null +++ b/fusion_accounting_bank_rec/static/src/views/kanban/bank_rec_kanban_view.js @@ -0,0 +1,20 @@ +/** @odoo-module **/ + +/** + * Custom view type "fusion_bank_rec_kanban" — registers the controller + * with the views registry so window actions can specify + * fusion_bank_rec_kanban. + */ + +import { registry } from "@web/core/registry"; +import { BankRecKanbanController } from "./bank_rec_kanban_controller"; + +export const fusionBankRecKanbanView = { + type: "fusion_bank_rec_kanban", + Controller: BankRecKanbanController, + display_name: "Bank Reconciliation", + icon: "fa-exchange", + multiRecord: true, +}; + +registry.category("views").add("fusion_bank_rec_kanban", fusionBankRecKanbanView);