How to Create a Business Process Flow and Get active stage of record and Update the Stage using C# in D365:

  •  Create a Business Process Flow 

            Ex: apy_businessprocessflow

  •         On Create of Contact record Create a business process flow and Get active stage and Set the Stage
  •     Register Plugin on Create of Contact Entity
      
        using Microsoft.Xrm.Sdk;

        using System; 

namespace APY.Plugins.Sales

{

    public class ManageContact : IPlugin

    {

        public void Execute(IServiceProvider serviceProvider)

        {

            ITracingService tracer = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

            IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

            IOrganizationService service = factory.CreateOrganizationService(null); 

            if (context.MessageName == "Create" && context.StageType() == ExecutionContextExtensions.StageTypeValues.PostExecution)

            {

                Entity contactTarget = (Entity)context.InputParameters["Target"];

                if (contactTarget.LogicalName != "contact")

                {

                    return;

                } 

                BusinessProcessFlow businessProcessFlow = new BusinessProcessFlow(contactTarget, service);

                businessProcessFlow.CreateBPFInstanceForTheContact();

            }

        }

}

}

Below method is to create a BPF record

  public void CreateBPFInstanceForTheContact()

        {

            Entity activeProcessInstance = GetActiveBPFDetails();

            if (activeProcessInstance == null)

            {

                var patientFlowRecord = new Entity("apy_businessprocessflow");

                patientFlowRecord.Attributes["bpf_contactid"] = Record.ToEntityReference();

                Service.Create(patientFlowRecord);

            }

        }

Get the active BPF stage details

public Entity GetActiveBPFDetails()

        {

            Entity activeProcessInstance = null;

            RetrieveProcessInstancesRequest entityBPFsRequest = new RetrieveProcessInstancesRequest

            {

                EntityId = Record.Id,

                EntityLogicalName = Record.LogicalName

            };

            RetrieveProcessInstancesResponse entityBPFsResponse = (RetrieveProcessInstancesResponse)Service.Execute(entityBPFsRequest);                                         

                                             int currentStagePosition = -1;

            RetrieveActivePathResponse pathResp = businessProcessFlow.GetAllStagesOfSelectedBPF(activeBPFId, activeStageId, ref currentStagePosition);

            Entity contact = Service.Retrieve(Record.LogicalName, Record.Id, new ColumnSet("fullname", "firstname", "lastname"));

                                           Dictionary<int, string> stageKeyValue = new Dictionary<int, string>();          

                                for (int i = 0; i < pathResp.ProcessStages.Entities.Count; i++)

            {

                stageKeyValue.Add(i, pathResp.ProcessStages.Entities[i].Attributes["stagename"].ToString());

            }

            if (entityBPFsResponse.Processes != null && entityBPFsResponse.Processes.Entities.Count > 0)

            {

                activeProcessInstance = entityBPFsResponse.Processes.Entities[0];

            }

  else if (hasScheduledImplantDate && currentStagePosition <= GetStagePosition(stageKeyValue, ActivationStage))

            {

                businessProcessFlow.UpdateProcessStage(GetStagePosition(stageKeyValue, FineTuneStage), processFlowName, activeBPFId, pathResp);

            }

            return activeProcessInstance;

        }

Get stage Position

public int GetStagePosition(Dictionary<int, string> stageKeyValue, string stageName)

        {

            return stageKeyValue.Where(x => x.Value == stageName).Select(y => y.Key).FirstOrDefault();

        }

Get all the stage of selected BPF 

  public RetrieveActivePathResponse GetAllStagesOfSelectedBPF(Guid activeBPFId, Guid activeStageId, ref int currentStagePosition)

        {

            RetrieveActivePathRequest pathReq = new RetrieveActivePathRequest

            {

                ProcessInstanceId = activeBPFId

            };

            RetrieveActivePathResponse pathResp = (RetrieveActivePathResponse)Service.Execute(pathReq);

            for (int i = 0; i < pathResp.ProcessStages.Entities.Count; i++)

            {

                if (pathResp.ProcessStages.Entities[i].Attributes["processstageid"].ToString() == activeStageId.ToString())

                {

                    currentStagePosition = i;

                }

            }

            return pathResp;

        }

  • Unit Test case for Business process flow

using FakeXrmEasy;
using FakeXrmEasy.FakeMessageExecutors;
using apy.Plugins.MarketingAutomation;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.Linq;
using static FakeXrmEasy.FakeMessageExecutors.AddListMembersListRequestExecutor;

namespace UnitTests
{
    [TestClass]
    public class businessprocessflowTest
    {


        Dictionary<string, int> processStagesNames = new Dictionary<string, int>(){
                                {"Stage1", 0 },
                                {"Stage2", 1 },
                                 {"Stage3", 2 },
                                {"Stage4", 3 },
                                 {"Stage5", 4 },
                                {"Stage6", 5 },
                                 {"Stage7", 6 },
                                {"Stage8", 7 },
                                 {"Stage9", 8 },
                                {"Stage10", 9 }
              };

        private List<Entity> _data;
        private XrmFakedContext _context;

        [TestInitialize]
        public void InitilizeDataAndContext()
        {

            _data = new List<Entity>();
            _context = new XrmFakedContext();
            _context.AddExecutionMock<OrganizationRequest>((req) =>
            {
                return new OrganizationResponse()
                {
                    Results =
                    {
                        { "LeadCollection", new EntityCollection() }
                    }
                };
            });
        }

        EntityReference processstage = null;

[TestMethod]
        public void addContactToAppointmentStageJourney_ActiveStageIs_AppointmentStage()
        {
            var contactId = Guid.NewGuid();
            var businessprocessflowinstanceid = Guid.NewGuid();
            var activestageid = Guid.NewGuid();
            var contact = new Entity("contact", contactId);
            contact.Attributes.Add("donotbulkemail", false);
            contact.Attributes.Add("firstname", "firstname");
            contact.Attributes.Add("statecode", new OptionSetValue(0));

            var keyValueSubscriptionListName = new Entity("apy_keyvaluepair", Guid.NewGuid());
            keyValueSubscriptionListName.Attributes.Add("apy_name", "SubscriptionList_PathToapy");
            keyValueSubscriptionListName.Attributes.Add("apy_value", diqSubscriptionList.Id.ToString());

            _data = InitializeBPFInstance(_data, contact, 4, _context, businessprocessflowinstanceid);

            var businessprocessflow = new Entity("apy_businessprocessflow", businessprocessflowinstanceid);
            businessprocessflow.Attributes.Add("businessprocessflowinstanceid", businessprocessflowinstanceid);
            businessprocessflow.Attributes.Add("bpf_contactid", contact.ToEntityReference());
            businessprocessflow.Attributes.Add("activestageid", processstage);
            _data.Add(businessprocessflow);
            _data.Add(keyValueSubscriptionListName);
            _data.Add(contact);
            _context.Initialize(_data);
            var ctx = _context.GetDefaultPluginContext();
            ctx.MessageName = "Create";
            ctx.InputParameters["Target"] = businessprocessflow;
            ctx.PostEntityImages["PostImage"] = businessprocessflow;
            ctx.Stage = 40;

            _context.ExecutePluginWith<Managebusinessprocessflow>(ctx);

            for (int i = 0; i < _data.Count; i++)
            {
                if (_data[i].LogicalName == "apy_businessprocessflow")
                {
                    var activeStageIdFromBPF = _context.CreateQuery("apy_businessprocessflow").Where(e => e.Id == _data[i].Id)
                                 .Select(e => e.GetAttributeValue<EntityReference>("activestageid")).FirstOrDefault();

                    var activeStageName = _context.CreateQuery("processstage").Where(e => e.Id == activeStageIdFromBPF.Id)
                            .Select(e => e.GetAttributeValue<string>("stagename")).FirstOrDefault();

                    Assert.AreEqual(activeStageName, "Appointment Stage", "BPF Stage is updated");
                }
            }
        }
        private List<Entity> InitializeBPFInstance(List<Entity> _data, Entity contact, int index, XrmFakedContext _context, Guid businessprocessflowinstanceid)
        {
            var workflowProcess = new Entity("workflow", Guid.NewGuid());
            workflowProcess.Attributes.Add("name", "Patient Flow");
            workflowProcess.Attributes.Add("uniquename", "apy_businessprocessflow");

            List<Entity> processStagesList = new List<Entity>();
            foreach (var bpfProcessStage in processStagesNames)
            {
                Entity processStage = new Entity("processstage", Guid.NewGuid());
                processStage.Attributes.Add("stagename", bpfProcessStage.Key);
                processStage.Attributes.Add("processid", workflowProcess.ToEntityReference());
                processStagesList.Add(processStage);
            }

            var bpfInstance = new Entity("apy_businessprocessflow", businessprocessflowinstanceid);
            bpfInstance.Attributes.Add("bpf_name", "Patient Flow");
            bpfInstance.Attributes.Add("processid", workflowProcess.ToEntityReference());
            bpfInstance.Attributes.Add("bpf_contactid", contact.ToEntityReference());
            bpfInstance.Attributes.Add("processstageid", processStagesList[index].Id);

            processstage = processStagesList[index].ToEntityReference();

            for (int i = 0; i < processStagesList.Count; i++)
            {
                _data.Add(processStagesList[i]);
            }
            _data.Add(workflowProcess);
            _data.Add(bpfInstance);

            RetrieveProcessInstancesRequest entityBPFsRequest = new RetrieveProcessInstancesRequest
            {
                EntityId = contact.Id,
                EntityLogicalName = contact.LogicalName
            };

            _context.AddExecutionMock<RetrieveProcessInstancesRequest>((req) =>
            {
                return new RetrieveProcessInstancesResponse()
                {
                    Results = new ParameterCollection()
                    {
                        { "Processes", new EntityCollection() {Entities = {bpfInstance} } }
                    }
                };
            });

            RetrieveActivePathRequest pathReq = new RetrieveActivePathRequest
            {
                ProcessInstanceId = bpfInstance.Id
            };

            _context.AddExecutionMock<RetrieveActivePathRequest>((req) =>
            {
                return new RetrieveActivePathResponse()
                {
                    Results = new ParameterCollection()
                    {
                        { "ProcessStages", new EntityCollection(processStagesList) }
                    }
                };
            });

            return _data;
        }
}
}

Comments

Popular posts from this blog

Basic Plugin Code in D365 using C#

CURD (Create, Update, Retrieve and Delete) Operation in D365 using Power Shell Script

Meta Data Using WebApiRequest