Name
global.PlannedTaskUtils
Description
Planned Task utility functions, commonly called from business rules
Script
var PlannedTaskUtils = Class.create();
/*
* Set children to same start state as parent
*/
PlannedTaskUtils.startChildren = function(gr, workState) {
if(glb_changeTrigger && !this.isAncestor(glb_changeTrigger, gr)) {
// Don't set the state of the child nodes since this node is
// not under the same subtree whose root triggered this
return;
}
gs.log("PlannedTaskUtils.startChildren");
var child = new GlideRecord('planned_task');
child.addQuery('parent', gr.getUniqueValue());
child.addQuery('time_constraint', 'asap');
child.addQuery('start_date', gr.start_date);
child.addActiveQuery();
child.query();
gs.print(" PlannedTaskUtils.startChildren:: child query: "
+ child.getEncodedQuery() + " = " + child.getRowCount());
while (child.next()) {
child.state = workState;
child.update();
gs.log(" PlannedTaskUtils.startChildren:: updated "
+ child.getDisplayValue() + " to state " + workState);
}
};
/*
* Restart children when parent is restarted (active changes to true)
*/
PlannedTaskUtils.reactivateChildren = function(parent) {
gs.log("PlannedTaskUtils.restartChildren");
var child = new GlideRecord('planned_task');
child.addQuery('parent', parent.getUniqueValue());
child.addInactiveQuery();
child.query();
gs.print(" PlannedTaskUtils.restartChildren:: child query: "
+ child.getEncodedQuery() + " = " + child.getRowCount());
while (child.next()) {
child.active = true;
child.work_start = "";
child.work_end = "";
child.percent_complete = 0;
child.update();
gs.log(" PlannedTaskUtils.restartChildren:: " + child.getDisplayValue()
+ " restarted");
}
};
/*
* Start or queue successor tasks when predecessor is closes
*/
PlannedTaskUtils.startSuccessors = function(task, startState) {
gs.log("PlannedTaskUtils.startSuccessors");
gs.log("PlannedTaskUtils.startSuccessors:: is task still active: "
+ task.active);
// Find all successors
var rel = new GlideRecord('planned_task_rel_planned_task');
rel.addQuery('parent', task.getUniqueValue());
rel.addQuery('type.name', 'Predecessor of::Successor of');
rel.query();
gs.log(" PlannedTaskUtils.startSuccessors:: rel query: "
+ rel.getEncodedQuery() + " = " + rel.getRowCount());
while (rel.next()) {
var successorId = rel.child.toString();
// For this successor, search for any more active predecessors
var rel2 = new GlideRecord('planned_task_rel_planned_task');
rel2.addQuery('child', successorId);
// rel2.addQuery('parent', "!=", task.getUniqueValue());
rel2.addQuery('type.name', 'Predecessor of::Successor of');
rel2.addQuery('parent.active', true);
rel2.query();
gs.log(" PlannedTaskUtils.startSuccessors:: rel2 query: "
+ rel2.getEncodedQuery() + " = " + rel2.getRowCount());
if (rel2.hasNext()) {
// this task still has active predecessors, skip it
gs
.log(" PlannedTaskUtils.startSuccessors:: predecessors found doing nothing");
continue;
}
// No active predecessors, start it
// If the relationship has lag, or the successor is to start on a
// specific date, schedule
if (rel.child.time_constraint == 'start_on'
|| rel.lag.getGlideObject().getNumericValue() > 0) {
gs
.log(" PlannedTaskUtils.startSuccessors:: scheduling task for future");
PlannedTaskUtils.triggerTask(rel.child.getRefRecord(), startState);
} else {
// No need to schedule...start the task now
var successor = rel.child.getRefRecord();
if (successor.isValidRecord()) {
gs
.log(" PlannedTaskUtils.startSuccessors:: starting successor "
+ successor.getDisplayValue());
successor.state = startState;
successor.update();
}
}
}
};
/*
* schedule a lag task for some time in the future
*/
PlannedTaskUtils.triggerTask = function(task, startState) {
// Search for a pre-existing trigger
var trigger = new GlideRecord("sys_trigger");
trigger.addQuery("document_key", task.getUniqueValue());
trigger.query();
if (trigger.next()) {
// You found a trigger...update it with the new start time
trigger.next_action = task.start_date;
trigger.update();
} else {
// You didnt find a trigger...create one
var newTrigger = new GlideRecord("sys_trigger");
newTrigger.name = 'Start planned task ' + task.short_description;
newTrigger.next_action = task.start_date;
newTrigger.document = 'planned_task';
newTrigger.document_key = task.getUniqueValue();
newTrigger.script = "var taskGr = new GlideRecord('planned_task'); if (taskGr.get('"
+ task.getUniqueValue()
+ "')) {taskGr.state = "
+ startState
+ "; taskGr.update();}";
newTrigger.job_id.setDisplayValue('RunScriptJob');
newTrigger.trigger_type = 0;
newTrigger.insert();
}
};
/*
* Close parent when all child tasks are closed
*/
PlannedTaskUtils.closeParent = function(task, closeState) {
// get active tasks with same parent
var sibling = new GlideRecord('planned_task');
sibling.addQuery('parent', task.parent);
sibling.addActiveQuery();
sibling.query();
if (sibling.hasNext()) {
// parent still has active task, do nothing
return;
}
// all of the parent's children are closed, so close parent
var parent = task.parent.getRefRecord();
if (!parent.isValidRecord()) {
return;
}
parent.state = closeState;
parent.update();
};
/*
* Start parent when a child starts
*/
PlannedTaskUtils.startParent = function(task, state) {
if (JSUtil.nil(task.parent))
return;
var parent = task.parent.getRefRecord();
if (parent.state == state)
return;
parent.state = state;
parent.update();
};
PlannedTaskUtils.isAncestor = function(ancestor, task) {
if(ancestor.sys_id === task.sys_id) {
return true;
}
var path = task;
var alreadySeen = new Object();
var i = 0;
while(!JSUtil.nil(path)) {
i++;
if(alreadySeen.hasOwnProperty(path.getValue('sys_id'))) {
// loop
break;
}
if(path.getValue('sys_id') === ancestor.getValue('sys_id')) {
return true;
}
alreadySeen[path.getValue('sys_id')] = 1;
path = path.parent.getRefRecord();
}
return false;
};
Sys ID
8de20f06c0a80a6c1dc02759ee9d4e95