Dynamics 365 has introduced the new feature of Concurrent
Business Process Flows. Here is a couple of good articles on that:
Even though this is called a feature I have found it as
quite troublesome so far. It’s true that in some organizations different
departments would need to run different processes on the same entity in which
case this makes sense. But how if we want to make sure that only one BPF should
be active at a time for a record? Right now we can’t do it without writing some
fair amount of coding. Ideally Microsoft should have given the option to turn
on or off the concurrent business process flows either at Organisation level or
Entity level.
One of my clients had this requirement of having multiple
BPFs for an entity but only one should be active at a time; i.e. everybody in
the business unit should follow that process.
If user A has started the BPF1 and let’s say user B come and
switch the Process to BPF2.
As Alex had mentioned here
I used a plugin to achieve this. Inside the plugin I get the GUIDs of all the
users in the Business Unit, then create the IOrganizationService object using
each User GUID
OrganizationService UserService =
serviceFactory.CreateOrganizationService(userid);
and execute a SetProcessRequest with that
IOrganizationService instance to set the business process flow in the backend.
SetProcessRequest req = new SetProcessRequest();
req.Target = new EntityReference(“EntityLogicalName”, recordGuid);
req.NewProcess = new EntityReference("process", GuidOfTHeBusinessProcessFlow);
var resp = UserService.Execute(req);
This way you can make sure the same Business Process Flow is
used by all users.
But please note that each user should have write privileges
on the entity to execute the SetProcessRequest. If not it throws an exception.
So if all the users does not have write privileges on the entity you can
provide the privilege temporarily dynamically in the plugin itself and once the code is executed you can revert.
UpdateRole(serviceContext,
service, "Security Role name", PrivilegeDepth.Local);
public void UpdateRole(XrmServiceContext
serviceContext, IOrganizationService service, string roleName, PrivilegeDepth depth)
{
var securityRole =
serviceContext.RoleSet.Where(ro => ro.Name == roleName).FirstOrDefault();
var roleRequest = new RetrieveRolePrivilegesRoleRequest { RoleId = securityRole.Id };
var roleResponse =
service.Execute(roleRequest);
var privilegeQuery = new QueryExpression {
EntityName = "privilege", ColumnSet = new ColumnSet(true) };
var privileges =
service.RetrieveMultiple(privilegeQuery);
var entityPrivileges =
privileges.Entities.ToList()
.Where(p
=> p.GetAttributeValue<string>("name").ToLower()
.Contains("entityLogicalName"))
.ToList();
foreach (var priv in entityPrivileges)
{
if (priv.Attributes.Contains("name")
&& priv.Attributes["name"].ToString() == "prvWrite"+ "entityLogicalName")
{
AddPrivilegesRoleRequest addPrivilegesRequest = new AddPrivilegesRoleRequest
{
RoleId = securityRole.Id,
Privileges = new[]
{
new RolePrivilege
{
PrivilegeId =
priv.Id,
Depth=depth
}
}
};
service.Execute(addPrivilegesRequest);
break;
}
}
}