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

SOShipLineSplit DAC扩展在发货分配中异常问题求助

如何避免Acumatica确认发货时SOShipLineSplit的Usr字段被置为NULL?

我来分析下你遇到的两个问题,并给出针对性的解决方案:


问题回顾

你尝试两种方式扩展SOShipLineSplit DAC:

方案1:原表添加Usr字段

  • 成功在UI添加字段,创建发货单时数据能正常持久化到数据库
  • 问题:确认发货后,自定义字段被置为NULL

方案2:创建独立扩展表

  • 手动创建了SOShipLineSplitStandalone表
  • 问题:创建发货单后,扩展表中无记录插入

方案1的解决办法(原表Usr字段被置空)

这个问题的核心原因是:Acumatica在确认发货的逻辑中,会重新生成或更新SOShipLineSplit记录,但默认不会复制自定义字段的值。以下是具体修复步骤:

1. 规范DAC扩展的命名(避免大小写匹配问题)

首先检查你的DAC扩展代码,Acumatica对BQL字段的大小写是敏感的,建议严格遵循命名规范:

public class SOShipLineSplitExtended : PXCacheExtension<SOShipLineSplit> 
{ 
    #region UsrEntryA 
    public abstract class usrEntryA : PX.Data.IBqlField { } 
    [PXDBInt] 
    [PXDefault(6, PersistingCheck = PXPersistingCheck.Nothing)] 
    [PXUIField(DisplayName = "UsrEntryA")] 
    public virtual int? UsrEntryA { get; set; } 
    #endregion 

    #region UsrEntryB 
    public abstract class usrEntryB : PX.Data.IBqlField { } 
    [PXDBBool] 
    [PXDefault(true, PersistingCheck = PXPersistingCheck.Nothing)] 
    [PXUIField(DisplayName = "UsrEntryB")] 
    public virtual bool? UsrEntryB { get; set; } 
    #endregion 
}

注意:抽象类名和字段名使用PascalCase,确保和数据库字段名(UsrEntryA/UsrEntryB)一致。

2. 扩展发货确认逻辑,复制自定义字段值

在SOShipmentEntry图形扩展中,添加事件处理确保自定义字段在记录更新/生成时被复制:

public class SOShipmentEntry_Extension : PXGraphExtension<SOShipmentEntry>
{
    // 处理SOShipLineSplit插入时复制自定义字段
    protected void _(Events.RowInserted<SOShipLineSplit> e)
    {
        if (e.Row == null) return;
        
        // 获取原始记录(如果是从已有记录复制生成的)
        SOShipLineSplit originalRecord = e.Cache.GetOriginal(e.Row);
        if (originalRecord != null)
        {
            var originalExt = PXCache<SOShipLineSplit>.GetExtension<SOShipLineSplitExtended>(originalRecord);
            var newExt = PXCache<SOShipLineSplit>.GetExtension<SOShipLineSplitExtended>(e.Row);
            
            // 复制自定义字段值
            newExt.UsrEntryA = originalExt.UsrEntryA;
            newExt.UsrEntryB = originalExt.UsrEntryB;
        }
    }

    // 重写确认发货方法,确保字段值被保留
    public delegate IEnumerable ConfirmShipmentDelegate(PXAdapter adapter);
    [PXOverride]
    public IEnumerable ConfirmShipment(PXAdapter adapter, ConfirmShipmentDelegate baseMethod)
    {
        // 先执行原始确认逻辑
        foreach (var result in baseMethod(adapter))
        {
            // 确认后检查并修复自定义字段(如果有丢失)
            foreach (SOShipLineSplit split in Base.SOShipLineSplit.Select())
            {
                var splitExt = PXCache<SOShipLineSplit>.GetExtension<SOShipLineSplitExtended>(split);
                // 如果字段为空,可设置默认值或从其他来源获取
                if (splitExt.UsrEntryA == null) splitExt.UsrEntryA = 6;
                if (splitExt.UsrEntryB == null) splitExt.UsrEntryB = true;
            }
            yield return result;
        }
    }
}

3. 检查是否有其他自定义逻辑干扰

确认是否有其他插件、事件处理或自定义代码在发货确认时清空了这些字段,比如RowUpdated事件中错误地重置了字段值。


方案2的解决办法(扩展表无记录插入)

你的核心错误是将扩展表的DAC定义成了PXCacheExtension<SOShipLineSplit>,但独立扩展表需要作为独立DAC实现,而非原DAC的缓存扩展。以下是修正步骤:

1. 修正扩展表的DAC定义

namespace SOShipLineSplitNS
{
    [PXTable(typeof(SOShipLineSplit.shipmentNbr), 
             typeof(SOShipLineSplit.lineNbr), 
             typeof(SOShipLineSplit.splitLineNbr), 
             IsOptional = true)]
    public class SOShipLineSplitStandalone : IBqlTable
    {
        #region CompanyID
        public abstract class companyID : PX.Data.IBqlField { }
        [PXDBInt(IsKey = true)]
        [PXDefault(typeof(AccessInfo.companyID))]
        public virtual int? CompanyID { get; set; }
        #endregion

        #region ShipmentNbr
        public abstract class shipmentNbr : PX.Data.IBqlField { }
        [PXDBString(15, IsKey = true)]
        [PXParent(typeof(SelectFrom<SOShipLineSplit>
                    .Where<SOShipLineSplit.shipmentNbr.IsEqual<SOShipLineSplitStandalone.shipmentNbr>
                    .And<SOShipLineSplit.lineNbr.IsEqual<SOShipLineSplitStandalone.lineNbr>
                    .And<SOShipLineSplit.splitLineNbr.IsEqual<SOShipLineSplitStandalone.splitLineNbr>>>))]
        public virtual string ShipmentNbr { get; set; }
        #endregion

        #region LineNbr
        public abstract class lineNbr : PX.Data.IBqlField { }
        [PXDBInt(IsKey = true)]
        public virtual int? LineNbr { get; set; }
        #endregion

        #region SplitLineNbr
        public abstract class splitLineNbr : PX.Data.IBqlField { }
        [PXDBInt(IsKey = true)]
        public virtual int? SplitLineNbr { get; set; }
        #endregion

        #region FieldInteger
        public abstract class fieldInteger : PX.Data.IBqlField { }
        [PXDBInt]
        [PXDefault(7, PersistingCheck = PXPersistingCheck.Nothing)]
        [PXUIField(DisplayName = "FieldInteger")]
        public virtual int? FieldInteger { get; set; }
        #endregion

        #region FieldBool
        public abstract class fieldBool : PX.Data.IBqlField { }
        [PXDBBool]
        [PXDefault(true, PersistingCheck = PXPersistingCheck.Nothing)]
        [PXUIField(DisplayName = "FieldBool")]
        public virtual bool? FieldBool { get; set; }
        #endregion
    }
}

2. 添加自动插入扩展表记录的事件处理

在SOShipmentEntry图形扩展中,添加RowInserted事件,确保创建SOShipLineSplit时自动生成扩展表记录:

protected void _(Events.RowInserted<SOShipLineSplit> e)
{
    if (e.Row == null) return;
    
    // 创建扩展表记录
    SOShipLineSplitStandalone extRecord = new SOShipLineSplitStandalone
    {
        ShipmentNbr = e.Row.ShipmentNbr,
        LineNbr = e.Row.LineNbr,
        SplitLineNbr = e.Row.SplitLineNbr
    };
    
    // 设置默认值并插入
    Base.Caches[typeof(SOShipLineSplitStandalone)].SetDefaultExt(extRecord);
    Base.Caches[typeof(SOShipLineSplitStandalone)].Insert(extRecord);
}

总结

  • 方案1更适合简单的自定义字段需求,核心是确保发货确认逻辑中复制自定义字段值
  • 方案2适合复杂的扩展场景,需要将扩展表作为独立DAC,并通过事件自动关联原表记录

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:19:02