Creating Calendar rules with Breaks in Microsoft Dynamics CRM 2015

By | November 18, 2015

Introduction:

Microsoft Dynamics CRM has comprehensive Calendar management capabilities to manage work schedules.

You are allowed to not only specify the work hours but also the break times when the resource would be unavailable.

Here we are demonstrating how to add breaks to daily work schedule programmatically.

Calendar and Calendar rules entities in CRM are always tricky to deal with, when it comes to handle them through program.

Sample Work ScheduleCalendar rules

In the below code we will Add a break on 6th April 2015 from 12:30 to 1:00 PM:

//First read the UserId for whom you need to add break
Guid userid = ((WhoAmIResponse)service.Execute(new WhoAmIRequest())).UserId;
//Next we need to get the Calendar associated with the user. Every user has a calendar associated with it.
Entity userEntity = service.Retrieve("systemuser", userid, new ColumnSet(new String[] { "calendarid" }));
//Get the calendar for the user
Entity userCalendarEntity = service.Retrieve("calendar", userEntity.GetAttributeValue<EntityReference>("calendarid").Id, new ColumnSet(true));
//The daily schedule of the user is stored in the form of calendar rules.
//Here we are retrieving all the calendar rules related to the particular User Calendar found earlier.
EntityCollection calendarRules = (EntityCollection)userCalendarEntity.Attributes["calendarrules"];

What is Inner Calendar?

Inner Calendars are created so that they can be used by other calendars to build different time slots or rules in the System.

// Create a new inner calendar
Entity newInnerCalendar = new Entity("calendar");

newInnerCalendar.Attributes["businessunitid"] = new EntityReference("businessunit", ((Microsoft.Xrm.Sdk.EntityReference)(userCalendarEntity["businessunitid"])).Id);

//create newInnerCalendar
Guid innerCalendarId = service.Create(newInnerCalendar);

First we are creating a calendar rule specifying the duration to be 1440 minutes i.e. 24 hours as we want to create this rule for one day only.

// Create a new calendar rule and assign the inner calendar id to it
Entity calendarRule = new Entity("calendarrule");

calendarRule.Attributes["duration"] = 1440; // 24hrs in minutes

//It specifies the extent of the Calendar rule,generally an Integer value.
calendarRule.Attributes["extentcode"] = 1;

//Pattern of the rule recurrence. As we have given FREQ=DAILY it will create a calendar rule on daily basis. We can even create on Weekly basis by specifying FREQ=WEEKLY.

INTERVAL=1; – This means how many days interval between the next same schedule. For e.g if the date was 6th April and interval was 2, it would create a schedule for 8th april, 10th april and so on…

COUNT=1; This means how many recurring records should be created, if in the above example the count was given as 2, it would create schedule for 6th and 8th and then stop. If the count was 3, it would go on until 10th and then stop

calendarRule.Attributes["pattern"] = "FREQ=DAILY;INTERVAL=1;COUNT=1";
//Rank is an Integer value which specifies the Rank value of the Calendar rule
calendarRule.Attributes["rank"] = 0;

// Timezone code to be set which the calendar rule will follow
calendarRule.Attributes["timezonecode"] = 035;

//Specifying the InnerCalendar Id
calendarRule.Attributes["innercalendarid"] = new EntityReference("calendar", innerCalendarId);

//Start time for the created Calendar rule
calendarRule.Attributes["starttime"] = new DateTime(2015, 04, 06, 0, 0, 0, DateTimeKind.Utc);

Now we will add this rule to the earlier retrieved calendar rules

calendarRules.Entities.Add(calendarRule);

// assign all the calendar rule back to the user calendar
userCalendarEntity.Attributes["calendarrules"] = calendarRules;
//update the user calendar entity that has the new rule
service.Update(userCalendarEntity);

//Above we created a Calendar rule, now below we are creating two more Calendar rules one specifying the Working hour in the day (i.e. on 6th April 2015) and other for specifying the Break time (30 minutes) in a day.

Calendar rule for Working Day :

Entity workingHourcalendarRule = new Entity("calendarrule");

//Duration of Working hours in minutes (9 hours i.e. 540 minutes)
workingHourcalendarRule.Attributes["duration"] = 540; //total work hours duration

//Effort available for a resource (User) during the time described by the calendar rule i.e. Capacity part in the Calendar rule
workingHourcalendarRule.Attributes["effort"] = 1.0;

// It is a Flag used in vary-by-day calendar rules.
workingHourcalendarRule.Attributes["issimple"] = true;

// offset 480 i.e. 8 hours from start time (12:00) i.e. Working hour start from 8 am

Now, what actually this “offset” mean?

In the earlier Calendar rule which we updated in CRM we had set the start time by default to 12 am by setting the below attribute:

“calendarRule.Attributes["starttime"] = new DateTime(2015, 04, 06, 0, 0, 0, DateTimeKind.Utc);”

workingHourcalendarRule.Attributes["offset"] = 480; //to indicate start time is 8 AM

//Rank of the Calendar Rule
workingHourcalendarRule.Attributes["rank"] = 0;

//Sub Type of the Calendar rule.For setting Work hours it is 1.
workingHourcalendarRule.Attributes["subcode"] = 1;

//Type of calendar rule such as working hours, break, holiday, or time off. 0 for working hours
workingHourcalendarRule.Attributes["timecode"] = 0;

// Local time zone for the calendar rule.
workingHourcalendarRule.Attributes["timezonecode"] = -1;

//Specifying the InnerCalendar Id

workingHourcalendarRule.Attributes["calendarid"] = new EntityReference("calendar", innerCalendarId);

Calendar rule for Setting Break in the Day from 12:30pm – 1pm

Entity calendarRulebreak = new Entity("calendarrule");

//Duration of Break: 30 minutes
calendarRulebreak.Attributes["duration"] = 30;

calendarRulebreak.Attributes["effort"] = 1.0;

calendarRulebreak.Attributes["issimple"] = true;

//We setting the offset to 750minutes (i.e. 12.5 hours) .As explained for above part here we are specifying when this rule will start. (I.e. when the break starts)
In our case it will be 12 am + 12.5 hours = 12:30 pm
//Duration of Break: 30 minutes
calendarRulebreak.Attributes["offset"] = 750;

calendarRulebreak.Attributes["rank"] = 0;

//SubCode=4 for Specifying Break
calendarRulebreak.Attributes["subcode"] = 4;

//TimeCode=2 for Specifying Break rule
calendarRulebreak.Attributes["timecode"] = 2;

// Local time zone for the calendar rule
calendarRulebreak.Attributes["timezonecode"] = -1;

calendarRulebreak.Attributes["calendarid"] = new EntityReference("calendar", innerCalendarId);

//Add working hour rule to InnerCalendar Rules
innerCalendarRules.Entities.Add(workingHourcalendarRule);

//Add Break Hour rule to InnerCalendar Rules
innerCalendarRules.Entities.Add(calendarRulebreak);

newInnerCalendar.Attributes["calendarrules"] = innerCalendarRules;
newInnerCalendar.Attributes["calendarid"] = innerCalendarId;

service.Update(newInnerCalendar);

In the new Inner Calendar which we created we will add the above two calendar rules and update the Inner calendar.

After successfully running the code you may see a record is created for the specified date with a Break added as seen below:Creating Calendar rules with Breaks

Conclusion:

The steps to get the calendar is

  1. Read the user calendar
  2. Create the inner calendar
  3. Create the calendar rule for the day
  4. Create the calendar rule for the work duration
  5. Create the calendar rule for the break duration.

Get more from your Dynamics CRM..Start monitoring User Adoption today!

4 thoughts on “Creating Calendar rules with Breaks in Microsoft Dynamics CRM 2015

  1. mauroldanr

    Hello
    I am trying to create an entrance in the Calendar if someone could give me an idea:

    I created an entity A which has some fields to define the periodicity and I need to save this in the Calendar, for example:
    Periodicity: Monthly Range: 01-March-2016 to 01-March-2017 Day of month: 10
    so I will need to create in the Calendar a entrance for each month since March 2016 till March 2017 the day 10
    Similar to periodicity Weekly, daily

    I have created an plugin in C# and my idea is create the logic here and save in the calendar with the information obtained. Is this possible?

    could you give me the whole class if this example in this post? I have error with service class

    Thank you

    Reply
    1. inogic Post author

      Hi,

      You have a custom entity A which will store the details for creating Workhours i.e. Month and day for which you want to create the workhour.

      Yes you can achieve this through a plugin provided you have all the data required to create the Calendar rules as shown in the blog.

      Also as you said you’re having issue with the service class.

      We are using the IOrganizationService object which you can obtain in the Plugin using below code in case you have missed it.
      public void Execute(IServiceProvider serviceProvider)
      {
      // object Organization service factory object
      IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

      // object organization object
      IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
      }

      Still if you are facing any errors then please copy paste your error here, so that we can look into it detail.

      Reply
  2. rahul

    Hi Inogic,

    First of all this post is simple awesome! coz it helped me alot and i am sure it will help many others too!

    I has a small doubt i am able to create a facility with some work hours (say 8 to 5) for weekly schedule. The concern is when i go to CRM and change the timings (say 9 to 6) it gets changed for all the days in the weeks.

    I wanted to know how to set different timings for different days in the weeks with break (say 12 PM: to 1 PM) through code!

    It would be great if it is possible to share the code, because have used the same code which you have given above.

    Thanks in advance!

    Reply
    1. inogic Post author

      Hi,

      Thanks for your comment.

      Regarding your query it seems you want to set the work Hours for a Week.

      Let us consider you want to set the Work hours for the Week from 10th April 2016 to 16 April 2016.

      Below is the code:

      Call the CreateCalendarRulesForWeekDay() Method from your function and make sure you have the below code:

      ///

      /// Method to create CalendarRules for Week
      ///

      private void CreateCalendarRulesForWeekDay()
      {
      DateTime weekStartDate = DateTime.MinValue;
      DateTime weekEndDate = DateTime.MinValue;
      Entity systemUserEntity = null;
      Entity userCalendarEntity = null;
      EntityCollection calendarRules = null;
      string[] weekPatternSet = null;
      try
      {
      string weekPattern = “SU,MO,TU,WE,TH,FR,SA”;
      weekStartDate = Convert.ToDateTime(“04/10/2016”);
      weekEndDate = Convert.ToDateTime(“04/16/2016”);

      //Get the calendar id of the user
      systemUserEntity = _service.Retrieve(“systemuser”, new Guid(_userId), new ColumnSet(new String[] { “calendarid” }));

      // Retrieve the calendar of the user
      userCalendarEntity = _service.Retrieve(“calendar”, ((Microsoft.Xrm.Sdk.EntityReference)(systemUserEntity.Attributes[“calendarid”])).Id, new ColumnSet(true));

      //Here we are retrieving all the calendar rules related to the particular User Calendar found earlier.
      calendarRules = (EntityCollection)userCalendarEntity.Attributes[“calendarrules”];

      //To Store SU,Mo,TU,WE,TH,FR,SA
      weekPatternSet = weekPattern.Split(‘,’);

      //Iterate for each day in a Week
      foreach (var dayInWeek in weekPatternSet)
      {
      Entity newInnerCalendar = null;
      Guid innerCalendarId = Guid.Empty;

      //When the workhour will start for particular day in a Week
      int workOffSet = GetOffSetValue(dayInWeek);

      //When the Break will start for particular day in a Week
      int breakOffSet = GetBreakOffSet(dayInWeek);

      //Working Work Hour duration in Minutes for particular day in a Week
      int workDuration = GetWorkDuration(dayInWeek);

      //Break Duration : 1 Hour
      int breakDuration = 60;

      newInnerCalendar = new Entity(“calendar”);

      newInnerCalendar.Attributes[“businessunitid”] = new EntityReference(“businessunit”, ((Microsoft.Xrm.Sdk.EntityReference)(userCalendarEntity[“businessunitid”])).Id);

      innerCalendarId = _service.Create(newInnerCalendar);

      // Create a new calendar rule and assign the inner calendar id to it
      Entity calendarRule = new Entity(“calendarrule”);

      calendarRule.Attributes[“pattern”] = “FREQ=WEEKLY;INTERVAL=1;BYDAY=” + dayInWeek + “”;

      //Set Create Calendar Rule record attributes referring Blog above
      //MonthDays
      int monDays = GetDaysInMonth(weekEndDate.Year, weekEndDate.Month);

      if (monDays == weekEndDate.Day)
      {
      if (weekEndDate.Month == 12)
      {
      calendarRule.Attributes[“effectiveintervalend”] = new DateTime(weekEndDate.Year, 1, 1, 0, 0, 0, DateTimeKind.Utc);
      }
      else
      {
      calendarRule.Attributes[“effectiveintervalend”] = new DateTime(weekEndDate.Year, weekEndDate.Month + 1, 1, 0, 0, 0, DateTimeKind.Utc);
      }
      }
      else
      {
      calendarRule.Attributes[“effectiveintervalend”] = new DateTime(weekEndDate.Year, weekEndDate.Month, weekEndDate.Day + 1, 0, 0, 0, DateTimeKind.Utc);
      }

      calendarRules.Entities.Add(calendarRule);

      // assign all the calendar rule back to the user calendar
      userCalendarEntity.Attributes[“calendarrules”] = calendarRules;

      // update the user calendar entity that has the new rule
      _service.Update(userCalendarEntity);

      //Create Working Calendar Rules record referring Blog above
      Entity workingHourcalendarRule = new Entity(“calendarrule”);

      workingHourcalendarRule.Attributes[“duration”] = workDuration;

      // offset 120 i.e. 2 hours from start time (12:00)
      workingHourcalendarRule.Attributes[“offset”] = workOffSet;

      //Set the rest of the attributes referring the blog above

      EntityCollection innerCalendarRules = new EntityCollection();
      innerCalendarRules.EntityName = “calendarrule”;

      Entity calendarRulebreak = new Entity(“calendarrule”);

      // Break Duration
      calendarRulebreak.Attributes[“duration”] = breakDuration;

      calendarRulebreak.Attributes[“offset”] = breakOffSet;

      //Set rest of the Attributes referring the blog above

      innerCalendarRules.Entities.Add(calendarRulebreak);

      innerCalendarRules.Entities.Add(workingHourcalendarRule);

      newInnerCalendar.Attributes[“calendarrules”] = innerCalendarRules;
      newInnerCalendar.Attributes[“calendarid”] = innerCalendarId;
      _service.Update(newInnerCalendar);

      }
      }
      catch (Exception err)
      {
      throw new Exception(err.Message);
      }

      }

      Also, you will need below functions along with this:

      ///

      /// Method to return the Work Duration in Minutes
      ///

      /// ///
      private int GetWorkDuration(string dayInWeek)
      {
      try
      {
      int duration = 0;
      switch (dayInWeek.ToLower())
      {
      case “su”:
      duration = 540;
      break;

      case “mo”:
      duration = 600;
      break;
      case “tu”:
      duration = 600;
      break;
      case “we”:
      duration = 600;
      break;
      case “th”:
      duration = 540;
      break;
      case “fr”:
      duration = 540;
      break;
      case “sa”:
      duration = 540;
      break;

      default:
      duration = 0;
      break;
      }

      return duration;
      }
      catch (Exception err)
      {
      throw new Exception(err.Message);
      }
      }

      ///

      /// Method to set the Start Time when the Break Starts From For a Particular Day
      ///

      /// ///
      private int GetBreakOffSet(string dayInWeek)
      {
      try
      {
      int offSetVal = 0;
      switch (dayInWeek.ToLower())
      {
      case “su”:
      offSetVal = 720;
      break;

      case “mo”:
      offSetVal = 780;
      break;
      case “tu”:
      offSetVal = 780;
      break;
      case “we”:
      offSetVal = 780;
      break;
      case “th”:
      offSetVal = 780;
      break;
      case “fr”:
      offSetVal = 780;
      break;
      case “sa”:
      offSetVal = 780;
      break;

      default:
      offSetVal = 0;
      break;
      }

      return offSetVal;
      }
      catch (Exception err)
      {
      throw new Exception(err.Message);
      }
      }

      ///

      /// Method to set the Start Time when the Work Hour Starts From For a Particular Day
      ///

      /// ///
      private int GetOffSetValue(string dayInWeek)
      {
      try
      {
      int offSetVal = 0;
      switch (dayInWeek.ToLower())
      {
      case “su”:
      offSetVal = 480;
      break;

      case “mo”:
      offSetVal = 540;
      break;
      case “tu”:
      offSetVal = 540;
      break;
      case “we”:
      offSetVal = 540;
      break;
      case “th”:
      offSetVal = 540;
      break;
      case “fr”:
      offSetVal = 540;
      break;
      case “sa”:
      offSetVal = 540;
      break;

      default:
      offSetVal = 0;
      break;
      }

      return offSetVal;
      }
      catch (Exception err)
      {
      throw new Exception(err.Message);
      }
      }

      ///

      /// This function is used get the month days
      ///

      /// /// ///
      private int GetDaysInMonth(int year, int month)
      {
      int monDays = 0;

      DateTime dt1 = new DateTime(year, month, 1);
      DateTime dt2 = dt1.AddMonths(1);
      TimeSpan ts = dt2 – dt1;
      monDays = Convert.ToInt32(ts.TotalDays);

      return monDays;
      }

      In this code we are using a global variable “_service” which is an Object of IOrganizationService.
      Using this code we have set the workhours from 10th April 2016 to 16th April 2016.

      Hope this helps.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *