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
相关产品推荐
相关产品推荐

