Configuring the work hours for a user is straightforward from the Dynamics 365 UI, a couple of clicks and you are done. However in the last years we saw an increase of Field Service projects, hence the necessity to automatize the creation and the update of user's works hours.
C# code to update the calendar entity has been around from CRM 2011, like this one:
Sample code to update user’s calendar programmatically (work hours) in CRM 2011
The code linked above works perfectly when you see the work hours inside the user calendar, however they don't appear inside the Field Service schedule board. How can we make sure the work hours appear everywhere?
Nearly 50 lines of code to create a work hour entry are (at least to me) a bit excessive, but this is the way Dynamics work. I tried to simplify the code by renaming the variables and adding the code necessary for the work hours to appear inside the schedule board.
C# code to update the calendar entity has been around from CRM 2011, like this one:
Sample code to update user’s calendar programmatically (work hours) in CRM 2011
The code linked above works perfectly when you see the work hours inside the user calendar, however they don't appear inside the Field Service schedule board. How can we make sure the work hours appear everywhere?
Nearly 50 lines of code to create a work hour entry are (at least to me) a bit excessive, but this is the way Dynamics work. I tried to simplify the code by renaming the variables and adding the code necessary for the work hours to appear inside the schedule board.
// we start with the user Id Guid userId = Guid.Empty; // instead of Guid.Empty here we should have the real user Id // we retrieve the calendarid from the user entity Entity user = service.Retrieve("systemuser", userId, new ColumnSet("calendarid")); Guid userCalendarId = user.GetAttributeValueIn the end to changes were necessary to make the work hour visible inside the Field Service schedule board:("calendarid").Id; // we retrieve the calendar record in order to get the Business Unit and the Calendar Rules Entity userCalendar = service.Retrieve("calendar", userCalendarId , new ColumnSet("businessunitid")); Guid calendarBusinessUnitRef = userCalendar.GetAttributeValue ("businessunitid"); EntityCollection calendarRules = userCalendar.GetAttributeValue ("calendarrules"); // we create a new calendar record (inner) Entity innerCalendar = new Entity("calendar"); innerCalendar["businessunitid"] = calendarBusinessUnitRef; // Field Service Schedule Board: we must define the type as Inner Calendar // https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/types-calendars innerCalendar["type"] = new OptionSetValue(-1); Guid innerCalendarId = service.Create(innerCalendar); // we create a calendar rule for the whole day we want to edit Entity dayRule = new Entity("calendarrule"); dayRule["duration"] = 1440; // 24 hours in minutes dayRule["effort"] = 1.0; dayRule["extentcode"] = 1; dayRule["pattern"] = "FREQ=DAILY;COUNT=1"; dayRule["rank"] = 0; dayRule["timezonecode"] = 110; // 110 is (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna // GetAllTimeZonesWithDisplayNameRequest can be used to retrieve all the timezones with their code dayRule["starttime"] = new DateTime(2019, 3, 28, 0, 0, 0, DateTimeKind.Utc); dayRule["innercalendarid"] = new EntityReference("calendar", innerCalendarId); // Field Service Schedule Board: we must also define the calendarid reference to the user calendar dayRule["calendarid"] = new EntityReference("calendar", userCalendarId); // we attach it to the Calendar Rules of the user calendarRules.Entities.Add(dayRule); // we update the user calendar to refresh the calendar rules collection Entity updateUserCalendar = new Entity("calendar", userCalendarId); updateUserCalendar["calendarrules"] = calendarRules; service.Update(updateUserCalendar); // we define the calendar rule containing our work hour Entity exactCalendarRule = new Entity("calendarrule"); exactCalendarRule["duration"] = 120; // 2 hours in minutes exactCalendarRule["effort"] = 1.0; exactCalendarRule["issimple"] = true; exactCalendarRule["offset"] = 480; // 8 hours in minutes from start time (12:00) exactCalendarRule["rank"] = 0; exactCalendarRule["subcode"] = 1; exactCalendarRule["timecode"] = 0; exactCalendarRule["timezonecode"] = 110; // same timezone as the day rule exactCalendarRule["calendarid"] = new EntityReference("calendar", innerCalendarId); // we add the calendar rule to a collection EntityCollection innerCalendarRules = new EntityCollection(); innerCalendarRules.EntityName = "calendarrule"; innerCalendarRules.Entities.Add(exactCalendarRule); // we update the inner calendar with the new calendar rules innerCalendar["calendarrules"] = innerCalendarRules; innerCalendar["calendarid"] = innerCalendarId; service.Update(innerCalendar);
- We must define the type for the Inner Calendar
- We must reference the user calendar inside the calendar rule the the whole day