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.reconciled') def _compute_payment_residual(self): """Compute the residual amount from payment journal items For testing: show all residual amounts regardless of reconciliation status """ for pay in self: if not pay.move_id: pay.payment_residual = 0.0 pay.payment_residual_currency = 0.0 continue # Get ALL move lines - let's see what's there all_lines = pay.move_id.line_ids # Sum ALL residual amounts to see what's happening total_residual = sum(all_lines.mapped('amount_residual')) total_residual_currency = sum(all_lines.mapped('amount_residual_currency')) # For debugging - let's try multiple approaches: # Approach 1: All lines residual approach1_residual = total_residual approach1_residual_currency = total_residual_currency # Approach 2: Only reconcilable account lines reconcilable_lines = all_lines.filtered(lambda line: line.account_id.reconcile) approach2_residual = sum(reconcilable_lines.mapped('amount_residual')) approach2_residual_currency = sum(reconcilable_lines.mapped('amount_residual_currency')) # Approach 3: Receivable/Payable account lines only rec_pay_lines = all_lines.filtered(lambda line: line.account_id.account_type in ('asset_receivable', 'liability_payable')) approach3_residual = sum(rec_pay_lines.mapped('amount_residual')) approach3_residual_currency = sum(rec_pay_lines.mapped('amount_residual_currency')) # For now, let's use the approach that gives us the largest non-zero value # This will help us identify which approach works candidates = [ abs(approach1_residual), abs(approach2_residual), abs(approach3_residual), abs(approach1_residual_currency), abs(approach2_residual_currency), abs(approach3_residual_currency) ] max_value = max(candidates) if candidates else 0.0 if abs(approach1_residual) == max_value: pay.payment_residual = abs(approach1_residual) pay.payment_residual_currency = abs(approach1_residual_currency) elif abs(approach2_residual) == max_value: pay.payment_residual = abs(approach2_residual) pay.payment_residual_currency = abs(approach2_residual_currency) elif abs(approach3_residual) == max_value: pay.payment_residual = abs(approach3_residual) pay.payment_residual_currency = abs(approach3_residual_currency) else: # Fallback to currency residuals pay.payment_residual = abs(approach1_residual_currency) pay.payment_residual_currency = abs(approach1_residual_currency)