如何在 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
部署时需要注意:
- subreport 必须是完整、能够独立执行的
.rpxreport definition。 ReportName必须指向 subreport。如果误指回主 report,就会形成递归加载。- 两个 report 应部署在同一个可解析的 report definition 位置。
- 不要同时维护数据库版本和服务器文件版本。
- 发布 Customization Project 后,应清理应用缓存或重启对应实例,再重新测试。
- 如果使用 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。
然后按以下顺序测试:
- 在主 report 中加入空白 subreport,只传递
DocType和RefNbr。 - 确认
ReportName没有指向主 report。 - 确认参数名称、数据类型和允许空值设置完全匹配。
- 确认服务器只会解析到一个版本的 subreport definition。
- 暂时移除 subreport 中的 group、aggregate 和复杂表达式。
- 分别验证无数据、单笔付款、多笔付款和冲销付款。
- 最后加入 group footer 和付款合计。
如果删除 group footer 后仍然报错,问题很可能来自已发布的 definition、数据库中的 definition,或者缓存里仍有旧版本,并不是 footer 控件“残留”在主 report 中。此时应检查实际加载的 report 名称和已发布版本,不要继续在多个位置复制同名 .rpx。
建议使用自定义 subreport 展示 Payment 和 Prepayment 明细,并用 ARInvoice.CuryDocBal 显示客户当前应付余额。只有当 CuryDocBal 不符合特定打印时点或业务口径时,才在主 report 中单独汇总 ARAdjust。
备注:内容仅供参考。
