• Blog
  • Designing a Workflow Engine for nopCommerce CMS Part 3: States and Transitions

Designing a Workflow Engine for nopCommerce CMS Part 3: States and Transitions

  • 10:59:53 PM
  • Saturday, October 21, 2017

This is Part 3 of a seven-part series describing how to implement Workflow Engine for nopCommerce CMS. Click here for Part 1
Now that we've got the Workwlow model created, we can start building models for the actual process itself. In this part, we'll design the models that will hold the different States an Entity can be in as part of a Workflow, and we'll also design the tables that show how to get from one State to another (which are called Transitions). First, though, we need a table that shows what different types of States can exist. Let's get started!

State Types

A State Type is a categorization of the individual States. In our design, it is an unchangeable list, so in code we would probably use an Enumeration to represent it. Since we're making this database design fully-normalized, we're going to include this set of data as a table, with the following structure:

Because we don't want to have any user-defined State Types, there's no relationship to Workflow for this table. We're treating this table as unchangeable, and will always have the following values:

Here's the reasoning for each of these types:

  • Should only be one per workflow. This state is the state into which a new Entity is placed when it is created.
  • Default: A regular state with no special designation.
  • Complete: A state signifying that any Entity in this state have completed normally.
  • Denied: A state signifying that any Entity in this state has been denied (e.g. never got started and will not be worked on).
  • Cancelled: A state signifying that any Entity in this state has been cancelled (e.g. work was started but never completed).
  • Auto transition: A state signifying that any Entity in this state should be implemented associated action and entity should be transited to the next state.
  • Wait: A state signifying that any Entity in this state have been assigned to somebody and waited any action.

Every State must have exactly one of these State Types. But what makes a State?

States

A State is a position in the Workflow that a given Entity can be in at any given moment. States are unique to Workflow, and each State has a name, a description, and a type. Our State model looks like this:

namespace DevPartner.Nop.Plugin.Core.Models.Workflow
{
    [SystemName("State")]
    public class StateModel : DPModel
    {
        [AttExtRefType("StateType")]
        [Required]
        [ShowOnListPage]
        [EditorTemplate("DropdownList")]
        public int StateType { get; set; }

        [DPParent]
        public WorkflowModel Parent { get; set; }
    }
}

IMPORTANT NOTE: We should add StateType to AttExtRef before converting model to our DB.

if not exists(select 1 from [dbo].[DP_AttExtRefType] where [Name] = 'StateType')
begin

	DECLARE @stateTypeExtRefTypeId int

	INSERT INTO [dbo].[DP_AttExtRefType]
			   ([Name]
			   ,[ExtTableName]
			   ,[ExtIdFieldName])
		 VALUES
			   ('StateType'
			   ,'DP_StateType'
			   ,'Id')

	SET @stateTypeExtRefTypeId = @@IDENTITY

	INSERT INTO [dbo].[DP_AttExtRefFields]
			   ([AttExtRefTypeId]
			   ,[FieldName]         
			   ,[IsSearchable]
			   ,[AttDataTypeId])
		 VALUES
			   (@stateTypeExtRefTypeId
			   ,'Name'
			   ,1
			   ,6)
end 

We should remember, though, that each Workflow is supposed to represent a flow chart, and to do that we need to be able to move Entities between the States. We can do so by designing models for Transitions.

Transitions

If a the lead store owner approves an entity, and it should now go to the vendors according to their subscription, how can we design our data so as to represent that that move is possible? We create a Transition.

A Transition is a path between two States that shows how an Entity can travel between them. Transitions are unique to Workflow. Our Transition model looks like this:

namespace DevPartner.Nop.Plugin.Core.Models.Workflow
{
    [SystemName("Transition")]
    public class TransitionModel : DPModel
    {
        [DataSource("../*[@type='State']")]
        [Required]
        [ShowOnListPage]
        [EditorTemplate("DropdownList")]
        public int FromState { get; set; }

        [DataSource("../*[@type='State']")]
        [Required]
        [ShowOnListPage]
        [EditorTemplate("DropdownList")]
        public int ToState { get; set; }

        [DPParent]
        public WorkflowModel Parent { get; set; }
    }
}
What did we accomplish?

In this post, we gave form to the building blocks of the Workflow by defining the States where an Entity can exist and the Transitions between those States.
We still have an outstanding problem, though: how do we invoke our Transitions? How do we actually cause an Entity to move from one State to another? All that and more in the next post, Part 4 of this adventure, which discusses Actions.