Learn all you need to know about our finite-state machine feature and how it easily allows you to build custom, complext state machines and easy implement them on your web applications.

1. Introduction

OMNIA Platform enables you to model a finite-state machine (FSM) to describe the states and transitions that occur during the entity lifetime.

The State Machine can change from one state to another in response to some external inputs. The change from one state to another is called a transition. A State Machine is defined by a list of its states and transitions.

2. Model State Machines

By choosing Business / State Machines in the sidebar, you will have access to the State Machines’ management screen, in which will be presented the existing data of the model.

How to create a State Machine?

Select the option Add new and define the following properties:

  • Related to: the entity that will be managed using the State Machine;
  • Description: a textual explanation of this State Machine(can be used as development documentation).

After creating a new state machine, will be automatically created two states: Initial (the State Machine’s initial state) and Completed.

Also, a new Enumeration will be created containing the existing states (this enumeration will be updated everytime a state is added or removed). The Enumeration will be named using the State Machine name with the sufix “States” (e.g.: the State Machine to the entity Customer will be named CustomerStateMachine and the Enumeration CustomerStateMachineStates).

In the entity to which the State Machine was created, will be added two system attributes: _state (to store the current state of the record) and _assigned (to store to whom is assigned the entity in the current state).

How to create a State?

Business / State Machine / States

Accessing to the details of a State Machine you can add a new state. To do that, in the States list, select the option Add new and define the following properties:

  • Name: the name of the state (needs to be unique inside the state machine);
  • Description: the textual explanation of the state’s purpose (can be used as development documentation);
  • Is the initial state?: if the state is the initial one or not;
  • Disable all attributes?: if marked, all the attributes will be all be shown as read-only, when the entity is in the state;
  • Disable all operations?: if marked, all the operations (e.g.: save, add lines, etc.) will be disabled, when the entity is in the state;
  • Assign to (C# expression): a C# expression to define to whom will be assigned the record when it is in this state.

Note 1: If the Disable all attributes propery is checked, will be possible to define an exception list of attributes. The attributes in this exception list will not have the read-only property overriden.

Note 2: If the Disable all operations propery is checked, will be possible to define an exception list of operations. The operations in this exception list will not have the value overriden.

Note 3: If there is any User Interface Behaviour in the entity’s Form to set an attribute as read-only (or editable) or to set an operation as disabled (or enabled), the configuration set in the Behaviour will be maintained.

How to define the initial state?

Business / State Machine / States / State

In the details page of a State Machine, selecting one of the existing states is possible to change the State Machine’s initial state.

In the State’s details page, select the option Edit State and mark the property Is the initial state?.

Since a State Machine can have one, and only one, initial state, after marking a state as initial, the previous initial state will be unmarked. If you try to remove the initial state will get an error remembering you that you need one initial state.

How to assign the entity to someone in a given State?

Business / State Machine / States / State

In the details page of a State Machine, selecting one of the existing states is possible to change to whom the State’s is assigned, using the property Assign to (C# expression).

In the State’s details page, select the option Edit State and change the property Assign to (C# expression).

Everytime the entity is saved in the State, the C# code expression provided in the Assign to property is evaluated and the result is stored in the system attribute _assigned.

The C# expression must return a string, as seen on the example below:

//Assign to role "Administration" is the TotalAmount value is equal or bigger than 1000. Otherwise, assign to role "Approver"

if(this.TotalAmount >= 1000)
    return "Administration";
else
    return "Approver";

The string returned on this behaviour can contain any possible value (a security role, a reference to another entity, …).

The assignation of the entity to someone does not limit the acess to that entity. The queries of that entity type must be reviewed to control access.

How to disable all attributes in a given State?

Business / State Machine / States / State

In the details page of a State Machine, selecting one of the existing states is possible to set all attributes as read-only when a record is in the State.

In the State’s details page, select the option Edit State and mark the property Disable all attributes?.

How to disable all operations in a given State?

Business / State Machine / States / State

In the details page of a State Machine, selecting one of the existing states is possible to set all operations as disabled when a record is in the State.

In the State’s details page, select the option Edit State and mark the property Disable all operations?.

How to enable an attribute in a given State?

Business / State Machine / States / State / Enabled Attributes

The Enabled Attributes list works as an exception list to the disabled attributes.

It’s possible to define a set of enabled attributes in each state.

In order to do that, access the details page of a State Machine and select a state. In the Enabled Attributes list, select the option Add new and define the following properties:

  • Which is the attribute to enable?: the path to the attribute to enable - corresponds to the attribute name (if the attribute is inside a collection, the path should be the collection name and the attribute’s name joined using a dot).

Note: This is only possible if the property Disable all attributes? is checked.

How to enable an operation in a given State?

Business / State Machine / States / State / Enabled Operations

The Enabled Operations list works as an exception list to the disabled operations.

It’s possible to define a set of enabled operations in each state.

In order to do that, access the details page of a State Machine and select a state. In the Enabled Operations list, select the option Add new and define the following properties:

  • The operation is related to…: define if the operation to enable is over the current Entity or a given Collection Attribute of the Entity. This will influence the opeation types “(Which is the operation to enable?)” that the user can select;
  • Which is the attribute?: the path to the operation to enable - corresponds to the attribute name, if the attribute is a collection (if the operation is relative to the entity, the path should be left empty);
  • Which is the operation to enable?: the operation type (Add, Update or Delete).
    • Add - Can be used when a collection is referenced in the Path. Use this to enable the user to Add new entries to the collection.
    • Update - Can be used to enable the user to save the entity in the current state. Leave the Path empty to use it.
    • Delete - Can be used for both entity and collections. Use this to enable Entity delete or remove entries from Collection.

Note: This is only possible if the property Disable all operations? is checked.

How to create a Decision?

Business / State Machine / States / State / Decisions

A decision allows the users to take an action when the entity is in a specific state.

It’s possible to define a set of allowed decisions in each state. In order to do that, access the details page of a State Machine and select a state. In the Decisions list, select the option Add new and define the following properties:

  • Name: the name of the decision (needs to be unique inside the state);
  • Description: the textual explanation of the decision’s purpose (can be used as development documentation);
  • Should the user write a comment when taking the decision?: the type of comment that will be prompted to the user, when the decision is made (None, Optional or Required);
  • Order: an integer representing the order of the decision in the state.

Note: When a state has decisions, a new Enumeration is created to store the state’s decisions. Everytime a decision is added or removed, the Enumeration is updated. The Enumeration will be named using the State Machine name, the State name and the sufix “Decisions” (e.g.: the State Machine to the entity Customer will be named CustomerStateMachine and the Enumeration representing the decision of the state Initial CustomerStateMachineInitialDecisions).

How to create a Transition?

Business / State Machine / States / State / Transitions

A transition describes a condition, that when is met, moves the entity from the current state to a new one.

It’s possible to define a set of transitions in each state. In order to do that, access the details page of a State Machine and select a state. In the Transitions list, select the option Add new and define the following properties:

  • Name: the name of the transition (needs to be unique inside the state);
  • Description: the textual explanation of the transition’s purpose (can be used as development documentation);
  • Go to state: the state to where the entity will be moved when the transition is successfully evaluated;
  • Evalution type: the type of the evaluation - Automatic (based on a C# expression) or Decision (based on a user’s decision);
  • Based on decision: the decision used to evaluate if the transition should occur (if a C# expression is provided, the two conditions need to be true to the transition occur) - only available in the Evaluation type “Decision”;
  • Evaluate using the C# expression: The C# expression used to evaluate if the transition should occur;
  • Order: an integer representing the order of evaluation of the transition in the state.

How to condition a Transition?

Business / State Machine / States / State / Transitions

A transition can be conditioned using one of two methods: Automatic evaluation or Decision evaluation.

Automatic evaluation: The automatic evaluation only uses the C# code expression to decide if the transition will occur or not.

Decision evaluation: The decision evaluation uses the user’s decision and the C# code expression to decide if the transition will occur or not. If the C# code expression is not provided, only the decision will be take in consideration.

To change the way how to evaluate a Transition, edit a transition (accessing to the state details, in the Transitions list) and change the following properties to correspond to the model needs: Evaluation type, Based on decision and Evaluate using the C# expression.

How to manage State and Decision labels?

Each State Machine has an Enumeration representing its States.

The same way, each State has an Enumeration representing its Decisions.

In order, to change the labels of a State or a Decision, it’s only neccessary to change the label of the respective Enumeration.

3. State Machine Entity Behaviours

Transition behaviours

In the modeler, you can add behaviours to be triggered when a transition happens. These behaviours will be executed either when the entity enters (In) in a given state or exits (Out) a given state.

In and Out behaviours execute in a transaction together with the state machine evaluation and receive the old state and the new state respectively.

Project structure

In the behaviours project, you will find in the Entity folder a file with the name “{Entity}.StateMachine.cs” (example: Customer.StateMachine.cs). The state machine definition is in this C# class, side by side with the entity Operations class.

In the StateMachine.cs file you will find the following methods:

  • EvaluateStateTransitions: Used by the platform to decide the next state. This method can’t be changed and is a representation of the modeled State Machine.
  • EvaluateStateTransition_{State}_{TransitionName}: Transition boolean expression method to decide if the transition should take place. The data from the current entity can be accessed since this is a method of the class.
  • AssignTo_{State}: Assign expression method to decide the value of the _assing attribute when the entity is in a given state. The data from the current entity can be accessed since this is a method of the class.
  • On{State}In: Expression method to be executed when the entity enters the State. Old state is received in the variable fromState.
  • On{State}Out: Expression method to be executed when the entity exits the State. New state is received in the variable toState.

The state machine in the context of the entity lifecycle

The evaluation of the State Machine happens immediately before the Platform invokes the Before Save behaviours.

Accessing the user Decision

In the context of entity behaviours, the modeler can access to the Decision taken through the Context using _Context.Operation.Decision. Example:

if("Accept".Equals(_Context.Operation.Decision))
{
    ...
}

Accessing the user comment

In the context of entity behaviours, the modeler can access to the Comment written by the user through the Context using _Context.Operation.Comment.

4. State Machine UI Behaviours

When a user selects a decision, the Save action is performed. When the BeforeSave behaviour is executed it is possible to use the user’s decision in the JavaScript code.

Accessing the user Decision

Accessing the context, it’s possible to know the decision the user has selected.

In the following sample is shown how to use the decision value in a condition.

if(this._context.operation.decision === 'Accept'){
    ...
}

How to control the available decisions?

In this sample, the decision myDecison is hidden from the decision selector:

    this._metadata.attributes.decisionSelector.elements.myDecision.isHidden = true;