Home > Apex, salesforce > Salesforce.com Workflow to the Second

Salesforce.com Workflow to the Second

December 22nd, 2011 Leave a comment Go to comments

I recently came across the requirement for a workflow rule to fire on the update of a record but only if the update occurred more than a couple seconds after the record was created. Why this crazy requirement? Here is a example of the problem I was faced with.

Image you have two custom objects, Exam and Question. There is a master detail relationship between the two where many Questions can be associated with one Exam. There are also some roll-up summary fields on the Exam that count number of questions, number answered correctly, etc. Now also image (lots of imagining today so I hope you can harness your inner child imagination skills) you have a Visualforce page that assigns exams to users. This Visualforce page essentially clones a an Exam and Questions and assigns these to a user. First it inserts the Exam and then all related Questions. On the Exam object there is a workflow rule that need to execute when an Exam is updated. The problem is this workflow rule kept firing every time I inserted Exams and Questions for a user. Why is this happening? I am only inserting records, right? Wrong-a-long-a-ding-dong!!!

So what is happening here? Why is an update occurring on the Exam record when all I am doing is inserting records? The culprit are those very cool, but pesky, roll-up summary fields. When you have a roll-up summary field on a record any time you insert or update a child record an update will occur on the parent. So in the example above every time I would insert the the Questions it would cause on update action on the Exam. This is documented but it might not be something you come across every day. It’s also not obvious as everything happens so fast in the code the Created Date and Last Modified Date on the Exam show the same values in the user interface. If you queried these two date fields you would see they are milliseconds apart.

So how to solve this? There are a few options. We could set a flag, a checkbox field, on the Exam called Disable Workflow that we set to true on the insert of the Exam and then after inserting the Questions we could uncheck this box. In our workflow rule we could prevent the rule from executing by referencing this field. This would work but I don’t like it for a couple reasons. The first is that I hate adding fields to the database that aren’t really needed. Secondly, it’s less efficient as it requires multiple DML (update) operations to make everything flow smoothly. Another options is to get super crafty with our workflow rule.

The insert of the Exam and Questions is going to be finished in milliseconds. What if we make the rule fire on updates but only on updates a few seconds after the record is created. What we need to do is determine the time between the created date of the record and now in seconds. When working with formula fields or validations rules the duration of one day is represented as the value of 1. If we know this we can use our superior deductive reasoning skills to figured out the value for one second.

1 / 24 = 0.0416667 is one hour
0.0416667 / 60 = .00069444 is one minute
0.00001157 = one second

Now in our workflow rule we have have a formula like this:

…and it will evaluate to true on updates but only if those updates are greater than 1 second after the record was created.

Categories: Apex, salesforce
  1. December 23rd, 2011 at 10:27 | #1

    I remember when I used to have some sort of idea what you were talking about. Now am lucky to understand the title of your posts!

  2. Paul
    December 23rd, 2011 at 11:30 | #2

    I like this, but, it doesn’t cover things like latency in the platform. For instance, what happens if the rollup calculation takes > 1 second to complete? Would recommend 3-5 seconds there. It’s still pretty much impossible for a user to make an edit so close to another due to the fact that the platform is too slow in page loads to support it, so it’s more safe.

    Cheers,
    /p

  3. December 23rd, 2011 at 12:07 | #3

    Great idea! I’ve had the same problem before, but this solution didn’t occur to me. However, I have to agree with Paul. This still leaves a crevasse for the chaos monkey to enter the equation.

    In my opinion, consistent code is a better solution than using a field as communication. I totally agree that using fields in this manner is terrible, and I hate doing it! I’ll do it if I have to, but I’ll document the reason for the field’s existence well, and also name it differently, like Param_Trg_Runworkflow__c or something.

    Still, it’s a great idea!

  4. December 23rd, 2011 at 14:59 | #4

    Paul and Alex,

    You are absolutely right, great observations. In my actual implementation I think I wait 5 seconds.

    -Jason

  5. Vinay
    December 24th, 2011 at 08:33 | #5

    Great idea!! But only problem is that i cant you a ISCHANGED() operation in such a workflow as the workflow is triggering after the change is already done.

  6. Andy
    February 2nd, 2012 at 21:13 | #6

    Presumably you have some kind of status field already, tracking whether the exam is in progress, completed, etc. You could have a “Not Started” status which the WF references to determine whether to fire or not.

  7. Abhijeet Baneka
    June 26th, 2012 at 01:38 | #7

    If someone wants to run a workflow only on insert based on roll up summary field they can use below criteria.

    NOT(ISNEW()) && Total_completed_Permission_Items__c == 0 && ISCHANGED(Total_completed_Permission_Items__c)

    –> Total_completed_Permission_Items__c == 0 -> Rollup summary field.