第三章 支付(account.payment)
Outstanding Credit
如果我们在开票之前登记了付款,那么odoo会在发票中提示该客户拥有可未结清的信用凭据,也就是说该客户拥有还没有核销的预付款。那么odoo是依据怎样的逻辑来判断的呢?
odoo17.0
我们在发票模型(account.move)中发现了用来判断是否存在未结清信用凭据的字段invoice_has_outstanding, 看一下它的具体逻辑:
# account.move
invoice_has_outstanding = fields.Boolean(
groups="account.group_account_invoice,account.group_account_readonly",
compute='_compute_payments_widget_to_reconcile_info',
)
...
def _compute_payments_widget_to_reconcile_info(self):
for move in self:
# 默认设置未结清信用为False
move.invoice_outstanding_credits_debits_widget = False
move.invoice_has_outstanding = False
# 未提交的发票不显示未结清凭据
if move.state != 'posted' \
or move.payment_state not in ('not_paid', 'partial') \
or not move.is_invoice(include_receipts=True):
continue
pay_term_lines = move.line_ids\
.filtered(lambda line: line.account_id.account_type in ('asset_receivable', 'liability_payable'))
# 过滤域: 科目类型为应收/应付&发票状态已提交&合作伙伴为发票合作伙伴的关联方&核销状态为False&(余额不等于0或货币余额不为0)
domain = [
('account_id', 'in', pay_term_lines.account_id.ids),
('parent_state', '=', 'posted'),
('partner_id', '=', move.commercial_partner_id.id),
('reconciled', '=', False),
'|', ('amount_residual', '!=', 0.0), ('amount_residual_currency', '!=', 0.0),
]
payments_widget_vals = {'outstanding': True, 'content': [], 'move_id': move.id}
# 进项票添加过滤条件 余额数值小于0
# 销项票添加过滤条件 余额数值大于0
if move.is_inbound():
domain.append(('balance', '<', 0.0))
payments_widget_vals['title'] = _('Outstanding credits')
else:
domain.append(('balance', '>', 0.0))
payments_widget_vals['title'] = _('Outstanding debits')
for line in self.env['account.move.line'].search(domain):
# 如果支付货币和发票货币相同,直接计算货币余额的绝对值
# 否则将支付货币转换为公司本位币后再取绝对值
if line.currency_id == move.currency_id:
# Same foreign currency.
amount = abs(line.amount_residual_currency)
else:
# Different foreign currencies.
amount = line.company_currency_id._convert(
abs(line.amount_residual),
move.currency_id,
move.company_id,
line.date,
)
# 如果余额等于0则未结清凭据依旧为False
if move.currency_id.is_zero(amount):
continue
# 将新结清凭据赋值到payments_widget_vals中
payments_widget_vals['content'].append({
'journal_name': line.ref or line.move_id.name,
'amount': amount,
'currency_id': move.currency_id.id,
'id': line.id,
'move_id': line.move_id.id,
'date': fields.Date.to_string(line.date),
'account_payment_id': line.payment_id.id,
})
if not payments_widget_vals['content']:
continue
# 标记该发票有未结清凭据
move.invoice_outstanding_credits_debits_widget = payments_widget_vals
move.invoice_has_outstanding = True
我们在分析了未结清凭据的实现逻辑,可以看出odoo在查找发票是否存在未结清凭据时的逻辑是:
- 日记账分录的合作伙伴是当前发票的关联商业实体且发票状态为已提交
- 日记账分录(account.move.line)的科目应该是应收(asset_receivable)或应付(liability_payable)
- 日记账状态未未核销且余额(货币余额)不为0
- 对于进项票,日记账分录的余额应该小于0
- 对于销项票,日记账分录的余额应该大于0
只有满足上述5个条件的日记账分录才会被视作未结清凭证出现在发票的表单视图的右下角。