Dynamics AX窗体传递新增Journal Line触发凭证号报错求替代方案
问题根因
你直接调用LedgerJournalTrans.write()会提前触发日记账行的凭证号分配逻辑,号段会被标记为已占用,但由于这步写入没有绑定完整的业务提交上下文,后续新建行时号段分配逻辑会判定上一个凭证号已被使用,又找不到对应的持久化记录,就会抛出无法分配新凭证号的报错。
原来的未保存行传参失效问题,本质是你传参时调用的是全局表缓冲区,没有拿到窗体数据源中未持久化的临时游标数据,而非必须写入数据库才能传参。
可选方案1(推荐:无需写入数据库,无号段冲突风险)
直接传递窗体数据源的当前行游标,不需要提前调用write()持久化数据,即可把未保存行的所有字段值传递到目标窗体,步骤如下:
- 删掉代码中
LedgerJournalTrans.write();这一行 - 修改传参逻辑,从数据源取当前游标而非全局表缓冲区:
{ Args args; FormRun formRun; LedgerJournalTrans curLedgerJournalTrans; // 声明当前行游标变量 ;; // 从数据源获取当前选中的行,包含未保存的临时数据 curLedgerJournalTrans = LedgerJournalTrans_ds.cursor(); if (LedgerJournalTable.ledgerJournalName().LHAmBankCBPS) { args= new Args(); args.record(curLedgerJournalTrans); // 直接传游标缓冲区,不需要写入数据库 args.parm(curLedgerJournalTrans.Voucher); args.name(formstr(CBPSGJLookup)); formRun=classFactory.formRunClass(args); formRun.init(); formRun.run(); formRun.wait(); formRun.detach(); super(); ledgerjournaltrans_ds.executeQuery(); ledgerjournaltrans_ds.refresh(); this.update(); } else { throw info(strfmt("%1","Only CBPS journal able to use this button")); } info(strfmt("%1","End program")); }
- 同步调整目标窗体
CBPSGJLookup的参数接收逻辑:不要通过RecId去数据库查询对应行数据,直接读取args.record()返回的缓冲区的字段值即可,未保存行的RecId为0属于正常情况。
可选方案2(如需提前持久化行时使用)
如果业务逻辑要求必须先保存行才能打开选择窗体,可以通过号段预留+事务控制解决凭证号报错问题:
- 调用
LedgerJournalTrans.write()前开启事务 - 若用户在选择窗体中取消操作,直接回滚事务,同时释放预占用的凭证号段
- 只有用户确认选择后再提交事务,正式占用凭证号
额外优化点
你当前代码中的super()调用放在了if分支内部,建议调整到方法开头或统一的执行路径上,避免部分分支没有触发父类逻辑导致的窗体异常。
内容的提问来源于stack exchange,提问作者Raynon
相关产品推荐
相关产品推荐

