Name
global.PlannedTaskUtilsV2
Description
Planned Task utility functions, commonly called from business rules
Script
var PlannedTaskUtilsV2 = Class.create();
/*
* Restart children when parent is restarted (active changes to true)
*/
PlannedTaskUtilsV2.reactivateChildren = function(parent, previousState) {
var plannedTaskStateUtil = new PlannedTaskStateUtil(parent);
var defaultSkipped = plannedTaskStateUtil.getDefaultSkippedState();
gs.log("PlannedTaskUtilsV2.restartChildren");
var api = new SNC.PlannedTaskAPI();
var stateBucket = plannedTaskStateUtil.getBucketForState(parent.state);
/*if(stateBucket != null){
var children = api.getDescendants(current, false);
var percentCompleteHelper = new PercentCompleteHelper();
percentCompleteHelper.clearStack(parent);
var childStateUtil;
var childDefaultOpen;
var childDefaultSkipped;
while (children.next()) {
childStateUtil = new PlannedTaskStateUtil(children);
childDefaultOpen = plannedTaskStateUtil.getDefaultOpenState();
childDefaultSkipped = plannedTaskStateUtil.getDefaultSkippedState();
if (previousState != defaultSkipped && children.state == childDefaultSkipped)
continue;
children.active = true;
if (stateBucket != PlannedTaskStateUtil.WORK_IN_PROGRESS)
children.state = childStateUtil.getValidStateForBucket(stateBucket, parent.state);
else if (previousState == defaultSkipped && stateBucket == PlannedTaskStateUtil.WORK_IN_PROGRESS)
children.state = childDefaultOpen;
children.work_start = "";
children.work_end = "";
children.percent_complete = 0;
percentCompleteHelper.process(children);
children.update();
gs.log(" PlannedTaskUtilsV2.restartChildren:: " + children.getDisplayValue() + " restarted " + children.state);
}
percentCompleteHelper.rollup(parent);
percentCompleteHelper.clearStack(parent);
}*/
// Else For Perfomance - Call below
if(parent.getValue('sys_id') != parent.getValue('top_task') && parent.instanceOf("pm_project"))
api.updateSubProjectState(parent, {}, plannedTaskStateUtil.getDefaultPendingState());
else
api.updateProjectState(parent, {}, plannedTaskStateUtil.getDefaultPendingState());
};
/*
* Set children when parent state is changed to Open/Pending
*/
PlannedTaskUtilsV2.setChildrenState = function(parent, bucket, state) {
gs.log("PlannedTaskUtilsV2.setChildrenState");
// var treeNavigator = new SNC.NestedIntervalUtilities("planned_task");
// var children = treeNavigator.getDescendants(current, false);
var plannedTaskStateUtil = new PlannedTaskStateUtil(parent);
var projectMgmtApi = new SNC.PlannedTaskAPI();
if(parent.getValue('sys_id') != parent.getValue('top_task') && parent.instanceOf("pm_project"))
projectMgmtApi.updateSubProjectState(parent, {}, plannedTaskStateUtil.getDefaultPendingState());
else
projectMgmtApi.updateProjectState(parent, {}, plannedTaskStateUtil.getDefaultPendingState());
// var children = projectMgmtApi.getDescendants(current, false);
// var childStateUtil;
// var childState;
// while (children.next()) {
// childStateUtil = new PlannedTaskStateUtil(children);
// childState = childStateUtil.getValidStateForBucket(bucket, state);
// children.active = true;
// children.state = childState;
// children.work_start = "";
// children.work_end = "";
// children.percent_complete = 0;
// children.update();
// }
};
PlannedTaskUtilsV2.startSuccessors = function(task, bucket) {
gs.print("PlannedTaskUtilsV2.startSuccessors - " + task.getValue('sys_id'));
// var tree = new SNC.NestedIntervalUtilities("planned_task");
// var sysIdsToStart = tree.getLeafNodesForStateChange(task.getUniqueValue(), true); //true : leaves of successor nodes
var projectMgmtApi = new SNC.PlannedTaskAPI();
var sysIdsToStart = projectMgmtApi.getLeafNodesForStateChange(task.getUniqueValue(), true); //true : leaves of successor nodes
var stateUtil;
gs.print("PlannedTaskUtilsV2.startSuccessors - sysIdsToStart : " + sysIdsToStart);
for (var i = 0; i < sysIdsToStart.length; ++i) {
var taskToStart = new GlideRecord('planned_task');
var sysId = sysIdsToStart[i];
taskToStart.get(sysId);
stateUtil = new PlannedTaskStateUtil(taskToStart);
if(stateUtil.isStatePending(taskToStart.getValue('state'))) {
var state = stateUtil.getDefaultStateForBucket(bucket);
taskToStart.state = state;
taskToStart.update();
}
}
};
/*
* schedule a lag task for some time in the future
*/
PlannedTaskUtilsV2.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
*/
PlannedTaskUtilsV2.closeParent = function(task, closeState) {
// get active tasks with same parent
var sibling = new GlideRecord('planned_task');
sibling.addQuery('parent', task.parent);
sibling.addNullQuery('orig_sys_id');
sibling.addQuery('sys_id', '!=', task.sys_id);
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 = new GlideRecord("planned_task");
if (!parent.get(task.parent))
return;
parent.state = closeState;
parent.update();
};
/*
* Changes the parent state according to the child states
*/
PlannedTaskUtilsV2.setParentState = function(task, isDeleted) {
gs.log("PlannedTaskUtilsV2.setParentState " + task.getDisplayValue());
var parent = new GlideRecord("planned_task");
if (!parent.get(task.parent))
return;
if (parent.sys_class_name.toString() === 'sn_cim_register')
return;
var ptRollupApi = new PlannedTaskRollupApi();
if(!(ptRollupApi.isValidRollUp(task.getValue('sys_class_name'), parent.getValue('sys_class_name') , 'state')))
return;
var lookupTable = parent.sys_class_name;
var tempGr = new GlideRecord(parent.sys_class_name);
if(tempGr.instanceOf('pm_project') || tempGr.instanceOf('pm_project_task')){
lookupTable = tempGr.instanceOf('pm_project') ? 'pm_project' : 'pm_project_task';
}
var sysClassExclusions = ptRollupApi.getRollupExclusions(lookupTable,'state');
var siblings = function(){
var gr = new GlideRecord('planned_task');
gr.addQuery('parent', task.parent);
if(sysClassExclusions.length >0 )
gr.addQuery('sys_class_name', 'NOT IN', sysClassExclusions.join(','));
gr.addNullQuery('orig_sys_id');
gr.addQuery('sys_id', '!=', task.sys_id);
gr.query();
return gr;
};
var stateUtil = new PlannedTaskStateManagement(task, parent, siblings);
var state = stateUtil.manageStateChange(isDeleted);
if ( state != parent.getValue('state') ) {
gs.log("-->Log parent state updating.." +state);
parent.setValue('state', state);
parent.update();
}
};
/*
* Sets parent's state when child task is deleted
*/
PlannedTaskUtilsV2.handleParentStateOnChildDelete = function(task) {
//If there is only one child left, need to use that state for the parent
var parentStateUtil = new PlannedTaskStateUtil(task.top_task);
if(parentStateUtil.getBucketForState(task.top_task.state) == PlannedTaskStateUtil.WORK_IN_PROGRESS)
PlannedTaskUtilsV2.startSuccessors(task, PlannedTaskStateUtil.WORK_IN_PROGRESS);
var parentGr = new GlideRecord("planned_task");
if (!parentGr.get(task.parent))
return;
var ptRollupApi = new PlannedTaskRollupApi();
if(!(ptRollupApi.isValidRollUp(task.getValue('sys_class_name'), parentGr.getValue('sys_class_name') , 'state')))
return;
var lookupTable = parentGr.sys_class_name;
var tempGr = new GlideRecord(parentGr.sys_class_name);
if(tempGr.instanceOf('pm_project') || tempGr.instanceOf('pm_project_task')){
lookupTable = tempGr.instanceOf('pm_project') ? 'pm_project' : 'pm_project_task';
}
var sysClassExclusions = ptRollupApi.getRollupExclusions(lookupTable,'state');
var sibling = new GlideAggregate('planned_task');
sibling.addQuery('parent', task.parent);
sibling.addNullQuery("orig_sys_id");
sibling.addQuery('sys_id', '!=', task.sys_id);
if(sysClassExclusions.length >0 )
sibling.addQuery('sys_class_name', 'NOT IN', sysClassExclusions.join(','));
sibling.query();
var siblingCount = sibling.getRowCount();
if(siblingCount == 0)
return;
if (siblingCount == "1" && sibling.next()) {
var parent = current.parent.getRefRecord();
parentStateUtil = new PlannedTaskStateUtil(parent);
var stateOfTheOnlyRemaininchildState = sibling.state;
var siblingStateUtil = new PlannedTaskStateUtil(sibling);
var siblingStateBucket = siblingStateUtil.getBucketForState(sibling.state);
parent.state = parentStateUtil.getValidStateForBucket(siblingStateBucket, sibling.state);
parent.update();
}else{
var stateUtil = new PlannedTaskStateUtil(task);
var closeState = stateUtil.getDefaultCloseState();
PlannedTaskUtilsV2.setParentState(task, true);
}
};
/*
* Start parent when a child starts
*/
PlannedTaskUtilsV2.startParent = function(task, bucket) {
if (JSUtil.nil(task.parent))
return;
var parent = new GlideRecord("planned_task");
if (!parent.get(task.parent))
return;
var parentStateUtil = new PlannedTaskStateUtil(parent);
var state = parentStateUtil.getValidStateForBucket(bucket, task.state);
if (parent.state == state)
return;
this.setParentState(task);
};
PlannedTaskUtilsV2.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;
};
/*
* Set all leaf nodes with no predecessors to same start state as parent based on time constraint
*/
PlannedTaskUtilsV2.startLeaves = function(gr, bucket) {
gs.print("PlannedTaskUtilsV2.startLeaves");
//var nestedInterval = new SNC.NestedIntervalUtilities("planned_task");
//var sysIdsToStart = nestedInterval.getLeafNodesForStateChange(gr.sys_id, false); //true : leaves of successor nodes
var projectMgmtApi = new SNC.PlannedTaskAPI();
var sysIdsToStart = projectMgmtApi.getLeafNodesForStateChange(gr.sys_id, false);
gs.print(" PlannedTaskUtilsV2.startLeaves:: is starting " + sysIdsToStart.length + " | leaves - " + bucket +
" | sysIds- " + sysIdsToStart.join(","));
for (var i = 0; i < sysIdsToStart.length; ++i) {
var taskToStart = new GlideRecord('planned_task');
var sysId = sysIdsToStart[i];
taskToStart.get(sysId);
var taskStateUtil = new PlannedTaskStateUtil(taskToStart);
var state = taskStateUtil.getValidStateForBucket(bucket, gr.state);
taskToStart.state = state;
taskToStart.update();
}
};
/*
* Set all leaf nodes with no predecessors to same start state as parent based on time constraint
*/
PlannedTaskUtilsV2.closeChildren = function(gr, state, includePercentComplete) {
gs.log("PlannedTaskUtilsV2.closeChildren");
// var nestedInterval = new SNC.NestedIntervalUtilities("planned_task");
var projectMgmtApi = new SNC.PlannedTaskAPI();
var nowTime = gs.nowDateTime();
gs.print(" PlannedTaskUtilsV2.closeChildren:: Now time " + nowTime);
var taskKeyVals = {
"state": state,
//"work_end": nowTime,
//"percent_complete": "100",
"active": "false",
"closed_by": gs.getUserID(),
"closed_at": new GlideDateTime()
};
if(includePercentComplete)
taskKeyVals["percent_complete"] = "100"
// nestedInterval.closeWholeProject(gr, taskKeyVals);
if(gr.getValue('sys_id') != gr.getValue('top_task') && gr.instanceOf("pm_project"))
projectMgmtApi.closeWholeSubProject(gr, taskKeyVals);
else
projectMgmtApi.closeWholeProject(gr, taskKeyVals);
};
/*
* Open the Project and Its Children
*/
PlannedTaskUtilsV2.openProject = function(gr) {
gs.log("PlannedTaskUtilsV2.openProject");
var api = new SNC.PlannedTaskAPI();
var plannedTaskStateUtil = new PlannedTaskStateUtil(gr);
if(gr.getValue('sys_id') != gr.getValue('top_task') && gr.instanceOf("pm_project"))
api.updateSubProjectState(gr, {}, plannedTaskStateUtil.getDefaultOpenState());
else
api.updateProjectState(gr, {}, plannedTaskStateUtil.getDefaultOpenState());
};
PlannedTaskUtilsV2.getParentStartOnBehavior = function(parentGr){
PPMDebug.log('PlannedTaskUtilsV2.getParentStartOnBehavior evaluating '+ parentGr.getUniqueValue())
var parentCannotBeStartOn = false; // default behavior
var preEngineHandler = new PreEngineHandlers();
var enginePreferences = preEngineHandler.getEnginePreferencesJSON(parentGr.getValue('sys_class_name'));
if (enginePreferences != null && enginePreferences.hasOwnProperty('parent_cannot_be_start_on')) {
parentCannotBeStartOn = enginePreferences.parent_cannot_be_start_on;
}
PPMDebug.log('parentCannotBeStartOn value is '+ parentCannotBeStartOn);
return parentCannotBeStartOn;
};
Sys ID
d5938c22eb810100b749215df106fe9c