PAYATHON 2026

如何通过 Odoo API RPC 创建发票关联付款?

支付阿杰

结论

在 Odoo 11 中,为发票创建付款时,建议使用付款登记向导 account.register.payments,然后调用 create_payments()。调用时,需要通过 context 传入待付款发票:

{
    'active_model': 'account.invoice',
    'active_ids': [invoice_id],
    'active_id': invoice_id
}

这套流程会创建 account.payment、过账付款,并核销付款与发票。单独调用 account.payment.create() 通常无法完成整个流程,因为新建的付款记录仍是草稿状态。

XML-RPC 示例

以下示例基于这些条件:

  • 发票已经确认,状态为 open;
  • invoice_id 是 account.invoice 的记录 ID;
  • journal_id 是银行或现金日记账;
  • payment_method_id 是可用于收款的方法,例如手工付款方式;
  • 当前用户有创建和过账付款的权限。
import xmlrpc.client
from datetime import date

url = 'https://odoo.example.com'
db = 'your_database'
username = 'api@example.com'
password = 'your_password'

common = xmlrpc.client.ServerProxy(
    '{}/xmlrpc/2/common'.format(url)
)

uid = common.authenticate(db, username, password, {})

if not uid:
    raise RuntimeError('Odoo authentication failed')

models = xmlrpc.client.ServerProxy(
    '{}/xmlrpc/2/object'.format(url)
)

invoice_id = 123
journal_id = 8
payment_method_id = 1

context = {
    'active_model': 'account.invoice',
    'active_ids': [invoice_id],
    'active_id': invoice_id,
}

wizard_id = models.execute_kw(
    db,
    uid,
    password,
    'account.register.payments',
    'create',
    [{
        'payment_date': date.today().strftime('%Y-%m-%d'),
        'journal_id': journal_id,
        'payment_method_id': payment_method_id,
    }],
    {
        'context': context,
    }
)

result = models.execute_kw(
    db,
    uid,
    password,
    'account.register.payments',
    'create_payments',
    [[wizard_id]],
    {
        'context': context,
    }
)

print(result)

付款金额可以省略,向导通常会根据 active_ids 中未付发票的金额填入默认值。如果只支付部分金额,可以在创建向导时指定 amount:

wizard_id = models.execute_kw(
    db,
    uid,
    password,
    'account.register.payments',
    'create',
    [{
        'amount': 500.00,
        'payment_date': '2026-08-31',
        'journal_id': journal_id,
        'payment_method_id': payment_method_id,
        'communication': 'INV/2026/001',
    }],
    {
        'context': context,
    }
)

查询可用的付款方式

不要默认 payment_method_id 一定是 1。可以先读取付款日记账允许使用的收款方式:

journal = models.execute_kw(
    db,
    uid,
    password,
    'account.journal',
    'read',
    [[journal_id]],
    {
        'fields': [
            'name',
            'type',
            'inbound_payment_method_ids',
        ]
    }
)[0]

print(journal)

处理客户发票付款时,应从 inbound_payment_method_ids 中选择一个 ID。退款和供应商付款的方向不同,可能需要使用 outbound_payment_method_ids。

也可以查询手工付款方式:

payment_methods = models.execute_kw(
    db,
    uid,
    password,
    'account.payment.method',
    'search_read',
    [[
        ['payment_type', '=', 'inbound'],
        ['code', '=', 'manual'],
    ]],
    {
        'fields': ['id', 'name', 'code', 'payment_type'],
        'limit': 10,
    }
)

print(payment_methods)

直接创建 account.payment

如果不使用向导,也可以直接创建 account.payment,将发票写入 invoice_ids,再调用 post():

payment_id = models.execute_kw(
    db,
    uid,
    password,
    'account.payment',
    'create',
    [{
        'payment_type': 'inbound',
        'partner_type': 'customer',
        'partner_id': partner_id,
        'amount': 500.00,
        'currency_id': currency_id,
        'journal_id': journal_id,
        'payment_method_id': payment_method_id,
        'payment_date': '2026-08-31',
        'communication': 'INV/2026/001',
        'invoice_ids': [(4, invoice_id, 0)],
    }]
)

models.execute_kw(
    db,
    uid,
    password,
    'account.payment',
    'post',
    [[payment_id]]
)

其中:

'invoice_ids': [(4, invoice_id, 0)]

这是 Odoo 的关系字段命令,作用是把已有发票加入 invoice_ids,不会创建新发票。

普通客户发票通常使用:

'payment_type': 'inbound'
'partner_type': 'customer'

供应商账单付款通常使用:

'payment_type': 'outbound'
'partner_type': 'supplier'

直接创建付款时,需要自行确保合作伙伴、币种、金额、付款方向和日记账都与发票一致。使用 account.register.payments 向导通常更稳妥,也更接近 Odoo 后台点击“登记付款”按钮时执行的业务流程。

注意事项

  • 发票必须已经确认,并处于可付款状态。草稿发票无法正常核销。
  • create_payments() 接收向导记录 ID 列表,因此参数需要写成 [[wizard_id]]。
  • 创建向导和调用 create_payments() 时都应传入 context,否则向导可能无法确定目标发票。
  • 日期应使用 YYYY-MM-DD 格式。
  • 日记账一般应为 bank 或 cash 类型。
  • 多币种付款还可能受公司币种、付款日汇率和差额处理规则影响。
  • account.register.payments 是临时模型,不应把向导记录 ID 当作最终付款 ID 保存。执行完成后,应在 account.payment 中查询实际生成的付款。
  • Odoo 11 的第三方模块可能会覆盖付款向导或增加必填字段。如果使用标准参数仍提示缺少字段,可以先通过 fields_get 查看当前数据库中该模型的实际字段定义。

备注:内容仅供参考。