Acumatica中PORecieptEntry事件更新PO自定义复选框不生效问题
问题描述
在Acumatica中更新对应PO Receipt的行记录时,需要将PO屏幕内的UsrSendPONotifications复选框值设为true。原有代码执行后该字段始终保持为false,未生效。
原有实现代码:
protected void POReceipt_RowUpdated(PXCache cache, PXRowUpdatedEventArgs e) { var row = (POReceipt)e.Row; if (row == null) return; else { POReceiptLine receiptLine = new PXSelect<POReceiptLine, Where<POReceiptLine.receiptNbr, Equal<Required<POReceiptLine.receiptNbr>>>>(Base).Select(row.ReceiptNbr); if(receiptLine == null) return; else { POOrder poOrder = new PXSelect<POOrder, Where<POOrder.orderType, Equal<Required<POOrder.orderType>>, And<POOrder.orderNbr, Equal<Required<POOrder.orderNbr>>>>>(Base).Select(receiptLine.POType, receiptLine.PONbr); if(poOrder == null) return; else { POOrderExt poExt = poOrder.GetExtension<POOrderExt>(); poExt.UsrSendPONotifications = true; cache.SetValueExt<POOrderExt.usrSendPONotifications> (poOrder,poExt.UsrSendPONotifications); } } }
失效原因
- 缓存对象使用错误:事件传入的
cache是POReceipt类型的缓存,修改POOrder记录必须调用POOrder自身对应的缓存对象,跨缓存调用SetValueExt不会生效。 - 缺少更新标记:给字段赋值后没有调用对应缓存的
Update方法标记记录变更,系统不会识别到这条PO记录有修改,自然不会保存字段变更。 - 收货行查询逻辑有漏洞:一张PO Receipt通常关联多条收货行,原代码仅查询第一条收货行匹配PO,若第一条行未关联PO、或一张收货单对应多个PO,会出现匹配失败、漏更新的问题。
- 未优先读取缓存数据:直接从数据库查询PO记录,可能覆盖当前上下文中已经存在的缓存修改,造成数据不一致。
修复代码
protected void POReceipt_RowUpdated(PXCache cache, PXRowUpdatedEventArgs e) { var receipt = e.Row as POReceipt; if (receipt == null) return; // 获取POOrder类型对应的正确缓存对象 PXCache poOrderCache = Base.Caches[typeof(POOrder)]; // 对PO去重,避免重复更新同一条PO HashSet<(string, string)> processedPO = new HashSet<(string, string)>(); // 遍历当前收货单所有关联的收货行 foreach (POReceiptLine line in PXSelect<POReceiptLine, Where<POReceiptLine.receiptNbr, Equal<Required<POReceiptLine.receiptNbr>>>> .Select(Base, receipt.ReceiptNbr)) { if (string.IsNullOrEmpty(line.PONbr)) continue; var poKey = (line.POType, line.PONbr); if (processedPO.Contains(poKey)) continue; processedPO.Add(poKey); // 优先从缓存中读取PO记录,保证数据一致性 POOrder poOrder = (POOrder)poOrderCache.Locate(new POOrder { OrderType = line.POType, OrderNbr = line.PONbr }); if (poOrder == null) { poOrder = PXSelect<POOrder, Where<POOrder.orderType, Equal<Required<POOrder.orderType>>, And<POOrder.orderNbr, Equal<Required<POOrder.orderNbr>>>>> .Select(Base, line.POType, line.PONbr); } if (poOrder == null) continue; POOrderExt poExt = poOrder.GetExtension<POOrderExt>(); // 字段已经是目标值时跳过,减少无效操作 if (poExt.UsrSendPONotifications == true) continue; // 通过POOrder缓存设置字段值,标记更新 poOrderCache.SetValueExt<POOrderExt.usrSendPONotifications>(poOrder, true); poOrderCache.Update(poOrder); } }
优化建议
- 如果需要保证收货单保存成功后才更新PO标记,建议将逻辑迁移到
POReceipt_RowPersisted事件,仅在e.Operation为PXDBOperation.Insert或PXDBOperation.Update时执行,避免用户取消收货单编辑时误修改PO数据。 - 若业务要求PO标记更新后立刻持久化到数据库,可在
Update调用后追加poOrderCache.Persist(poOrder, PXDBOperation.Update),注意做好循环触发判断,避免出现死循环。
内容的提问来源于stack exchange,提问作者AcumaticaZ
相关产品推荐
相关产品推荐

