Odoo15中发票/供应商账单支付匹配与分配实现问询
Odoo15 发票/供应商账单支付分配实现方案
已在Odoo15的account.payment模型中添加one2many字段,用于列出客户未全额支付的发票/供应商账单,现需实现过账支付时的部分/全额支付分配功能,以下是当前已编写的代码:
现有代码实现
AccountPayment 模型扩展
class AccountPayment(models.Model): _inherit = "account.payment" payment_line_ids = fields.One2many('account.payment.line', 'payment_id', string="发票调整") @api.onchange('partner_id') def _onchange_partner_id(self): line_vals = [] for rec in self: rec.payment_line_ids = False if rec.partner_id: partner_moves = self.env['account.move'].search([ ('partner_id', '=', rec.partner_id.id), ('state', '=', 'posted'), ('payment_state', 'in', ('not_paid', 'partial')) ]) for mov in partner_moves: open_invoice_lines = { 'move_id': mov.id, 'date': mov.date, 'date_due': mov.invoice_date_due, 'original_amount': mov.amount_total, 'balance_amount': mov.amount_residual, 'payment_id': rec.id, } line_vals.append((0, 0, open_invoice_lines)) rec.payment_line_ids = line_vals
AccountPaymentLine 模型定义
class AccountPaymentLine(models.Model): _name = 'account.payment.line' payment_id = fields.Many2one('account.payment') move_id = fields.Many2one('account.move', string="发票/账单") date = fields.Date(string="日期") date_due = fields.Date(string="到期日") original_amount = fields.Float(string="原始金额") balance_amount = fields.Float(string="剩余金额") allocation_amount = fields.Float(string="分配金额")
支付分配界面

核心实现思路
1. 分配金额合法性校验
- 在
account.payment.line中添加约束,避免分配金额超出剩余金额或为负数:from odoo.exceptions import ValidationError @api.constrains('allocation_amount', 'balance_amount') def _check_allocation_amount(self): for line in self: if line.allocation_amount < 0 or line.allocation_amount > line.balance_amount: raise ValidationError("分配金额不能为负,且不能超过账单剩余金额") - 在
account.payment中校验总分配金额不超过支付金额:@api.constrains('payment_line_ids', 'amount') def _check_total_allocation(self): for rec in self: total_allocated = sum(line.allocation_amount for line in rec.payment_line_ids) if total_allocated > rec.amount: raise ValidationError("总分配金额不能超过支付金额")
2. 过账时自动创建对账记录
重写account.payment的post方法,根据分配金额自动完成支付与账单的对账:
def post(self): res = super(AccountPayment, self).post() for payment in self: if payment.payment_line_ids: for line in payment.payment_line_ids.filtered(lambda l: l.allocation_amount > 0): # 获取支付凭证的对应科目行 payment_lines = payment.move_id.line_ids.filtered( lambda l: l.account_id == payment.destination_account_id ) # 获取账单的未清科目行 invoice_lines = line.move_id.line_ids.filtered( lambda l: l.account_id == payment.destination_account_id and l.amount_residual != 0 ) # 执行对账(Odoo自动处理部分/全额对账逻辑) (payment_lines + invoice_lines).reconcile() return res
3. 前端交互优化
- 在支付表单视图中设置
payment_line_ids为可编辑树形视图,方便输入分配金额:<field name="payment_line_ids"> <tree editable="bottom"> <field name="move_id"/> <field name="date"/> <field name="date_due"/> <field name="original_amount"/> <field name="balance_amount"/> <field name="allocation_amount"/> </tree> </field> - 添加实时计算的剩余可分配金额字段:
remaining_amount = fields.Float(compute='_compute_remaining_amount', string="剩余可分配金额") @api.depends('amount', 'payment_line_ids.allocation_amount') def _compute_remaining_amount(self): for rec in self: total_allocated = sum(line.allocation_amount for line in rec.payment_line_ids) rec.remaining_amount = rec.amount - total_allocated
4. 多币种场景适配(可选)
若涉及多币种支付,需在onchange方法或约束中添加币种校验,确保分配金额的币种与支付、账单币种一致,必要时处理汇率转换逻辑。
内容的提问来源于stack exchange,提问作者code_explorer
相关产品推荐
相关产品推荐

