PAYATHON 2026

SAP B1 AR INVOICE 与 Incoming Payment 查询无结果

支付小周

结论

查询结果为空,主要有两个原因:

  1. RCT2 应通过发票内部键关联 OINV.DocEntry,不能使用 OINV.DocNum = RCT2.BaseAbs。
  2. RCT1 和 RCT3 使用了 INNER JOIN,相当于要求同一笔 Incoming Payment 既有支票明细,又有信用卡明细。大多数付款不满足这个条件,因此会被过滤掉。

SAP Business One 中的单据通常通过 DocEntry 关联。DocNum 是用户看到的单据编号。付款可能采用现金、银行转账、支票或信用卡,并不一定同时存在多种付款明细,所以 RCT1 和 RCT3 应使用 LEFT JOIN。

正确的表关系

各表之间的核心关系如下:

ORCT.DocEntry = RCT2.DocNum
RCT2.DocEntry = OINV.DocEntry
RCT2.InvType  = 13
ORCT.DocEntry = RCT1.DocNum
ORCT.DocEntry = RCT3.DocNum
OINV.DocEntry = INV1.DocEntry

各表的用途如下:

  • ORCT:Incoming Payment 表头。
  • RCT2:Incoming Payment 核销的单据。
  • OINV:A/R Invoice 表头。
  • INV1:A/R Invoice 行。
  • RCT1:支票付款明细。
  • RCT3:信用卡付款明细。
  • OCRD:Business Partner 主数据。
  • OWHS:仓库主数据。
  • [@AUND]:用户自定义表。

RCT2.InvType = 13 将关联对象限定为 A/R Invoice,避免将贷项凭证、日记账等其他对象错误地关联到 OINV。

调整后的查询

SELECT
    T5.DocNum      AS INVOICENO,
    T5.DocEntry    AS INVOICE_DOCENTRY,
    T0.DocNum      AS PAYMENTNO,
    T0.DocEntry    AS PAYMENT_DOCENTRY,
    T0.DocDate,
    T0.TrsfrDate,
    T0.TrsfrRef,
    T0.CardName,
    T0.DocTotal,
    T4.VoucherNum,
    T0.Comments,
    T2.Phone1,
    T0.CashSum,
    T0.CreditSum,
    T0.CheckSum,
    T0.TrsfrSum,
    T3.DueDate      AS CHECKDATE,
    T3.CheckNum     AS CHECKNO,
    T3.Details      AS MAYBEBANKNAME,
    T5.U_UnitCode,
    T5.U_Type,
    T7.WhsName,
    T7.City,
    T8.U_FloorNo
FROM ORCT T0
INNER JOIN RCT2 T1
    ON T0.DocEntry = T1.DocNum
   AND T1.InvType = 13
INNER JOIN OINV T5
    ON T5.DocEntry = T1.DocEntry
INNER JOIN OCRD T2
    ON T0.CardCode = T2.CardCode
LEFT JOIN RCT1 T3
    ON T0.DocEntry = T3.DocNum
LEFT JOIN RCT3 T4
    ON T0.DocEntry = T4.DocNum
LEFT JOIN INV1 T6
    ON T5.DocEntry = T6.DocEntry
LEFT JOIN OWHS T7
    ON T6.WhsCode = T7.WhsCode
LEFT JOIN [dbo].[@AUND] T8
    ON T5.U_UnitCode = T8.Code;

查询中的显示字段也做了相应调整:

  • 发票号取 OINV.DocNum,也就是 T5.DocNum。
  • Incoming Payment 的可见付款编号取 ORCT.DocNum,也就是 T0.DocNum。
  • 额外输出 DocEntry,便于排查内部关联关系。

为什么原查询会失败

1. 发票连接键错误

原查询使用了以下条件:

INNER JOIN OINV T5
    ON T5.DocNum = T1.BaseAbs

DocNum 是显示给用户的业务编号,通常不用于连接单据表。Incoming Payment 的发票分配行通常通过 RCT2.DocEntry 保存被核销单据的内部键,因此应改为:

INNER JOIN OINV T5
    ON T5.DocEntry = T1.DocEntry
   AND T1.InvType = 13

如果当前数据库版本或本地化字段结构不同,应先检查 RCT2 中实际保存的 DocEntry、InvoiceId、BaseAbs 和 InvType 值。标准查询关系通常是 RCT2.DocEntry = OINV.DocEntry。

2. 付款方式表不应全部使用 INNER JOIN

原查询同时使用了:

INNER JOIN RCT1 ...
INNER JOIN RCT3 ...

这要求一笔付款必须同时包含:

  • RCT1 中的支票记录;
  • RCT3 中的信用卡记录。

如果付款只使用银行转账、现金、支票或信用卡中的一种,就无法满足这两个条件。

应改为:

LEFT JOIN RCT1 ...
LEFT JOIN RCT3 ...

现金和银行转账金额主要保存在 ORCT 表头中,不要求存在对应的明细行。

3. RCT1、RCT3 应关联付款的 DocEntry

原查询使用了:

T0.DocNum = T3.DocNum
T0.DocNum = T4.DocNum

这组条件混用了可见单据编号和内部键。通常应写成:

T0.DocEntry = T3.DocNum
T0.DocEntry = T4.DocNum

虽然字段名是 DocNum,但 RCT1.DocNum 和 RCT3.DocNum 在这些子表中保存的是所属付款的内部键。

建议分段验证

查询没有结果时,可以逐层添加 JOIN,检查数据是在哪一层被过滤掉的。

先检查付款及其核销单据:

SELECT
    T0.DocEntry,
    T0.DocNum,
    T1.InvType,
    T1.DocEntry AS AppliedDocEntry,
    T1.SumApplied
FROM ORCT T0
INNER JOIN RCT2 T1
    ON T0.DocEntry = T1.DocNum;

然后只检查 A/R Invoice:

SELECT
    T0.DocNum AS PaymentNo,
    T2.DocNum AS InvoiceNo,
    T1.SumApplied
FROM ORCT T0
INNER JOIN RCT2 T1
    ON T0.DocEntry = T1.DocNum
   AND T1.InvType = 13
INNER JOIN OINV T2
    ON T2.DocEntry = T1.DocEntry;

确认这两段查询都有结果后,再依次添加 RCT1、RCT3、INV1、OWHS 和用户自定义表。

注意事项

  • 一笔 Incoming Payment 可以核销多张发票,因此可能返回多行。
  • 一张发票可以包含多个 INV1 行,不同行还可能使用不同仓库。连接 INV1 后,结果行数会继续增加。
  • 如果一笔付款有多个支票或多条信用卡记录,同时又关联多张发票,直接连接这些表可能造成笛卡尔式放大。例如,两张发票、两个支票和三个发票行可能组合出多条结果。
  • 如果只需要发票表头的 UDF,不需要仓库信息,可以移除 INV1 和 OWHS,以减少重复行。
  • [@AUND] 应使用 LEFT JOIN。如果使用 INNER JOIN,只要 U_UnitCode 为空、代码不存在或格式不完全一致,整条付款记录就会被过滤掉。
  • 如果需要排除已取消的付款或发票,可以根据业务需求添加 T0.Canceled = 'N' 和 T5.CANCELED = 'N'。这两个条件并不是解决空结果所必需的。

备注:内容仅供参考。