Custom workflow to send e-mail after some specific working days provided at account creation
This post is to send an email on account creation to the account holder after some specific days(in this code: 7). The email will be sent after 7 working days as described in the organization's Calendar and presuming every Saturday & Sunday as holiday.
Step 1: Create new project in Visual Studio and select 'Class Library'. Then copy the code as below and save. Build the solution to get library file(*.dll)
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 BusinessClosure
{
public class BusinessClosure : CodeActivity
{
[Output("SendDate")] // Name of variable to send output to CRM on registering the workflow
public OutArgument<DateTime> SendDate { get; set; } //This is the name that will showup when we use this custom workflow in CRM
IWorkflowContext wc;
IOrganizationServiceFactory serviceFactory;
IOrganizationService service;
/// <summary>
/// Self executable function from which execution will start
/// </summary>
/// <param name="context"></param>
protected override void Execute(CodeActivityContext context)
{
int actualDays = 0; //Counter to calculate actual days to delay the email
int workingDays = 0; //Counter to calculate working days
int delayDay = 7; //Variable to hold no. of days by which we need to delay the mail
///To get service and context from CRM
wc = context.GetExtension<IWorkflowContext>();
serviceFactory = context.GetExtension<IOrganizationServiceFactory>();
service = serviceFactory.CreateOrganizationService(wc.InitiatingUserId);
//To retrieve businessclosurecalendarid from the CRM
var organization = service.Retrieve("organization", wc.OrganizationId, new ColumnSet("businessclosurecalendarid"));
///To retrieve date of creation of account and no. of days to delay the email sending
Entity account = (Entity)service.Retrieve("account", wc.PrimaryEntityId, new ColumnSet(new String[] { "createdon","first_delayemail" }));
DateTime date = ((DateTime)account.Attributes["createdon"]);
// Checking if the user has filled the days to delay the mail
try
{
delayDay = Convert.ToInt32(account.Attributes["first_delayemail"].ToString()); //setting delayDay with the specified value
}
catch (Exception)
{
}
///To check working days should not be greater than delay days
while (workingDays < delayDay)
{
date = date.AddDays(1); //Increasing date by one day
actualDays++; //Increasing actual no. of days
if (IsWeekDay(date) && IsNotClosure(date)) //Condition to check if the date lies on a holiday or not
{
workingDays++; //Increasing working days
}
}
SendDate.Set(context, date); //Setting out variable to the actual date on which the email will be sent
}
/// <summary>
/// Function to check if the date lies on weekdays
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
protected bool IsWeekDay(DateTime date)
{
var day = date.DayOfWeek;
return day != DayOfWeek.Saturday && day != DayOfWeek.Sunday;
}
/// <summary>
/// Function to check if the date does not lie on planned holidays
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
protected bool IsNotClosure(DateTime date)
{
var organization = service.Retrieve("organization", wc.OrganizationId, new ColumnSet("businessclosurecalendarid")); //Getting business closure calendar ID
///Query to fetch calendar ID
QueryExpression qe = new QueryExpression();
qe.EntityName = "calendar";
qe.ColumnSet = new ColumnSet();
qe.ColumnSet.Columns.Add("calendarid");
qe.Criteria = new FilterExpression();
qe.Criteria.AddCondition("calendarid", ConditionOperator.Equal, organization["businessclosurecalendarid"].ToString());
EntityCollection ec = service.RetrieveMultiple(qe); //Fetching all holidays records
var ds = ec.Entities[0].GetAttributeValue<EntityCollection>("calendarrules").Entities; //Fetching calendar rules from CRM
foreach (Entity e in ds) //Iterating each holiday duration
{
DateTime start = (DateTime)e["effectiveintervalstart"]; //Getting start date of holiday
DateTime end = (DateTime)e["effectiveintervalend"]; //Getting end date of holiday
if (date >= start && date <= end) //Checking if the date lies in between holiday duration
{
return false;
}
}
return true;
}
}
}
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 BusinessClosure
{
public class BusinessClosure : CodeActivity
{
[Output("SendDate")] // Name of variable to send output to CRM on registering the workflow
public OutArgument<DateTime> SendDate { get; set; } //This is the name that will showup when we use this custom workflow in CRM
IWorkflowContext wc;
IOrganizationServiceFactory serviceFactory;
IOrganizationService service;
/// <summary>
/// Self executable function from which execution will start
/// </summary>
/// <param name="context"></param>
protected override void Execute(CodeActivityContext context)
{
int actualDays = 0; //Counter to calculate actual days to delay the email
int workingDays = 0; //Counter to calculate working days
int delayDay = 7; //Variable to hold no. of days by which we need to delay the mail
///To get service and context from CRM
wc = context.GetExtension<IWorkflowContext>();
serviceFactory = context.GetExtension<IOrganizationServiceFactory>();
service = serviceFactory.CreateOrganizationService(wc.InitiatingUserId);
//To retrieve businessclosurecalendarid from the CRM
var organization = service.Retrieve("organization", wc.OrganizationId, new ColumnSet("businessclosurecalendarid"));
///To retrieve date of creation of account and no. of days to delay the email sending
Entity account = (Entity)service.Retrieve("account", wc.PrimaryEntityId, new ColumnSet(new String[] { "createdon","first_delayemail" }));
DateTime date = ((DateTime)account.Attributes["createdon"]);
// Checking if the user has filled the days to delay the mail
try
{
delayDay = Convert.ToInt32(account.Attributes["first_delayemail"].ToString()); //setting delayDay with the specified value
}
catch (Exception)
{
}
///To check working days should not be greater than delay days
while (workingDays < delayDay)
{
date = date.AddDays(1); //Increasing date by one day
actualDays++; //Increasing actual no. of days
if (IsWeekDay(date) && IsNotClosure(date)) //Condition to check if the date lies on a holiday or not
{
workingDays++; //Increasing working days
}
}
SendDate.Set(context, date); //Setting out variable to the actual date on which the email will be sent
}
/// <summary>
/// Function to check if the date lies on weekdays
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
protected bool IsWeekDay(DateTime date)
{
var day = date.DayOfWeek;
return day != DayOfWeek.Saturday && day != DayOfWeek.Sunday;
}
/// <summary>
/// Function to check if the date does not lie on planned holidays
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
protected bool IsNotClosure(DateTime date)
{
var organization = service.Retrieve("organization", wc.OrganizationId, new ColumnSet("businessclosurecalendarid")); //Getting business closure calendar ID
///Query to fetch calendar ID
QueryExpression qe = new QueryExpression();
qe.EntityName = "calendar";
qe.ColumnSet = new ColumnSet();
qe.ColumnSet.Columns.Add("calendarid");
qe.Criteria = new FilterExpression();
qe.Criteria.AddCondition("calendarid", ConditionOperator.Equal, organization["businessclosurecalendarid"].ToString());
EntityCollection ec = service.RetrieveMultiple(qe); //Fetching all holidays records
var ds = ec.Entities[0].GetAttributeValue<EntityCollection>("calendarrules").Entities; //Fetching calendar rules from CRM
foreach (Entity e in ds) //Iterating each holiday duration
{
DateTime start = (DateTime)e["effectiveintervalstart"]; //Getting start date of holiday
DateTime end = (DateTime)e["effectiveintervalend"]; //Getting end date of holiday
if (date >= start && date <= end) //Checking if the date lies in between holiday duration
{
return false;
}
}
return true;
}
}
}
Step 2: Register workflow in CRM
2.1 Open Plugin registration tool
2.2 Select library file(*.dll) and register assembly
3.1 Go to settings and then solutions
3.4 Fill details and select your custom workflow
3.5 Insert wait condition and give condition to it
3.6 Select to send email and fill details in it as below
3.7 Finally it will look like this
3.8 Save and activate the workflow
Comments
Post a Comment