You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Acumatica技术问询:修改POLine承诺日期时SOLine视图始终返回空值的问题排查

问题:POLine承诺日期变更时无法更新SOLine自定义字段,视图返回空值

我现在遇到一个问题:当POLine的PromisedDate字段发生变更时,我想要同步更新关联SOLine上的自定义字段UsrPOPromisedDate。我写了一段Acumatica图扩展代码,但不管怎么试,SalesOrderLine视图始终返回空值。奇怪的是,把代码里的BQL转换成T-SQL执行时,能得到预期的关联SOLine记录。有没有大佬能帮我看看问题出在哪?

我的代码如下:

using PX.Data;
using PX.KWW.MyProject.DAC;
using PX.Objects.PO;
using PX.Objects.SO;
namespace MyProject.Graph
{
    public class POOrderEntryExt : PXGraphExtension<POOrderEntry>
    {
        public PXSelectJoin<
            SOLine,
            InnerJoin<SOLineSplit, On<SOLineSplit.orderType, Equal<SOLine.orderType>,
                And<SOLineSplit.orderNbr, Equal<SOLine.orderNbr>,
                And<SOLineSplit.lineNbr, Equal<SOLine.lineNbr>>>>>,
            Where<SOLineSplit.pOType, Equal<Current<POLine.orderType>>,
                And<SOLineSplit.pONbr, Equal<Current<POLine.orderNbr>>,
                And<SOLineSplit.pOLineNbr, Equal<Current<POLine.lineNbr>>>>>
            > SalesOrderLine;

        protected virtual void _(Events.FieldUpdated<POLine, POLine.promisedDate> eventHandler, PXFieldUpdated baseHandler)
        {
            baseHandler?.Invoke(eventHandler.Cache, eventHandler.Args);
            POLine pOLine = eventHandler.Row;
            if (pOLine is null) return;

            SOLine sOLine = SalesOrderLine.Current;
            SOLineExtension sOLineExtension = sOLine.GetExtension<SOLineExtension>();
            if (sOLine is null || sOLineExtension is null) return;

            sOLineExtension.UsrPOPromisedDate = pOLine.PromisedDate;
            SalesOrderLine.Update(sOLine);
        }
    }
}

问题分析与解决方案

嗨,我来帮你捋捋这个问题!核心原因其实很简单:你的视图没有主动执行查询操作

在Acumatica里,PXSelectJoin定义的视图并不会自动去数据库捞数据,除非你主动调用Select()或者SelectSingle()方法。你现在直接取SalesOrderLine.Current,它只会返回之前已经加载到视图缓存里的记录——而在FieldUpdated事件触发时,这个视图压根没执行过查询,所以自然返回空值。而你用T-SQL能查到结果,说明BQL的逻辑是对的,只是代码里少了触发查询的步骤。

修复后的代码

我帮你调整了代码,主要加了主动查询的逻辑,同时考虑了可能存在多条关联SOLine的情况:

using PX.Data;
using PX.KWW.MyProject.DAC;
using PX.Objects.PO;
using PX.Objects.SO;
namespace MyProject.Graph
{
    public class POOrderEntryExt : PXGraphExtension<POOrderEntry>
    {
        public PXSelectJoin<
            SOLine,
            InnerJoin<SOLineSplit, On<SOLineSplit.orderType, Equal<SOLine.orderType>,
                And<SOLineSplit.orderNbr, Equal<SOLine.orderNbr>,
                And<SOLineSplit.lineNbr, Equal<SOLine.lineNbr>>>>>,
            Where<SOLineSplit.pOType, Equal<Current<POLine.orderType>>,
                And<SOLineSplit.pONbr, Equal<Current<POLine.orderNbr>>,
                And<SOLineSplit.pOLineNbr, Equal<Current<POLine.lineNbr>>>>>
            > SalesOrderLine;

        protected virtual void _(Events.FieldUpdated<POLine, POLine.promisedDate> eventHandler, PXFieldUpdated baseHandler)
        {
            baseHandler?.Invoke(eventHandler.Cache, eventHandler.Args);
            POLine pOLine = eventHandler.Row;
            if (pOLine is null) return;

            // 主动执行查询,遍历所有关联的SOLine记录
            foreach (SOLine sOLine in SalesOrderLine.Select())
            {
                SOLineExtension sOLineExtension = sOLine.GetExtension<SOLineExtension>();
                if (sOLineExtension == null) continue;

                sOLineExtension.UsrPOPromisedDate = pOLine.PromisedDate;
                // 直接更新SOLine缓存,确保变更生效
                Base.Caches<SOLine>().Update(sOLine);
            }
        }
    }
}

几点额外说明

  1. Select()触发查询SalesOrderLine.Select()会执行你定义的BQL,从数据库获取符合条件的SOLine记录。
  2. 遍历处理所有结果:虽然大部分情况下一个POLine只会关联一个SOLine,但用foreach遍历能避免遗漏特殊情况。
  3. 直接更新缓存:用Base.Caches<SOLine>().Update(sOLine)比视图的Update方法更直接,能确保变更被正确写入Acumatica的缓存体系,后续保存时会同步到数据库。

这样修改后,应该就能正常更新SOLine的自定义字段啦!


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

火山引擎 最新活动