Business Rules in CRM

What are Business Rules?

–          In CRM 2013, the Business Rules are introduced to allow end users to apply basic form logic without writing JavaScript in CRM

–          It provides simple declarative interface to implement


What things are possible using Business Rules?

–          Hide/Show fields on the form

–          Set field values

–          Enable/Disable fields

–          Set field requirements

–          Validate data and show error messages


4 ways to configure Business Rules

–          Solution -> Entity -> Business Rules

4.1

–          Solution -> Entity -> Field

4.2

–          Form Editor

4.3

–          Form Editor -> Field (Field Properties) -> Business Rules

4.4


How Business Rules work?

–          Business rules are applied based on the scope of the business rules selected during creation. Only activated business rules will be applied on the respective entity forms.

–          By default the scope is set to All Forms. To make the business rule available to specific form, you need to change the scope of the business rule.

5

–          In below order the logic is applied to the form field:

1. System Scripts

2. Custom JavaScript

3. Business Rules

Note: If there are multiple Business Rules applied on single field, then the rule in the order in which rules are activated. Hence if you want any business rule to be applied first, then you need to activate that rule at the last.


How to edit existing Business Rule?

To edit existing Business Rule, first deactivate the rule and then edit. To apply the updated logic, you will need to activate the rule again.


Advantages

–          Allows end user/ CRM customizer to apply logic quickly without writing any code

–          Enabling and Disabling of logic is simple

–          Easy to test the written logic by Preview option on the Form


Limitations

–          No complex logic is supported.

–          Business Rules does not run on Form Save event. They only run on Form Load and Field Changes.

–          Custom JavaScript event on the ‘OnChange’ event of field will not work if you set field value using Business Rules.

–          The rule will not run if the field mentioned in the rule is not available on the form. It will not throw an error. Hence user will not come to know about the error.

–          Business Rules does not work on Tabs/Sections/Sub Grids etc.

–          Does not allow else condition. Hence to apply If Else logic, you need to create separate business rules for each condition.

–          Only AND logic can be applied in the Business Rule. No OR logic.


How to setup logic in Business Rules?

Business Rules are divided into 3 sections:

–          Conditions

a. Conditions can be checked on fields only

b. Below operators are available

6

–          Actions

Actions are the tasks that can be performed by the Business Rules. Actions will be performed only if all conditions are true.

o   Show error message: Used to show any custom error message on any field based on the condition. This does not allow the form to save.

o   Set field value: Allows to set value to any field.

o   Set Business Required: Allows to set any field either required or not required.

o   Set visibility: Allows to show/hide the field.

o   Lock or Unlock field: Allows to make field read-only or editable.

–          Description (Optional)

Gives description of Business Rule. This is optional and does not appear anywhere else.


Examples

–          Assumptions:

I have custom entity named “Business Rules Demo” with below fields:

– Field 1 – Two Options

– Field 2 – Option Set { A, B, C, D }

– Field 3 – Single Line of Text

– Field 4 – Single Line of Text

– Field 5 – Single Line of Text

  1. If Field 1 = True

Then

Hide Field 3

Make Field 4 Required

Set Field 5 to ‘Hello’

Disable Field 2

Show error message on Field 1 as ‘Field 3 is hidden’

Else

Show Field 3

Make Field 4 not required

Set Field 5 to ‘Bye’

Enable Field 2

For this, we need to create 2 business rules; 1 for If part and other for Else part as below:

7

8

Note: To copy the business rule, open business rule and use ‘Save As’ option. This will create copy of the business rule.

Custom error message will be shown as below:

9

  1. To check if any field is blank or not, use Contains Data and Does Not Contain Data operator in the condition.

References

http://technet.microsoft.com/en-us/library/dn531086(v=crm.6).aspx

 

How to fetch related CRM entity records using Link Entities in single call?

Problem Statement:

We have multiple related entities in CRM. We want to fetch data from those entities by performing join operations on their Lookup fields.

Solutions:

  1. Fetch records from all the required entities and use LINQ or Loops to perform joins by checking conditions on lookup fields.

Disadvantages:

  1. Makes multiple calls to CRM which impacts on performance of an application
  2. We fetch unnecessary data as we don’t perform join operation after all entities’ data is fetched which also impacts on performance of an application
  3. Use Link Entity class to apply join conditions on Lookup fields and fetch data from different entities in single call.

Advantages:

  1. Filters data before fetching the data to get only required records.
  2. Call to the CRM is made only once which improves performance.

LinkEntity Class:

  1. Use of LinkEntity class:

LinkEntity allows to connect multiple related entities in CRM to perform Join Operation. We can add as many LinkEntity objects in QueryExpression to perform various Join Operation and filter the data while fetching. For more information visit: http://msdn.microsoft.com/en-us/library/bb957073.aspx

  1. How to use LinkEntity class?

In the examples given below, I have used the constructors of LinkEntity class to perform Join Operations on multiple related entities.

For more information visit: http://msdn.microsoft.com/en-us/library/bb957073.aspx

Examples:

Note: In this article, I am going to explain only approach 2 i.e. how to use Link Entities to fetch data from related CRM entities.

Assumptions:

We have 5 CRM entities and are related as shown below.

Example 1: Fetch All Active Employee records and their companies (Simple Join)

  1. How to perform Join Operation?
FilterExpression employeeFilter = newFilterExpression(LogicalOperator.And);employeeFilter.AddCondition("statecode", ConditionOperator.Equal, 0);FilterExpression companyFilter = newFilterExpression(LogicalOperator.And);companyFilter.AddCondition("statecode", ConditionOperator.Equal, 0);QueryExpression expression = newQueryExpression()

{

EntityName = "new_employee",

ColumnSet = newColumnSet(newString[] { "employeename", "employeeid" }),

Criteria = employeeFilter

};

LinkEntity leCompany = newLinkEntity("new_employee", "new_company", "new_empcompanyid", "new_companyid", JoinOperator.LeftOuter);

leCompany.EntityAlias = "company";

leCompany.Columns.AddColumns("companyname", "companyaddress");

leCompany.LinkCriteria = companyFilter;

expression.LinkEntities.Add(leCompany);

EntityCollection results =  DAL.RetrieveMultiple(expression);
  1. How to read fields from each records?
String employeename, companyname, companyaddress;foreach (Entity record in results.Entities){employeename = record.Contains(“employeename”) ? Convert.ToString(record[“employeename”]) : “”;companyaddress = record.Contains(“company.companyaddress”) ? Convert.ToString(((AliasedValue)record[“company.companyaddress”]).Value) : “”;companyname = record.Contains(“company.companyname”) ? Convert.ToString(((AliasedValue)record[“company.companyname”]).Value) : “”;}
  1. Explanation:

In this example, I have simply performed Left Join on Company and Employee entity and fetched Employee and their associated companies in the result set. I have also shown that how to retrieve related entities’ fields from the result set.

Example 2: Fetch employees with their company data. Fetch only employees who are in ‘Accounts’ department (Multiple Join operations on same entity)

  1. How to perform Join Operation?
FilterExpression employeeFilter = newFilterExpression(LogicalOperator.And);employeeFilter.AddCondition(“statecode”, ConditionOperator.Equal, 0);FilterExpression companyFilter = newFilterExpression(LogicalOperator.And);companyFilter.AddCondition(“statecode”, ConditionOperator.Equal, 0);FilterExpression departmentFilter = newFilterExpression(LogicalOperator.And);

departmentFilter.AddCondition(“statecode”, ConditionOperator.Equal, 0);

departmentFilter.AddCondition(“new_departmentname”, ConditionOperator.Equal, “Accounts”);

QueryExpression expression = newQueryExpression()

{

EntityName = “new_employee”,

ColumnSet = newColumnSet(newString[] { “employeename”, “employeeid” }),

Criteria = employeeFilter

};

LinkEntity leCompany = newLinkEntity(“new_employee”, “new_company”, “new_empcompanyid”, “new_companyid”, JoinOperator.LeftOuter);

leCompany.EntityAlias = “company”;

leCompany.Columns.AddColumns(“companyname”, “companyaddress”);

leCompany.LinkCriteria = companyFilter;

LinkEntity leDepartment = newLinkEntity(“new_employee”, “new_department”, “new_departmentid”, “new_departmentid”, JoinOperator.Inner);

leDepartment.LinkCriteria = departmentFilter;

leDepartment.EntityAlias = “department”;

leDepartment.Columns.AddColumns(“departmentname”);

expression.LinkEntities.Add(leCompany);

expression.LinkEntities.Add(leDepartment);

EntityCollection results = DAL.RetrieveMultiple(expression);

  1. Explanation:

This is similar example as Example 1, but in this I have shown how to perform multiple join operations on the same entity. Here the join is performed between Company and Employee (Left Join) and Employee and Department (Inner Join). Also shown how to restrict data by applying filters in the related entities.

Example 3: Fetch employees, their company information and the branch of the company (Multiple Join Operations on different entities).

  1. How to perform Join Operation?
FilterExpression employeeFilter = newFilterExpression(LogicalOperator.And);employeeFilter.AddCondition(“statecode”, ConditionOperator.Equal, 0);FilterExpression companyFilter = newFilterExpression(LogicalOperator.And);companyFilter.AddCondition(“statecode”, ConditionOperator.Equal, 0);FilterExpression branchFilter = newFilterExpression(LogicalOperator.And);

branchFilter.AddCondition(“statecode”, ConditionOperator.Equal, 0);

QueryExpression expression = newQueryExpression()

{

EntityName = “new_employee”,

ColumnSet = newColumnSet(newString[] { “employeename”, “employeeid” }),

Criteria = employeeFilter

};

LinkEntity leCompany = newLinkEntity(“new_employee”, “new_company”, “new_empcompanyid”, “new_companyid”, JoinOperator.LeftOuter);

leCompany.EntityAlias = “company”;

leCompany.Columns.AddColumns(“companyname”, “companyaddress”);

leCompany.LinkCriteria = companyFilter;

LinkEntity leBranch = leCompany.AddLink(“new_branch”, “new_branchid”, “new_branchid”, JoinOperator.Inner);

leBranch.LinkCriteria = branchFilter;

leBranch.EntityAlias = “branch”;

leBranch.Columns.AddColumns(“branchname”);

expression.LinkEntities.Add(leCompany);

EntityCollection results = DAL.RetrieveMultiple(expression);

  1. How to read fields from each record?
String employeename, companyname, companyaddress, branchname;foreach (Entity record in results.Entities){employeename = record.Contains(“employeename”) ?Convert.ToString(record[“employeename”]) : “”;companyaddress = record.Contains(“company.companyaddress”) ? Convert.ToString(((AliasedValue)record[“company.companyaddress”]).Value) : “”;companyname = record.Contains(“company.companyname”) ? Convert.ToString(((AliasedValue)record[“company.companyname”]).Value) : “”;branchname = record.Contains(“branch.branchname”) ? Convert.ToString(((AliasedValue)record[“branch.branchname”]).Value) : “”;

}

  1. Explanation:

In this example, I have shown how to perform multiple joins on different entities. Here the join is performed between Employee and Company entities. Another join operation is performed between Company and Branch entities.