如何通过 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...}]
)
主要有两个问题:
288必须对应一条字段完整且已正确创建的account.payment记录,不能只是任意付款 ID。- 上下文不能作为普通位置参数传入,需要放在
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()。
备注:内容仅供参考。
