You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Odoo 15:如何通过Python XML-RPC API为发票关联指定未结付款(模拟界面添加按钮功能)

Got it, let's walk through exactly how to link that existing customer payment (your unapplied credit, or crédits en circulation) to a newly created invoice using Odoo 15's XML-RPC API. I’ve worked through this exact workflow before, so here’s the step-by-step breakdown that mirrors what the UI’s "Ajouter" button does under the hood.

First, a quick note on the Odoo logic: When you click "Ajouter" in the invoice UI to attach an unapplied payment, Odoo is actually reconciling the payment's accounting lines with the invoice's receivable lines. So our API approach needs to replicate that reconciliation process, not just add the payment to a field on the invoice.


Step 1: Set Up Your XML-RPC Connection

Assuming you already have this, but here’s a quick reminder for context:

import xmlrpc.client

# Replace these with your Odoo instance details
ODOO_URL = "https://your-odoo-domain.com"
ODOO_DB = "your-database-name"
ODOO_USER = "your-username"
ODOO_PASS = "your-password"

# Authenticate and get the model proxy
common = xmlrpc.client.ServerProxy(f"{ODOO_URL}/xmlrpc/2/common")
uid = common.authenticate(ODOO_DB, ODOO_USER, ODOO_PASS, {})
models = xmlrpc.client.ServerProxy(f"{ODOO_URL}/xmlrpc/2/object")

Step 2: Validate Your Payment and Invoice

Before doing anything, make sure:

  • The payment is a posted, unreconciled inbound customer payment (matches your "unapplied credit" status)
  • The payment and invoice belong to the same customer

Add these checks to avoid errors:

# Replace with your existing payment ID and newly created invoice ID
PAYMENT_ID = 123
INVOICE_ID = 456

# Fetch payment details to validate
payment = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
    'account.payment', 'read',
    [[PAYMENT_ID], ['payment_type', 'state', 'reconciled', 'partner_id', 'move_id']])[0]

# Validate payment status
if payment['payment_type'] != 'inbound' or payment['state'] != 'posted' or payment['reconciled']:
    raise ValueError("Payment must be a posted, unreconciled inbound customer payment.")

# Validate customer match between payment and invoice
invoice_partner = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
    'account.move', 'read',
    [[INVOICE_ID], ['partner_id']])[0]['partner_id'][0]

if payment['partner_id'][0] != invoice_partner:
    raise ValueError("Payment and invoice must belong to the same customer.")

Step 3: Fetch the Reconciliation Lines

We need to get the specific accounting lines from both the payment and invoice that need to be reconciled:

  1. Invoice's receivable line: The line representing the customer's outstanding balance on the invoice
  2. Payment's unapplied lines: The lines representing the unapplied credit from the payment
# Get the invoice's unreconciled receivable line
invoice_receivable_line = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
    'account.move.line', 'search_read',
    [[
        ['move_id', '=', INVOICE_ID],
        ['account_id.internal_type', '=', 'receivable'],
        ['reconciled', '=', False]
    ]],
    ['id'])[0]
invoice_line_id = invoice_receivable_line['id']

# Get the payment's unreconciled accounting lines
payment_lines = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
    'account.move.line', 'search_read',
    [[
        ['move_id', '=', payment['move_id'][0]],
        ['reconciled', '=', False]
    ]],
    ['id'])
payment_line_ids = [line['id'] for line in payment_lines]

Step 4: Reconcile the Lines

This is the key step that mimics the UI's "Ajouter" button. We’ll call Odoo’s built-in reconciliation method to link the payment lines to the invoice line:

# Reconcile the payment lines with the invoice's receivable line
models.execute_kw(ODOO_DB, uid, ODOO_PASS,
    'account.move.line', 'reconcile',
    [payment_line_ids + [invoice_line_id]])

Notes for Edge Cases

  • Partial Reconciliation: If the payment amount is larger than the invoice, you can pass additional parameters to the reconcile method to handle the leftover credit (like writeoff_amount or writeoff_account_id).
  • Multi-Currency: If dealing with multi-currency, ensure the payment and invoice currencies match, or add currency handling logic to the reconciliation call.

内容的提问来源于stack exchange,提问作者VictorYvergniaux

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 20:32:34