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

采购收货分配面板自定义字段UsrWgtIndex值异常求助

Acumatica采购收货分配面板自定义字段计算异常:始终显示第一行值而非对应行结果

我在Acumatica的采购收货(Purchase Receipts)分配(Allocation)面板中添加了自定义字段UsrWgtIndex,需求是让这个字段等于同一行下另一自定义字段UsrWgtPerUnit的总和。但现在遇到了异常:打开不同的分配面板时,UsrWgtIndex始终显示第一行交易的计算值,而不是当前打开的对应行的结果。

我的代码如下,逻辑上应为每行交易计算总和并赋值给对应行的UsrWgtIndex,但实际未达预期:

namespace PX.Objects.PO { 
    public class POReceiptEntry_Extension: PXGraphExtension < POReceiptEntry > { 
        #region Event Handlers 
        decimal totalCgt = 0 M, tempTotal = 0 M; 
        protected void POReceiptLine_RowSelected(PXCache cache, PXRowSelectedEventArgs e) { 
            POReceiptLine poRLine = (POReceiptLine) e.Row; 
            if (poRLine != null) { 
                totalCgt = 0 M; 
                foreach(POReceiptLineSplit line in Base.splits.Select()) { 
                    POReceiptLineSplitExt poReceiptLineSplitExt = line.GetExtension < POReceiptLineSplitExt > (); 
                    var recentQty = poReceiptLineSplitExt.UsrWgtPerUnit; 
                    var temp = Convert.ToDecimal(recentQty); 
                    totalCgt = totalCgt + temp; 
                }; 
                var cgt = Convert.ToDecimal(totalCgt); 
                if (totalCgt != null) { 
                    cache.SetValue < POReceiptLineExt.usrTotalWgt > (poRLine, cgt); 
                    //This line is setting the value of usrWgtIndex 
                    cache.SetValue < POReceiptLineExt.usrWgtIndex > (poRLine, cgt); 
                }; 
            } 
        } 
    } 
}

补充细节:

  • 自定义字段usrWgtIndex属于数据类POReceiptLine,但控件放置在分配面板上。
  • 测试发现:若将相同值分配给分配面板的UnassignedQty字段,或同时修改POReceiptLine中的其他字段,均能正常工作;仅修改分配面板上的自定义字段时出现此异常。
  • 未将UsrWgtIndex添加到DAC LotSerOptions,因为尝试用setValueEXT方法赋值时,未找到LotSerOptionsExt,故将其放在POReceiptLine中,通过cache.SetValue<POReceiptLineExt.usrWgtIndex>(poRLine, cgt);赋值。

问题根源分析

我帮你梳理下代码里的几个关键问题:

  1. 全局变量状态污染:类级别的totalCgt和tempTotal会在多次行选择操作中保留之前的计算值,导致后续行的计算结果被污染。
  2. 未过滤当前行的拆分记录:Base.splits.Select()会获取所有的拆分记录,而不是当前选中的POReceiptLine对应的拆分,所以你计算的是所有行的UsrWgtPerUnit总和,而非当前行的。
  3. 缓存更新方式错误:使用SetValue而不是SetValueExt,无法触发Acumatica缓存的更新事件,导致界面无法正确刷新对应字段的值。
  4. 事件上下文不匹配:分配面板的上下文是POReceiptLineSplit,但字段属于POReceiptLine,当拆分记录的UsrWgtPerUnit变化时,没有触发主行的重新计算。

修正后的代码

namespace PX.Objects.PO
{
    public class POReceiptEntry_Extension : PXGraphExtension<POReceiptEntry>
    {
        #region Event Handlers

        protected void POReceiptLine_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
        {
            POReceiptLine poRLine = e.Row as POReceiptLine;
            if (poRLine == null) return;

            decimal totalCgt = 0M;

            // 只查询当前POReceiptLine对应的拆分记录
            foreach (POReceiptLineSplit line in Base.splits.SelectWhere<POReceiptLineSplit,
                Where<POReceiptLineSplit.receiptNbr, Equal<Current<POReceiptLine.receiptNbr>>,
                And<POReceiptLineSplit.lineNbr, Equal<Current<POReceiptLine.lineNbr>>>>>())
            {
                POReceiptLineSplitExt poReceiptLineSplitExt = line.GetExtension<POReceiptLineSplitExt>();
                // 空值判断,避免转换异常
                if (poReceiptLineSplitExt.UsrWgtPerUnit != null)
                {
                    totalCgt += Convert.ToDecimal(poReceiptLineSplitExt.UsrWgtPerUnit);
                }
            }

            // 使用SetValueExt触发缓存更新,确保界面同步刷新
            cache.SetValueExt<POReceiptLineExt.usrTotalWgt>(poRLine, totalCgt);
            cache.SetValueExt<POReceiptLineExt.usrWgtIndex>(poRLine, totalCgt);
        }

        // 监听拆分字段变化,实时更新主行总和
        protected void POReceiptLineSplit_UsrWgtPerUnit_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e)
        {
            POReceiptLineSplit split = e.Row as POReceiptLineSplit;
            if (split == null) return;

            // 获取当前拆分对应的主行记录
            POReceiptLine poLine = Base.transactions.Select<POReceiptLine,
                Where<POReceiptLine.receiptNbr, Equal<Current<POReceiptLineSplit.receiptNbr>>,
                And<POReceiptLine.lineNbr, Equal<Current<POReceiptLineSplit.lineNbr>>>>>();
            
            if (poLine != null)
            {
                // 触发主行的RowSelected事件,重新计算总和
                Base.transactions.Cache.RaiseRowSelected(poLine);
            }
        }

        #endregion
    }
}

关键修正说明

  • 移除全局变量:把totalCgt移到RowSelected方法内部,每次计算都是独立的,避免状态残留。
  • 精准过滤拆分记录:用SelectWhere筛选出当前POReceiptLine对应的拆分,确保计算的是当前行的总和。
  • 替换为SetValueExt:这个方法会触发缓存的更新事件,让界面能实时同步字段值,解决你提到的只有修改系统字段才生效的问题。
  • 添加字段更新事件:当UsrWgtPerUnit的值变化时,自动触发主行的重新计算,保证分配面板上的UsrWgtIndex能实时更新。

额外注意事项

  • 确认UsrWgtPerUnit字段在DAC中定义为可空类型(比如public decimal? UsrWgtPerUnit { get; set; }),避免空引用转换异常。
  • 检查分配面板上的UsrWgtIndex控件,确保DataField属性正确指向POReceiptLine的UsrWgtIndex字段,数据源设置正确关联主记录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:03:52