
Hello All,
I am trying to find business hours from the calendar and while i was exploring for options i did not find anything other than creating a custom workflow activity that queries the calendar and determining any holidays and weekends. I would like to really use a non code solution, is it possible?
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Workflow;
using System;
using System.Activities;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WorkHours
{
public class CalculateBusinessHours : CodeActivity
{
[RequiredArgument]
[Input("Start Date")]
public InArgument StartDate { get; set; }
[RequiredArgument]
[Input("End Date")]
public InArgument EndDate { get; set; }
[RequiredArgument]
[Input("Exclude Weekend?")]
public InArgument ExcludeWeekend { get; set; }
[RequiredArgument]
[Input("Exclude Busines Closure")]
public InArgument ExcludeBusinessClosure { get; set; }
[Output("Minutes")]
public OutArgument Minutes { get; set; }
[Output("Hours")]
public OutArgument Hours { get; set; }
protected override void Execute(CodeActivityContext excontext)
{
IWorkflowContext context = excontext.GetExtension();
IOrganizationServiceFactory factory = excontext.GetExtension();
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
List Closures = new List();
Util helper = new Util();
if (ExcludeBusinessClosure.Get(excontext))
{
Closures = helper.GetClosureConfig(service);
}
#region CalculateMinutes
int TotalMinutes = CalculateMinutes(StartDate.Get(excontext), EndDate.Get(excontext), Closures, ExcludeWeekend.Get(excontext), 8, 30, 17, 0, service);
decimal TotalHours = CalculateHours(TotalMinutes);
Minutes.Set(excontext, TotalMinutes);
Hours.Set(excontext, TotalHours);
#endregion
}
private int CalculateMinutes(DateTime StartDate, DateTime EndDate, List ListClosure, bool ExcludeWeekend, int StartHours, int StartMinutes, int EndHours, int EndMinutes, IOrganizationService service)
{
#region Office Start/End Time
TimeSpan OfficeStart = new TimeSpan(StartHours, StartMinutes, 0);
TimeSpan OfficeEnd = new TimeSpan(EndHours, EndMinutes, 0);
#endregion
#region CalculateMinutes
Util helper = new Util();
//Converting Local time from UTC
DateTime EDate = TimeConversionUtility.GetLocalTime(EndDate, service);
DateTime SDate = TimeConversionUtility.GetLocalTime(StartDate, service);
StartDate = SDate.AddSeconds(SDate.Second * -1);
EndDate = EDate.AddSeconds(EDate.Second * -1);
int TotalMinutes = 0;
while (StartDate < EndDate)
{
bool IsDayAddRequired = true;
#region Logic for calculating Minutes
if (!helper.IsBusinessClosure(StartDate, ListClosure))
{
if (ExcludeWeekend)
{
if (helper.IsInDaysConfigured(StartDate))
{
if (StartDate.TimeOfDay >= OfficeStart && StartDate.TimeOfDay <= OfficeEnd)
{
if (StartDate.Date == EndDate.Date)
{
if (EndDate.TimeOfDay > OfficeEnd)
EndDate = EndDate.Date.AddHours(EndHours).AddMinutes(EndMinutes);
TimeSpan span = EndDate.Subtract(StartDate);
TotalMinutes = (int)span.TotalMinutes;
//IsDayAddRequired = true;
//Logic for subtracting Lunch break
if (EndDate.TimeOfDay >= new TimeSpan(12, 30, 0) && StartDate.TimeOfDay <= new TimeSpan(12, 0, 0))
{
//Subtract Lunch
TotalMinutes = TotalMinutes - 30;
}
else if (EndDate.TimeOfDay >= new TimeSpan(12, 0, 0) && EndDate.TimeOfDay <= new TimeSpan(12,30,0))
{
TotalMinutes = TotalMinutes - EndDate.Minute;
}
}
else
{
TimeSpan span = StartDate.Date.AddHours(EndHours).AddMinutes(EndMinutes).Subtract(StartDate);
TotalMinutes = (int)span.TotalMinutes;
//Subtract Lunch break
TotalMinutes = TotalMinutes - 30;
//IsDayAddRequired = true;
}
}
else if (StartDate.TimeOfDay < OfficeStart)
{
StartDate = StartDate.Date.AddHours(StartHours).AddMinutes(StartMinutes);
IsDayAddRequired = false;
}
}
}
else
{
if (StartDate.TimeOfDay >= OfficeStart && StartDate.TimeOfDay <= OfficeEnd)
{
if (StartDate.Date == EndDate.Date)
{
TimeSpan span = EndDate.Subtract(StartDate);
TotalMinutes = (int)span.TotalMinutes;
//IsDayAddRequired = true;
}
else
{
TimeSpan span = StartDate.Date.AddHours(EndHours).AddMinutes(EndMinutes).Subtract(StartDate);
TotalMinutes = (int)span.TotalMinutes;
//IsDayAddRequired = true;
}
}
else if (StartDate.TimeOfDay < OfficeStart)
{
StartDate = StartDate.Date.AddHours(StartHours).AddMinutes(StartMinutes);
IsDayAddRequired = false;
}
}
}
#endregion
if (IsDayAddRequired)
StartDate = StartDate.AddDays(1).Date.AddHours(StartHours).AddMinutes(StartMinutes);
}
return TotalMinutes;
#endregion
}
private decimal CalculateHours(int TotalMinutes)
{
return (TotalMinutes / 60M);
}
}
class Util
{
public bool IsInDaysConfigured(DateTime Dt)
{
bool IsValidForTheDay = false;
switch (Dt.DayOfWeek)
{
case DayOfWeek.Sunday:
IsValidForTheDay = false;
break;
case DayOfWeek.Monday:
IsValidForTheDay = true;
break;
case DayOfWeek.Tuesday:
IsValidForTheDay = true;
break;
case DayOfWeek.Wednesday:
IsValidForTheDay = true;
break;
case DayOfWeek.Thursday:
IsValidForTheDay = true;
break;
case DayOfWeek.Friday:
IsValidForTheDay = true;
break;
case DayOfWeek.Saturday:
IsValidForTheDay = false;
break;
}
return IsValidForTheDay;
}
public bool IsBusinessClosure(DateTime Dt, List BusinessClosure)
{
bool IsBusinessClosure = false;
foreach (ClosureConfig rule in BusinessClosure)
{
if (Dt >= rule.Start && Dt <= rule.End)
{
IsBusinessClosure = true;
}
}
return IsBusinessClosure;
}
public List GetClosureConfig(IOrganizationService service)
{
List list = new List();
QueryByAttribute query = new QueryByAttribute();
query.EntityName = "calendar";
query.Attributes.Add("name");
query.Values.Add("Business Closure Calendar");
query.ColumnSet = new ColumnSet(true);
EntityCollection collection = service.RetrieveMultiple(query);
EntityCollection CalenderRules = collection.Entities[0].Attributes["calendarrules"] as EntityCollection;
foreach (Entity Calender in CalenderRules.Entities)
{
if (Calender.Attributes.Contains("effectiveintervalend") && Calender.Attributes.Contains("effectiveintervalstart"))
{
DateTime StartDate = (DateTime)Calender.Attributes["effectiveintervalstart"];
DateTime EndDate = (DateTime)Calender.Attributes["effectiveintervalend"];
list.Add(new ClosureConfig() { Start = StartDate, End = EndDate });
}
}
return list;
}
}
class ClosureConfig
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
}
}
Hi Suresh_Satti,
Unfortunately, there is no OOB way to do this. You could post an idea at here(experience.dynamics.com/.../) to progress this feature.