How to add validation to Create shipment and confirm shipment in Acumatica

Hello everybody,

today I want to write a few words on my latest time spending in Acumatica. Recently I was asked to add additional validations to actions Create shipment:

and Confirm Shipment:

Idea was the following, if user clicks on Create shipment action or at Confirm Shipment action, some function should be executed which throws exception and prevents Creation/confirmation of shipment if some conditions are not meet. 

At first glance task was trivial. I supposed that all that will be needed, just override method Create Shipment of SOOrderEntry and Cofirm Shipment of SOShipmentEntry. And jumped right to the code. 

In order to modify behavior of those two methods, I've created override of Action of SOOrderEntry and added validation inside of that method. My code looked like this:

		[PXOverride]
		public IEnumerable Action(PXAdapter adapter, int? actionID, DateTime? shipDate, String siteCD, String operation, 
			String ActionName, 
			Func<PXAdapterint?, DateTime?, stringstringstringIEnumerable> baseMethod)
		{
            
			List<SOOrder> list = new List<SOOrder>();
			foreach (SOOrder order in adapter.Get<SOOrder>())
			{
				list.Add(order);
			}
			if (actionID == 1)
			{
                //throwed exception here!. WRONG WAY!!!!

I've tested it on Sales Orders page, got exception, added additional code and send it to QA with feeling that I'm great. Unfortunately I was far from making task as done. The next day QA told me that on processing screen my code didn't work at all, 

and asked me to deal with it in another way. As usually programmers and QA's have love-hate relationship, but I myself always happy to deal with QA. I can say that it's always better if QA return you a bug, then angry customer with your boss 

asks you to fix a bug.

So I started coding one more time. I've tried few other ways, for example I've overrided method Persist of SOShipmentEntry like this:

                [PXOverride]
		public void Persist(Action del)
		{
                      //if validation fails, throw exception here. WRONG WAY
}

and before giving that staff to QA I've decided to give a test for this approach and much to my shame it also didn't work as expected. And on the level of processing screen I've got plenty of weird exeptions, and not even exceptions created by my code.

In case if nothing works, the only think that you can do involves deep immersion in Acumatica source code. After deeging deeper here is what I've found inside of action Create shipment:

  1. Create shipment method is not executed right away after click on Actions -> Create shipment. Before that some plumbing code is executed.
  2. Save.Press() is executed multiple times, so when I've throwed exception, then methods for Shipment creation as well as confirmation weren't executed at all.
  3. After pretty big amoung of plumbing code method CreateShipment is executed.

After seeing such behavior I've decided to override methods CreateShipment and ConfirmShipment. Both of those methods are implemented in graph SOShipmentEntry. Override in Acumatica looks pretty stratightforward, especially with anonymous delegates.

Both of those methods I've included in extension of SOShipmentEntry, and methods looks like those:

[PXOverride]
public void CreateShipment(SOOrder order, int? SiteID, DateTime? ShipDate, bool? useOptimalShipDate,
    string operation, DocumentList<SOShipment> list, PXQuickProcess.ActionFlow quickProcessFlow,
    Action<SOOrderint?, DateTime?, bool?, stringDocumentList<SOShipment>, PXQuickProcess.ActionFlow> baseCreateShipment)
{
    var unpaidBalacne = GetDocumentBalance(order);
 
    ShipmentValidator.ValidateShipment(Base, order, unpaidBalacne, WorkFlowMessages.creditLimitExceeded);
    baseCreateShipment(order, SiteID, ShipDate, useOptimalShipDate, operation, list, quickProcessFlow);
}
[PXOverride]
public virtual void ConfirmShipment(SOOrderEntry docgraph, SOShipment shiporder,
    Action<SOOrderEntrySOShipment> baseConfirmShipment)
{
    var shipLines = PXSelect<SOShipLineWhere<SOShipLine.shipmentNbrEqual<Required<SOShipLine.shipmentNbr>>,
            And<SOShipLine.shipmentTypeEqual<Required<SOShipLine.shipmentType>>>>>
        .Select(Base, shiporder.ShipmentNbr, shiporder.ShipmentType).ToList().Select(a => a.GetItem<SOShipLine>());
 
    foreach (SOShipLine shipLine in shipLines)
    {
        ValidateSOShipLine(shipLine, false);
    }
    baseConfirmShipment(docgraph, shiporder);
}

After those changes each page, including processing pages started to work smoothly.

Summary

All of those conclusions that I've made would be impossible to make without debugging of Acumatica source code. Next time when I'll face some not working out of the box my code, I'll jump into debugging and proper debugging right away.

No Comments

Add a Comment