A very frequent requirement that customers present for their CRM system functionality is that they will get automatic reminders from it when an item recorded into the database requires their attention after a specific date is reached. This might be a hard, physical date like a contract expiring or a softer variable such as a follow-up date on an open opportunity. Since receiving email notifications from various online services is such a ubiquitous pattern for process reminders these days, it’s only natural that the CRM system is expected to behave the same way.
What sounds like a straightforward thing to implement with the help of the Dynamics CRM workflow processes isn’t necessarily such an easy task – at least if you want the reminder workflow to operate correctly under all the possible circumstances. In a scenario where the reminder is set by the user via a value entered into a date field there’s a number of other variables that you should take into consideration besides that single data entry. For a developer who is used to dealing with user inputs and exceptions this may be just another routine task of figuring out the logic surrounding the reminder date variable, but for a functional consultant who typically works more directly with the end users and mainly just points & clicks in the CRM customization menus for building out the required functionality this may not be such familiar territory. I’ll be the first to admit that I struggle with workflow logic a lot.
Given how much time I’ve spent wondering “how should I do this” when it comes to CRM workflows, the wording of this blog post’s title is pretty bold. Is there really a single right way to build reminder workflows and do I know nearly enough about them to claim the privilege of defining the proper design pattern for them? This is actually just more of a provocation through which I’m hoping to gather feedback on the inevitable shortcomings of this post via the comments section. Another reason behind this choice of the title is that I stand on the shoulders of giants when it comes to my knowledge about CRM workflows, meaning everything I know about them I’ve read from blogs elsewhere and I’ll try my best to highlight the articles deserving most attention via linking to them as we move forward.
In this post I’ll use a scenario where the opportunity record has been extended with a custom follow-up date field. Entering a date into the field is done by any user who has access to update the opportunity. When the follow-up date is reached, a reminder should be sent to the owner of the opportunity, but only if the record is still in an open status, since won or lost opportunities don’t require reminders anymore. Sounds logical? Good, then let’s start working on implementing all the required business logic onto the Dynamics CRM workflow editor canvas.
The first thing we need to decide on when designing workflows is defining the criteria on when should we be performing any actions to begin with. In our scenario, any moment a user could enter a value into our reminder date field is a potential trigger for our workflow logic, so we should have the process started both on the create event of the record as well as the change event of the field in question.
Since we’re dealing with an optional field that doesn’t necessarily contain any value, we should check this right away. It’s not enough that there is a value in the field, but it also needs to be something we can act upon. There are two general things that interest us: 1) is the record sill active (meaning does it require any reminders) and 2) is the reminder date in the future. There’s no point in us sending an email to a user right away if he or she mistakenly enters a date that’s passed last month already, so better to just ignore any such input values and do nothing in this case.
Wait conditions and stopping the workflow
If we’ve determined that there is a valid reason for our workflow to take note of the event to which it has been attached to, the next step is to… just wait. No, I didn’t mean you can just start slacking away with your workflow design! Waiting in itself is a topic deserving your full attention as a CRM customizer, since there are more than just one type of waits in the platform we’re working with. Read this great article by Paul Nieuwelaar for an in-depth discussion on the different options available.
There are multiple possible outcomes that should cause our workflow process to wake up. It’s not only the events when a follow-up action should be performed but also any path that leads to a state where the workflow is no longer required. After all, you really don’t want to have an ever increasing number of workflow instances left forever waiting in your CRM system, hogging up resources unnecessarily. So, in our scenario, whenever the status of an opportunity changes to something else than “open” before the reminder date is reached, we’ll want to stop our workflow.
This brings up another best practice regarding Dynamics CRM workflows. We have the option of stopping a workflow with the status values of “Succeeded” or “Cancelled”. As a general rule of thumb, you should always choose to stop your workflow as “Succeeded” unless you have a good reason to do otherwise. This is because a “Cancelled” value is considered an exception in the workflow process job execution and it will leave a permanent record into the system for debugging purposes. If the stopping is just business as usual for your workflow logic, let the system job be deleted by choosing the “Succeeded” option. Only use the “Cancelled” value if you intend to go through and review all the cancelled process instances when testing or debugging your workflows.
Change of date
Since our trigger field is just a normal date field on the opportunity form, we need to take into consideration the fact that a user may at any stage go and update the date value. For example, when the opportunity in question gets delayed due to lack of actions from the customer’s decision makers, the opportunity follow-up reminder would naturally also get postponed to a later date. Whether a reminder has already been sent for the record or not doesn’t actually matter to us, since what we’re dealing with in this scenario is a reusable reminder field that should always work reliably and deliver a notification at the time specified by the user.
Since our start conditions were tied to not just the creation of a new record but also any changes made to the follow-up date field, this will create a new instance of the workflow process whenever the field value is updated. We don’t want to have multiple concurrent waiting workflows for the same record and we most certainly don’t want to send more than one reminder at the follow-up date, so we need a logic to get rid of the old process instance when a new one is created. But how do we tell the existing workflow that a new version has been created?
There’s one additional “gotcha” in this situation that relates to how Dynamics CRM deals with null values in workflow parameters. Suppose the user determines that no follow-up reminders are necessary for the record anymore and clears the follow-up date field on the form. The workflow process that tries to evaluate this value will throw an exception, as illustrated in this post by Allan Varcoe. Not only would this cause issues with having cancelled workflow instances piling up in the system, it would also stop us from executing any other logic in such a workflow.
Luckily there’s a workaround to this issue and it fits our needs perfectly. As described by Allan, what we can do is store the current value of the follow-up date into a hidden field when we start our workflow. We then use the cached value in this field to compare it with any subsequent new values entered by the user into the actual follow-up date field. So, on the very first line of our workflow process we would add the following update action:
Then at the waiting stage, in addition to waiting for the opportunity status change event, we’ll add a parallel wait branch that will monitor the changes in the follow-up date field. If at some point in time the field value on the opportunity record no longer matches the one that was cached into our hidden field at the start of this workflow instance, we know that the current workflow instance is no longer required and we can gracefully terminate it.
This will make sure that there is always a maximum of one workflow instance waiting for the specific follow-up date on a single record. We could have built a similar type of logic also in the form of a workflow instance counter that would have always incremented a field value upon the start of the workflow, but due to the possible exceptions being thrown if a user clears the date field, this is a much better approach for us to take.
Sending out the reminder
If an opportunity record passes through all of these conditional gates that we’ve set up, it most likely will be a valid target for a reminder message. Alternatively, we may have simply missed some possible outcome and need to add further conditions to the workflow rule. This is one reason why it often makes sense to build the business logic in a format of continuous elimination, meaning you keep adding criteria that filters out any scenarios where you don’t want the action to be performed (in which case you just stop the workflow as succeeded with no actions taken) and wait until the very end to actually perform the work that you originally set out to do with the workflow.
In this example we’ll send out an email message to the opportunity owner when the reminder date is reached. Now, a question that some of you may have on your mind is “why not just create a related task with a deadline as the reminder?” While it’s true that a very simple way for dealing with the reminder requirement would have been to add a new task record when a date value is entered on the opportunity record, this would make it very complex for us to later on validate the need for the reminder if any of the outcomes we’ve discussed above would have taken place (change of status, new dates being entered etc.). This is why in general I’m not in favor of creating any task records in advance to serve as a reminder, but rather prefer to wait until the last minute to see if an action is really required. If you wish, you can of course add a task record alongside the email notification to act as a more persistent reminder.
While you might think that the Send Email action would be a very straightforward thing to implement in a workflow, I recommend you to take a different route and instead add a separate child workflow that will take care of the actual email sending. Why? Because this will provide an additional “shield” for any events that may occur between the time the workflow instance is created and the moment the actual email should be sent out. For example, if you wish to change any properties in the email message (changes in the organization’s processes, new sales director wants to be included as CC in all the reminders etc.), then any waiting workflow instances may have already cached a copy of the original definition, making it difficult to change the process on the fly. On-demand child workflows will not suffer from such handicap.
By having the email send step included in a child workflow that is executed on demand rather than after a long waiting period, we are effectively implementing the dispatcher workflow pattern described by Dave Berry. To understand all the benefits of this pattern, I recommend you to review Dave’s article, as well as this extremely thorough piece by Adam Vero on when and how to use child workflows in Dynamics CRM. These things are far from obvious to the casual CRM customizer, but after reading the real life examples presented by Dave and Adam you’ll most likely want to start using child workflows in many more scenarios than what you’ve previously thought.
Putting it all together
We’ve now managed to build a workflow process for sending out the opportunity follow-up reminder, which will look something like this:
The child workflow will consist of just the email sending step, so that’s not covered in the screenshot above. Since interpreting the logic behind a workflow from the steps configured in the workflow editor can sometimes be a bit challenging, I’ve also drawn the logical flow of the process into a series of steps illustrated in the following picture:
As always, there’s certainly more than one “right way” of designing a workflow process to implement a custom business logic in Microsoft Dynamics CRM. Hopefully this example has given you some ideas of how to make your reminder workflows cover the possible outcomes in a simple date field based scenario, allowing you to further extend the model to meet the requirements of specific business processes.