Workflow States: General Information

In this chapter, you will learn how to define and configure states of a workflow by using Workflow API.

Learning Objectives

In this chapter, you will learn how to do the following:

  • Define the set of states of the workflow
  • Add states to the screen configuration
  • Configure states in a workflow

Applicable Scenarios

You define and configure states of a workflow when you are defining a new workflow or customizing an existing workflow.

Workflow States

Each workflow consists of multiple workflow states. Each state corresponds to a value of the state-identifying field.

Currently, the workflow engine supports only state-identifying fields of the String type that have a predefined set of allowed values. The values of the state-identifying field are usually defined in the PXStringList attribute. To define the state-identifying field, you need to call the StateIdentifierIs method for the new screen configuration and provide the field as the parameter. For details, see Step 3: Overriding the Configure Method.

Adding a Workflow State

To define the set of states, you сall the WithFlowStates method in the lambda expression specified for the AddDefaultFlow method and provide the set of states in the parameter, as the following code shows. You define each state by calling the Add method and specifying the state-identifier string as a generic parameter. As a parameter of the Add method, you specify a lambda expression where you can configure the state.

context.AddScreenConfigurationFor(screen =>
   screen.StateIdentifierIs<status>()
   .AddDefaultFlow(flow =>
      flow.WithFlowStates(fss =>
      {
         fss.Add<State.hold>(flowState => flowState.IsInitial());
         fss.Add<State.open>(flowState => { … });
         ...
      })
Note: To add a state to an existing workflow, you call the Add method in the UpdateDefaultFlow method inside the UpdateScreenConfigurationFor method.

Each workflow must have one state that is marked as the initial state. It provides the default value of the state-identifier field for a newly created record. You mark a state as initial by calling the IsInitial method, as shown in the code above.

Configuring States

You can add, update, or delete states in a screen configuration by calling the Add, Update, or Delete method, respectively.

Inside the lambda expression passed to the Add or Update method, you configure the state. For each workflow state, you can do the following:

  • Specify that a state should be the initial state of a workflow by calling the IsInitial method.
    Note: Only one state can be the initial state of a workflow.
  • Specify the properties that the specified DAC fields should have in this state by calling the WithFieldStates method.

    You can specify such properties as requirement, visibility, and availability. Settings specified in the WithFieldStates method override the parameter values specified in the DAC field attributes.

  • Specify which actions are available in this state and configure the appearance of these actions in this state, such as whether the action should be duplicated on the form toolbar. You do this by calling the WithActions method.
  • Specify which event handlers are available in this state by calling the WithEventHandlers method.
  • Specify a list of field assignments that will be performed when a record enters the state and when a record leaves the state.

    To provide a list of fields whose values should be assigned when a record enters the state, use the flowState.WithOnEnterAssignments method when defining the state. The field assignments listed in the method are applied to the state for which the method was called.

    To provide the list of fields whose values should be assigned to a state when a record leaves a state, use the flowState.WithOnLeaveAssignments method when defining the state. The field assignments listed in the method are applied to the state for which the method was called.

    An example of using these methods is shown in the following code.

    flowStates.Add<State.hold>(flowState =>
    {
      return flowState
        .WithActions(actions => …);
        .WithOnEnterAssignments(fields => fields.Add<inclCustOpenOrders>(false));
        .WithOnLeaveAssignments(fields => fields.Add<inclCustOpenOrders>(true));
        ...
    }

    In the code above, the inclCustOpenOrders field is assigned false when the record state is changed to hold (after the transition to this state is completed), and the inclCustOpenOrders field is assigned true before the hold state is changed to some other state (before the transition is started).