diff --git a/fusion_accounting_bank_rec/__manifest__.py b/fusion_accounting_bank_rec/__manifest__.py index 9b64e374..6ffb2545 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.3', + 'version': '19.0.1.0.4', 'category': 'Accounting/Accounting', 'sequence': 28, 'summary': 'Native V19 bank reconciliation widget with AI confidence scoring + behavioural learning.', diff --git a/fusion_accounting_bank_rec/models/__init__.py b/fusion_accounting_bank_rec/models/__init__.py index 89320e0e..9bbbac47 100644 --- a/fusion_accounting_bank_rec/models/__init__.py +++ b/fusion_accounting_bank_rec/models/__init__.py @@ -2,3 +2,5 @@ from . import fusion_reconcile_pattern from . import fusion_reconcile_precedent from . import fusion_reconcile_suggestion from . import fusion_bank_rec_widget +from . import account_bank_statement_line +from . import account_reconcile_model diff --git a/fusion_accounting_bank_rec/models/account_bank_statement_line.py b/fusion_accounting_bank_rec/models/account_bank_statement_line.py new file mode 100644 index 00000000..40ef7af6 --- /dev/null +++ b/fusion_accounting_bank_rec/models/account_bank_statement_line.py @@ -0,0 +1,52 @@ +"""Inherit account.bank.statement.line to add Phase 1 widget compute fields. + +These fields are NOT stored — they're computed on-the-fly so the OWL widget +can render confidence badges without round-tripping. Performance OK because +the widget loads ~50-200 lines per kanban open and each compute is a single +indexed query into fusion.reconcile.suggestion. +""" + +from odoo import api, fields, models + + +class AccountBankStatementLine(models.Model): + _inherit = "account.bank.statement.line" + + # Top suggestion + its band — for the inline AI confidence badge + fusion_top_suggestion_id = fields.Many2one( + 'fusion.reconcile.suggestion', + compute='_compute_top_suggestion', + store=False, + help="Highest-ranked pending AI suggestion for this line") + fusion_confidence_band = fields.Selection( + [('high', 'High'), ('medium', 'Medium'), ('low', 'Low'), ('none', 'None')], + compute='_compute_top_suggestion', + store=False, + default='none', + help="Quick-render colour band for the OWL widget badge") + + # Mirror of Enterprise's bank_statement_attachment_ids surface field. + # Defined here so fusion's widget can render attachments without + # depending on account_accountant being installed. + bank_statement_attachment_ids = fields.One2many( + 'ir.attachment', + compute='_compute_bank_statement_attachment_ids', + help="Attachments on the underlying account.move; mirrored for the OWL widget") + + def _compute_top_suggestion(self): + Suggestion = self.env['fusion.reconcile.suggestion'].sudo() + for line in self: + top = Suggestion.search([ + ('statement_line_id', '=', line.id), + ('state', '=', 'pending'), + ('rank', '=', 1), + ], limit=1) + line.fusion_top_suggestion_id = top + line.fusion_confidence_band = top.confidence_band if top else 'none' + + @api.depends('move_id', 'move_id.attachment_ids') + def _compute_bank_statement_attachment_ids(self): + for line in self: + line.bank_statement_attachment_ids = ( + line.move_id.attachment_ids if line.move_id else self.env['ir.attachment'] + ) diff --git a/fusion_accounting_bank_rec/models/account_reconcile_model.py b/fusion_accounting_bank_rec/models/account_reconcile_model.py new file mode 100644 index 00000000..ca9dab92 --- /dev/null +++ b/fusion_accounting_bank_rec/models/account_reconcile_model.py @@ -0,0 +1,20 @@ +"""Inherit account.reconcile.model to add Phase 1 AI integration hooks. + +This is a minimal extension placeholder for now — Phase 1+ phases may +expand it (e.g., to attach AI confidence rules to reconcile-model +auto-fires). The shared-field-ownership for `created_automatically` +already lives in fusion_accounting_core; this file is for fusion_bank_rec +specific extensions only. +""" + +from odoo import fields, models + + +class AccountReconcileModel(models.Model): + _inherit = "account.reconcile.model" + + fusion_ai_confidence_threshold = fields.Float( + string="AI confidence threshold", + default=0.0, + help="If >0.0, fusion AI suggestions matching this rule are auto-applied " + "only when their confidence ≥ this threshold. 0.0 = no AI filtering.")