Name
sn_hr_sp.hr_DashboardUtil
Description
Utility to help display cases on the HRJ Dashboard.
Script
var hr_DashboardUtil = Class.create();
//Default tables
hr_DashboardUtil.hrCaseTables = sn_hr_core.hr.TABLE_CASE_EXTENSIONS.toString();
hr_DashboardUtil.approvalTables = sn_hr_core.hr.TABLE_CASE_EXTENSIONS.slice();
hr_DashboardUtil.approvalTables.push('sc_request');
hr_DashboardUtil.LIST_TODO = 'TODO';
hr_DashboardUtil.LIST_OPEN = 'OPEN';
hr_DashboardUtil.LIST_CLOSED = 'CLOSED';
hr_DashboardUtil.QUERY_LIMIT = 10;
hr_DashboardUtil.prototype = {
initialize: function() {
this._user = gs.getUserID();
this._portalUtil = new sn_hr_sp.hr_PortalUtil();
},
getMyTodos : function(limit) {
var todoQueryInfo = {queryList : [this._approvalTodoQuery(false, false), this._acceptanceTodoQuery(), this._taskTodoQuery(false, false, false), this._taskTodoQuery(true, false, false)],
recordWatchers : [{table: 'sn_hr_core_case' , filter: 'active=true^opened_for=' + this._user},
{table: 'sn_hr_core_task' , filter: 'active=true^assigned_to=' + this._user},
{table: 'sysapproval_approver' , filter: 'state=requested^approverIN' + new sn_hr_core.hr_Utils().getApprovals(this._user)},
{table: 'sc_request' , filter: 'active=true^requested_for=' + this._user}]};
return this._constructOrderedList(todoQueryInfo, limit, hr_DashboardUtil.LIST_TODO);
},
getMyOpenItems : function(limit) {
var openItemQueryInfo = {queryList : [this._openedForCaseQuery(false), this._requestedForQuery(false), this._approvalTodoQuery(null, null), this._taskTodoQuery(null, null, null)],
recordWatchers : [{table: 'sn_hr_core_case' , filter: 'active=true^opened_for=' + this._user},
{table: 'sn_hr_core_task' , filter: 'active=true^assigned_to=' + this._user},
{table: 'sysapproval_approver' , filter: 'state=requested^approverIN' + new sn_hr_core.hr_Utils().getApprovals(this._user)},
{table: 'sc_request' , filter: 'active=true^requested_for=' + this._user}]};
if (new GlidePluginManager().isActive('com.snc.service_management.core'))
openItemQueryInfo.queryList.push(this._openedForOrderQuery(false));
return this._constructOrderedList(openItemQueryInfo, limit, hr_DashboardUtil.LIST_OPEN);
},
getMyCompletedItems : function(limit) {
var completedItemQueryInfo = {queryList : [this._openedForCaseQuery(true), this._requestedForQuery(true), this._approvalTodoQuery(true, true), this._taskTodoQuery(null, true, true)],
recordWatchers : [{table: 'sn_hr_core_case' , filter: 'active=false^opened_for=' + this._user},
{table: 'sn_hr_core_task' , filter: 'active=false^assigned_to=' + this._user},
{table: 'sysapproval_approver' , filter: 'stateINapproved,rejected,not_required^approver=' + this._user},
{table: 'sc_request' , filter: 'active=false^requested_for=' + this._user}]};
if (new GlidePluginManager().isActive('com.snc.service_management.core'))
completedItemQueryInfo.queryList.push(this._openedForOrderQuery(true));
return this._constructOrderedList(completedItemQueryInfo, limit, hr_DashboardUtil.LIST_CLOSED);
},
_constructOrderedList : function (queryInfo, limit, listType) {
var parentCaseIds;
var slotsToFill = limit + 1;
if (listType == hr_DashboardUtil.LIST_TODO)
parentCaseIds = this._checkTodoQueries(queryInfo, slotsToFill);
else
parentCaseIds = this._checkUnprioritizedQueries(queryInfo, slotsToFill, listType);
var caseInfo = {parentCaseList : {items : [], hasMoreItems : parentCaseIds.recordsToShow.length > limit}, watchers : queryInfo.recordWatchers};
for (var j = 0; j < parentCaseIds.recordsToShow.length && j < limit; j++)
caseInfo.parentCaseList.items.push({recordInfo : parentCaseIds.recordsToShow[j]});
return caseInfo;
},
/*------------------------* To-Do Items *------------------------*/
_checkTodoQueries : function (queryInfo, slotsToFill) {
var parentCaseIds = {recordsToShow : [], excludedRecords : [], excludedParents : []};
for (var i = 0; i < queryInfo.queryList.length && parentCaseIds.recordsToShow.length < slotsToFill; i++)
this._paginateTodoQueriesQuery(queryInfo.queryList[i], parentCaseIds, slotsToFill);
return parentCaseIds;
},
_paginateTodoQueriesQuery : function(queryFunction, parentCaseIds, slotsToFill) {
var start = 0;
var parentAdded = false;
do {
var grQuery = queryFunction(parentCaseIds.excludedRecords, parentCaseIds.excludedParents);
grQuery.chooseWindow(start, start + hr_DashboardUtil.QUERY_LIMIT);
grQuery.query();
if (!grQuery.hasNext()) //No more records
return;
while (grQuery.next() && parentCaseIds.recordsToShow.length < slotsToFill) {
if (this._reconcileDisplayItem(grQuery, parentCaseIds, hr_DashboardUtil.LIST_TODO))
parentAdded = true;
}
if (parentAdded) {
parentAdded = false;
start = 0;
}
else
start += hr_DashboardUtil.QUERY_LIMIT;
} while (parentCaseIds.recordsToShow.length < slotsToFill);
},
/*------------------------* Open/Closed Items *------------------------*/
_checkUnprioritizedQueries : function (queryInfo, slotsToFill, listType) {
var parentCaseIds = {recordsToShow : [], excludedRecords : [], excludedParents : []};
var queryStatus = this._initializeQueryStatus(queryInfo);
while (queryStatus.length > 0 && parentCaseIds.recordsToShow.length < slotsToFill) {
var selectedIndex = this._chooseResultFromQueries(queryStatus, listType);
var gr = this._getRelevantRecord(queryStatus[selectedIndex].query);
if (gr && this._reconcileDisplayItem(gr, parentCaseIds, listType)) {
for (var i = 0; i < queryStatus.length; i++)
queryStatus[i].resetWindow = true;
}
if (!queryStatus[selectedIndex].query.next())
this._moveQueryPointer(queryStatus, selectedIndex, parentCaseIds);
}
return parentCaseIds;
},
//Initialize queries/windows; add those that have results to status object
_initializeQueryStatus : function (queryInfo) {
var queryStatus = [];
for (var i = 0; i < queryInfo.queryList.length; i++) {
var query = queryInfo.queryList[i];
var queryInstance = query();
queryInstance.chooseWindow(0, hr_DashboardUtil.QUERY_LIMIT);
queryInstance.query();
if (queryInstance.next())
queryStatus.push({query: queryInstance, queryFunction : query, window : 0, resetWindow : false});
}
return queryStatus;
},
//Pick a query result based on list priority
_chooseResultFromQueries : function (queryStatus, listType) {
var chosenIndex = 0;
var comparisonField = listType == hr_DashboardUtil.LIST_CLOSED ? 'closed_at' : 'sys_created_on';
var currentQueryDateTime = new GlideDateTime();
var maxDateTime= new GlideDateTime(this._getDateForRelevantRecord(queryStatus[0].query, comparisonField));
for (i = 1; i < queryStatus.length; i++) {
currentQueryDateTime.setValue(this._getDateForRelevantRecord(queryStatus[i].query, comparisonField));
if (currentQueryDateTime.compareTo(maxDateTime) == 1) {
maxDateTime.setValue(currentQueryDateTime.getValue());
chosenIndex = i;
}
}
return chosenIndex;
},
//Increment the query; grab the next window if this one is exhausted
_moveQueryPointer : function (queryStatus, selectedIndex, parentCaseIds) {
var gr = queryStatus[selectedIndex].queryFunction(parentCaseIds.excludedRecords, parentCaseIds.excludedParents);
if (queryStatus[selectedIndex].resetWindow) {
queryStatus[selectedIndex].window = 0;
queryStatus[selectedIndex].resetWindow = false;
}
else
queryStatus[selectedIndex].window += hr_DashboardUtil.QUERY_LIMIT;
gr.chooseWindow(queryStatus[selectedIndex].window, queryStatus[selectedIndex].window + hr_DashboardUtil.QUERY_LIMIT);
gr.query();
//Remove query if it has run out
if (!gr.next())
queryStatus.splice(selectedIndex, 1);
else
queryStatus[selectedIndex].query = gr;
},
/*---------------------* Helper Functions *---------------------*/
_getDateForRelevantRecord : function(gr, field) {
if (gr.getRecordClassName() == 'sysapproval_approver')
return gr.sysapproval[field];
else if (gr.getRecordClassName() == 'sn_hr_core_task')
return gr.parent[field];
else
return gr[field];
},
_getRelevantRecord : function (gr) {
var relevantRecord ;
if (gr.getRecordClassName() == 'sysapproval_approver')
relevantRecord = gr.sysapproval.getRefRecord();
else if (gr.getRecordClassName() == 'sn_hr_core_task')
relevantRecord = gr.parent.getRefRecord();
else
relevantRecord = gr;
if (relevantRecord.isValidRecord() && (hr_DashboardUtil.hrCaseTables.indexOf(relevantRecord.getRecordClassName()) || relevantRecord.canRead()))
return relevantRecord;
return null;
},
_getGroupByCase : function(gr, level, skipParentDisplay) {
level = level || 3;
var isCase = hr_DashboardUtil.hrCaseTables.indexOf(String(gr.sys_class_name)) >= 0;
var selfCheck = {record : gr, isOpenedForCase : isCase && gr.opened_for == gs.getUserID(), isAuthorizedSPCase : isCase && sn_hr_core.hr_Case.userHasSubjectPersonAccess(gr)};
if (gs.nil(gr.parent) || level == 1)
return selfCheck;
var parentCheck = this._getGroupByCase(gr.parent.getRefRecord(), level - 1);
var parentIsGroupBy = parentCheck.isOpenedForCase || parentCheck.isAuthorizedSPCase;
//Show by Opened For parent if that parent is not intermediate to another Opened For case
if (parentIsGroupBy && (skipParentDisplay || this._getGroupByCase(parentCheck.record, null, true).record.getUniqueValue() == parentCheck.record.getUniqueValue()))
return parentCheck;
else
return selfCheck;
},
getHeaderTodoCountForCase : function(recordId, isOpenedForCase) {
var todoCount = 0;
var todoQueries = [this._approvalTodoQuery(false, true, recordId, isOpenedForCase, false, true),
this._acceptanceTodoQuery(recordId, isOpenedForCase, false, true),
this._taskTodoQuery(null, false, true, recordId, isOpenedForCase, false, true)];
for (var i = 0; i < todoQueries.length; i++) {
var todoQuery = todoQueries[i]();
todoQuery.query();
if (todoQuery.next())
todoCount += Number(todoQuery.getAggregate('COUNT'));
}
return todoCount;
},
getHeaderTodoCount : function() {
var todoCount = 0;
var todoQueries = [this._approvalTodoQuery(false, false, null, null, false, true),
this._acceptanceTodoQuery(null, null, false, true),
this._taskTodoQuery(null, false, false, null, null, false, true)];
for (var i = 0; i < todoQueries.length; i++) {
var todoQuery = todoQueries[i]();
todoQuery.query();
if (todoQuery.next())
todoCount += Number(todoQuery.getAggregate('COUNT'));
}
return todoCount;
},
_hasAnyTodos : function(recordId, isOpenedForCase) {
var todoQueries = [this._taskTodoQuery(null, null, null, recordId, isOpenedForCase, true, false)];
if (this._user == gs.getUserID()) {
todoQueries.push(this._approvalTodoQuery(null, null, recordId, isOpenedForCase, true, false));
todoQueries.push(this._acceptanceTodoQuery(recordId, isOpenedForCase, true, false));
}
for (var i = 0; i < todoQueries.length; i++) {
var todoQuery = todoQueries[i]();
todoQuery.query();
if (todoQuery.hasNext())
return true;
}
return false;
},
_hasActiveTodos : function(recordId, isOpenedForCase) {
var todoQueries = [this._approvalTodoQuery(false, true, recordId, isOpenedForCase, true, false),
this._acceptanceTodoQuery(recordId, isOpenedForCase, true, false),
this._taskTodoQuery(null, false, true, recordId, isOpenedForCase, true, false)];
for (var i = 0; i < todoQueries.length; i++) {
var todoQuery = todoQueries[i]();
todoQuery.query();
if (todoQuery.hasNext())
return true;
}
return false;
},
_hasLifecycleEvents: function(gr) {
if (hr_DashboardUtil.hrCaseTables.indexOf(String(gr.sys_class_name)) == -1)
return false;
this._portalUtil._gr = gr;
return this._portalUtil.isOpenedForView() && this._portalUtil.hasLifecycleEvents();
},
_reconcileDisplayItem : function(gr, parentCaseIds, listType) {
var baseRecord = this._getRelevantRecord(gr);
if (baseRecord) {
var sys_id = baseRecord.getUniqueValue();
if (parentCaseIds.excludedRecords.indexOf(sys_id) >= 0)
return false;
else
parentCaseIds.excludedRecords.push(sys_id);
var alreadyIncluded = false;
var relevantParent = this._getGroupByCase(baseRecord);
this._portalUtil._gr = relevantParent.record;
var parentId = relevantParent.record.getUniqueValue();
var isGroupByCase = relevantParent.isOpenedForCase || relevantParent.isAuthorizedSPCase;
for (var i = 0; i < parentCaseIds.recordsToShow.length; i++) {
if (parentCaseIds.recordsToShow[i].sys_id == parentId) {
alreadyIncluded = true;
break;
}
}
if (!alreadyIncluded) {
parentCaseIds.excludedRecords.push(parentId);
if (isGroupByCase)
parentCaseIds.excludedParents.push(parentId);
//Show To-Do cases in Open Cases list
var satisfiesListCriteria = (listType == hr_DashboardUtil.LIST_CLOSED && !relevantParent.record.active) ||
(listType != hr_DashboardUtil.LIST_CLOSED && relevantParent.record.active);
//Do not show Subject Person cases that have no associated records beneath
var notSoloSPCase = listType == hr_DashboardUtil.LIST_TODO || !relevantParent.isAuthorizedSPCase || relevantParent.isOpenedForCase || new hr_PortalUtil(relevantParent.record).getChildTodoInfo().length > 0;
if (satisfiesListCriteria && notSoloSPCase) {
var recordInfo = this._portalUtil._getRelevantInfoForRecord(relevantParent.record);
recordInfo.hasLifecycleEvents = this._hasLifecycleEvents(relevantParent.record);
parentCaseIds.recordsToShow.push(recordInfo);
}
}
return true;
}
return false;
},
/*------------------------* Queries *------------------------*/
_acceptanceTodoQuery : function(parentId, parentIsOpenedFor, limitToOne, isAggregate) {
var self = this;
return function(excludes, parentExcludes) {
var acceptanceCases = new GlideRecord('sn_hr_core_case');
if (isAggregate) {
acceptanceCases = new GlideAggregate('sn_hr_core_case');
acceptanceCases.addAggregate('COUNT');
}
acceptanceCases.addQuery('opened_for', self._user);
acceptanceCases.addQuery('active', true);
acceptanceCases.addQuery('state', '20');
if (parentId) {
var condition = acceptanceCases.addQuery('sys_id', parentId);
if (parentIsOpenedFor)
condition.addOrCondition('parent', parentId).addOrCondition('parent.parent', parentId);
if (limitToOne)
acceptanceCases.setLimit(1);
}
else {
if (excludes && excludes.length > 0)
acceptanceCases.addQuery('sys_id', 'NOT IN', excludes);
if (parentExcludes && parentExcludes.length > 0)
acceptanceCases.addNullQuery('parent').addOrCondition('parent.sys_id', 'NOT IN', parentExcludes);
}
if (!isAggregate)
acceptanceCases.orderBy('sys_created_on');
return acceptanceCases;
};
},
_approvalTodoQuery : function(checkCompleted, checkParentCompleted, parentId, parentIsOpenedFor, limitToOne, isAggregate) {
var self = this;
return function(excludes, parentExcludes) {
var grApproval = new GlideRecord('sysapproval_approver');
if (isAggregate) {
grApproval = new GlideAggregate('sysapproval_approver');
grApproval.addAggregate('COUNT');
}
if (checkCompleted)
grApproval.addQuery('approver', self._user);
else
grApproval.addQuery('approver', 'IN' , new sn_hr_core.hr_Utils().getApprovals(self._user));
if (checkCompleted) {
grApproval.addQuery('state','IN','approved, rejected,not_required');
if (checkParentCompleted)
grApproval.orderByDesc('sysapproval.closed_at');
else
grApproval.orderByDesc('sysapproval.sys_created_on');
}
else if (!gs.nil(checkCompleted)) {
grApproval.addQuery('state', 'requested');
if (!isAggregate)
grApproval.orderBy('sys_created_on');
}
if (parentId) {
var condition = grApproval.addQuery('sysapproval', parentId);
if (parentIsOpenedFor)
condition.addOrCondition('sysapproval.parent', parentId).addOrCondition('sysapproval.parent.parent', parentId);
if (limitToOne)
grApproval.setLimit(1);
}
else {
grApproval.addQuery('sysapproval.sys_class_name', 'IN', hr_DashboardUtil.approvalTables);
if (checkParentCompleted)
grApproval.addQuery('sysapproval.active', 'false');
else if (!gs.nil(checkParentCompleted))
grApproval.addQuery('sysapproval.active', 'true');
if (excludes && excludes.length > 0)
grApproval.addQuery('sysapproval.sys_id', 'NOT IN', excludes);
if (parentExcludes && parentExcludes.length > 0)
grApproval.addNullQuery('sysapproval.parent').addOrCondition('sysapproval.parent.sys_id', 'NOT IN', parentExcludes);
}
return grApproval;
};
},
_taskTodoQuery : function(filterDueDate, checkCompleted, checkParentCompleted, parentId, parentIsOpenedFor, limitToOne, isAggregate) {
var self = this;
return function(excludes, parentExcludes) {
var grTask = new GlideRecord('sn_hr_core_task');
if (isAggregate) {
grTask = new GlideAggregate('sn_hr_core_task');
grTask.addAggregate('COUNT');
}
grTask.addQuery('assigned_to', self._user);
grTask.addQuery('state', '!=', '1');
if (checkCompleted) {
grTask.addQuery('active', false);
grTask.addNotNullQuery('closed_at');
if (checkParentCompleted)
grTask.orderByDesc('parent.closed_at');
else
grTask.orderByDesc('parent.sys_created_on');
}
else if (!gs.nil(checkCompleted)) {
grTask.addQuery('active', true);
if (!gs.nil(filterDueDate)) {
if (filterDueDate)
grTask.addNullQuery('due_date');
else {
grTask.addNotNullQuery('due_date');
grTask.orderBy('due_date');
}
}
}
if (parentId) {
var condition = grTask.addQuery('parent', parentId);
if (parentIsOpenedFor)
condition.addOrCondition('parent.parent', parentId).addOrCondition('parent.parent.parent', parentId);
if (limitToOne)
grTask.setLimit(1);
}
else {
grTask.addQuery('parent.sys_class_name', 'IN', hr_DashboardUtil.hrCaseTables);
grTask.addQuery('parent.state', '!=', '1');
if (checkParentCompleted)
grTask.addQuery('parent.active', 'false');
else if (!gs.nil(checkParentCompleted))
grTask.addQuery('parent.active', 'true');
if (excludes && excludes.length > 0)
grTask.addQuery('parent.sys_id', 'NOT IN', excludes);
if (parentExcludes && parentExcludes.length > 0)
grTask.addNullQuery('parent.parent').addOrCondition('parent.parent.sys_id', 'NOT IN', parentExcludes);
}
return grTask;
};
},
_openedForCaseQuery : function(checkCompleted) {
var self = this;
return function(excludes, parentExcludes) {
var grCase = new GlideRecord('sn_hr_core_case');
grCase.addQuery('opened_for', self._user).addOrCondition('hr_service.subject_person_access', true).addCondition('subject_person', self._user);
grCase.addQuery('state', '!=', '1');
if (checkCompleted) {
grCase.addQuery('active', false);
grCase.addNotNullQuery('closed_at');
grCase.orderByDesc('closed_at');
}
else {
grCase.addActiveQuery();
grCase.orderByDesc('sys_created_on');
}
if (excludes && excludes.length > 0)
grCase.addQuery('sys_id', 'NOT IN', excludes);
if (parentExcludes && parentExcludes.length > 0)
grCase.addNullQuery('parent').addOrCondition('parent.sys_id', 'NOT IN', parentExcludes);
return grCase;
};
},
_openedForOrderQuery : function(checkCompleted) {
var self = this;
return function(excludes, parentExcludes) {
var grOrder = new GlideRecord('sm_order');
grOrder.addQuery('opened_for', self._user).addOrCondition('caller', self._user);
grOrder.addQuery('state', '!=', '1');
if (checkCompleted) {
grOrder.addQuery('active', false);
grOrder.addNotNullQuery('closed_at');
grOrder.orderByDesc('closed_at');
}
else {
grOrder.addActiveQuery();
grOrder.orderByDesc('sys_created_on');
}
if (excludes && excludes.length > 0)
grOrder.addQuery('sys_id', 'NOT IN', excludes);
if (parentExcludes && parentExcludes.length > 0)
grOrder.addNullQuery('parent').addOrCondition('parent.sys_id', 'NOT IN', parentExcludes);
return grOrder;
};
},
_requestedForQuery : function(checkCompleted) {
var self = this;
return function(excludes, parentExcludes) {
var grRequest = new GlideRecord('sc_request');
grRequest.addQuery('requested_for', self._user);
if (checkCompleted) {
grRequest.addQuery('active', false);
grRequest.addNotNullQuery('closed_at');
grRequest.orderByDesc('closed_at');
}
else {
grRequest.addActiveQuery();
grRequest.orderByDesc('sys_created_on');
}
if (excludes && excludes.length > 0)
grRequest.addQuery('sys_id', 'NOT IN', excludes);
if (parentExcludes && parentExcludes.length > 0)
grRequest.addNullQuery('parent').addOrCondition('parent.sys_id', 'NOT IN', parentExcludes);
return grRequest;
};
},
type: 'hr_DashboardUtil'
};
Sys ID
d6d8fe05533132003585c3c606dc34b6