Task 17 — Add Phase 1 widget compute fields and AI hooks:
- account.bank.statement.line: fusion_top_suggestion_id (m2o, unstored),
fusion_confidence_band (selection, unstored), bank_statement_attachment_ids
(one2many compute, mirrors Enterprise's surface field for the OWL widget).
- account.reconcile.model: fusion_ai_confidence_threshold (float).
- Bumps manifest 19.0.1.0.3 → 19.0.1.0.4.
V19 note: dropped @api.depends('id') on _compute_top_suggestion (NotImplementedError
in V19); compute is on-demand for unstored field anyway.
Made-with: Cursor
53 lines
2.2 KiB
Python
53 lines
2.2 KiB
Python
"""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']
|
|
)
|