Skip to main content
Solved

I can’t remove the attribute from AlternateID.

  • February 12, 2026
  • 5 replies
  • 76 views

Forum|alt.badge.img

Hi everyone,

I’m trying to customize SOLine.AlternateID, but the original Acumatica logic is interfering with my functionality. Specifically, I need to remove the AlternativeItemAttribute from SOLine.AlternateID.

Here’s what I tried so far:

        #region AlternateID
[PXMergeAttributes(Method = MergeMethod.Merge)]
[PXRemoveBaseAttribute(typeof(AlternativeItemAttribute))]
[PXDBDefault(null, PersistingCheck = PXPersistingCheck.Nothing)]
[BZAlternativeItemAttribute(INPrimaryAlternateType.CPN, typeof(SOLine.inventoryID), typeof(SOLine.subItemID), typeof(SOLine.uOM))]
protected virtual void SOLine_AlternateID_CacheAttached(PXCache sender) { }
#endregion

However, this doesn’t seem to remove the attribute completely. Has anyone successfully removed or replaced the AlternativeItemAttribute from AlternateID? Any guidance or best practices would be greatly appreciated.

Best answer by VaheGhazaryan

HI All,

Thank you all for your help! I was able to solve the issue after all. Here is my solution.

        #region AlternateID || Added custom modification by Biz_Vahe
[PXMergeAttributes(Method = MergeMethod.Merge)]
[PXRemoveBaseAttribute(typeof(AlternativeItemAttribute))]
[BZAlternativeItem(INPrimaryAlternateType.CPN,
typeof(SOLine.customerID),
typeof(SOLine.inventoryID),
typeof(SOLine.subItemID),
typeof(SOLine.uOM),
typeof(SOLine),
typeof(BZSOLineExt.usrBZIsReplacedKit))]
protected virtual void SOLine_AlternateID_CacheAttached(PXCache sender) { }
#endregion

public class BZAlternativeItemAttribute : AlternativeItemAttribute
{

private readonly Type _dacType;
private readonly Type _flagFieldType;

public static bool IsActive() => true;
public BZAlternativeItemAttribute(INPrimaryAlternateType primaryAltType, Type bAccountID, Type inventoryID, Type subItemID, Type uom, Type dacType, Type flagFieldType) : base(primaryAltType, bAccountID, inventoryID, subItemID, uom)
{
_dacType = dacType;
_flagFieldType = flagFieldType;
}

public override void RowInserting(PXCache sender, PXRowInsertingEventArgs e)
{
if (!IsReplacedKit(sender, e.Row))
{
base.RowInserting(sender, e);
}
}

public override void RowUpdating(PXCache sender, PXRowUpdatingEventArgs e)
{
if (!IsReplacedKit(sender, e.Row))
{
base.RowUpdating(sender, e);
}
}

private bool IsReplacedKit(PXCache cache, object row)
{
if (row == null)
return false;

if (!_dacType.IsAssignableFrom(row.GetType()))
return false;

string flagFieldName = _flagFieldType.Name;
object rawValue = cache.GetValue(row, flagFieldName);
return rawValue is bool flag && flag;
}
}
}

 

5 replies

zherring
Jr Varsity III
Forum|alt.badge.img
  • Jr Varsity III
  • February 12, 2026

Instead of doing “MergeMethod.Merge” try using “MergeMethod.Replace” and just specifying the exact attributes you want. That should replace all the attributes with the ones you want.


Forum|alt.badge.img
  • Author
  • Jr Varsity III
  • February 12, 2026

@zherring , MergeMethod.Replace results in this error on the screen.

 


abhimanyuprajapati52
Jr Varsity I
Forum|alt.badge.img

Hi ​@zherring,

The error happens because SOLine.AlternateID has a complex base attribute stack with internal dependencies. When using MergeMethod.Replace, you must completely rebuild the entire attribute declaration (PXDB, PXUIField, selector logic, etc.). If anything is missing, the framework throws the CacheAttached exception you’re seeing.

However, AlternateID is tightly integrated with inventory cross-reference logic through AlternativeItemAttribute, and fully removing it is generally not supported because other parts of the SO logic depend on it.

In practice, completely removing AlternativeItemAttribute is not recommended.

A safer and more maintainable approach is:

• Keep the base attribute
• Create a custom attribute inheriting from AlternativeItemAttribute
• Override only the specific behavior you need to change

This preserves the internal framework wiring while allowing you to adjust the functionality safely.


Forum|alt.badge.img
  • Author
  • Jr Varsity III
  • Answer
  • March 18, 2026

HI All,

Thank you all for your help! I was able to solve the issue after all. Here is my solution.

        #region AlternateID || Added custom modification by Biz_Vahe
[PXMergeAttributes(Method = MergeMethod.Merge)]
[PXRemoveBaseAttribute(typeof(AlternativeItemAttribute))]
[BZAlternativeItem(INPrimaryAlternateType.CPN,
typeof(SOLine.customerID),
typeof(SOLine.inventoryID),
typeof(SOLine.subItemID),
typeof(SOLine.uOM),
typeof(SOLine),
typeof(BZSOLineExt.usrBZIsReplacedKit))]
protected virtual void SOLine_AlternateID_CacheAttached(PXCache sender) { }
#endregion

public class BZAlternativeItemAttribute : AlternativeItemAttribute
{

private readonly Type _dacType;
private readonly Type _flagFieldType;

public static bool IsActive() => true;
public BZAlternativeItemAttribute(INPrimaryAlternateType primaryAltType, Type bAccountID, Type inventoryID, Type subItemID, Type uom, Type dacType, Type flagFieldType) : base(primaryAltType, bAccountID, inventoryID, subItemID, uom)
{
_dacType = dacType;
_flagFieldType = flagFieldType;
}

public override void RowInserting(PXCache sender, PXRowInsertingEventArgs e)
{
if (!IsReplacedKit(sender, e.Row))
{
base.RowInserting(sender, e);
}
}

public override void RowUpdating(PXCache sender, PXRowUpdatingEventArgs e)
{
if (!IsReplacedKit(sender, e.Row))
{
base.RowUpdating(sender, e);
}
}

private bool IsReplacedKit(PXCache cache, object row)
{
if (row == null)
return false;

if (!_dacType.IsAssignableFrom(row.GetType()))
return false;

string flagFieldName = _flagFieldType.Name;
object rawValue = cache.GetValue(row, flagFieldName);
return rawValue is bool flag && flag;
}
}
}

 


Chris Hackett
Community Manager
Forum|alt.badge.img
  • Acumatica Community Manager
  • March 18, 2026

Thank you for sharing your solution with the community ​@VaheGhazaryan!