Skip to main content
Answer

Trying to concatenate the ShipmentNbr field to SHPXXXXX-BAccount.acctCD

  • May 30, 2025
  • 6 replies
  • 76 views

Joe Schmucker
Captain II
Forum|alt.badge.img+3

Hello friends!

My customer wants me to change the auto numbered value for a Shipment to be the Shipment Number + the Customer ID (acctCD).

They promised that the acctCD for a customer is never going to be more than 5 characters.  The shipment field is 15 characters so an example would be SHPXXXXXX-JOE1

I am trying to change the Shipment Nbr that is created when the Shipment is saved.  I am using the RowPersisting event to do it.

However, even if I invoke the base handler at the start of the method, the ShipmentNbr field is still “<NEW>”.

I’m not sure where in the process I can get the Acumatica assigned ShipmentNbr and override it.

 

protected void SOShipment_RowPersisting(PXCache cache, PXRowPersistingEventArgs e, PXRowPersisting InvokeBaseHandler)
{
if (InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);

var row = (SOShipment)e.Row;

//I THINK I should have the Shipment Nbr at this point but I don't

string custCD = string.Empty;

if (cache.GetStatus(row) == PXEntryStatus.Inserted)
{
BAccount2 customer = SelectFrom<BAccount2>.Where<BAccount2.bAccountID.IsEqual<@P.AsInt>>.View.Select(Base, row.CustomerID);
if (customer != null)
{
custCD = row.ShipmentNbr + "-" + customer.AcctCD.Substring(0, 5).Trim();
if (custCD.Trim().Length <= 15)
{
cache.SetValue(e.Row, "ShipmentNbr", custCD);
}
}
}
}

 

Best answer by darylbowman

That’s overriding the RowPersisting event within the AutoNumberAttribute.

You should be able to do something like this:

public class CustomAutoNumberShipmentNbrAttribute : AutoNumberAttribute
{
public CustomAutoNumberShipmentNbrAttribute() :
base(typeof(SOSetup.shipmentNumberingID), typeof(SOShipment.shipDate)) { }

public override void RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
{
SOShipment row = e.Row as SOShipment;
if (sender.GetStatus(row) == PXEntryStatus.Inserted)
{
base.RowPersisting(sender, e);

// Codes

// Not sure if row.ShipmentNbr is filled yet
sender.SetValue(row, _FieldName, $"{row.ShipmentNbr}-{acctCD}");
}
}
}

Then replace [AutoNumber] on ShipmentNbr like this:

[PXMergeAttributes(Method = MergeMethod.Append)]
[PXRemoveBaseAttribute(typeof(AutoNumberAttribute))]
[CustomAutoNumberShipmentNbr]
protected virtual void _(Events.CacheAttached<SOShipment.shipmentNbr> e) { }

 

6 replies

darylbowman
Captain II
Forum|alt.badge.img+15

This will give you the next numbering sequence:

var numberingValue = AutoNumberAttribute.GetNextNumber(cache, row, numberingID, date);

 


Joe Schmucker
Captain II
Forum|alt.badge.img+3
  • Author
  • Captain II
  • May 30, 2025

Hi ​@darylbowman!

That gives me the Shipment Nbr.  But it is not persisting my value to the DB.  I tried cache.SetValue(e.Row, "ShipmentNbr", custCD); cache.SetValueExt(e.Row, "ShipmentNbr",custCD); and row.ShipmentNbr = custCD; hoping that might make a difference, but no luck.

Out of desperation, I tried doing the same thing in RowPersisted.  It changed the value on the screen, but the underlying record was saved with the standard number.

I found an article showing how to override the Persist method, but I cannot get the signature to work.  I don’t even know if that is a place where I could do this.

This was the code from the StackOverflow.  I tried to adapt it but there are red squiggles all over the place.

 public override void RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
{
InventoryItem row = e.Row as InventoryItem;
if(sender.GetStatus(row) == PXEntryStatus.Inserted)
{
base.RowPersisting(sender, e);

INSetup setup = PXSelectBase<INSetup, PXSelectReadonly<INSetup>.Config>.Select(sender.Graph, Array.Empty<object>());
INSetupExtension setupExt = setup.GetExtension<INSetupExtension>();
string nextNumber;

object newValue = sender.GetValue(e.Row, this._FieldOrdinal);
if(!string.IsNullOrEmpty((string)newValue))
{
INItemClass itemClass = PXSelectReadonly<INItemClass, Where<INItemClass.itemClassID, Equal<Required<INItemClass.itemClassID>>>>.Select(sender.Graph, row.ItemClassID);
if(itemClass != null)
{
nextNumber = AutoNumberAttribute.GetNextNumber(sender, e.Row, setupExt.InventoryNumbering1ID, DateTime.Now);
}
else
{
nextNumber = AutoNumberAttribute.GetNextNumber(sender, e.Row, setupExt.InventoryNumbering2ID, DateTime.Now);
}
sender.SetValue(e.Row, this._FieldName, nextNumber);
}
}
}

 

I am a bad developer.  


darylbowman
Captain II
Forum|alt.badge.img+15
  • Answer
  • May 30, 2025

That’s overriding the RowPersisting event within the AutoNumberAttribute.

You should be able to do something like this:

public class CustomAutoNumberShipmentNbrAttribute : AutoNumberAttribute
{
public CustomAutoNumberShipmentNbrAttribute() :
base(typeof(SOSetup.shipmentNumberingID), typeof(SOShipment.shipDate)) { }

public override void RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
{
SOShipment row = e.Row as SOShipment;
if (sender.GetStatus(row) == PXEntryStatus.Inserted)
{
base.RowPersisting(sender, e);

// Codes

// Not sure if row.ShipmentNbr is filled yet
sender.SetValue(row, _FieldName, $"{row.ShipmentNbr}-{acctCD}");
}
}
}

Then replace [AutoNumber] on ShipmentNbr like this:

[PXMergeAttributes(Method = MergeMethod.Append)]
[PXRemoveBaseAttribute(typeof(AutoNumberAttribute))]
[CustomAutoNumberShipmentNbr]
protected virtual void _(Events.CacheAttached<SOShipment.shipmentNbr> e) { }

 


Joe Schmucker
Captain II
Forum|alt.badge.img+3
  • Author
  • Captain II
  • May 30, 2025

Thank you so much ​@darylbowman !

Final working code:

	public class CustomAutoNumberShipmentNbrAttribute : AutoNumberAttribute
{
public CustomAutoNumberShipmentNbrAttribute() :
base(typeof(SOSetup.shipmentNumberingID), typeof(SOShipment.shipDate))
{ }

public override void RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
{
SOShipment row = e.Row as SOShipment;
if (sender.GetStatus(row) == PXEntryStatus.Inserted)
{
base.RowPersisting(sender, e);

string custCD = string.Empty;

BAccount2 customer = SelectFrom<BAccount2>.Where<BAccount2.bAccountID.IsEqual<@P.AsInt>>.View.Select(sender.Graph, row.CustomerID);
if (customer != null)
{
custCD = customer.AcctCD.Substring(0, 5).Trim();
if (custCD.Trim().Length <= 15)
{
sender.SetValue(row, _FieldName, $"{row.ShipmentNbr}-{custCD}");
}
else
{
sender.SetValue(row, _FieldName, row.ShipmentNbr);
}
}

}
}
}

 


darylbowman
Captain II
Forum|alt.badge.img+15

Interesting. So in the RowPersisting event on the graph, row.ShipmentNbr is not yet set, but in RowPersisting on the ShipmentNbr field, it is?


Joe Schmucker
Captain II
Forum|alt.badge.img+3
  • Author
  • Captain II
  • May 30, 2025

FYI, I removed all my code except for the previous post.  

(this is also in my extension)

        [PXMergeAttributes(Method = MergeMethod.Append)]
        [PXRemoveBaseAttribute(typeof(AutoNumberAttribute))]
        [CustomAutoNumberShipmentNbr]
        protected virtual void _(Events.CacheAttached<SOShipment.shipmentNbr> e) { }

The ShipmentNbr is <NEW> until the base.RowPersisting(sender, e); fires.  Then there is a number I can use.