Introduction
Have you wanted to customize the SO Process orders screen? Notice that many actions found here are shared in the Sales Order entry screen. How are these actions linked between the two screens? Our goal today is to explore the relationship between these screens, and how these actions are invoked from the processing screen.
Processing Orders
In the screen Process Orders (SO501000), we find similar selections in the Action drop-down, as found in the Sales Order entry screen (SO301000). For example, Create Shipment and Cancel Order actions are found on both screens. Using the code inquiry tool, we can open the graph file which powers the sales order entry screen – SOOrderEntry.cs. Upon inspection, we notice members such as:
- putOnHold
- cancelOrder
- releaseFromCreditHold
- createShipment
Before we continue, there is an interesting history of Acumatica pre-version 2017. In those versions, the workflows of standard document lifecycles such as Sales Order, Purchase Order, Invoices, etc, were defined using Automation Workflows. Each lifecycle was defined internally with an ugly XML file, which defined document & field states, menu actions, reports, and values. Acumatica allowed the developer to modify the XML file to override the default workflow. In addition, an automation workflow menu assisted the developer with creating these alterations via a separate screen (which still exists). It certainly made the job easier but was not a great help to learn about the link between the processing screen actions and the document entry screen.
With the code browser, it’s easier to learn how the actions are shared between the screens.
Upon first look at the graph SOCreateShipment.cs, we notice several members of the class
- Orders data view
- Filter
- RowSelected event
- RowUpdated event
But notice there are no natural named types for our actions drop-down? Should we expect to see named members for each one of these actions in the graph?
Let’s remember one of the pillars of object-oriented programming – encapsulation. As we can infer, it is not good practice to define the contents of each action, repeatedly, on both screens.
So as we look at the graph code, notice the data view Orders. This data view is of type PXFilteredProcessing, which inherits from PXProcessingBase. PXProcessing class defines the PXView, to form the selection criteria of our records. Notice in the custom constructor for the Records dataview passes the Filter.Owner ID field, in order to append the OuterView Where criteria of the data view. This is used to help select records in which the current user has ownership of the Contact record.
A typical design pattern for processing screens is to define the processing delegate in the graph constructor. In our case, we do not see this. Further down the graph code, notice the RowSelected event.
GIST: https://gist.github.com/tocohara/681c603dbe5f3aa059534373a5e66f14
Several Acumatica processing screens use the Filter RowSelected event to invoke a data process delegate. For example, we see this in the screen Release Retainage (AR510000).
GIST: https://gist.github.com/tocohara/9c879a1e6670adeb921c6296c7fd1bc6
In that case, the SetProcessDelegate is more obvious. But what about our sales order processing screen? Return to the SOProcessFilter RowSelected event. SetProcessWorkflowAction is a member of PXProcessingBase. Let’s use our a reflector tool in order to explore this member.
GIST: https://gist.github.com/tocohara/3e92bb85c5cf5a62438b2bfaa19be5a5
We find some interesting statements within this method. In particular, there are some variables set in the body of this method to notice
- screenId
- actionName
We have a way to learn what the screen Id and action name is, the ProcessOrder graph, during the RowSelected event. Notice the Action type is S0301000$PrepareInvoice (in this case, we chose the Prepare Invoice action in the processing screen).
Upon further investigation of the details of method SetProcessWorkflowAction, notice a call to a deeper method named _SetProcessTargetInternal. What we discover is the code that creates screen and menu variables by splitting the Action variable along with the $ character. This is important since they are used further down the method, to invoke workflow automation, specifically by screen and action ID.
GIST: https://gist.github.com/tocohara/e74897a1c42ff9c630946f4eb9efb0e4
The code goes quite deeper than this method, but eventually, the link between the screen SO301000 and graph SOOrderEntry is established in the graph. Later the action is invoked in a batch.
If you are curious about the storage of this relation, check out table AUDefinitionDetail:
Summary
In this post, we have explored the graphs for the Process Orders screen. We investigated the Actions member. By using a reflector tool, we discovered the screen ID and the Action name is intercepted deep in members of the PXProcessBase class, in order to invoke the actions in the sales order entry screen.
I hope that you have found this useful – and always – Happy Coding!