Workflow via Code – Part 1

In an ongoing effort to enhance No Code / Low Code capabilities for Acumatica, a powerful Workflow Engine was released in Acumatica 2020 R2 to replace the older Automation Steps screen starting with a handful of standard screens. Automation Steps allowed a sysadmin to alter the behavior of a screen, but it was very painful to transfer from one instance of Acumatica to another. The new Workflow Engine could be maintained within a customization project and easily migrated to a new instance.

Over the two major releases in 2021, the new Workflow Engine was implemented on most if not all standard screens in Acumatica, and so our company worked to migrate our screens to it as well. Originally, my sysadmin asked to maintain workflows in the UI of Customization Projects. However, upgrades and improvements to the Workflow Engine gave us some challenges in migrating to 2021 R2, so we opted to move the main workflow to code like Acumatica did on standard screens. In this series, Part 1 will show how to define the basic shell of the workflow, and then each subsequent part will show how to add another layer of complexity.

Step 1 – Setup for an “Initial State”

The new workflow engine runs on “State” or status of the primary DAC on the screen. While we all are familiar with standard states such as Hold, Open, and Complete, the workflow UI needs a starting point. Setting up the initial state takes 2 parts. First, in the Statuses class where the constants are defined for each state, add a state for Initial as shown in line 15 of the following gist.

View this gist on GitHub

Next, within the graph for the screen, add an PXAutoAction as show in the following gist.

View this gist on GitHub

Step 2 – Create the Workflow Extension

Next, we need to create the basic shell of a workflow. This is where it gets a little more complicated to explain, so take a look a the gist below, and then we will walk through the parts.

View this gist on GitHub
  • Line 2 – This is the using statement that will give us access to the workflow methods.
  • Line 7 – This is needed when we add some features later, but it’s a convenient time to remember to add it as part of the shell.
  • Line 8 – Allows us to drop constant reference to our primary DAC. In this case, CMMSWorkOrder. We can refer to just the fields of it directly instead of specifying the DAC itself every time.
  • Line 9 – Allows us to simply refer to the status class as State. Among other things, it can make our “rinse and repeat” of setting up workflows easier by allowing our structure to always be “State.hold” instead of changing “State” to match whatever our status class is every time.
  • Line 11 – Extends the base graph to allow us to add our code.
  • Line 13 – This method makes a call to determine when the graph extension should be active. All graph extensions should have an IsActive() method.
  • Line 16 – Overrides the screen configuration and calls our Configure method that will be added next.
  • Line 21 – Defines our screen configuration method where we will add the workflow definitions for our screen.
  • Line 24 – Adds our new screen configuration. If we were adding elements to the workflow of an existing screen, we would use UpdateScreenConfigurationFor instead.
  • Line 27 – Identifies the status field of our primary DAC as the driver for the workflow.
  • Line 28 – Adds a Default Workflow. This line is only necessary because we don’t have a workflow defined yet for our screen, so this establishes our workflow as the default.
  • Line 31 – Adds a section for the states that we will use in our workflow. Generally speaking, every possible status for the primary DAC should be defined here.
  • Line 34 – Defines our initial state.
  • Lines 37 – 39 – Defines each valid status of the primary DAC.
  • Line 41 – Starts the definition of transitions (state changes) for the workflow.
  • Line 43 – Creates a transition group for multiple possible to states. A 1:1 from-to can be defined as a simple transition, but when the from state can result in multiple possible to states, a transition group simplifies processing and readability for the workflow.
  • Line 45 – Tells the workflow to transition the status to Hold which will be triggered when a new record is initialized. In a sense, this is the workflow equivalent of the DAC PXDefault of the status field. After we learn about conditions in a later post, we can add a condition to this transition and add more possible to transitions for different conditions.


While the code shown here does not seem to do much on its own, it is the critical foundation of setting up a new workflow for your custom screen. This code sample simply defines the valid states of the primary DAC and transitions the status field from the initial state to the desired status for new records… in this case Hold.

The screen below shows the sample screen where the workflow is being added. Note that actions defined within the graph code are shown on the menu bar and that the legacy “Hold” checkbox is on the screen.

In Part 2, we will look closer into adding actions to the workflow, including placement of predefined actions onto the drop-down menu and adding new actions directly within the workflow.

Happy Coding!

Leave a Reply