How to customise the SLA in MS CRM
How to Read Orgnisation Business Closure
Today we are going to learn how to customise your SLA.
Although MS has provided Enhanced SLA which can full-fill most of the business requirements but when requirements are so complicate that can't be handled using system Enhanced SLA, developing a custom SLA functionality is the only solution.
In this post we'll not discuss anything regarding CRM System SLA because there are many posts out there on the internet for the same and if you are here reading this post, means you want your SLA to work beyond CRM System SLA.
Here i have created a hypothetical scenario on the basis of which your customer might want the SLA to run.
1.
a) As a training scenario, i have considered that for your customer wants different SLA hours for cases assigned to different teams which are working in different shifts (here we'll cal,l it SLA window).
b) Lets suppose there are 20 different teams in an organisation for which different SLA needs to be set up, then such custom SLA solution are suitable.
b) We will take care of Organisation Business Closure as well in calculating SLA.
2. I have created a Custom entity named SLA Configurator in my organisation with following fields:
Field Name | Data Type | Validation | Purpose |
Name | Text | NA | A name for SLA record |
SLA window Start | whole number | Range 0-24 | Defines
SLA start time or shift Start time |
SLA window End | whole number | Range 0-24 | Defines
SLA end time or shift end time |
Team | Lookup | NA | Team
for which this SLA needs to be implemented |
Resolution SLA in hrs | whole number | Range as required | Total No of SLA
hrs for this scenario |
3.
a) Now what we need to do is that on creation of case, needs to get the team for which the case has been created, and fetch the proper SLA configuration records according to the team.
b) We'll write this whole logic in a plugin which will fire on create of Case. I assume that you will be able to do that.
c) Below is the function to which we'll pass SLA Configuration Record and organisation service object as parameters. It'll return you the date to which your Resolve by needs to be set.
Calculation are as follows:
- A Case is created for Team1
- SLA Configuration Master have following data for Team1
Let's say case created on 31 May,2016 01:00PM
Case assigned to Team1
SLA hrs for Team1 : 24
SLA start window: 10 AM
SLA End Window: 07 PM
Business Closure have holiday on 1st June,2016
Then Resolve by:
31st May,2016 : 06 hrs (1 PM- 7 PM)
1st June : Holiday in Business Closure
2nd June : 09 hrs (10 AM-07 PM)
3rd June : 09 hrs (10 AM-07 PM)
Total Working hrs : 24 hrs
Resolve By : 03 June,2016 07:00PM
Below is the code snippet:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static DateTime CalculateSla(Entity SLAConfigurator, IOrganizationService service)
{
int workstarttime = 0;
int workendtime = 24;
if (SLAConfigurator.Contains("new_slastartwindow") && SLAConfigurator.Contains("new_slaendwindow"))
{
int start = SLAConfigurator.GetAttributeValue<int>("new_slastartwindow");
int end = SLAConfigurator.GetAttributeValue<int>("new_slaendwindow");
if (end > start)
{
workstarttime = start;
workendtime = end;
}
}
int SLAInMin = 600; //Default Value
if(SLAConfigurator.Contains("new_resolvesla"))
SLAInMin = SLAConfigurator.GetAttributeValue<int>("new_resolvesla") * 60;
DateTime tempdate = DateTime.UtcNow.ToLocalTime();
while (SLAInMin > 0)
{
if (tempdate.Hour >= workstarttime && tempdate.Hour < workendtime && lookinbusinessclosure(tempdate, service))
{
tempdate = tempdate.AddMinutes(1);
SLAInMin--;
}
else
{
while (!(tempdate.Hour >= workstarttime && tempdate.Hour < workendtime && lookinbusinessclosure(tempdate, service)))
{
tempdate = tempdate.AddMinutes(1);
}
}
}
return tempdate;
}
#region businessclosure
private static IEnumerable<Entity> GetBusinessClosureCalendarRules(IOrganizationService service)
{
// Get Organization Business Closure Calendar Id
Guid orgId = ((WhoAmIResponse)service.Execute(new WhoAmIRequest())).OrganizationId;
var organization = service.Retrieve("organization", orgId, new ColumnSet("businessclosurecalendarid"));
var query = new QueryExpression("calendar")
{
ColumnSet = new ColumnSet(true),
Criteria = new FilterExpression()
};
// Add condition to get Get Calander where CalanderId is equal to Organization's businessclosurecalendarid
query.Criteria.AddCondition(new ConditionExpression("calendarid", ConditionOperator.Equal, organization["businessclosurecalendarid"].ToString()));
// Get Calendar
var businessClosureCalendar = service.RetrieveMultiple(query).Entities[0];
// Return the Calendar rules
return businessClosureCalendar != null ? businessClosureCalendar.GetAttributeValue<EntityCollection>("calendarrules").Entities : null;
}
public static bool lookinbusinessclosure(DateTime tempdate, IOrganizationService service)
{
IEnumerable<Entity> businessClosures = null; //Define it static globally
if (businessClosures == null)
{ businessClosures = GetBusinessClosureCalendarRules(service); }
foreach (var closure in businessClosures)
{
var startDate = (DateTime)closure["effectiveintervalstart"];
var endDate = (DateTime)closure["effectiveintervalend"];
if (tempdate >= startDate && tempdate <= endDate)
return false;
}
return true; //true if not a holdiday
}
#endregion
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4. Here we have taken care of Business closure as well. So this is how you can set up your custom SLA.
Your requirements might be different and based on that you can customise it as you want.
Comments are highly appreciated..!!!
Happy CRMing