已在ARTran/APTran/GLTran DAC创建Stock Number字段,如何将AR/AP明细自定义值粘贴至GL交易?
嘿,我来帮你搞定这个问题!既然你已经在ARTran、APTran和GLTran这三个DAC里都创建了Stock Number这个数据库绑定的自定义字段,要把AR发票、AP账单明细里的字段值自动同步到GL交易中,核心思路是利用Acumatica的事件处理机制,在单据释放或者GL交易创建的时候自动复制字段值。下面分场景给你具体的实现方案:
一、处理AR发票释放时的字段传递
当你释放AR发票生成GL交易时,我们可以扩展ARReleaseProcess这个负责发票释放的Graph,在原释放逻辑执行完成后,把ARTran里的Stock Number同步到对应的GLTran记录中。
public class ARReleaseProcessExt : PXGraphExtension<ARReleaseProcess> { // 重写ReleaseDoc方法,拦截释放流程 public delegate void ReleaseDocDelegate(ARRegister doc, PXResult<ARInvoice, CurrencyInfo, Terms> res, bool isPrebooking); [PXOverride] public void ReleaseDoc(ARRegister doc, PXResult<ARInvoice, CurrencyInfo, Terms> res, bool isPrebooking, ReleaseDocDelegate baseMethod) { // 先执行系统自带的释放逻辑 baseMethod(doc, res, isPrebooking); ARInvoice targetInvoice = res; // 查询当前发票下的所有AR明细行 foreach (ARTran arTran in PXSelect<ARTran, Where<ARTran.tranType, Equal<Required<ARTran.tranType>>, And<ARTran.refNbr, Equal<Required<ARTran.refNbr>>>>>.Select(Base, targetInvoice.DocType, targetInvoice.RefNbr)) { // 找到对应批次下的GL交易记录 foreach (GLTran glTran in PXSelect<GLTran, Where<GLTran.batchNbr, Equal<Required<GLTran.batchNbr>>, And<GLTran.tranType, Equal<Required<GLTran.tranType>>, And<GLTran.refNbr, Equal<Required<GLTran.refNbr>>>>>.Select(Base, doc.BatchNbr, targetInvoice.DocType, targetInvoice.RefNbr)) { // 替换成你实际的自定义字段名(默认前缀是Usr) ARTranExt arTranExt = arTran.GetExtension<ARTranExt>(); GLTranExt glTranExt = glTran.GetExtension<GLTranExt>(); if (!string.IsNullOrEmpty(arTranExt.UsrStockNumber)) { glTranExt.UsrStockNumber = arTranExt.UsrStockNumber; Base.GLTran.Update(glTran); } } } } }
二、处理AP账单释放时的字段传递
和AR发票的逻辑完全一致,我们只需要扩展APReleaseProcess这个Graph,实现APTran到GLTran的字段同步:
public class APReleaseProcessExt : PXGraphExtension<APReleaseProcess> { public delegate void ReleaseDocDelegate(APRegister doc, PXResult<APInvoice, CurrencyInfo, Terms> res, bool isPrebooking); [PXOverride] public void ReleaseDoc(APRegister doc, PXResult<APInvoice, CurrencyInfo, Terms> res, bool isPrebooking, ReleaseDocDelegate baseMethod) { baseMethod(doc, res, isPrebooking); APInvoice targetBill = res; foreach (APTran apTran in PXSelect<APTran, Where<APTran.tranType, Equal<Required<APTran.tranType>>, And<APTran.refNbr, Equal<Required<APTran.refNbr>>>>>.Select(Base, targetBill.DocType, targetBill.RefNbr)) { foreach (GLTran glTran in PXSelect<GLTran, Where<GLTran.batchNbr, Equal<Required<GLTran.batchNbr>>, And<GLTran.tranType, Equal<Required<GLTran.tranType>>, And<GLTran.refNbr, Equal<Required<GLTran.refNbr>>>>>.Select(Base, doc.BatchNbr, targetBill.DocType, targetBill.RefNbr)) { APTranExt apTranExt = apTran.GetExtension<APTranExt>(); GLTranExt glTranExt = glTran.GetExtension<GLTranExt>(); if (!string.IsNullOrEmpty(apTranExt.UsrStockNumber)) { glTranExt.UsrStockNumber = apTranExt.UsrStockNumber; Base.GLTran.Update(glTran); } } } } }
三、手动创建GL交易时自动填充字段
如果用户手动创建GL交易并关联已有的AR发票/AP账单,我们可以扩展GLTranEntry,当用户选择单据类型和编号时,自动拉取对应的Stock Number:
public class GLTranEntryExt : PXGraphExtension<GLTranEntry> { // 当单据类型变更时触发 protected void _(Events.FieldUpdated<GLTran.tranType> e) { FillStockNumber(e.Row); } // 当单据编号变更时触发 protected void _(Events.FieldUpdated<GLTran.refNbr> e) { FillStockNumber(e.Row); } // 核心填充逻辑 private void FillStockNumber(GLTran row) { if (row == null || string.IsNullOrEmpty(row.TranType) || string.IsNullOrEmpty(row.RefNbr)) return; // 判断是AR还是AP单据 if (ARInvoice.ARDocType.Contains(row.TranType)) { ARTran arTran = PXSelect<ARTran, Where<ARTran.tranType, Equal<Required<ARTran.tranType>>, And<ARTran.refNbr, Equal<Required<ARTran.refNbr>>>>>.Select(Base, row.TranType, row.RefNbr); if (arTran != null) { GLTranExt glExt = row.GetExtension<GLTranExt>(); glExt.UsrStockNumber = arTran.GetExtension<ARTranExt>().UsrStockNumber; Base.GLTran.Update(row); } } else if (APInvoice.APDocType.Contains(row.TranType)) { APTran apTran = PXSelect<APTran, Where<APTran.tranType, Equal<Required<APTran.tranType>>, And<APTran.refNbr, Equal<Required<APTran.refNbr>>>>>.Select(Base, row.TranType, row.RefNbr); if (apTran != null) { GLTranExt glExt = row.GetExtension<GLTranExt>(); glExt.UsrStockNumber = apTran.GetExtension<APTranExt>().UsrStockNumber; Base.GLTran.Update(row); } } } }
关键注意事项
- 替换代码中所有的
UsrStockNumber为你实际创建的自定义字段名(Acumatica中自定义字段默认以Usr为前缀) - 确保GLTran的自定义字段和ARTran/APTran的字段类型完全一致(比如都是字符串、相同长度)
- 如果一个AR/AP明细行对应多个GL分录,你可以修改查询条件,通过
LineNbr(行号)来精确匹配,避免字段值被重复覆盖 - 所有代码要放在Acumatica能识别的自定义项目命名空间下,部署后记得发布自定义项目
- 先在测试环境验证逻辑,确认无误后再部署到生产环境
内容的提问来源于stack exchange,提问作者RuslanDev
相关产品推荐
相关产品推荐

