Get Business Process Flow Stages in a defined sequence within Microsoft Dynamics 365 CRM

By | December 12, 2022

Introduction

Recently while working on one of our requirements, we came across a scenario where we needed to arrange the Business Process stages in the order in which it was mentioned on the entity record. So, we tried to get the stages from the processstage table, but the resultant stages on querying the processstage table were not in the same order as presented in the form. In this blog, we will see how to trace a possible solution to get all the Business Process Flow (BPF) stages in their defined sequence.

Scenario

Now as per our requirement, we have added a custom stage i.e. the Verification stage after the Qualify stage in the out-of-the-box leadtoopportunitysalesprocess BPF.

As explained above, when we query the stages we would want them in a defined order. However, on querying the processstage table using OData query the stages are not returned in their defined order and we get our custom Verification stage towards the end. As can be seen from the below screenshot we continue to get the same result even when we order the OData query by versionnumber

Query:

[OrganizationURI]/data/v9.0/processstages?$filter=_processid_value=’27919E14D1-6489-4852-ABD0-A63A6ECAAC5D’&$select=stagename&$orderby=versionnumber

Business Process Flows

Solution  

In the quest to find a way to get the Business Process stages in their respective order, we went back to the basics which lead us to the Processes(workflow) table. So basically, in Dynamics CRM the Processes table not only holds the Workflows but also holds the Business Process Flows, Actions and Dialogs. This Processes table consists of an attribute clientdata which holds the order of the stages. Below is the fetch for the same.

Note: To get the stages of their desired Business Process Flow, one must know the GUID of their respective Business Process Flow to apply the filer on.

<fetch>

<entity name="workflow">

<attribute name="clientdata"/>

<filter>

<condition attribute="workflowid " operator="eq" value="919e14d1-6489-4852-abd0-a63a6ecaac5d"/>

</filter>

</entity>

</fetch>

clientdata is just a JSON string that contains the details of the process stages. Below is the class object we would use to deserialize the clientdata JSON.

public class List

{

public string description { get; set; }

public Steps steps { get; set; }

public string stageId { get; set; }

public string nextStageId { get; set; }

}

public class Stepsdata

{

public Steps steps { get; set; }

}

public class StepLabels

{

public List<object> list { get; set; }

}

public class Steps

{

public List<List> list { get; set; }

}

Once, we Deserialize the JSON data it will be shown as the below image

As can be seen from the above screenshot the steps property is an array that holds the stages in their respective order.

So, in the below screenshot in the 1st position, we see the Qualify stage and in the 2nd position, we see the Verification stage. The 0th position doesn’t seem to hold any stage details.

Further from the below screenshots, we can also see that each object of the steps property holds another steps property which holds additional details of the stages such as the stage description, etc.

In the below code, we have used nested foreach to segregate the JSON formatted data and loop through the parent and child steps capturing the required details from the respective Business Process Flow stages.

In the code, we have printed the description value which is the stage name in a trace, but you can definitely go ahead further and use these details as per your business use case.

public void sequenceBPFStages(IOrganizationService service, ITracingService trace)

{

List<StepLabels> convertJson = new List<StepLabels>();

convertJson = clientData.Deserialize<StepLabels>();

 

//Here we will get the BPF stages inside list of steps, so below we have added //foreach loop of steps inside for loop of list of steps

 

for (int i = 0; i < convertJson.steps.list.Count; i++)

{

//Check if no steps present then do not go inside loop

 

if (convertJson.steps.list.Count > 0)

{

foreach (var item in convertJson.steps.list[i].steps.list)

{

//Name of Bpf stage – in json we will get description //field which is Name of BPF stage

String bpfStagesName = item.description != "" ? item.description : string.Empty;

trace.Trace("Bpf Stages name" + bpfStagesName);

 

 

}

}

}

}

Conclusion

Thus, we saw how querying on the Processes (workflow) table gives us the Business Process Flow stages in their defined sequence.