Recently I received a requirement to set the Incident Auto Closure date to 'CreatedOn' + 7 working days. To add working days to 'CreatedOn' date, we need to exclude all the weekend and business closures. I came up with the following solution to achieve the required outcome.
Add the following Class to your project to calculate working day and business closures.
using System; using System.Collections.Generic; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Query; namespace HayerCrmPackage.Plugins { public class AddWorkingDaysClass { ////// Add working days to a specific date by calculating Business Closure and weekends /// public static DateTime AddWorkingAndBusinessClosureDays(DateTime specificDate, int workingDaysToAdd, IOrganizationService service, IPluginExecutionContext context) { var currentDate = specificDate; var businessClosures = GetBusinessClosureCalendarRules(context, service); // Calculate the working days by taking out the weekends int completeWeeks = workingDaysToAdd / 5; DateTime date = specificDate.AddDays(completeWeeks * 7); workingDaysToAdd = workingDaysToAdd % 5; for (int i = 0; i < workingDaysToAdd; i++) { date = date.AddDays(1); while (!IsWorkingDayOfWeek(date)) { date = date.AddDays(1); } } // Calculate the working days by taking out Business Closures for (var i = currentDate; i <= date; i = i.AddDays(1)) { if (i.DayOfWeek == DayOfWeek.Saturday || i.DayOfWeek == DayOfWeek.Sunday) continue; foreach (var closure in businessClosures) { var startDate = (DateTime)closure["effectiveintervalstart"]; var endDate = (DateTime)closure["effectiveintervalend"]; var range = new DateRange(startDate, endDate); if (range.Includes(i)) { date = date.AddDays(1); if (date.DayOfWeek == DayOfWeek.Saturday) { date = date.AddDays(2); i = i.AddDays(1); } else if (date.DayOfWeek == DayOfWeek.Sunday) { date = date.AddDays(1); } } } } return date; } ////// Get Business Closure Calendar Rules /// private static IEnumerable<Entity> GetBusinessClosureCalendarRules(IPluginExecutionContext context, IOrganizationService service) { // Get Organization Business Closure Calendar Id var organization = service.Retrieve("organization", context.OrganizationId, new ColumnSet("businessclosurecalendarid")); var query = new QueryExpression("calendar") { ColumnSet = new ColumnSet(true), Criteria = new FilterExpression() }; // Add condition to get Get Calander where CalanderId is equal to Organization's businessclosurecalendarid query.Criteria.AddCondition(new ConditionExpression("calendarid", ConditionOperator.Equal, organization["businessclosurecalendarid"].ToString())); // Get Calendar var businessClosureCalendar = service.RetrieveMultiple(query).Entities[0]; // Return the Calendar rules return businessClosureCalendar != null ? businessClosureCalendar.GetAttributeValue<EntityCollection>("calendarrules").Entities : null; } private static bool IsWorkingDayOfWeek(DateTime date) { var day = date.DayOfWeek; return day != DayOfWeek.Saturday && day != DayOfWeek.Sunday; } public interface IRange<T> { T Start { get; } T End { get; } bool Includes(T value); } public class DateRange : IRange<DateTime> { public DateRange(DateTime start, DateTime end) { Start = start; End = end; } public DateTime Start { get; private set; } public DateTime End { get; private set; } public bool Includes(DateTime value) { return (Start <= value) && (value < End); } } } }
To consume above class in your plugin, use the following code:
using System; using System.Linq; using HayerCrmPackage.Plugins.Entities; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Client; using Microsoft.Xrm.Sdk.Query; namespace HayerCrmPackage.Plugins { public class PreCaseCreate : Plugin { public PreCaseCreate() : base(typeof(PreCaseCreate)) { base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(20, "Create", "incident", new Action<LocalPluginContext>(ExecutePreCaseCreate))); } protected void ExecutePreCaseCreate(LocalPluginContext localContext) { if (localContext == null) { throw new ArgumentNullException("localContext"); } var pluginContext = localContext.PluginExecutionContext; var service = localContext.OrganizationService; var context = new OrganizationServiceContext(service); var targetEntity = (pluginContext.InputParameters != null && pluginContext.InputParameters.Contains("Target")) ? (Entity)pluginContext.InputParameters["Target"] : null; // Converting Entity to Incident var incident = (targetEntity != null && targetEntity.LogicalName == Incident.EntityLogicalName) ? targetEntity.ToEntity<Incident>() : null; // If you want to update the number of working days to add, change the value of 2nd parameter below incident.new_AutoClosureDate = AddWorkingDaysClass.AddWorkingAndBusinessClosureDays(DateTime.Now, 7, service, pluginContext); } } }Happy Coding
P. S. Hayer
(ਪ੍ਰੇਮਜੀਤ ਸਿੰਘ ਹੇਰ)
Ref:
1. Adding Working Week Days to a Specific Date
2. Check if Date Time is in Date Range
Please check my other (non-CRM) blog here:
Programming Blogs
No comments :
Post a Comment