Mixing Workflow Rules and Triggers Part 2

In an earlier post, I wrote about how I sometimes use workflow rules for manage the logic for my triggers. I sometimes use a similar trick to get workflow rules to fire. Let’s say I have a requirement to send an email to the account owner when something happens on the account, but I want to allow each user to set his or her email preferences. My solution ends up being to use a custom setting to store the user’s email preferences. I can’t set up criteria in my workflow rules to look at the account owner’s custom setting preferences, so I’ll need a trigger to decide if the email needs to be sent. I don’t want to have to write all the logic for sending the email in my trigger. I’d prefer to use the declarative side of things to handle that.

First, I’ll create the custom setting. I’ll make it hierarchical so I can set preferences at the org, profile and user level.

Custom Setting

Second, I’ll add a field on the account that will be used by my workflow rule.

custom field

Third, I’ll add a workflow rule that sends an email and also does a field update to clear the send email field on the account.

workflow rule

Finally, I’ll create my trigger to update the field above which should cause the workflow rule to fire:

trigger HotAccountNotification on Account (before update, before insert) {
    Account[] AccountsToUpdate = new Account[]{};
    for (Account a : trigger.new) {
        //only send an email if the rating is Hot
        if (a.Rating == 'Hot') { 
            // only send the email if we are inserting a new record or updating the rating on an existing one
            if (Trigger.isInsert || (Trigger.isUpdate && Trigger.oldmap.get(a.id).Rating != 'Hot')) {
                // Check custom setting to see if the email should be sent
                EmailPref__c ep = EmailPref__c.getInstance(a.OwnerId);
                if (ep.Send_Hot_Account_Email__c) {
                    a.Send_Hot_Email__c = true;
                    // Since there is a workflow rule on this object with a field update 
                    // that clears the send hot email field as soon as it fires,
                    // we can't really assert that the trigger fired.
                    if (Test.isRunningTest()) {
                        a.Description = 'Hot Account Notification Trigger Fired';

You’ll notice one interesting thing about the trigger. On line 16, I use the Test.isRunningTest Method to update another field on the record. The reason I do this is so I can do some proper assertions in my test methods. If I didn’t have this block of code, then the trigger would fire, the field would get updated, the workflow rule would fire and then the field update would reset it back to unchecked. This all happens in the same transaction so I have no way of using an asserting on the Send Hot Email field. Instead, I’m going to update another field only during tests and check to make sure it was updated as expected in my test method.

9 thoughts on “Mixing Workflow Rules and Triggers Part 2”

  1. This is fantastic! Could I please ask you to provide your unit test code, too? I can’t code my way out of a box, but I could definitely use this in my instance!

    1. Hi Jake,

      I’ll be posting a followup blog post on how the test class might look. Bear in mind that I made up this scenario for demonstration purposes.

  2. Hi Daniel,

    I was wondering if the email that goes out through the trigger->workflow route gets counted against the daily limit for Apex emails (1000 I believe)

    Any idea?


    1. I’m pretty sure that since the email is sent my the workflow rule, you aren’t subject to the Apex email limit. It uses the workflow email limit instead.

Leave a Reply