PAYATHON 2026

如何通过 XML RPC 在 Odoo 11 中登记发票付款?

支付老李

结论

这个报错通常不是 XML-RPC 引起的,而是创建 account.payment 时没有设置 partner_type。在 Odoo 11 中,为客户发票登记收款时,需要同时设置:

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

缺少 partner_type 时,Odoo 在过账付款的过程中无法判断该使用哪类付款序列,可能出现以下错误:

local variable 'sequence_code' referenced before assignment

关联发票时还需要使用 Odoo 的 Many2many 命令,不能直接传入普通的 ID 列表。

直接创建并过账付款

假设 invoice_id 是已经通过 action_invoice_open 验证的客户发票,可以按下面的方式登记付款:

invoice_id = x

payment_vals = {
    'amount': 32.0,
    'payment_date': '2018-12-25',
    'payment_type': 'inbound',
    'partner_type': 'customer',
    'payment_method_id': 2,
    'journal_id': 8,
    'currency_id': 1,
    'partner_id': 853,
    'invoice_ids': [(6, 0, [invoice_id])],
}

payment_id = odoo.execute_kw(
    'account.payment',
    'create',
    [payment_vals]
)

odoo.execute_kw(
    'account.payment',
    'post',
    [[payment_id]]
)

这里需要留意两个字段:

'partner_type': 'customer'

以及:

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

[(6, 0, [invoice_id])] 的作用是用指定的发票 ID 设置整个 Many2many 关系。

使用 odoorpc ORM 接口

如果使用 odoo.env 风格,也可以这样写:

Payment = odoo.env['account.payment']

payment_id = Payment.create({
    'amount': 32.0,
    'payment_date': '2018-12-25',
    'payment_type': 'inbound',
    'partner_type': 'customer',
    'payment_method_id': 2,
    'journal_id': 8,
    'currency_id': 1,
    'partner_id': 853,
    'invoice_ids': [(6, 0, [x])],
})

Payment.browse(payment_id).post()

建议在创建付款时直接写入 invoice_ids,不要先创建付款,再用普通列表给关联发票赋值。

更接近界面操作的方式

Odoo 11 的“登记付款”按钮通常通过临时向导 account.register.payments 完成。调用这个向导时,需要将发票信息放在 RPC 的 context 关键字参数中:

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

wizard_id = odoo.execute_kw(
    'account.register.payments',
    'create',
    [{
        'payment_date': '2018-12-25',
        'journal_id': 8,
        'payment_method_id': 2,
    }],
    {'context': context}
)

odoo.execute_kw(
    'account.register.payments',
    'create_payments',
    [[wizard_id]],
    {'context': context}
)

向导会根据当前发票补充客户、币种、金额和付款方向等信息,因此更接近 Odoo 界面中的标准操作流程。

具体哪些字段可以写入,可能会受到 Odoo Online 实例所安装模块和用户访问权限的影响。如果创建向导时提示某个字段不可写,可以先通过 fields_get 查看该实例的实际字段定义。

第二次调用存在的问题

下面的调用方式有误:

odoo.execute_kw(
    'account.payment',
    'action_validate_invoice_payment',
    [[288], {...context...}]
)

主要有两个问题:

  1. 288 必须对应一条字段完整且已正确创建的 account.payment 记录,不能只是任意付款 ID。
  2. 上下文不能作为普通位置参数传入,需要放在 execute_kw 的关键字参数中:
odoo.execute_kw(
    'account.payment',
    'action_validate_invoice_payment',
    [[payment_id]],
    {'context': context}
)

对于已经创建并关联发票的付款,通常可以直接调用 post()。如果需要复现界面的“登记付款”流程,则应使用 account.register.payments 向导。

上线前应检查的字段

不建议长期硬编码 payment_method_id、journal_id 和 currency_id。上线前至少需要确认:

  • partner_id 与发票上的客户一致。
  • 客户发票使用 partner_type = 'customer'。
  • 收款使用 payment_type = 'inbound'。
  • journal_id 指向允许收款的银行或现金日记账。
  • payment_method_id 是该日记账支持的入款方式。
  • currency_id 与发票、日记账及公司配置兼容。
  • payment_date 使用 Odoo 日期格式 YYYY-MM-DD,不需要传入时间。
  • 发票已经验证,并且尚未全额核销。
  • XML-RPC 用户有权创建和过账付款,也能访问相关日记账。

当前代码所需的最小修正是增加 partner_type='customer',通过 Many2many 命令关联发票,然后调用 post()。

备注:内容仅供参考。