You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dynamics AX窗体传递新增Journal Line触发凭证号报错求替代方案

问题根因

你直接调用LedgerJournalTrans.write()会提前触发日记账行的凭证号分配逻辑,号段会被标记为已占用,但由于这步写入没有绑定完整的业务提交上下文,后续新建行时号段分配逻辑会判定上一个凭证号已被使用,又找不到对应的持久化记录,就会抛出无法分配新凭证号的报错。
原来的未保存行传参失效问题,本质是你传参时调用的是全局表缓冲区,没有拿到窗体数据源中未持久化的临时游标数据,而非必须写入数据库才能传参。

可选方案1(推荐:无需写入数据库,无号段冲突风险)

直接传递窗体数据源的当前行游标,不需要提前调用write()持久化数据,即可把未保存行的所有字段值传递到目标窗体,步骤如下:

  1. 删掉代码中LedgerJournalTrans.write();这一行
  2. 修改传参逻辑,从数据源取当前游标而非全局表缓冲区:
{
    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"));
}
  1. 同步调整目标窗体CBPSGJLookup的参数接收逻辑:不要通过RecId去数据库查询对应行数据,直接读取args.record()返回的缓冲区的字段值即可,未保存行的RecId为0属于正常情况。

可选方案2(如需提前持久化行时使用)

如果业务逻辑要求必须先保存行才能打开选择窗体,可以通过号段预留+事务控制解决凭证号报错问题:

  • 调用LedgerJournalTrans.write()前开启事务
  • 若用户在选择窗体中取消操作,直接回滚事务,同时释放预占用的凭证号段
  • 只有用户确认选择后再提交事务,正式占用凭证号

额外优化点

你当前代码中的super()调用放在了if分支内部,建议调整到方法开头或统一的执行路径上,避免部分分支没有触发父类逻辑导致的窗体异常。


内容的提问来源于stack exchange,提问作者Raynon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 08:36:04