Files
Odoo-Modules/fusion_accounting/models/accounting_match_history.py
gsinghpal 3cc93b8783 changes
2026-04-04 15:37:16 -04:00

170 lines
6.9 KiB
Python

import json
import logging
from odoo import models, fields, api
_logger = logging.getLogger(__name__)
TOOL_LABELS = {
'get_unreconciled_bank_lines': 'Get Unreconciled Bank Lines',
'get_unreconciled_receipts': 'Get Unreconciled Receipts',
'match_bank_line_to_payments': 'Match Bank Line to Payments',
'auto_reconcile_bank_lines': 'Auto-Reconcile Bank Lines',
'apply_reconcile_model': 'Apply Reconcile Model',
'unmatch_bank_line': 'Unmatch Bank Line',
'get_reconcile_suggestions': 'Get Reconcile Suggestions',
'sum_payments_by_date': 'Sum Payments by Date',
'get_bank_line_details': 'Get Bank Line Details',
'check_recurring_pattern': 'Check Recurring Pattern',
'match_internal_transfers': 'Match Internal Transfers',
'find_unreconciled_cheques': 'Find Unreconciled Cheques',
'reconcile_payroll_cheques': 'Reconcile Payroll Cheques',
'suggest_bank_line_matches': 'Suggest Bank Line Matches',
'search_matching_entries': 'Search Matching Entries',
'calculate_hst_balance': 'Calculate HST Balance',
'create_expense_entry': 'Create Expense Entry',
'find_missing_itc_bills': 'Find Missing ITC Bills',
'find_missing_tax_invoices': 'Find Missing Tax Invoices',
'get_tax_report': 'Get Tax Report',
'get_ar_aging': 'Get AR Aging',
'get_overdue_invoices': 'Get Overdue Invoices',
'get_partner_balance': 'Get Partner Balance',
'get_ap_aging': 'Get AP Aging',
'get_unpaid_bills': 'Get Unpaid Bills',
'find_duplicate_bills': 'Find Duplicate Bills',
'create_vendor_bill': 'Create Vendor Bill',
'register_bill_payment': 'Register Bill Payment',
'get_profit_loss': 'Get Profit & Loss',
'get_balance_sheet': 'Get Balance Sheet',
'get_trial_balance': 'Get Trial Balance',
'get_cash_flow': 'Get Cash Flow',
'compare_periods': 'Compare Periods',
'get_invoicing_summary': 'Get Invoicing Summary',
'get_billing_summary': 'Get Billing Summary',
'get_collections_summary': 'Get Collections Summary',
'create_payroll_journal_entry': 'Create Payroll Journal Entry',
'find_adp_without_payment': 'Find ADP Without Payment',
'get_adp_receivable_aging': 'Get ADP Receivable Aging',
'register_adp_batch_payment': 'Register ADP Batch Payment',
'get_close_checklist': 'Get Month-End Checklist',
'find_draft_entries': 'Find Draft Entries',
'find_wrong_direction_balances': 'Find Wrong Direction Balances',
'find_duplicate_entries': 'Find Duplicate Entries',
'get_payroll_entries': 'Get Payroll Entries',
'get_cra_remittance_status': 'Get CRA Remittance Status',
}
class FusionAccountingMatchHistory(models.Model):
_name = 'fusion.accounting.match.history'
_description = 'Fusion Accounting Match History'
_order = 'proposed_at desc'
_rec_name = 'display_label'
display_label = fields.Char(
string='Label', compute='_compute_display_label', store=True,
)
session_id = fields.Many2one(
'fusion.accounting.session', string='Session',
index=True, ondelete='cascade',
)
tool_name = fields.Char(string='Tool Name', required=True, index=True)
tool_display_name = fields.Char(
string='Tool', compute='_compute_tool_display_name', store=True,
)
tool_params_pretty = fields.Text(
string='Parameters', compute='_compute_pretty_json',
)
tool_result_pretty = fields.Text(
string='Result', compute='_compute_pretty_json',
)
tool_params = fields.Text(string='Tool Parameters (JSON)')
tool_result = fields.Text(string='Tool Result (JSON)')
ai_reasoning = fields.Text(string='AI Reasoning')
ai_confidence = fields.Float(string='AI Confidence', digits=(3, 2))
rule_id = fields.Many2one(
'fusion.accounting.rule', string='Applied Rule',
ondelete='set null',
)
proposed_at = fields.Datetime(
string='Proposed At',
default=fields.Datetime.now,
required=True,
)
decision = fields.Selection(
selection=[
('approved', 'Approved'),
('rejected', 'Rejected'),
('pending', 'Pending'),
('auto', 'Auto-Executed'),
],
string='Decision',
default='pending',
index=True,
)
decided_at = fields.Datetime(string='Decided At')
decided_by = fields.Many2one('res.users', string='Decided By')
rejection_reason = fields.Text(string='Rejection Reason')
correct_action = fields.Text(string='Correct Action (JSON)')
bank_statement_line_id = fields.Many2one(
'account.bank.statement.line', string='Bank Statement Line',
ondelete='set null',
)
move_line_ids = fields.Many2many(
'account.move.line', string='Journal Items',
)
amount = fields.Monetary(string='Amount', currency_field='currency_id')
currency_id = fields.Many2one(
'res.currency', string='Currency',
default=lambda self: self.env.company.currency_id,
)
partner_id = fields.Many2one('res.partner', string='Partner')
company_id = fields.Many2one(
'res.company', string='Company',
default=lambda self: self.env.company,
)
@api.depends('tool_name')
def _compute_tool_display_name(self):
for rec in self:
rec.tool_display_name = TOOL_LABELS.get(rec.tool_name, (rec.tool_name or '').replace('_', ' ').title())
@api.depends('tool_params', 'tool_result')
def _compute_pretty_json(self):
for rec in self:
for src, dst in [('tool_params', 'tool_params_pretty'), ('tool_result', 'tool_result_pretty')]:
raw = getattr(rec, src) or '{}'
try:
parsed = json.loads(raw)
setattr(rec, dst, json.dumps(parsed, indent=2, default=str, ensure_ascii=False))
except (json.JSONDecodeError, TypeError):
setattr(rec, dst, raw)
@api.depends('tool_name', 'proposed_at', 'decision')
def _compute_display_label(self):
for rec in self:
label = TOOL_LABELS.get(rec.tool_name, (rec.tool_name or '').replace('_', ' ').title())
date_str = rec.proposed_at.strftime('%b %d %H:%M') if rec.proposed_at else ''
decision_str = dict(rec._fields['decision'].selection).get(rec.decision, '')
rec.display_label = f"{label}{decision_str} ({date_str})" if date_str else label
def action_approve(self):
self.write({
'decision': 'approved',
'decided_at': fields.Datetime.now(),
'decided_by': self.env.user.id,
})
for rec in self:
if rec.rule_id:
rec.rule_id._record_decision(approved=True)
def action_reject(self):
self.write({
'decision': 'rejected',
'decided_at': fields.Datetime.now(),
'decided_by': self.env.user.id,
})
for rec in self:
if rec.rule_id:
rec.rule_id._record_decision(approved=False)