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

调用CopyOrder遇SOOrder记录冲突错误,求进程检测命令及解决办法

问题场景

调用PX.Objects.SO.SOOrderEntry.CopyOrder(PXAdapter adapter)时触发错误:

Error: Another process has added the 'SOOrder' record. Please try again

询问是否有方式检测当前是否存在其他正在执行的处理,并附上了自定义的订单头计算代码及触发事件:

自定义订单头计算方法(calcultotal)

SOOrder cmd=CurrentSOOrder.Select();
PXTrace.WriteInformation("CMD"+cmd.OrderNbr);
cmd.GetExtension<SOOrderExt>().Usrtotalcout=totalcout;
cmd.GetExtension<SOOrderExt>().Usrpourcentcout=0;
if ((totalnet!=0) && (totalcout!=0))    
{
    cmd.GetExtension<SOOrderExt>().Usrpourcentcout=(totalnet-totalcout)/(totalnet)*100;
}    
try
{
    Base.Caches[typeof(PX.Objects.SO.SOOrder)].MarkUpdated(cmd);  
    Base.Document.View.RequestRefresh(); 
}
catch(Exception e)
{
    PXTrace.WriteInformation(e.StackTrace);
}
return true;    
}     

SOOrder_RowUpdated触发事件

protected void SOOrder_RowUpdated(PXCache cache, PXRowUpdatedEventArgs e)
{
    var row = (SOOrder)e.Row;
    if (row==null) return;
    row.OverrideTaxZone=true;
    calcultotal(false); // calcul l'entête pour les webservices      
}   
问题分析与解决

一、检测并发/正在执行的处理

Acumatica没有直接的命令式检测工具,但可以通过以下代码片段排查:

  • 检查是否有长时间运行的操作:
    Guid? runningOpId = PXLongOperation.GetRunningOperationID(Base);
    if (runningOpId != null)
    {
        PXTrace.WriteInformation("当前存在运行中操作,ID:" + runningOpId);
    }
    
  • 查看缓存内的修改记录,判断是否有未提交的冲突操作:
    // CopyOrder执行前后分别输出
    PXTrace.WriteInformation("CopyOrder前SOOrder缓存修改数:" + Base.Caches[typeof(SOOrder)].GetModified().Count());
    // 执行CopyOrder逻辑
    PXTrace.WriteInformation("CopyOrder后SOOrder缓存修改数:" + Base.Caches[typeof(SOOrder)].GetModified().Count());
    

二、修复CopyOrder冲突问题

错误根源是CopyOrder过程中,RowUpdated事件触发的自定义修改与原生复制逻辑产生缓存冲突。你的代码直接从CurrentSOOrder查询记录并标记更新,在复制订单时,缓存内同时存在原订单和新订单,导致状态混乱。

代码优化方案

  1. 修改calcultotal方法,直接使用事件传入的订单行,避免查询CurrentSOOrder:
    private bool calcultotal(SOOrder targetOrder, bool someFlag)
    {
        if (targetOrder == null) return false;
        var orderExt = targetOrder.GetExtension<SOOrderExt>();
        
        orderExt.Usrtotalcout = totalcout;
        orderExt.Usrpourcentcout = 0;
        if ((totalnet != 0) && (totalcout != 0))    
        {
            orderExt.Usrpourcentcout = (totalnet - totalcout) / totalnet * 100;
        }    
        
        try
        {
            Base.Caches[typeof(SOOrder)].MarkUpdated(targetOrder);  
        }
        catch(Exception e)
        {
            PXTrace.WriteInformation(e.StackTrace);
        }
        return true;    
    }
    
  2. 调整RowUpdated事件,直接传入当前行:
    protected void SOOrder_RowUpdated(PXCache cache, PXRowUpdatedEventArgs e)
    {
        var row = (SOOrder)e.Row;
        if (row == null) return;
        
        row.OverrideTaxZone = true;
        calcultotal(row, false);      
    }
    
  3. 重写CopyOrder操作,临时禁用自定义RowUpdated事件,避免干扰复制逻辑:
    public PXAction<SOOrder> CustomCopyOrder;
    [PXButton(CommitChanges = true)]
    [PXUIField(DisplayName = "Copy Order")]
    protected IEnumerable customCopyOrder(PXAdapter adapter)
    {
        // 临时移除自定义RowUpdated事件
        Base.RowUpdated.RemoveHandler<SOOrder>(SOOrder_RowUpdated);
        try
        {
            // 执行原生CopyOrder逻辑
            return Base.CopyOrder.Press(adapter);
        }
        finally
        {
            // 恢复事件处理
            Base.RowUpdated.AddHandler<SOOrder>(SOOrder_RowUpdated);
        }
    }
    

额外优化建议

  • 优先使用RowPersisting事件替代RowUpdated,该事件在记录保存前触发,避免缓存冲突
  • 修改扩展字段时,使用cache.SetValueExt触发Acumatica原生验证逻辑:
    cache.SetValueExt<SOOrderExt.usrTotalcout>(targetOrder, totalcout);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 02:37:45