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 Closure of All Tasks:
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:
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 Closure of All Tasks:
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:
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;
}
Hi there
Is this a client script? If not then what type
Cheers
W.
These scripts run server-side and are placed in the script field of a workflow ‘Wait for condition’ activity.
Thank you very much Mark
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?
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.
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?
@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).
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?
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.
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.
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.
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;
}
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;
}
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
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.
Thank you soo much! I have been looking for this code and so happy you have posted! This works much better than “Join”!
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
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.
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
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.
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.
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?
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.
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?