Friday, September 30, 2016

Tuesday, September 27, 2016

Those who come more from an engineering background might be
familiar with the concept of state machines. This article explains an easy
implementation in CRM.

State machines are basically a way to model an object’s life
cycle, including the different states or statuses it can have along with the
transitions that are possible to go from one state to another. In an example
below we have an airline ticket and how the status of the ticket can transition
in different scenarios:

The key about state machines is that it restricts invalid
state changes. For example, you cannot go from “Used” to “paid” because once
the ticket is used, it can no longer change. In some sate machines you might
also want to specify which states are read-only as opposed to “editable” and
you can even define additional conditions such as having the correct privilege
(e.g. only a manager is able to issue a refund).

Now you can apply this concept of state machines to CRM
entities. Although these state machines can be quite complex in real life, in
CRM entities most of the times this is not too complex. If you have a simple
state machine to model, there is the feature in CRM (often overlooked) called
status transitions.

You can actually define which status can lead to which
status. Below is the CRM implementation of the state machine of my example:

Now in the CRM form you will notice that it will remove the
invalid state transitions from the available status reasons. For example, if my
record is on status reason “Reserved” I cannot change it to “Ticketed” because
I need to mark it as paid first:

If I had not defined a transition from the current status
reason to an “Inactive” state then I am not able to de-activate the record and
change the state to “Inactive”:

Also note that the transition validations are valid even
outside the scope of CRM forms. If you try to perform an invalid status update
from workflow/plugin/SDK you would get this error:

Monday, September 26, 2016

When you configure an SLA item in CRM, you have the option
to specify the “Failure” and “Warning” times as a duration.

The format of these fields Is the same as any other CRM
duration field, but what does it really mean? For example, if you set it to 10
days, is it 10 calendar days? Is it 10 business days? You might be surprised it
is neither!

First let’s backtrack a little bit and look at the SLA definition.
At the SLA level you can define “Business Hours” which captures the business
days of the week, business hours of the day as well as any holidays during
which an SLA should not apply. Let’s see what happens to your 10 day SLA
depending on your business hour configuration in different scenarios. For
simplicity I will assume you do not have “pause” when the record is on-hold.

1.No Business Hours

If you leave this “Business Hours” field blank, then the
system will assume 24x7 and therefore, the “Failure” and “Warning” times you
set are simply calendar days, it will be simply a duration which is quite straight-forward.
Therefore, when you create the record, you will have exactly 10 days (240
hours) before the SLA fails.

2.Business Hours Configured (Work Days only)

In this case you configure your Business Hours only for the
work days (e.g. Mon-Fri) but you leave the work hours as 24-hour (i.e. your
business day has 24 hours):

In this case, what happens to your 10-day SLA is that it
becomes a 10 business day SLA. Therefore, when you create a case, you will have
14 calendar days before the SLA fails because the weekend days will not be
counted.

3.Business Hours Configured (Including Work Hours)

Now this is where things get really messy unexpectedly.
Imagine you configure your business hours to be Mon-Fri from 09:00 to 17:00 so
that you have 8 working hours per business day. What happens to the 10-day SLA
failure?

I create a case and to my surprise, the system gives me
almost 42 calendar days to resolve the case before failing SLA:

This seems really random. What happens here is that the “Failure”
time of 10 days is actually a duration
(not the actual count of calendar or business days). In other words, the SLA
will fail after 240 “business hours”. Because I only have 8 business hours per
day then this means 30 business days and because of the weekends it ends up
giving me almost 42 days. This is definitely not what I would expected when I
configured by failure time to 10 days. Therefore, I just decided to leave my
work hours as 12am-12am (24 hours) and then I would fall under #2 above in
which I get 10 business days for resolving the case as I expected.

Adding holidays to your calendar works similar to the work
days, it will just exclude the entire day from the count. Do not expect the
timer to “pause” when you are outside of working hours because the timer has
actually been increased to account for the time that you will have outside of
business hours, so the timer countdown is always real time (duration) and can
only pause when you configure pause for “on-hold” status.

I hope you find this useful, I think unless you have really
fast SLAs (defined in hours or minutes) it almost makes no sense to think about
configuring working hours. My conclusion is that if you SLAs which are defined
in number of days you most likely should leave the work hours to 24 hours in
order for the timer to make sense. Alternatively if you keep working hours you would need to define your SLA items as a function of business hours, so for my example, if the business hours are from 9am to 5pm then that means that for a 10 business day SLA I would need to define my failure time as 10*(number of business hours per day) = 80 hours. The small caveat here is that if you change your business hours then you need to update all your SLA items as the above formula could have changed. In either case you should still configure your workdays to
exclude weekends if desired though.

Tuesday, September 20, 2016

The alternative keys feature introduced in CRM 2015 U1 turns
out to be extremely useful, especially for integration scenrios in which you
might want to keep a record of an “external key” from another system or you
want to enforce duplicate prevention (for real).

In some cases you would like to make the alternative key
contain an OptionSet type of field. For example, I wanted to define an
alternative key based on “Contact Type” and “Email” so that CRM could check
that no contacts of the same type with the same email address.

However, when you try to define the key on the contact
entity I could no select my “Contact Type” field as part of the key:

So I can see a number of fields and realize that only fields
of numeric or text value are available to pick. After some research I found
that it is documented in the SDK that only
these fields can be added to a key:

So no luck! The only option you have is to create a hidden
text field which will hold the value of your OptionSet but as text and then add
that field to your key. I try to define this field as a calculated fiueld but
then again, calculated fields cannot be added to alternate keys (this is by
experiment, not by documentation). Therefore, I had to define a business rule
to populate that field based on the options of your OptionSet. In my example,
my OptionSet has options “Nurse” and “Doctor” so I create the business rule as
follows (note you should set “Scope” to “Entity”)

Now I am able to add the calculated field to my key:

After this is done, I can test to make sure I can create
both a nurse and a doctor with the same email but if I try to create 2 nurses
with the same email I get the error:

So this works. It is not the most elegant solution since you
are essentially duplicating data. However, if you must include an OptionSet
field as part of a key this could be an easy way to enforce it :-)

Monday, September 19, 2016

An old CRM problem is that sometimes when you define N:N
relationships between 2 entities, you find this relationship not available for
search in Advanced Find. Don’t worry about it this article will give you the
work-around you need.

Consider a scenario in which I have accounts and I have
industry entities. An account can be in multiple industries and an industry can
have multiple accounts; therefore I have defined an N:N Relationship between
Account and Industry entity:

Now as part of the requirements I want to enable users to be
able to build Advanced Find queries based on this relationship. For example:

·Find all accounts in the “Banking” industry

·List the accounts with industry code FIN002

So you might think this is was easy to do with Advanced
find, however, you might not be able to find this relationship when looking for
the related records under account in Advanced Find:

So I went back to the N:N relationship definition to see if
I did something wrong. I found that there is a checkbox called “Searchable” and
was already set to “Yes”:

So why I cannot search based on this relationship? The
answer is tricky. The relationship actually appears in advanced find whenever you
set the “Display Option” to “Use Plural Name” or “Custom Label” on the side of
the relationship with you want to show under the “related” section in advanced
find. In my example, I would need to set the “Display Option” to “Plural Name”
on the Industry side of the relationship so that I can perform the queries such
as retrieving all accounts in a given industry:

After I do this and publish all customizations, the “Industry”
entity magically appears in advanced find allowing me to perform my query:

And voila. Now the only question I still have is: What the
heck is that “Searchable” checkbox on the relationship for? Feel free to comment
if you know the answer J

About me

I used to be part of the CRM product team at Microsoft and I recently joined the Avanade Canada team as a consultant in the CRM Service Line, I developed a sort of delight in seeing how Dynamics CRM is evolving as a platform (xRM) and how its feature set has matured to be able to model and address plenty of business scenarios beyond Customer Relationship Management. I was recently given the Microsoft MVP award in Dynamics CRM and I am really excited to be part of the program and continue contributing to the CRM community.