microsoft-crm-2016

Business Process Flow Disappears after December Update in Microsoft Dynamics CRM

Microsoft Dynamics CRM is now part of Microsoft Dynamics 365 business solution. For on-premise customers, your CRM will be rebranded with December Update. December Update also brought some new cool function which will improve users and administrators productivity (like an editable grid). As a part of these changes, Microsoft created a completely new editor for Business Process Flows. I really appreciate two things:

  • It is much easier to edit complicated Business Process Flows.
  • You can run specific Workflow for each flow stage.

However, we experienced an error after an update of our development environment. Some of our flows were somehow damaged during the update. After the update, the flows were not visible on entities forms. When I run the “Switch Process” command, I saw an error. I dug in logs to get more information about the error, but I found only Unexpected Exception messages. It was also impossible to deactivate the flows or to export them as a part of a solution. Finally, I was able to run the “Save as” command to create a copy of the flows. I set one of the copies as the highest priority process (using the “Order Process Flow” command). Then a new record for the entity was created successfully with the flow active on its form. Unfortunately, I was not a final solution because it did not solve the problem for already existing records.

Dynamics CRM Power Pane

Dynamics CRM Power Pane is a very useful tool for Dynamics CRM. This tool is distributed as an extension for Google Chrome and you can download it in Chrome Store. (Google Chrome is one of officially supported browsers. I have been using Google Chrome with Dynamics CRM 2016 on premise for about 7 months and in my experience, it works perfectly.) Dynamics CRM Power Pane has several interesting and useful function.

It is very easy to use. After adding the extension into your Chrome you will see a new orange lightning icon in the left up corner. After clicking on the icon, you will see a menu like on the picture.

Business manager from a different business unit in Microsoft CRM

Security management is very nice and straightforward in Microsoft Dynamics CRM 2016. In a previous post I wrote about a security report which allows you to see permissions of all users at one place. However I found out one issue which can be little tricky to solve.

Our customer decided to split one department into two departments. The original department (let’s call it Old1) still existed. Customer created two additional departments inside it (let’s call them New1 and New2). So we have created new business units New1 and New2 and we set Old1 and the Parent Business for both of them. We changed Business Units for Users to either New1 or New2. Finally we filled in Manager fields for both the Business Units. We assigned a special security roles to the both managers. This role allows them to see all records created by all persons from the same business unit for one specific entity. Everything looked nice.

But we received an incident that the manager of one of the departments doesn’t see a record of his subsidiary employee. I checked the Business Unit entity. The manager was set as Manager at New1. However, the subsidiary employee was set to New2. I tried to change the Business Unit of the employee to New1 and then to change the manager. But then I saw an error:

The user is not in parent user's business hierarchy.

So the problem was at the Business Unit Manager setting. I fixed it by setting the manager as the New2 Business Unit Manager.

Conclusion: CRM doesn’t check the Business Unit Manager field. You can set there an user from any business unit. However, if you make a mistake you will face similar incident.

Dynamics CRM Security Report

Microsoft Dynamics CRM has a very sophisticated security model. You can create security roles and assign permissions to entities for these roles. Then you assign security roles to teams or to a single user. All the possibilities give you a lot of power to control security permission for your users. However, it can get quite complicated to check permission for a single selected users. To do it, you must open all user’s security roles and then you have to check security roles of all user’s teams. And you have to compare all the roles and select the highest level for each access right and for each entity. This can be a time consuming task. It would be nice to have all the information available in a single report. This report could be for example used for external security audits or regular internal audit.

If you are using Dynamics CRM On-Premise, you can check the permission in Dynamics CRM database. I have created a database view which read user’s permission assigned to user and to all user’s teams. You can see the SQL code below.

SELECT BU.Name AS BusinessUnit,
	U.LastName + ' ' + U.FirstName AS FullName,
	--PRIV.[Name],
	isnull(EN.OriginalLocalizedCollectionName, EN.Name) AS EntityName,
	R.Name AS RoleName,
	CASE PRIV.AccessRight
		WHEN 1 THEN '2 Read'
		WHEN 2 THEN '3 Write'
		WHEN 4 THEN '5 Append'
		WHEN 16 THEN '6 AppendTo'
		WHEN 32 THEN '1 Create'
		WHEN 65536 THEN '4 Delete'
		WHEN 262144 THEN '7 Share'
		WHEN 524288 THEN '8 Assign'
		ELSE PRIV.Name
	END AS AccessRight,
	MAX(P.PrivilegeDepthMask) as PriviledgeDepthMask
FROM [AIMTEC_MSCRM].[dbo].[Role] R WITH (NOLOCK)
	INNER JOIN [AIMTEC_MSCRM].[dbo].[RolePrivileges] P WITH (NOLOCK)
        ON P.[RoleId]=R.ParentRootRoleId
	INNER JOIN [AIMTEC_MSCRM].[dbo].[PrivilegeObjectTypeCodes] PTOTC WITH (NOLOCK)
		ON PTOTC.PrivilegeId = P.PrivilegeId
	INNER JOIN [AIMTEC_MSCRM].[dbo].[EntityView] EN  WITH (NOLOCK)
		ON EN.ObjectTypeCode = PTOTC.ObjectTypeCode
	INNER JOIN [AIMTEC_MSCRM].[dbo].[Privilege] PRIV WITH (NOLOCK)
        ON P.[PrivilegeId]=PRIV.[PrivilegeId]
	INNER JOIN [AIMTEC_MSCRM].[dbo].[FilteredPrivilege] FPRIV WITH(NOLOCK)
		ON PRIV.PrivilegeId = FPRIV.privilegeid
	INNER JOIN [AIMTEC_MSCRM].[dbo].[FilteredTeamRoles] TR WITH (NOLOCK)
		ON R.RoleId = TR.roleid
	INNER JOIN [AIMTEC_MSCRM].[dbo].[Team] TEAM  WITH (NOLOCK)
		ON TEAM.TeamId = TR.teamid
	INNER JOIN [AIMTEC_MSCRM].[dbo].[FilteredTeamMembership] TEME WITH (NOLOCK)
		ON TEAM.TeamId = TEME.teamid
	INNER JOIN [AIMTEC_MSCRM].[dbo].[SystemUser] U WITH(NOLOCK)
		ON U.SystemUserId = TEME.systemuserid
	INNER JOIN [AIMTEC_MSCRM].[dbo].[BusinessUnit] BU WITH(NOLOCK)
		ON BU.BusinessUnitId = U.BusinessUnitId
--WHERE R.[RoleId]=R.[ParentRootRoleId]
WHERE U.IsDisabled = 0
group by  U.LastName + ' ' + U.FirstName,
	isnull(EN.OriginalLocalizedCollectionName, EN.Name),
	CASE PRIV.AccessRight
		WHEN 1 THEN '2 Read'
		WHEN 2 THEN '3 Write'
		WHEN 4 THEN '5 Append'
		WHEN 16 THEN '6 AppendTo'
		WHEN 32 THEN '1 Create'
		WHEN 65536 THEN '4 Delete'
		WHEN 262144 THEN '7 Share'
		WHEN 524288 THEN '8 Assign'
		ELSE PRIV.Name
	END,
	BU.Name,
	R.Name

UNION ALL

SELECT BU.Name AS BusinessUnit,
	U.LastName + ' ' + U.FirstName AS FullName,
	isnull(EN.OriginalLocalizedCollectionName, EN.Name) AS EntityName,
	R.Name AS RoleName,
	CASE PRIV.AccessRight
		WHEN 1 THEN '2 Read'
		WHEN 2 THEN '3 Write'
		WHEN 4 THEN '5 Append'
		WHEN 16 THEN '6 AppendTo'
		WHEN 32 THEN '1 Create'
		WHEN 65536 THEN '4 Delete'
		WHEN 262144 THEN '7 Share'
		WHEN 524288 THEN '8 Assign'
		ELSE PRIV.Name
	END AS AccessRight,
	MAX(P.PrivilegeDepthMask) as PriviledgeDepthMask
FROM [AIMTEC_MSCRM].[dbo].[SystemUser] U WITH(NOLOCK)
	INNER JOIN [AIMTEC_MSCRM].[dbo].[FilteredSystemUserRoles] FSUR WITH(NOLOCK)
		ON U.SystemUserId = FSUR.systemuserid
	INNER JOIN [AIMTEC_MSCRM].[dbo].[Role] R WITH (NOLOCK)
		ON R.RoleId = FSUR.roleid
	INNER JOIN [AIMTEC_MSCRM].[dbo].[RolePrivileges] P WITH (NOLOCK)
        ON P.[RoleId]=R.ParentRootRoleId
	INNER JOIN [AIMTEC_MSCRM].[dbo].[PrivilegeObjectTypeCodes] PTOTC WITH (NOLOCK)
		ON PTOTC.PrivilegeId = P.PrivilegeId
	INNER JOIN [AIMTEC_MSCRM].[dbo].[EntityView] EN  WITH (NOLOCK)
		ON EN.ObjectTypeCode = PTOTC.ObjectTypeCode
	INNER JOIN [AIMTEC_MSCRM].[dbo].[Privilege] PRIV WITH (NOLOCK)
        ON P.[PrivilegeId]=PRIV.[PrivilegeId]
	INNER JOIN [AIMTEC_MSCRM].[dbo].[BusinessUnit] BU WITH(NOLOCK)
		ON BU.BusinessUnitId = U.BusinessUnitId
WHERE U.IsDisabled = 0
group by  U.LastName + ' ' + U.FirstName,
	isnull(EN.OriginalLocalizedCollectionName, EN.Name),
	CASE PRIV.AccessRight
		WHEN 1 THEN '2 Read'
		WHEN 2 THEN '3 Write'
		WHEN 4 THEN '5 Append'
		WHEN 16 THEN '6 AppendTo'
		WHEN 32 THEN '1 Create'
		WHEN 65536 THEN '4 Delete'
		WHEN 262144 THEN '7 Share'
		WHEN 524288 THEN '8 Assign'
		ELSE PRIV.Name
	END,
	BU.Name,
	R.Name

I used Excel pivot table for the security group. I select users (grouped by business department) for a row dimension and entities for a column dimension. The values are maximums of the PriviledgeDepthMask value. Don’t forget to select the maximum function because user have the highest assigned permission. I also added conditional formatting which is consistent with CRM security settings interface.

a0003-001

Here you can see that the User 13 has higher security permissions than other users. So this user account probably belongs to some power user to department manager.