TransientModel that filters unreconciled bank lines by journal + date range + strategy and runs engine.reconcile_batch. Shows reconciled_count / skipped_count / error_summary in result view. Made-with: Cursor
79 lines
2.8 KiB
Python
79 lines
2.8 KiB
Python
"""Auto-reconcile wizard.
|
|
|
|
Lets the user pick filters (journal, date range, strategy) and runs
|
|
fusion.reconcile.engine.reconcile_batch on all matching unreconciled
|
|
bank lines. Shows summary of results.
|
|
"""
|
|
|
|
from odoo import _, fields, models
|
|
|
|
|
|
class FusionAutoReconcileWizard(models.TransientModel):
|
|
_name = "fusion.auto.reconcile.wizard"
|
|
_description = "Auto-Reconcile Bank Statement Lines Wizard"
|
|
|
|
journal_id = fields.Many2one(
|
|
'account.journal', string="Bank Journal",
|
|
domain=[('type', '=', 'bank')], required=True)
|
|
date_from = fields.Date(string="Date From")
|
|
date_to = fields.Date(string="Date To", default=fields.Date.today)
|
|
strategy = fields.Selection([
|
|
('auto', 'Auto (try amount-exact, then multi-invoice, then FIFO)'),
|
|
('amount_exact', 'Amount Exact only'),
|
|
('fifo', 'FIFO only'),
|
|
('multi_invoice', 'Multi-invoice combination only'),
|
|
], default='auto', required=True)
|
|
only_with_partner = fields.Boolean(
|
|
string="Only lines with a partner",
|
|
default=True,
|
|
help="Most safer matches require a known partner. Untick to attempt "
|
|
"matching for orphan lines too (uses memo tokenization).")
|
|
|
|
state = fields.Selection([
|
|
('draft', 'Draft'),
|
|
('done', 'Done'),
|
|
], default='draft')
|
|
reconciled_count = fields.Integer(readonly=True)
|
|
skipped_count = fields.Integer(readonly=True)
|
|
error_count = fields.Integer(readonly=True)
|
|
error_summary = fields.Text(readonly=True)
|
|
|
|
def _build_domain(self):
|
|
self.ensure_one()
|
|
domain = [
|
|
('journal_id', '=', self.journal_id.id),
|
|
('is_reconciled', '=', False),
|
|
]
|
|
if self.date_from:
|
|
domain.append(('date', '>=', self.date_from))
|
|
if self.date_to:
|
|
domain.append(('date', '<=', self.date_to))
|
|
if self.only_with_partner:
|
|
domain.append(('partner_id', '!=', False))
|
|
return domain
|
|
|
|
def action_run(self):
|
|
self.ensure_one()
|
|
Line = self.env['account.bank.statement.line']
|
|
lines = Line.search(self._build_domain(), limit=1000)
|
|
result = self.env['fusion.reconcile.engine'].reconcile_batch(
|
|
lines, strategy=self.strategy)
|
|
errors = result.get('errors', [])
|
|
self.write({
|
|
'state': 'done',
|
|
'reconciled_count': result.get('reconciled_count', 0),
|
|
'skipped_count': result.get('skipped', 0),
|
|
'error_count': len(errors),
|
|
'error_summary': '\n'.join(
|
|
f"Line {e['line_id']}: {e['error']}" for e in errors[:20]
|
|
) or False,
|
|
})
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'res_model': self._name,
|
|
'res_id': self.id,
|
|
'view_mode': 'form',
|
|
'target': 'new',
|
|
'context': self.env.context,
|
|
}
|