Retrieving a Holiday Calendar in a Dynamics 365 Plugin

Isaac Stephens, 22 June 2020

In Dynamics 365 you can create Holiday Calendars which contain the dates when your business observes a holiday. These are important when using SLAs as they will be taken into account when handling response times. However, you may want to use these holidays in your own custom logic. For example, you may have a custom Due Date field that needs to take into account Holidays.

To create Holidays in Dynamics 365, open up Advanced Settings and head to “Service Management”. Under the “Service Terms” section there will be an option called “Holiday Schedule”, in here you are able to create and manage your Holiday Calendars.

image 

Once you have created the calendar you can retrieve the dates within it using a Query Expression in a plugin/console app or using the WebAPI in JavaScript. I will go over the method for retrieving using C#.

In this example, we will be adding some days to a date in order to get a date in the future. We will be getting these days from a field called Response days and  the date will be from a field called Sent On, the variable ‘target’ is the Entity variable that contains our fields/attributes. The purpose of this example is to get a Due Date that is equal to Sent On plus Response Days.

int responseDays = target.GetAttributeValue<int>("mag_responsedays");
DateTime sentOn = target. GetAttributeValue <DateTime>("mag_senton");

We then need to retrieve all the calendar rules, which are the dates associated with a calendar. This is done using a QueryExpression shown below  , ‘calendarrules’ does not have to be specified as a column of the QueryExpression as this is a special case entity where that is not required:

private List<Entity> GetCalendarRules(IOrganizationService sdk)
{
   List<Entity> calendarRules = new List<Entity>(); 
   Entity businessClosureCalendar = null;   

   QueryExpression q = new QueryExpression("calendar") { NoLock = true };
   q.Criteria.AddCondition("type", ConditionOperator.Equal, 2);
   q.Criteria.AddCondition("name", ConditionOperator.Equal, "Holidays");

   EntityCollection businessClosureCalendars = sdk.RetrieveMultiple(q);

   if (businessClosureCalendar.Entities.Count > 0) { 
       businessClosureCalendar = businessClosureCalendars.Entities[0];
       calendarRules = businessClosureCalendar.Get<EntityCollection>("calendarrules").Entities.ToList();
   }

   return calendarRules;
}

This method retrieves a calendar called ‘Holidays’ that is of type 2 (Holiday Schedule), takes the first one and then gets the rules from this Calendar as a list of Entities using the code below:

businessClosureCalendar.GetAttributeValues<EntityCollection>("calendarrules").Entities.ToList();

This list is then returned and is converted into a List of DateTimes to make it easier to handle, this is done using the code below:

List<DateTime> holidays = calendarRules
                    .Select(rule => rule.GetAttributeValue<DateTime>("starttime")))
                    .Where(date => date >= DateTime.UtcNow)
                    .ToList();

To then complete the logic of ignoring holidays you use a loop to iterate until it has added the Response Days to the Sent On Date, however, we also want to add extra time over the holidays. This works as shown below:

DateTime dueDate = sentOn;

while (responseDays > 0)
{
   dueDate = dueDate.AddDays(1);
   if (!holidays.Contains(dueDate))
   {
      responseDays--;
   }
}

target["mag_duedate"] = dueDate;

Now you have all the pieces of code you can put it together and deploy into your environment and start having your due dates automatically set to the correct day.