Wait for Closure of all Tasks in Graphical Workflow

//Wait for Closure of all Tasks in Graphical Workflow

Wait for Closure of all Tasks in Graphical Workflow

A

common Graphical Workflow requirement in ServiceNow is to tell the workflow to wait for some trigger before continuing. The ‘Wait For condition’ activity is available out-of-box and is very simple to configure. Usually when working with Service Requests or Change Requests I am asked how you can set up the workflow to wait for completion of all associated tasks before closing the Request Item or Change Request ticket. This can be easily accomplished by using a script in your ‘Wait For condition’ activity to query for any associated tasks that are still marked as ‘Active’. If the task is marked as ‘Active’ then it hasn’t been closed yet and the workflow should wait for that closure. Here are some sample scripts that I’ve used before to wait for task completion on both Request Items and Change Requests.


The scripts below can be pasted into the ‘Wait For condition’ activity script field as shown here…

Request Item ‘Wait For’ Scripts
Request Item – Wait for Closure of All Tasks:

//Query for all tasks to see if they are inactive
var rec = new GlideRecord('sc_task');
rec.addQuery('request_item', current.sys_id);
rec.addQuery('active', true);
rec.query();
if(rec.hasNext()){
answer = false;
}
else{
//Continue
answer = true;
}

Request Item – Wait for Closure of Workflow-generated Tasks:

//Query for all tasks to see if they are inactive
var rec = new GlideRecord('sc_task');
rec.addQuery('request_item', current.sys_id);
rec.addNotNullQuery('wf_activity');
rec.addQuery('active', true);
rec.query();
if(rec.hasNext()){
answer = false;
}
else{
//Continue
answer = true;
}
Change Request ‘Wait For’ Scripts
Change Request – Wait for Closure of All Tasks:

//Query for all tasks to see if they are inactive
var rec = new GlideRecord('change_task');
rec.addQuery('change_request', current.sys_id);
rec.addQuery('active', true);
rec.query();
if(rec.hasNext()){
answer = false;
}
else{
//Continue
answer = true;
}

Change Request – Wait for Closure of Workflow-generated Tasks:

//Query for all tasks to see if they are inactive
var rec = new GlideRecord('change_task');
rec.addQuery('change_request', current.sys_id);
rec.addNotNullQuery('wf_activity');
rec.addQuery('active', true);
rec.query();
if(rec.hasNext()){
answer = false;
}
else{
//Continue
answer = true;
}
Whether or not a task is checked in a workflow depends on the ‘Parent’ association as defined in the ‘SNC – Run parent workflows’ business rule on the task table. You may have to modify that business rule or create a modified version of it for the tables you’re working with. The logic behind the business rule is that it waits for certain closure conditions on child tasks and then runs workflows on any associated parents to check for things like ‘Wait for’ conditions. If your child tasks don’t meet these conditions then the parent task workflow will not be triggered when updates to the tasks are made.
By | 2018-07-09T15:00:08-06:00 August 16th, 2010|Categories: Graphical workflow|Tags: , , |24 Comments

About the Author:

24 Comments

  1. Wayne February 21, 2012 at 7:22 pm - Reply

    Hi there
    Is this a client script? If not then what type
    Cheers
    W.

    • Mark Stanger February 21, 2012 at 7:33 pm - Reply

      These scripts run server-side and are placed in the script field of a workflow ‘Wait for condition’ activity.

      • Wayne February 22, 2012 at 11:40 am - Reply

        Thank you very much Mark

  2. Cameron March 11, 2013 at 3:43 pm - Reply

    I used your Request Item – Wait for Closure of Workflow-generated Tasks – and it’s worked except for one small thing. After the condition of all tasks being complete, I have the Condition then linked to a notification to the Caller (or user, or the person that put in the ticket) to let them know all tasks have been completed. But instead of just one notification, it shoots out individual emails for each task that was completed. In this case 5 tasks.

    Summary – I have 5 tasks to be completed while there is a Wait for Condition (close all tasks) before sending out a notification. That notification then sends out 5 times.

    How do I correct that?

    • Mark Stanger March 11, 2013 at 4:58 pm - Reply

      I’m not sure how this activity would impact that in any way. As long as you trigger your notification in the request item workflow right after this activity completes, it should run fine.

      • Michelle March 12, 2013 at 3:04 pm - Reply

        If the notification is triggered right after this condition statement, then isn’t the table sc_task, with it’s multiple tasks, used to define the notification function? If the sc_task table has multiple tasks and is assigned to the notification function, then won’t the notification function cycle through all the tasks and send out an email notification for each?

        • Mark Stanger March 12, 2013 at 5:13 pm - Reply

          @Michelle, the notification in my examples is running from a catalog item workflow. It has no triggers based on the catalog tasks. It simply waits for all of the catalog tasks to be marked complete. I suppose what you describe is possible, but it would probably require workflows or business rule triggers at the task level (which I almost never do).

  3. Scott April 23, 2013 at 7:32 pm - Reply

    Hi Mark,
    I have a custom task table that has a workflow where it creates a number of tasks on a non-standard REQ. the first task (for this example I’ll call this the parent task) has to be completed before the workflow triggers another 5-6 tasks simultaneously (again for this example we’ll call these child tasks) to various workgroup groups. these child tasks have no dependencies and can be actioned in their own time. When all tasks are closed a business rule then kicks in to auto close the REQ. After seeing this article it looks like all I needed to do was apply one of the above conditions.
    Anyway, my question to you is, is it possible for me to configure a “final” task, that doesnt get triggered until all the “child” tasks are completed?

    • Mark Stanger April 23, 2013 at 7:37 pm - Reply

      You can, you just have to query the right place for the appropriate tasks. I don’t know exactly what that script would be, but it would likely be very similar to what I’ve documented in this article.

    • Josh April 26, 2013 at 12:01 pm - Reply

      Hi Scott,

      You don’t really need to script anything and all of that can be done via workflow. The workflow editor has a utility called Join, which is pretty much what the script above does. Connect the “Child Tasks” to the join and once they are all are completed have the Join Completed action connect to your “Final Task”. If you need assistance just reply with your email and I can help you out.

    • Mark Stanger April 26, 2013 at 12:18 pm - Reply

      Thanks for the reply Josh. Now that I read this again I’m understanding a bit better. Josh is right, you shouldn’t need a script for this as long as the tasks are all generated from task activities in the workflow. You can handle the wait for between the initial task and the group of tasks by using the ‘Wait for’ attribute shown here.

      http://wiki.servicenow.com/index.php?title=Task_Activities#Activity_Variables_3

      Then you can use the join activity after the group of tasks like Josh explained.

      • Josh April 26, 2013 at 12:55 pm - Reply

        No problem Mark!

        Also instead of querying on the wait for condition, I’ve found the scratchpad works really well and saves a query.

        In the task you could use the advance script:

        workflow.scratchpad.my_task = task.setNewGuid();

        and then in the wait for script:

        var gr = new GlideRecord(“table_name”); // where table name is name of the table your tasks are on
        gr.get(workflow.scratchpad.my_task);
        if (gr.state == num) { //where num is the value of your closed state
        answer = true;
        }
        else{
        answer = false;
        }

        • Josh April 26, 2013 at 12:57 pm - Reply

          ops tiny mistake:

          and then in the wait for script:

          var gr = new GlideRecord(“table_name”); // where table name is name of the table your tasks are on
          gr.get(workflow.scratchpad.my_task);
          if (gr.state == num) { //where num is the value of your closed state
          answer = true;
          }
          else{
          answer = false;
          }

  4. Felipe Barbosa January 23, 2014 at 1:26 pm - Reply

    Hi Mark, thanks much for this. I have several wait for conditions running on a workflow for requested item, and I noticed that the wait for condition runs several times in sequence, while it doesn´t meet the criteria to set answer to true, the issue is that I have several workflows running at the same moment, and some of them are on the waiting for condition looping in the background, which is causing some performance issues. Is there a way to control when the wait for condition script runs to avoid overloading the instance?

    Thanks in advance.

    Best regards,

    Felipe

    • Mark Stanger January 24, 2014 at 5:41 am - Reply

      Not really. The workflow conditions are generally evaluated on updates to the associated records (which you definitely want to happen). If you’re seeing performance issues, then you probably need to look more closely at the number of workflows running and your overall workflow design.

  5. Chandra Miller March 12, 2015 at 9:21 pm - Reply

    Thank you soo much! I have been looking for this code and so happy you have posted! This works much better than “Join”!

  6. Juan Alfaro September 15, 2015 at 3:14 pm - Reply

    Hello Mark,

    Is there a similar script to use a wait for condition but on the request workflow? For example, for the request to be completed automatically once all requested items are completed?

    Thanks in advance,
    JP

    • Mark Stanger September 16, 2015 at 5:55 am - Reply

      That’s a built-in behavior of the tool so you shouldn’t need to modify anything to make that work. If it’s not working then there’s been a change made to your system that’s broken it. I would compare what you’ve got with a clean demo instance and make sure all of the business rules on the requested item and request tables are the same.

  7. Michel Hanna October 18, 2015 at 6:54 pm - Reply

    Hi,
    SN documentation (http://wiki.servicenow.com/index.php?title=Condition_Activities#Wait_for_condition) says that “The workflow evaluates the wait for condition each time the current record is updated.”
    But looking at your Request Item ‘Wait For’ Scripts, the current record is Request Item and the workflow it is waiting for a change in another table (Task to be inactive), but I from my understanding that wouldn’t update the current record which is a Request Item, and hence it shouldn’t trigger the workflow to re-evaluate the waitfor condition.
    I’m sure the examples you’ve provided are working fine, but I’m confused as to what triggers the workflow to evaluate the condition, if you please could verify.

    Thanks,
    Michel

    • Mark Stanger October 19, 2015 at 7:16 am - Reply

      Good question. The wiki documentation, while technically correct, is also incomplete. The ‘Wait for’ condition is evaluated whenever the workflow context is re-evaluated. This happens on any update of the ‘current’ record, but it can also be invoked at other times from a script. There is an out-of-box business rule named ‘SNC – Run parent workflows’ that checks each record when it is de-activated and then triggers the evaluation of workflow contexts for any parent record. That’s why this solution works. Catalog tasks and Change tasks are linked to a parent record and they trigger the parent workflow context when they’re de-activated.

      • Eric December 16, 2015 at 11:56 am - Reply

        I don’t know if it actually does work.

        I allow users to create ahdoc tasks along with the ones generated in the workflow. I use a workflow activity with this script at the end so it makes sure all tasks, regardless of who created it, are closed. If I close all the workflow-generated tasks first, and then close the manual ones, it never closes out the RITM. If I make a change on the RITM and save it, then it moves forward. But otherwise it is stuck there indefinitely.

      • Heather October 27, 2016 at 2:52 pm - Reply

        I also am having an issue where the workflow generated task is closing the RITM, even if a manual task has been added before the completion of the workflow task. Using Join only appears to work for the taks that have been created in the workflow and has no impact on the manual task which still closes the RITM. I tried using the below wait for condition but now it is keeping the RITM open even if all tasks have been completed. Is there anything you recommend for this scenario?

        • Mark Stanger October 27, 2016 at 2:55 pm - Reply

          My recommendation is what’s posted above. It really sounds like you’ve got some other issue in your system that might be causing a conflict with what’s been posted here.

  8. JR Guieb March 17, 2017 at 4:40 pm - Reply

    Hi Mark,

    This works great but I noticed the RITM will close only the last task that is closed is a WF generated task.

    If the last task that is closed is a manually created task the RITM stays open.

    I tested this in our own instance and in a brand new developer instance. Is there a way around this?

Leave A Comment