AX 2012 中 ledgerJournalTrans 的付款与发票关系
明确结论
LedgerJournalTrans 中的付款行和发票行之间没有可靠的主外键关系,不能只通过 Invoice 字段直接关联。
在 AX 2012 中:
- 过账前,付款日记账中选中的待结发票通常通过
SpecTrans保存标记结算关系。 - 过账后,需要通过
VendTrans和VendSettlement查询实际的结算关系。 LedgerJournalTrans.Invoice是业务编号,不是唯一键。即使付款日记账和发票日记账中的值相同,也不能将它作为唯一关联条件。
为什么不能直接关联 LedgerJournalTrans
LedgerJournalTrans 保存日记账行,过账后生成的供应商交易则保存在 VendTrans 中。一笔付款可以结算多张发票,一张发票也可能分多次支付,因此付款和发票之间本来就是多对多关系。
直接使用以下条件进行关联会有风险:
LedgerJournalTrans.Invoice == LedgerJournalTrans.Invoice
主要原因有:
- 不同供应商可能使用相同的发票号。
- 同一张发票可能分期支付。
- 一笔付款可能同时结算多张发票。
- 付款行的
Invoice字段不一定有值。 - 付款可能通过付款建议、手工标记或后续结算完成。
- 结算可能被冲销,也可能重新结算。
因此,Invoice、Voucher、AccountNum 和 TransDate 等字段只能帮助定位记录,不能代替结算表中保存的正式关系。
查询已过账的付款与发票
已过账交易的主要数据关系如下:
LedgerJournalTrans
↓ 过账
VendTrans
↓ 结算
VendSettlement
↓
另一个 VendTrans
VendSettlement 中常用的关联字段包括:
TransRecId:被结算供应商交易的VendTrans.RecIdOffsetRecid:参与结算的另一笔VendTrans.RecIdTransCompany:TransRecId所属公司OffsetCompany:OffsetRecid所属公司SettleAmountCur:结算金额SettlementVoucher:结算凭证
下面的 X++ 示例根据一笔 VendTrans 查询与其发生结算的其他供应商交易:
static void FindRelatedVendTransactions(Args _args)
{
VendTrans sourceTrans;
VendTrans relatedTrans;
VendSettlement settlement;
RecId sourceRecId = 5637144576; // 替换为实际 VendTrans.RecId
select firstOnly sourceTrans
where sourceTrans.RecId == sourceRecId;
if (!sourceTrans)
{
info("未找到指定的 VendTrans。");
return;
}
// sourceTrans 位于 VendSettlement.TransRecId 一侧
while select settlement
where settlement.TransRecId == sourceTrans.RecId
&& settlement.TransCompany == sourceTrans.DataAreaId
{
relatedTrans.clear();
changecompany(settlement.OffsetCompany)
{
select firstOnly relatedTrans
where relatedTrans.RecId == settlement.OffsetRecid;
}
if (relatedTrans)
{
info(strFmt(
"源交易=%1,关联交易=%2,发票=%3,结算金额=%4,结算凭证=%5",
sourceTrans.Voucher,
relatedTrans.Voucher,
relatedTrans.Invoice,
settlement.SettleAmountCur,
settlement.SettlementVoucher));
}
}
// sourceTrans 也可能位于 VendSettlement.OffsetRecid 一侧
while select settlement
where settlement.OffsetRecid == sourceTrans.RecId
&& settlement.OffsetCompany == sourceTrans.DataAreaId
{
relatedTrans.clear();
changecompany(settlement.TransCompany)
{
select firstOnly relatedTrans
where relatedTrans.RecId == settlement.TransRecId;
}
if (relatedTrans)
{
info(strFmt(
"源交易=%1,关联交易=%2,发票=%3,结算金额=%4,结算凭证=%5",
sourceTrans.Voucher,
relatedTrans.Voucher,
relatedTrans.Invoice,
settlement.SettleAmountCur,
settlement.SettlementVoucher));
}
}
}
在实际环境中,还需要判断 relatedTrans 属于发票、付款、贷项通知单还是其他供应商交易。不能只根据金额的正负值判断,因为冲销、退款和贷项通知单同样会影响金额符号。
从 LedgerJournalTrans 定位 VendTrans
如果只有已过账的 LedgerJournalTrans,通常要先根据公司、供应商账户、凭证号和过账日期查找对应的 VendTrans:
static VendTrans findVendTransFromJournalLine(
LedgerJournalTrans _journalLine)
{
VendTrans vendTrans;
select firstOnly vendTrans
where vendTrans.AccountNum == _journalLine.AccountNum
&& vendTrans.Voucher == _journalLine.Voucher
&& vendTrans.TransDate == _journalLine.TransDate;
return vendTrans;
}
这段代码仅用于说明定位方式,不能保证在所有配置下都能得到唯一记录。生产代码还需要结合当前环境中可用的字段缩小查询范围,例如:
DataAreaIdAccountNumVoucherTransDateInvoice- 金额及币种
- 日记账批次和过账凭证相关信息
如果同一凭证中包含多条供应商交易,必须确认查询结果是否唯一,不能直接依赖 firstOnly。
查询尚未过账的标记关系
付款日记账尚未过账时,系统中还没有最终的 VendSettlement 记录。用户在“结算未结交易”窗口中选中的发票,通常记录在 SpecTrans 中。
SpecTrans 保存临时或待处理的标记关系。查询时需要使用当前结算上下文中的以下字段:
SpecCompanySpecTableIdSpecRecIdRefCompanyRefTableIdRefRecId
其中,RefRecId 通常指向被标记的开放供应商交易记录。SpecTableId 和 SpecRecId 的具体取值取决于付款日记账的结算调用路径,也可能受到 AX 2012 定制的影响,因此不建议自行拼接查询条件。更稳妥的方式是沿用标准结算窗体或 SpecTransManager 使用的上下文来查询标记记录。
需要注意,SpecTrans 表示的是“准备结算”或“已经标记”,不是最终结算结果。付款取消过账、取消标记或重新选择发票后,这些关系都可能发生变化。
实际处理建议
如果要制作“发票对应哪些付款”的报表,可以按以下顺序处理:
- 从发票对应的
VendTrans开始查询。 - 通过
VendSettlement.TransRecId和VendSettlement.OffsetRecid双向查找相关交易。 - 读取另一侧对应的
VendTrans。 - 根据交易类型、发票号、凭证、金额和币种判断交易的业务性质。
- 使用
SettleAmountCur展示本次结算金额,不要直接把付款总额作为发票的支付金额。 - 按照报表口径处理结算冲销、部分结算和跨公司结算。
如果要查询付款日记账当前选中了哪些发票,应查询 SpecTrans,而不是 VendSettlement。
注意事项
VendTrans.Invoice和LedgerJournalTrans.Invoice都不是全局唯一值。- 同一笔付款可能对应多条
VendSettlement。 - 同一张发票也可能对应多条付款结算记录。
- 发生部分付款时,应使用结算金额,不能只比较原始交易金额。
- 查询时要考虑
TransCompany和OffsetCompany,启用了集中付款或跨公司结算时尤其如此。 - 是否显示已冲销的结算取决于报表口径,需要结合结算状态和冲销记录处理。
- AX 2012 的不同累计更新版本以及客户定制可能增加字段或改变结算流程。字段关系应以当前环境中的 AOT 表关系和标准结算代码为准。
备注:内容仅供参考。
