Guest blogger and CRM MVP Aaron Elder provides a (in his words) ‘worthy’ blog today. Our technical reviewers give this post high marks and kudos.
The Microsoft Dynamics CRM Service Scheduling Engine is a powerful and mysterious system. As a CRM developer you may be asking will this engine meet your needs? It’s hard to say because right now there is insufficient documentation and we need more information on how this thing actually works. In this post I hope to document a small portion of the system and provide some sample code to show how to programmatically define an availability schedule for a piece of equipment.
A good place to start to understand the basics of the Service Scheduling Engine is to read the following document (that I helped write): Service Scheduling: Optimizations and Considerations (See Pages: 5,6,7)
The scope of this post is to explain the basics of Calendar Rules and how you can programmatically create a set of rules for a “resource”, which is a person or thing and in this case is a piece of equipment. For this sample, you will need to understand the following CRM entities:
Entity |
Description |
Calendar |
A set of ordered rules that define free/busy times for users, business units, and services, and for resources or resource groups. Examples of events are working and non-working hours, vacations, appointments and weekly meetings. Calendars support recurring events and can be nested. In addition to time blocks, a calendar also specifies capacity rules in terms of ‘effort required’ for a specific resource and appointment type and ‘effort available’ per duration by a resource in their respective calendars. |
CalendarRule |
A rule defining free and busy times for a service and for resources or resource groups (for example, working, non-working, vacation, blocked). The mapping between a Calendar and a CalendarRule is essentially 1:1 or 1:N. A CalendarRule can also link back to an “inner calendar”. This is required because a CalendarRule cannot exist with a Calendar, so if you want to define another Rule you need another Calendar. CalendarRules that have no inner calendar are referred to as leafs and the ones that do are roots. |
Equipment |
A type of resource representing either a piece of equipment, such as a tool, or a facility or location, such as a room. Every Equipment has a single root CalendarRule. You can determine the base rule by looking at the CalendarId on the Equipment entity. |
For this post, I am going to break Calendar Rules into sub-types:
Entity |
Description |
Root |
A CalendarRule that contains an Inner Calendar (IE has nested rules). |
Leaf |
A CalendarRule that does not contain an Inner Calendar and as such is the end of the “branch”. |
For the purpose of this post, the relationships look something like this:
The following source sample creates a new schedule for a piece of equipment and says the equipment is available from 9AM to 5PM, every day and takes a 1 hour “lunch break” from 12-1pm. The resulting calendar is displayed at the end.
Important Notes
- This is a basic .NET 2.0 Console Application
- Be sure to update the OrganizationName
- Be sure to create a new Facility / Equipment in CRM and set its GUID on the testResource retrieve
- Be sure to read the COMMENTS in this code, I have put a lot of useful descriptions of what is going in throughout.
class Program static CrmService CurrentCrmService get CrmService service = new CrmService(); return service; static void Main(string[] args) CrmService service = Program.CurrentCrmService; // Retrieve a “known” piece of equipment – It is assumed this equipment has been created via the UI equipment testResource = (equipment)service.Retrieve(EntityName.equipment.ToString(), new Guid(“905B57D3-60DA-DC11-9EBF-0003FF0E509E”), new AllColumns()); #region Create Level 0 Rule // ====================================================================== // Create an “empty” calendar, we will use this later to bind to the Level 1 rule // Create rule to depict 8 am – 5pm schedule // This is a “root” rule and we want it to be the base on which we build // User’s timezone and description of the rule // Provide a user readable description // One full day (1440 minutes) // Happens “daily, repeating every day” – AKA “all days” // “Since the first day CRM is aware of” // The inner “empty” calendar will be used later with a Level 1 Rule // Get the Root Calendar, so we can update it // Append our Rule // Update the Calendar so it adds our new rule #endregion #region Create Level 1 Rule – To hold the working hours // ================================================================ calendarrule level1Rule = new calendarrule(); // This is a base rule that can be overridden // Day starts at midnight or Offset of “0”, we need to start at 9AM // The person will work for 8 hours so 8 * 60 // The person is available and able to be scheduled during this time calendar level0Cal = (calendar)service.Retrieve(EntityName.calendar.ToString(), innerCalendarId, new AllColumns()); // Update the Calendar so it adds our new rule #endregion #region Create another Level 1 Rule – To Define a “break” in the working hours // ================================================================== calendarrule lunchBreak = new calendarrule(); // Since the hours for the day are defined, we have to raise the importance of this to override 12-1 // Break starts at 12 NOON // Break lasts 1 hour // They are not available during lunch // Because it is a break level0Cal = (calendar)service.Retrieve(EntityName.calendar.ToString(), innerCalendarId, new AllColumns()); // Update the Calendar so it adds our new rule #endregion Console.WriteLine(“Complete – Press any key to continue…”); /// <summary> static calendarrule[] AddRuleToArray(calendarrule[] currentRules, calendarrule ruleToAdd) calendarrule[] newRules = new calendarrule[currentRules.Length + 1]; return newRules; /// <summary> static Guid CreateEmptyCalendar() CrmService service = Program.CurrentCrmService; // Determine the current user calendar newCal = new calendar(); // Create the Calendar return id; |
Here is the resulting schedule for this equipment, as seen from the UI:
Drilling into a particular day shows the “break”, since it’s rank is higher than the 9-5, it overrides as such…
Cheers,
CRM MVP and Chief CRM Architect at Ascentium