73 lines
2.9 KiB
Python
73 lines
2.9 KiB
Python
from odoo import api, fields, models, _
|
|
|
|
|
|
|
|
|
|
class AccountPayment(models.Model):
|
|
_inherit = 'account.payment'
|
|
|
|
# Computed residual amount field
|
|
payment_residual = fields.Monetary(
|
|
string='Payment Residual',
|
|
compute='_compute_payment_residual',
|
|
currency_field='currency_id',
|
|
help="Residual amount of this payment (amount not yet reconciled)",
|
|
readonly=True
|
|
)
|
|
|
|
payment_residual_currency = fields.Monetary(
|
|
string='Payment Residual Currency',
|
|
compute='_compute_payment_residual',
|
|
currency_field='currency_id',
|
|
help="Residual amount in payment currency",
|
|
readonly=True
|
|
)
|
|
|
|
@api.depends('move_id.line_ids.amount_residual',
|
|
'move_id.line_ids.amount_residual_currency',
|
|
'move_id.line_ids.account_id',
|
|
'move_id.line_ids.account_id.account_type',
|
|
'is_matched')
|
|
def _compute_payment_residual(self):
|
|
"""Compute the residual amount for payments.
|
|
|
|
Matched payments always display zero residual.
|
|
For unmatched payments, we first look at residuals on reconcilable counterpart
|
|
lines (receivable/payable/write-off). If those are fully cleared, we fall back
|
|
to the liquidity lines to surface outstanding balances waiting for bank
|
|
statement matching.
|
|
"""
|
|
for pay in self:
|
|
if pay.is_matched or not pay.move_id:
|
|
pay.payment_residual = 0.0
|
|
pay.payment_residual_currency = 0.0
|
|
continue
|
|
|
|
company_currency = pay.company_id.currency_id
|
|
payment_currency = pay.currency_id or company_currency
|
|
|
|
liquidity_lines, counterpart_lines, writeoff_lines = pay._seek_for_lines()
|
|
reconcilable_lines = (counterpart_lines + writeoff_lines).filtered(lambda l: l.account_id.reconcile)
|
|
|
|
residual = sum(reconcilable_lines.mapped('amount_residual'))
|
|
residual_currency = sum(
|
|
reconcilable_lines.mapped(
|
|
'amount_residual_currency' if payment_currency != company_currency else 'amount_residual'
|
|
)
|
|
)
|
|
|
|
liquidity_residual = sum(liquidity_lines.mapped('amount_residual'))
|
|
liquidity_residual_currency = sum(
|
|
liquidity_lines.mapped(
|
|
'amount_residual_currency' if payment_currency != company_currency else 'amount_residual'
|
|
)
|
|
)
|
|
|
|
if company_currency.is_zero(residual) and not company_currency.is_zero(liquidity_residual):
|
|
residual = liquidity_residual
|
|
if payment_currency.is_zero(residual_currency) and not payment_currency.is_zero(liquidity_residual_currency):
|
|
residual_currency = liquidity_residual_currency
|
|
|
|
pay.payment_residual = abs(residual)
|
|
pay.payment_residual_currency = abs(residual_currency)
|