131 lines
6.0 KiB
Python
131 lines
6.0 KiB
Python
from odoo import models, fields, api
|
|
from odoo.exceptions import UserError
|
|
|
|
|
|
class BankReconcileWizard(models.TransientModel):
|
|
_name = 'bank.reconcile.wizard'
|
|
_description = 'Bank Reconcile Wizard'
|
|
|
|
bank_line_ids = fields.Many2many('account.bank.statement.line',
|
|
string='Selected Bank Lines',
|
|
readonly=True)
|
|
journal_entry_id = fields.Many2one('account.move',
|
|
string='Journal Entry to Reconcile',
|
|
domain=[('state', '=', 'posted')])
|
|
journal_entry_line_id = fields.Many2one('account.move.line',
|
|
string='Journal Entry Line to Reconcile',
|
|
domain="[('move_id', '=', journal_entry_id), ('reconciled', '=', False)]")
|
|
total_bank_line_amount = fields.Float(string='Total Bank Line Amount', compute='_compute_total_bank_line_amount', store=True)
|
|
|
|
@api.onchange('journal_entry_id')
|
|
def _onchange_journal_entry_id(self):
|
|
"""Reset journal entry line when journal entry changes"""
|
|
if self.journal_entry_id:
|
|
self.journal_entry_line_id = False
|
|
else:
|
|
self.journal_entry_line_id = False
|
|
|
|
|
|
@api.depends('bank_line_ids')
|
|
def _compute_total_bank_line_amount(self):
|
|
"""Compute total amount of selected bank lines"""
|
|
for record in self:
|
|
record.total_bank_line_amount = sum(line.amount for line in record.bank_line_ids)
|
|
|
|
def action_reconcile(self):
|
|
"""Perform the reconciliation for each selected bank line"""
|
|
if not self.journal_entry_id:
|
|
raise UserError("Please select a journal entry to reconcile.")
|
|
|
|
if not self.journal_entry_line_id:
|
|
raise UserError("Please select a journal entry line to reconcile.")
|
|
|
|
# Validate that the total of individual line amounts doesn't exceed the journal entry line amount
|
|
journal_line_amount = self.journal_entry_line_id.debit or self.journal_entry_line_id.credit
|
|
if len(self.bank_line_ids) > 1:
|
|
total_bank_amount = sum(abs(line.amount) for line in self.bank_line_ids)
|
|
if total_bank_amount > journal_line_amount:
|
|
raise UserError(f"Total bank line amounts ({total_bank_amount}) cannot exceed the journal entry line amount ({journal_line_amount}).")
|
|
|
|
# Process each selected bank line individually
|
|
for bank_line in self.bank_line_ids:
|
|
self._reconcile_single_line(bank_line, self.journal_entry_line_id)
|
|
|
|
|
|
return {'type': 'ir.actions.act_window_close'}
|
|
|
|
def _reconcile_single_line(self, bank_line, journal_entry_line):
|
|
"""Reconcile a single bank line with a journal entry line"""
|
|
# Get the account from the journal entry line that will be on the opposite side
|
|
reconcile_account = journal_entry_line.account_id
|
|
|
|
# Use the individual bank line amount for each line
|
|
reconcile_amount = abs(bank_line.amount)
|
|
|
|
# According to requirement #5: if the bank line is debit,
|
|
# then the new journal entry after reconcile will have that bank account in debit
|
|
bank_account = bank_line.journal_id.default_account_id
|
|
bank_line_amount = bank_line.amount
|
|
|
|
# Determine if the bank line is debit (positive) or credit (negative)
|
|
if bank_line_amount >= 0: # Bank line is debit (money coming in)
|
|
# Bank account should be debited (requirement #5)
|
|
debit_account = bank_account
|
|
# The account from the selected journal entry line goes to credit (requirement #6)
|
|
credit_account = reconcile_account
|
|
else: # Bank line is credit (money going out)
|
|
# Bank account should be credited
|
|
credit_account = bank_account
|
|
# The account from the selected journal entry line goes to debit
|
|
debit_account = reconcile_account
|
|
|
|
# Set the amounts - make sure they are balanced
|
|
debit_amount = reconcile_amount
|
|
credit_amount = reconcile_amount
|
|
|
|
# Create a new journal entry for reconciliation with lines
|
|
reconciling_move = self.env['account.move'].create({
|
|
'journal_id': bank_line.journal_id.id,
|
|
'date': bank_line.date,
|
|
'ref': f'Reconciliation: {bank_line.name or "Bank Line"}',
|
|
'move_type': 'entry',
|
|
'line_ids': [
|
|
(0, 0, {
|
|
'account_id': debit_account.id,
|
|
'debit': debit_amount,
|
|
'credit': 0,
|
|
'name': f'Bank Reconciliation: {bank_line.name or ""}',
|
|
}),
|
|
(0, 0, {
|
|
'account_id': credit_account.id,
|
|
'debit': 0,
|
|
'credit': credit_amount,
|
|
'name': f'Bank Reconciliation: {bank_line.name or ""}',
|
|
})
|
|
]
|
|
})
|
|
|
|
# Post the reconciling journal entry
|
|
reconciling_move.action_post()
|
|
|
|
# Link the bank line to the reconciling move
|
|
bank_line.sudo().write({
|
|
'move_id': reconciling_move.id,
|
|
})
|
|
|
|
# Mark the bank line as reconciled in a separate operation
|
|
bank_line.sudo().write({
|
|
'is_reconciled': True,
|
|
})
|
|
|
|
# Try to reconcile the selected journal entry line with the corresponding line in the reconciling move
|
|
# Find the line in the reconciling move that has the same account as the journal entry line
|
|
reconciling_line = reconciling_move.line_ids.filtered(lambda l: l.account_id.id == reconcile_account.id and l.credit > 0)
|
|
|
|
# Try to reconcile the journal entry line with our reconciling line
|
|
if reconciling_line:
|
|
try:
|
|
(journal_entry_line + reconciling_line).reconcile()
|
|
except:
|
|
# If reconcile fails, we'll just link the moves
|
|
pass |