PAYATHON 2026

如何在 Acumatica Report Designer 发票中添加预付款

支付阿杰

结论

自定义 report 可以作为 Acumatica subreport 使用,不要求是 system report。运行 Invoice 时崩溃,问题通常出在 report definition 的解析位置、ReportName 配置,或者参数名称、类型不匹配,而不是因为 subreport 使用了自定义报表。

不过,subreport 中的汇总值通常无法直接“返回”给主 report。建议采用以下方式:

  • subreport 负责显示付款明细和付款合计;
  • Invoice 的未付余额直接读取 ARInvoice.CuryDocBal;
  • 如果需要按特定规则重新计算,则在主 report 中查询并汇总 ARAdjust,不要依赖 subreport 向外传值。

正确的数据关系

付款应用记录不需要关联 ARTran,应通过 Invoice 的单据键关联 ARAdjust:

ARInvoice.DocType = ARAdjust.AdjdDocType
ARInvoice.RefNbr  = ARAdjust.AdjdRefNbr

需要区分以下两组字段:

  • Adjd*:被调整的单据,也就是 Invoice。
  • Adjg*:发起调整的单据,例如 Payment、Prepayment 或 Credit Memo。

付款明细通常可以显示这些字段:

ARAdjust.AdjgDocType
ARAdjust.AdjgRefNbr
ARAdjust.AdjgDocDate
ARAdjust.CuryAdjdAmt

这些字段能否全部使用,取决于 Acumatica 版本以及 report schema 暴露的 DAC。界面中可能显示为 ARAdjust,不要仅根据数据库表名手动写成 ARAdjst。

部署 subreport

生产环境中,建议把主 report 和 subreport 一起放入 Customization Project 的 Reports 节点并发布,避免文件系统中的 .rpx 与数据库保存的版本互相覆盖。

例如,可以使用两个不重复的名称:

AR641000_Custom.rpx
AR641000_Adjustments.rpx

部署时需要注意:

  1. subreport 必须是完整、能够独立执行的 .rpx report definition。
  2. ReportName 必须指向 subreport。如果误指回主 report,就会形成递归加载。
  3. 两个 report 应部署在同一个可解析的 report definition 位置。
  4. 不要同时维护数据库版本和服务器文件版本。
  5. 发布 Customization Project 后,应清理应用缓存或重启对应实例,再重新测试。
  6. 如果使用 Acumatica SaaS,应通过 Customization Project 部署,不要依赖直接复制服务器文件。

“位于同一文件”通常是指位于同一个 report definition 路径或部署范围,不是把两个 report definition 合并进一个 .rpx 文件。

配置参数

subreport 不需要复制主 report 的全部业务逻辑,但它接收的参数名称和类型必须与主 report 传入的值一致。建议至少定义:

DocType
RefNbr

如果主 Invoice report 还依赖公司、分支或多公司上下文,应按照当前版本的主 report 配置保留相关参数。

subreport 可以使用以下过滤条件:

ARAdjust.AdjdDocType = @DocType
AND ARAdjust.AdjdRefNbr = @RefNbr

主 report 中的 subreport 参数映射应类似于:

DocType = [ARInvoice.DocType]
RefNbr  = [ARInvoice.RefNbr]

不要把参数映射为显示文本、格式化后的值或 ARTran 字段。例如,RefNbr 应传入原始单据编号:

[ARInvoice.RefNbr]

不要写成:

=Format('{0}', [ARInvoice.RefNbr])

参数是否区分大小写可能因版本和解析位置而异,因此配置时应保持名称完全一致。

subreport 内的付款合计

可以在 subreport 中按 Invoice 建立 group,并在 group footer 中汇总已应用金额:

=Sum([ARAdjust.CuryAdjdAmt])

如果只统计已释放且未作废的应用记录,需要在数据过滤中加入相应的状态条件。可用字段会随版本变化,不要直接假设字段名,应从当前版本 Report Designer 的 schema 中选择。

还需要先确定业务上如何定义“付款”:

  • 如果只包括实际付款,通常汇总 CuryAdjdAmt。
  • 如果还包括 cash discount,可能需要计入 CuryAdjdDiscAmt。
  • 如果还包括 write-off,可能需要计入 CuryAdjdWOAmt。
  • 是否把 Credit Memo 作为付款展示,应根据财务规则决定。

如果业务要求显示所有减少应收余额的调整,概念公式可以写成:

AppliedTotal =
    Sum(CuryAdjdAmt)
  + Sum(CuryAdjdDiscAmt)
  + Sum(CuryAdjdWOAmt)

但金额的符号、币种和冲销处理必须结合当前版本的实际数据验证,不能对所有 ARAdjust 记录直接进行无条件相加。

不要从 subreport 向主 report 返回合计

subreport 通常以独立的 report definition 执行。主 report 可以向它传递参数,却无法可靠读取 subreport 内部的 textbox、aggregate 或 report variable。

因此,下面这种表达式通常不可行:

InvoiceTotal - [Adjustments.PaymentTotal]

因为 PaymentTotal 只存在于 subreport 的执行上下文中。

如果主 Invoice 只需显示当前未付金额,直接使用:

=[ARInvoice.CuryDocBal]

这是首选方案。该值由 Acumatica 的应收逻辑维护,可以避免遗漏折扣、write-off、冲销和部分付款。

发票底部可以显示:

Original Amount: [ARInvoice.CuryOrigDocAmt]
Current Balance: [ARInvoice.CuryDocBal]

如果已应用金额只用于摘要展示,并且业务含义已经确认,可以计算:

=[ARInvoice.CuryOrigDocAmt] - [ARInvoice.CuryDocBal]

这个差额不一定全部来自现金付款,其中还可能包括折扣、write-off、Credit Memo 或其他调整。因此,标签最好写成“已应用金额”,不要在未经核对时标为“已付款”。

必须在主 report 中计算时的方案

如果 Accounting 要求主 report 中的某个 field 使用精确的付款合计,应把 ARAdjust 加入主 report 的 schema,并在主 report 自己的 group 中完成汇总。

不要把 ARTran 和 ARAdjust 直接平铺到同一个 detail dataset。假设一张 Invoice 有 5 条 ARTran 和 2 条 ARAdjust,连接后可能产生 10 行,导致 Invoice 金额和付款金额被重复累计。

可以采用以下方式:

  • Invoice 明细继续按 ARTran 分组;
  • 付款数据放入独立 group 或独立查询层;
  • 付款只在 Invoice 级别汇总;
  • 或者继续通过 subreport 显示付款,主 report 的余额则使用 ARInvoice.CuryDocBal。

如果 report schema 支持按 Invoice 关联 ARAdjust,主 report 中的概念表达式可以是:

=Sum([ARAdjust.CuryAdjdAmt])

该表达式必须放在 Invoice group scope 中,不能放在 ARTran detail scope 中。具体的 group 名称和带 scope 的 Sum 语法,应以当前 Acumatica 版本的 Report Designer 为准。

仅在存在付款时显示

如果主 report 中已有可用的余额或付款状态字段,可以直接用它控制可见性。例如,在确认差额确实代表已应用调整后,可以使用类似条件:

=[ARInvoice.CuryOrigDocAmt] > [ARInvoice.CuryDocBal]

如果可见性只能根据 subreport 的查询结果判断,主 report 通常无法在 subreport 执行前得知其行数。此时可以:

  • 允许 subreport 在没有数据时输出空白;
  • 在 subreport 内隐藏明细和 footer;
  • 在主 report schema 中增加 Invoice 级别的付款存在性判断。

不要使用 subreport 内部的 Count() 控制主 report 的外层 section,因为两者通常不在同一个执行上下文中。

排查 Invoice 崩溃的顺序

先独立运行 AR641000_Adjustments.rpx,并传入一组真实的 DocType 和 RefNbr 参数。如果独立运行失败,先不要嵌入 Invoice。

然后按以下顺序测试:

  1. 在主 report 中加入空白 subreport,只传递 DocType 和 RefNbr。
  2. 确认 ReportName 没有指向主 report。
  3. 确认参数名称、数据类型和允许空值设置完全匹配。
  4. 确认服务器只会解析到一个版本的 subreport definition。
  5. 暂时移除 subreport 中的 group、aggregate 和复杂表达式。
  6. 分别验证无数据、单笔付款、多笔付款和冲销付款。
  7. 最后加入 group footer 和付款合计。

如果删除 group footer 后仍然报错,问题很可能来自已发布的 definition、数据库中的 definition,或者缓存里仍有旧版本,并不是 footer 控件“残留”在主 report 中。此时应检查实际加载的 report 名称和已发布版本,不要继续在多个位置复制同名 .rpx。

建议使用自定义 subreport 展示 Payment 和 Prepayment 明细,并用 ARInvoice.CuryDocBal 显示客户当前应付余额。只有当 CuryDocBal 不符合特定打印时点或业务口径时,才在主 report 中单独汇总 ARAdjust。

备注:内容仅供参考。