Announcing the Global SNUG Board of Directors. Learn more here
‎08-07-2015 08:54 AM
I feel as though this should be a simple task but I am not proficient at scripting yet. I've not found anything quite spelling it out for me as to how to script it well.
Background
I have a workflow running on the Incident table who's purpose is to stop the SLA clock from running until the due date is met; at which point it clears the due date and sets the INC back to active.
Issue
The problem comes in when someone changes the 'Due Date' value to something else. The workflow still waits for the original date to continue with the workflow.
Goal
I wanted put some script to look at the 'Due Date' with the OnChange condition. to fix the problem. Or possibly use the 'Wait for Condition' action instead of the regular timer, because "The workflow evaluates the wait for condition each time the current record is updated." which would make the Due Date field be checked to make sure it still has the same due date.
any help would be very much appreciated. let me know if you need more detail to understand the issue.
Solved! Go to Solution.
‎12-10-2015 12:08 PM
I've been able to piece together a solution, thanks to some code posted by Dan Patino here.
Hopefully someone else will find this helpful.
I setup a business rule to run on the Task table, on updates when the due_date changes.
The parts of this code to enter in your own data are on lines 3 and 35.
var PAtimer = retrieveTriggerRecord('NAME OF TIMER');
NAME OF TIMER is literally just the name given to the timer action you want to be updated.
var newDT = new GlideDateTime(DATE FIELD);
DATE FIELD - I just put in the date field from the task table; current.due_date.getDisplayValue()
Here's the code in its entirety:
function onAfter(current, previous) {
//Reschedule Pending to Active timer
var PAtimer = retrieveTriggerRecord('NAME OF TIMER');
if(PAtimer != 'none')
rescheduleNextAction(PAtimer);
function retrieveTriggerRecord(timer){
//Find the workflow context record
var grContext = new GlideRecord("wf_context");
grContext.addQuery('id',current.sys_id);
grContext.query();
if(!grContext.next())
return 'none';
//Find the Workflow Executing record
var grExecuting = new GlideRecord("wf_executing");
grExecuting.addQuery("context", grContext.sys_id);
grExecuting.addQuery("activity.name", timer);
grExecuting.addQuery("activity.activity_definition.name", 'Timer');
grExecuting.query();
if (!grExecuting.next())
return 'none';
//Find the sys_trigger record
var grTrigger = new GlideRecord("sys_trigger");
grTrigger.addQuery("name", 'WFTimer' + grExecuting.sys_id.toString());
grTrigger.query();
if (grTrigger.next())
return grTrigger;
else
return 'none';
}
function rescheduleNextAction(trigger){
var newDT = new GlideDateTime(DATE FIELD);
trigger.next_action = newDT.toString();
trigger.update();
}
}
‎08-07-2015 02:23 PM
Simon,
I will have my couple of suggestions here:
1. When there is a timer activity running for a workflow, there will a job running in sys_trigger table which will invoke the Workflow whenever the timer ends. The record in sys_trigger will have name some thing like :
WFTimer06c9501574d79100178ea0568d3fab9d
In the above line '06c9501574d79100178ea0568d3fab9d' is sys_id of the Timer Activity which is being executed/waiting at that time. Thats how is know which workflow/timer activity needs to invoked whenever timer ends.
In the sys_trigger job, there will be another field called 'Next Action' which tells us the date and time the sys_trigger job needs to be run.
In your case what you can do is whenever Due date is changing you can have a business rule which updates the above sys_trigger job's Next Action to what ever date you need. You can uniquely identify the job using the sys_id of the Workflow Timer activity which you can get by querying the workflow context and there by querying the Workflow Executing Activities table.
But the above option has a disadvantage, when your workflows grow eventually when you do a GlideRecord on that table because of huge number that might cause performance issues later on.
2. Another Solution is, if the First activity of the Workflow is timer and the workflow is waiting for that timer to be done. You can have business rule whenever due date is changing which will delete the workflow context previously attached to the RITM and invoke a new Workflow with your desired due date.
3. Another solution will be implementing something other than timer activity. Its like you will have a custom field on the Incident like a flag. The workflow will wait for the flag to be true to move forward and you can have have a business rule which will create a entry in the sys_trigger job with Next Action as your due date and the script in the sys_trigger will update that flag.
Something like:
var newTrigger = new GlideRecord("sys_trigger");
newTrigger.name = 'Incident Timer - ' + current.number + ' - ' + current.sys_id; // This is to uniquely identify the sys_trigger job to update later
newTrigger.next_action = current.due_date; // Set the Next Action to Due Date
newTrigger.document = 'incident';
newTrigger.document_key = current.sys_id;
newTrigger.script = "var inc = new GlideRecord('incident'); inc.addQuery('sys_id', '" + current.sys_id + "'); inc.query(); if (inc.next()) { inc.u_wait = true; inc.update();}"; // Field u_wait is the flag
newTrigger.job_id.setDisplayValue('RunScriptJob');
newTrigger.trigger_type = 0;
newTrigger.insert();
Now if the Due Date is changing you can have a business rule which can query the sys_trigger using the uniquely identified name and update the Next Action with what ever date you like.
‎08-10-2015 07:15 AM
Thanks Mani,
This is great information to know, regarding the sys_trigger table. I think I am going to implement the first suggestion, however I am not so good at scripting. I have started the business rule to run when the 'due date' field is changed, but I do not know how to write the code for:
You can uniquely identify the job using the sys_id of the Workflow Timer activity which you can get by querying the workflow context and there by querying the Workflow Executing Activities table.
‎08-10-2015 07:35 AM
For example, in a before update business rule, you want to check out any business rule that's script contains sys_trigger:
var nowdt = new GlideDateTime();
nowdt.setDisplayValue(current.due_date);
var gr = new GlideRecord("sys_trigger");
gr.name = current.number + " State Movement";
gr.next_action = nowdt;
gr.trigger_type = 0; | // sys_trigger type Run Once |
gr.job_context = "Auto created schedule job for moving the state based on due date of " + current.number;
gr.script = "current.state = <your state value>; current.update();";
gr.insert();
‎08-10-2015 08:01 AM