Nov 20, 2017

Enforce Calculation of Rollup fields

Rollup fields are handy in many scenarios, it takes one hours to update by default. If the business case needs real time updating, we can write plugin/WF to enforce the recalculation based on trigger. In such situation, below generic method can be used.

public static void EnforceCalculationRollup(IOrganizationService OrganizationService, EntityReference record, string rollupField)
{
CalculateRollupFieldRequest rollupRequest = new CalculateRollupFieldRequest { Target = record, FieldName = rollupField };
CalculateRollupFieldResponse response = (CalculateRollupFieldResponse)OrganizationService.Execute(rollupRequest);
Entity entity = response.Entity;
OrganizationService.Update(entity);
}

Hope this helps!

Nov 6, 2017

Use Service Calendar programmatically to check user availability

Service Calendar is a key component used in Field service for scheduling the work. Anyway, Calendar alone can be used for many different usages since its showing the working hours/ availability of a User. Here I am illustrating how to pro-grammatically access the calendar.

First of all, lets see how to set users availability in the calendar. In order to make it simple I am going to set if someone is available in given day or not. (not going into different time slots, which is also possible). Go to any User and go to Work Hours. Then go to New Weekly Schedule as below;


Please set the schedule as you wish in the resulting pane as below; Since I am interested in daily basis, I select 24 hours.


Once save you will see calendar been updated.


Now, this is the code snippet to check the availability of the User through calendar;

public static bool IsUserAvailable(IOrganizationService OrganizationService, Guid UserId)
{
    bool isUserAvailable = false;

    QueryScheduleRequest scheduleRequest = new QueryScheduleRequest
    {
        ResourceId = UserId,
        Start = DateTimeUtility.RetrieveLocalTimeFromUTCTime(OrganizationService, DateTime.Now),
        End = DateTimeUtility.RetrieveLocalTimeFromUTCTime(OrganizationService, DateTime.Now.AddSeconds(5)),
        TimeCodes = new TimeCode[] { TimeCode.Available }
    };
    QueryScheduleResponse scheduleResponse = (QueryScheduleResponse)OrganizationService.Execute(scheduleRequest);
    if (scheduleResponse.TimeInfos.Length > 0)
        isUserAvailable = true;

    return isUserAvailable;
}

You may notice that I am passing the local time in QueryScheduleRequest in above code since I am setting the local time zone in the Calendar also. I am also giving here the methods to be be used in time conversions;

internal static DateTime RetrieveLocalTimeFromUTCTime(IOrganizationService service, DateTime utcTime)
{
    return RetrieveLocalTimeFromUTCTime(utcTime, RetrieveCurrentUsersSettings(service), service);
}

internal static int? RetrieveCurrentUsersSettings(IOrganizationService service)
{
    var currentUserSettings = service.RetrieveMultiple(
        new QueryExpression("usersettings")
        {
            ColumnSet = new ColumnSet("timezonecode"),
            Criteria = new FilterExpression
            {
                Conditions =
                {
                            new ConditionExpression("systemuserid", ConditionOperator.EqualUserId)
                }
            }
        }).Entities[0].ToEntity<Entity>();
    return (int?)currentUserSettings.Attributes["timezonecode"];
}

internal static DateTime RetrieveLocalTimeFromUTCTime(DateTime utcTime, int? timeZoneCode, IOrganizationService service)
{
    if (!timeZoneCode.HasValue)
        return DateTime.Now;
    var request = new LocalTimeFromUtcTimeRequest
    {
        TimeZoneCode = timeZoneCode.Value,
        UtcTime = utcTime.ToUniversalTime()
    };
    var response = (LocalTimeFromUtcTimeResponse)service.Execute(request);
    return response.LocalTime;
}

Hope this helps!