Acumatica Production Order Alloction 封装页多行报错及功能重写求助
生产订单Allocation分配功能复用问题解决方案
问题根因验证
你推测的LSProdMatlLine绑定事件未触发属于高频触发场景,除此之外还有两类常见原因也会导致新增第二行时报对象引用错误:
- 标准Allocation弹窗的
ProdMatlLine数据源默认绑定了行级initValue、modifiedField、validateWrite事件,自定义页面调用时如果没有将弹窗数据源和自定义页面的LSProdMatlLine数据源做事件透传,新增第二行时系统会尝试读取前一行的上下文缓存,找不到对应记录就抛出空引用 - 标准功能默认依赖生产订单列表页的上下文状态变量,自定义页面没有初始化
ProdTable相关的全局状态参数,新增多行时状态校验逻辑读取不到上下文就报错 - 新增行时
inventTrans关联逻辑没有触发,第二行尝试关联库存事务时找不到前一行的事务关联标识
Allocation功能标准使用规则
标准生产订单Allocation功能的默认调用逻辑约束:
- 必须在包含
ProdTable完整数据源的页面上下文中调用,调用前需要先将当前选中的生产订单记录绑定到全局参数ProdTable_Status- 分配弹窗的
ProdMatlLine数据源必须和调用页面的物料行数据源做视图关联,事件要做透传绑定- 每次新增分配行后会自动触发库存预留校验,必须保证预留维度参数在调用页面已经完成初始化
功能重写复用指导
第一步:添加事件透传绑定
在自定义页面调用Allocation弹窗的逻辑里,补充数据源事件绑定代码:
// 自定义页面调用Allocation弹窗前绑定行事件 Args args = new Args(); FormRun allocationDialog; args.record(prodTable); args.name(formStr(ProdProductionOrderAllocation)); allocationDialog = ClassFactory.formRunClass(args); allocationDialog.init(); // 绑定ProdMatlLine的行事件到自定义页面的LSProdMatlLine数据源 allocationDialog.dataSource(formDataSourceStr(ProdProductionOrderAllocation, ProdMatlLine)).addDynalink(fieldNum(ProdMatlLine, ProdId), LSProdMatlLine, fieldNum(LSProdMatlLine, ProdId)); // 透传initValue事件 allocationDialog.dataSource(formDataSourceStr(ProdProductionOrderAllocation, ProdMatlLine)).initValueDelegate += eventhandler(this, methodStr(MyCustomProdPage, prodMatlLine_InitValue)); allocationDialog.run(); allocationDialog.wait();
第二步:新增行上下文缓存处理
扩展Allocation弹窗逻辑,新增上下文缓存避免第二行读取空值:
[ExtensionOf(formStr(ProdProductionOrderAllocation))] public final class ProdProductionOrderAllocation_Extension { // 新增全局缓存变量存储已添加的行上下文 Map prodMatlLineCache = new Map(Types::Int64, Types::Record); public void init() { next init(); // 初始化时读取自定义页面传入的LSProdMatlLine上下文存入缓存 if(element.args().caller() is MyCustomProdPage) { MyCustomProdPage callerPage = element.args().caller(); LSProdMatlLine line = callerPage.LSProdMatlLine; prodMatlLineCache.insert(line.RecId, line); } } public void prodMatlLine_InitValue(ProdMatlLine _prodMatlLine) { // 新增行时从缓存读取上下文赋值,避免空引用 if(prodMatlLineCache.elements() > 0) { var enumerator = prodMatlLineCache.getEnumerator(); if(enumerator.moveNext()) { LSProdMatlLine cachedLine = enumerator.currentValue(); _prodMatlLine.ProdId = cachedLine.ProdId; _prodMatlLine.InventDimId = cachedLine.InventDimId; } } next prodMatlLine_InitValue(_prodMatlLine); } }
第三步:多行新增校验优化
禁用标准功能的单行强制校验逻辑,添加多行批量校验:
// 扩展ProdMatlLine数据源的validateWrite方法 [ExtensionOf(formDataSourceStr(ProdProductionOrderAllocation, ProdMatlLine))] public final class ProdMatlLine_Extension { public boolean validateWrite() { boolean ret; // 自定义页面调用时跳过单行上下文校验,新增所有行后统一校验 if(element.args().caller() is MyCustomProdPage) { ret = true; } else { ret = next validateWrite(); } return ret; } } // 扩展弹窗ok方法添加批量校验 [ExtensionOf(formStr(ProdProductionOrderAllocation))] public final class ProdProductionOrderAllocation_Ok_Extension { public void ok() { ProdMatlLine line; Str curAllocationId = element.allocationId(); if(element.args().caller() is MyCustomProdPage) { while select forUpdate line where line.AllocationId == curAllocationId { if(!line.validateWrite()) { warning(strFmt("第%1行分配数据校验失败", line.LineNum)); return; } } } next ok(); } }
内容的提问来源于stack exchange,提问作者Shaj
相关产品推荐
相关产品推荐

