Name
sn_nb_action.ActionServiceImpl
Description
A service to manage actions and interact with action handlers
Script
var ActionServiceImpl = Class.create();
ActionServiceImpl.prototype = {
initialize: function() {
this.nextBestActionDAO = sn_nb_action.NextBestActionUtil.getNextBestActionDAO();
this._log = new global.GSLog(sn_nb_action.Constants.PROP_LOG_LEVEL, this.type);
},
getActionsForUnsavedChanges: function(contextRecord, currentRecord, recommendationType, currentActions) {
var actionDetails = [];
var actionDetailsInNewState = [];
var actionDetailsInCompletedState = [];
var actionDetailsInSkippedState = [];
var result = {};
result.contextId = contextRecord.getUniqueValue();
result.contextState = contextRecord.getValue(sn_nb_action.Constants.COL_STATE);
var ruleOrderObj = this._getRuleOrder(currentActions);
for (var key in currentActions) {
if (currentActions.hasOwnProperty(key)) {
for (var i = 0; i < currentActions[key].length; i++) {
var currentDetail = currentActions[key][i];
var detailObject = this._getActionDetailObject(currentRecord, currentDetail, ruleOrderObj);
this._pushToDetailOrders(detailObject, actionDetails, actionDetailsInNewState, actionDetailsInCompletedState, actionDetailsInSkippedState);
}
}
}
actionDetailsInNewState.sort(this._sortByActionScore);
actionDetails = this._appendActionDetails(actionDetails, actionDetailsInNewState);
actionDetails = this._appendActionDetails(actionDetails, actionDetailsInCompletedState);
actionDetails = this._appendActionDetails(actionDetails, actionDetailsInSkippedState);
result.actionDetails = actionDetails;
return result;
},
getActions: function(contextRecord, currentRecord, recommendationType, currentActions) {
var states = [sn_nb_action.Constants.STATE_NEW, sn_nb_action.Constants.STATE_IN_PROGRESS,
sn_nb_action.Constants.STATE_COMPLETED, sn_nb_action.Constants.STATE_SKIPPED, sn_nb_action.Constants.STATE_IN_ERROR, sn_nb_action.Constants.STATE_ERROR_SKIPPED
];
var ruleOrderObj = this._getRuleOrderObj(contextRecord, sn_nb_action.Constants.STATE_NEW, recommendationType);
var actionDetailRecords = this.nextBestActionDAO.getAllActionDetails(contextRecord, states, recommendationType);
var result = {};
result.contextId = contextRecord.getUniqueValue();
result.contextState = contextRecord.getValue(sn_nb_action.Constants.COL_STATE);
var actionDetails = [];
var actionDetailsInNewState = [];
var actionDetailsInCompletedState = [];
var actionDetailsInSkippedState = [];
if (actionDetailRecords) {
while (actionDetailRecords.next()) {
if (!gs.nil(actionDetailRecords[sn_nb_action.Constants.COL_RULE]))
this.nextBestActionDAO.updateActionDetailOnUpgrade(actionDetailRecords);
var actionDetailOrders = this.nextBestActionDAO.getActionDetailOrders(actionDetailRecords);
var actionDetObj = sn_nb_action.ActionDetail.createFromRecord(actionDetailRecords, actionDetailOrders);
if (!this._hasActiveActionDetailOrder(actionDetObj) && !this._persistActionDetail(actionDetObj))
continue;
else if (actionDetObj.getState() == sn_nb_action.Constants.STATE_NEW && actionDetObj.getParentActionId()) {
var hideRA = this.hideRecommendation(actionDetailRecords);
if (hideRA)
continue;
}
try {
var actionDetail = this._fetchActionDetailProps(currentRecord, actionDetailRecords, actionDetObj, ruleOrderObj);
this._pushToDetailOrders(actionDetail, actionDetails, actionDetailsInNewState, actionDetailsInCompletedState, actionDetailsInSkippedState);
} catch (ex) {
this._log.error("Cannot fetch details for action detail " + actionDetailRecords.getUniqueValue());
}
}
actionDetailsInNewState.sort(this._sortByActionScore);
actionDetails = this._appendActionDetails(actionDetails, actionDetailsInNewState);
actionDetails = this._appendActionDetails(actionDetails, actionDetailsInCompletedState);
actionDetails = this._appendActionDetails(actionDetails, actionDetailsInSkippedState);
}
result.actionDetails = actionDetails;
return result;
},
_pushToDetailOrders: function(detailObject, actionDetails, actionDetailsInNewState, actionDetailsInCompletedState, actionDetailsInSkippedState) {
if (detailObject) {
if (detailObject.actionState.value == sn_nb_action.Constants.STATE_IN_PROGRESS)
actionDetails.push(detailObject);
else if (detailObject.actionState.value == sn_nb_action.Constants.STATE_NEW)
actionDetailsInNewState.push(detailObject);
else if (detailObject.actionState.value == sn_nb_action.Constants.STATE_COMPLETED)
actionDetailsInCompletedState.push(detailObject);
else
actionDetailsInSkippedState.push(detailObject);
}
},
_getActionTypeRecord: function(currentDetail) {
var actionTypeRecord = new GlideRecord(sn_nb_action.Constants.TBL_ACTION_TYPE_DEFINITION);
actionTypeRecord.get(currentDetail.actionTypeSysId);
return actionTypeRecord;
},
_getActionRecord: function(currentDetail) {
var actionRecord = new GlideRecord(currentDetail.actionTypeTable);
actionRecord.get(currentDetail.actionSysId);
return actionRecord;
},
executeAction: function(contextRecord, currentRecord, actionDetailSysId, actionMetadata) {
var actionDetailRecord;
if (sn_nb_action.NextBestActionUtil.isValidString(actionDetailSysId))
actionDetailRecord = this.nextBestActionDAO.getActionDetailBySysId(actionDetailSysId);
// if actionDetailSysId still contains actionSysId value try fetching actionDetailRecord again
if (!sn_nb_action.NextBestActionUtil.isValidRecord(actionDetailRecord))
actionDetailRecord = this.nextBestActionDAO.getActionDetail(contextRecord, actionDetailSysId);
var actionRecord = actionDetailRecord[sn_nb_action.Constants.COL_RECOMMENDED].getRefRecord();
var actionHandler = this._getActionHandler(actionDetailRecord);
var actionObj = actionHandler.executeAction(currentRecord, actionRecord, actionDetailRecord[sn_nb_action.Constants.COL_ACTION_INPUTS], sn_nb_action.Constants.TBL_ACTION_DETAIL, actionDetailRecord.getUniqueValue(), actionMetadata);
actionDetailRecord = this.nextBestActionDAO.getActionDetailBySysId(actionDetailSysId);
actionObj[sn_nb_action.Constants.COL_STATE] = actionDetailRecord[sn_nb_action.Constants.COL_STATE];
return actionObj;
},
useAction: function(contextRecord, currentRecord, actionDetailSysId) {
var actionDetailRecord;
if (sn_nb_action.NextBestActionUtil.isValidString(actionDetailSysId))
actionDetailRecord = this.nextBestActionDAO.getActionDetailBySysId(actionDetailSysId);
// if actionDetailSysId still contains actionSysId value try fetching actionDetailRecord again
if (!sn_nb_action.NextBestActionUtil.isValidRecord(actionDetailRecord))
actionDetailRecord = this.nextBestActionDAO.getActionDetail(contextRecord, actionDetailSysId);
if (this.hideRecommendation(actionDetailRecord)) {
return this._getHideActionResponse();
}
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionDetailRecord)) {
if (!gs.nil(actionDetailRecord[sn_nb_action.Constants.COL_RULE]))
this.nextBestActionDAO.updateActionDetailOnUpgrade(actionDetailRecord);
var actionDetailOrders = this.nextBestActionDAO.getActionDetailOrders(actionDetailRecord);
var actionDetObj = sn_nb_action.ActionDetail.createFromRecord(actionDetailRecord, actionDetailOrders);
var currentState = actionDetailRecord.getValue(sn_nb_action.Constants.COL_STATE);
if (actionDetailRecord.getValue(sn_nb_action.Constants.COL_STATE) != sn_nb_action.Constants.STATE_NEW && actionDetailRecord.getValue(sn_nb_action.Constants.COL_STATE) != sn_nb_action.Constants.STATE_IN_PROGRESS) {
this._log.error("Cannot use action detail " + actionDetailRecord.getUniqueValue() + ", state : " + currentState);
return false;
}
if (!this._hasActiveActionDetailOrder(actionDetObj)) {
this._log.error("Action detail " + actionDetailRecord.getUniqueValue() + ", cannot be started by user: " + gs.getUserDisplayName());
return false;
}
var actionHandler = this._getActionHandler(actionDetailRecord);
if (actionHandler && typeof actionHandler.initializeAction === "function") {
var actionRecord = actionDetailRecord[sn_nb_action.Constants.COL_RECOMMENDED].getRefRecord();
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionRecord)) {
try {
if (!sn_nb_action.NextBestActionUtil.isValidString(actionDetailRecord.attribute)) {
var actionObj = actionHandler.initializeAction(currentRecord, actionRecord, actionDetailRecord[sn_nb_action.Constants.COL_ACTION_INPUTS], sn_nb_action.Constants.TBL_ACTION_DETAIL, actionDetailRecord.getUniqueValue());
var actionState = sn_nb_action.Constants.STATE_IN_PROGRESS;
if (actionObj.actionState && actionObj.actionState != null && actionObj.actionState != "")
actionState = actionObj.actionState;
if (actionObj.actionAttr && actionObj.actionAttr != null) {
this.nextBestActionDAO.setActionAttribute(actionDetailRecord, actionObj.actionAttr);
actionDetObj.setAttribute(JSON.stringify(actionObj.actionAttr));
} else
actionObj.actionAttr = "";
this.nextBestActionDAO.setActionState(actionDetailRecord, actionState);
actionDetObj.setState(actionDetailRecord.getValue(sn_nb_action.Constants.COL_STATE));
actionDetObj.setStateDisplayValue(actionDetailRecord.getDisplayValue(sn_nb_action.Constants.COL_STATE));
this._log.debug("Action " + actionRecord.getUniqueValue() + " initialized.");
}
return this._fetchActionDetailProps(currentRecord, actionDetailRecord, actionDetObj);
} catch (ex) {
this._log.error("Failed to initialize action " + actionRecord.getUniqueValue() + "; " + ex);
}
} else
this._log.error("Could not find the action recommended in detail " + actionDetailRecord.getUniqueValue());
} else
this._log.error("Could not find the handler for action recommended in detail " + actionDetailRecord.getUniqueValue());
} else
this._log.warn("Could not find action detail for action " + actionDetailSysId);
return false;
},
dismissAction: function(contextRecord, currentRecord, actionDetailSysId) {
var actionDetailRecord;
if (sn_nb_action.NextBestActionUtil.isValidString(actionDetailSysId))
actionDetailRecord = this.nextBestActionDAO.getActionDetailBySysId(actionDetailSysId);
// if actionDetailSysId still contains actionSysId value try fetching actionDetailRecord again
if (!sn_nb_action.NextBestActionUtil.isValidRecord(actionDetailRecord))
actionDetailRecord = this.nextBestActionDAO.getActionDetail(contextRecord, actionDetailSysId);
if (this.hideRecommendation(actionDetailRecord)) {
return this._getHideActionResponse();
}
var currentState = actionDetailRecord.getValue(sn_nb_action.Constants.COL_STATE);
if (currentState == sn_nb_action.Constants.STATE_NEW) {
this._changeState(actionDetailRecord, sn_nb_action.Constants.STATE_SKIPPED);
return;
}
if (currentState == sn_nb_action.Constants.STATE_IN_PROGRESS || currentState == sn_nb_action.Constants.STATE_IN_ERROR) {
var actionHandler = this._getActionHandler(actionDetailRecord);
if (actionHandler) {
var actionRecord = actionDetailRecord[sn_nb_action.Constants.COL_RECOMMENDED].getRefRecord();
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionRecord)) {
try {
if (typeof actionHandler.dismissAction === "function") {
actionHandler.dismissAction(currentRecord, actionRecord, actionDetailRecord.getValue(sn_nb_action.Constants.COL_ATTRIBUTE));
}
} catch (ex) {
this._log.error("Failed to dismiss the recommended actions " + actionRecord.getUniqueValue());
}
}
} else
this._log.error("Could not find implementaion for action type " + actionDetailRecord.getUniqueValue());
}
return;
},
getActionDetail: function(contextRecord, currentRecord, actionDetailSysId) {
var actionDetailRecord;
if (sn_nb_action.NextBestActionUtil.isValidString(actionDetailSysId))
actionDetailRecord = this.nextBestActionDAO.getActionDetailBySysId(actionDetailSysId);
// if actionDetailSysId still contains actionSysId value try fetching actionDetailRecord again
if (!sn_nb_action.NextBestActionUtil.isValidRecord(actionDetailRecord))
actionDetailRecord = this.nextBestActionDAO.getActionDetail(contextRecord, actionDetailSysId);
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionDetailRecord)) {
if (!gs.nil(actionDetailRecord[sn_nb_action.Constants.COL_RULE]))
this.nextBestActionDAO.updateActionDetailOnUpgrade(actionDetailRecord);
var actionDetailOrders = this.nextBestActionDAO.getActionDetailOrders(actionDetailRecord);
var actionDetObj = sn_nb_action.ActionDetail.createFromRecord(actionDetailRecord, actionDetailOrders);
var currentState = actionDetailRecord.getValue(sn_nb_action.Constants.COL_STATE);
if (currentState == sn_nb_action.Constants.STATE_NEW && !this._hasActiveActionDetailOrder(actionDetObj)) {
this._log.error("Action detail " + actionDetailRecord.getUniqueValue() + ", cannot be fetched by user: " + gs.getUserDisplayName());
return false;
}
return this._fetchActionDetailProps(currentRecord, actionDetailRecord, actionDetObj);
} else
this._log.warn("Could not find action detail for the sys id " + actionDetailSysId);
return false;
},
_getActionScore: function(actionDetObj, ruleOrderObj) {
var actionScore = 0;
var state = actionDetObj.getState();
if (!gs.nil(ruleOrderObj)) {
var actionOrders = [];
var ruleActionOrderObj = actionDetObj.getRules();
for (var rule in ruleActionOrderObj)
actionOrders.push(ruleActionOrderObj[rule]);
actionOrders.sort(this._compareByInterOrder);
if (state == sn_nb_action.Constants.STATE_NEW)
actionScore = new sn_nb_action.NextBestActionRanking().getActionScore(actionOrders, ruleOrderObj);
if (gs.nil(actionOrders))
return false;
}
return actionScore;
},
_getTag: function(actionTypeRecord) {
var tag = '';
var rendererRecord = actionTypeRecord[sn_nb_action.Constants.COL_RENDERER].getRefRecord();
if (sn_nb_action.NextBestActionUtil.isValidRecord(rendererRecord))
tag = rendererRecord.getValue(sn_nb_action.Constants.COL_TAG) || "";
return tag;
},
_getIconName: function(actionTypeRecord) {
var iconName = '';
var designIconRecord = actionTypeRecord[sn_nb_action.Constants.COL_ICON].getRefRecord();
if (sn_nb_action.NextBestActionUtil.isValidRecord(designIconRecord))
iconName = designIconRecord.getValue(sn_nb_action.Constants.COL_NAME) || "";
return iconName;
},
_getHint: function(rules) {
var rAOrderArray = sn_nb_action.NextBestActionUtil.getObjectValues(rules);
rAOrderArray.sort(this._compareByInterOrder);
if (rAOrderArray.length > 0)
return rAOrderArray[0].getHint();
return false;
},
_getAttribute: function(actionDetObj) {
var attribute = actionDetObj.getAttribute();
var attrVal;
if (!gs.nil(attribute))
attrVal = JSON.parse(attribute);
if (!sn_nb_action.NextBestActionUtil.isValidString(attrVal))
attrVal = "";
return attrVal;
},
_getActionDetailObject: function(currentRecord, currentDetail, ruleOrderObj) {
var actionTypeRecord = this._getActionTypeRecord(currentDetail);
var actionRecord = this._getActionRecord(currentDetail);
var actionDetObj = sn_nb_action.ActionDetail.createFromUnsavedRecord(currentDetail, currentDetail.actionTypeTable, currentDetail.actionTypeSysId, actionRecord.getUniqueValue(), currentDetail.actionInputs);
this._setTitleAndDescription(actionTypeRecord, actionRecord, currentRecord, currentDetail, actionDetObj);
this._setCallToActions(actionTypeRecord, actionRecord, currentRecord, currentDetail, actionDetObj);
this._setCustomAttributes(actionTypeRecord, actionRecord, currentRecord, currentDetail, actionDetObj);
var actionType = actionTypeRecord.getDisplayValue(sn_nb_action.Constants.COL_TITLE);
var tag = this._getTag(actionTypeRecord);
var iconName = this._getIconName(actionTypeRecord);
var hint = this._getHint(currentDetail.ruleSysIds);
var actionScore = this._getActionScore(actionDetObj, ruleOrderObj);
var attrVal = this._getAttribute(actionDetObj);
var actionDetail = {
actionId: actionDetObj.getAction(),
actionDetailId: actionDetObj.getId(),
actionType: actionType,
actionState: {
label: actionDetObj.getStateDisplayValue(),
value: actionDetObj.getState()
},
title: actionDetObj.getTitle(),
description: actionDetObj.getDescription(),
recommendationHint: hint,
callToActions: actionDetObj.getCallToActions(),
renderer: tag,
iconName: iconName,
createdOn: actionDetObj.getCreatedOn(),
updatedOn: actionDetObj.getUpdatedOn(),
attributes: attrVal,
actionScore: actionScore,
customAttributes: actionDetObj.getCustomAttribute()
};
if (actionDetObj.getState() == sn_nb_action.Constants.STATE_IN_ERROR ||
actionDetObj.getState() == sn_nb_action.Constants.STATE_ERROR_SKIPPED) {
actionDetail['errorMessage'] = actionDetObj.getErrorMessage();
}
return actionDetail;
},
_fetchActionDetailProps: function(currentRecord, actionDetailRecord, actionDetObj, ruleOrderObj) {
this._addTitleAndDescription(currentRecord, actionDetailRecord, actionDetObj);
this._addCallToActions(currentRecord, actionDetailRecord, actionDetObj);
this._addCustomAttributes(currentRecord, actionDetailRecord, actionDetObj);
this._addCustomPreviewExpereince(currentRecord, actionDetailRecord, actionDetObj);
if (actionDetailRecord.state == sn_nb_action.Constants.STATE_IN_ERROR || actionDetailRecord.state == sn_nb_action.Constants.STATE_ERROR_SKIPPED) {
this._addErrorMessage(actionDetailRecord, actionDetObj);
}
var attrVal = JSON.parse(actionDetObj.getAttribute());
if (!sn_nb_action.NextBestActionUtil.isValidString(attrVal))
attrVal = "";
var actionType = "";
var tag = "";
var iconName = "";
//to handle upgrade scenario for completed guidances
var currentState = actionDetailRecord.getValue(sn_nb_action.Constants.COL_STATE);
if (currentState == sn_nb_action.Constants.STATE_COMPLETED && attrVal.recommender && !attrVal.hasOwnProperty('actionOutputs'))
attrVal = this._updateActionDetailAttributes(actionDetailRecord);
var actionTypeRecord = actionDetailRecord[sn_nb_action.Constants.COL_ACTION_TYPE].getRefRecord();
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionTypeRecord)) {
actionType = actionTypeRecord.getDisplayValue(sn_nb_action.Constants.COL_TITLE);
var rendererRecord = actionTypeRecord[sn_nb_action.Constants.COL_RENDERER].getRefRecord();
if (sn_nb_action.NextBestActionUtil.isValidRecord(rendererRecord))
tag = rendererRecord.getValue(sn_nb_action.Constants.COL_TAG) || "";
var designIconRecord = actionTypeRecord[sn_nb_action.Constants.COL_ICON].getRefRecord();
if (sn_nb_action.NextBestActionUtil.isValidRecord(designIconRecord))
iconName = designIconRecord.getValue(sn_nb_action.Constants.COL_NAME) || "";
}
var actionScore = 0;
if (!gs.nil(ruleOrderObj)) {
var actionOrders = [];
var ruleActionOrderObj = actionDetObj.getRules();
for (var rule in ruleActionOrderObj) {
if (ruleActionOrderObj[rule].isActive())
actionOrders.push(ruleActionOrderObj[rule]);
}
actionOrders.sort(this._compareByInterOrder);
if (actionDetailRecord.state == sn_nb_action.Constants.STATE_NEW)
actionScore = new sn_nb_action.NextBestActionRanking().getActionScore(actionOrders, ruleOrderObj);
var hint = this._getHint(ruleActionOrderObj);
}
var actionDetail = {
actionId: actionDetObj.getAction(),
actionDetailId: actionDetObj.getId(),
actionType: actionType,
actionState: {
label: actionDetObj.getStateDisplayValue(),
value: actionDetObj.getState()
},
title: actionDetObj.getTitle(),
description: actionDetObj.getDescription(),
recommendationHint: hint,
callToActions: actionDetObj.getCallToActions(),
renderer: tag,
iconName: iconName,
createdOn: actionDetObj.getCreatedOn(),
updatedOn: actionDetObj.getUpdatedOn(),
attributes: attrVal,
actionScore: actionScore,
customAttributes: actionDetObj.getCustomAttribute(),
customExperience: actionDetObj.getPreviewExperience(),
actionGroups: actionDetObj.getActionGroupsAsCommaSeparatedString()
};
if (actionDetObj.getState() == sn_nb_action.Constants.STATE_IN_ERROR ||
actionDetObj.getState() == sn_nb_action.Constants.STATE_ERROR_SKIPPED) {
actionDetail['errorMessage'] = actionDetObj.getErrorMessage();
}
return actionDetail;
},
//Returns true if Action Detail Record has atleast one active Action Detail Order Record
_hasActiveActionDetailOrder: function(actionDetObj) {
var ruleActionOrderObj = actionDetObj.getRules();
for (var rule in ruleActionOrderObj) {
if (ruleActionOrderObj[rule].isActive())
return true;
}
return false;
},
//updates the attributes of the action detail record
_updateActionDetailAttributes: function(actionDetailRecord) {
var attributes = JSON.parse(actionDetailRecord.getValue('attribute'));
var actionDetails = this._getActionAttributes(actionDetailRecord);
attributes['actionOutputs'] = actionDetails['actionOutputs'];
attributes = JSON.stringify(attributes);
actionDetailRecord.setValue('attribute', attributes);
actionDetailRecord.update();
return JSON.parse(attributes);
},
/*
* Checks if current user on basis of roles should be allowed access the recommendation
*/
_isAccessible: function(actionDetObj) {
var ruleActionOrderObj = actionDetObj.getRules();
for (var rule in ruleActionOrderObj) {
if (gs.hasRole(ruleActionOrderObj[rule].getRoles()))
return true;
}
return false;
},
// Returns true if a recommendation needs to persist even when rule recommending it is not satisfied anymore
_persistActionDetail: function(actionDetObj) {
var currentState = actionDetObj.getState();
if (currentState == sn_nb_action.Constants.STATE_IN_PROGRESS || currentState == sn_nb_action.Constants.STATE_COMPLETED || currentState == sn_nb_action.Constants.STATE_SKIPPED)
return true;
return false;
},
ignoreAction: function(contextRecord, actionSysId) {
var actionDetailRecord = this.nextBestActionDAO.getActionDetail(contextRecord, actionSysId);
if (!gs.nil(actionDetailRecord[sn_nb_action.Constants.COL_RULE]))
this.nextBestActionDAO.updateActionDetailOnUpgrade(actionDetailRecord);
var actionDetailOrders = this.nextBestActionDAO.getActionDetailOrders(actionDetailRecord);
var actionDetObj = sn_nb_action.ActionDetail.createFromRecord(actionDetailRecord, actionDetailOrders);
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionDetailRecord)) {
return this._changeState(actionDetailRecord, sn_nb_action.Constants.STATE_IGNORED);
} else
this._log.warn("Could not find action detail for action " + actionSysId);
return false;
},
skipAction: function(contextRecord, actionSysId, actionDetailSysId, actionInitialAttributes) {
var actionDetailRecord;
if (gs.nil(actionDetailSysId))
actionDetailRecord = this.nextBestActionDAO.getActionDetail(contextRecord, actionSysId);
else
actionDetailRecord = this.nextBestActionDAO.getActionDetailBySysId(actionDetailSysId);
var attributes = actionDetailRecord.getValue('attribute');
if (actionDetailRecord.state != sn_nb_action.Constants.STATE_SKIPPED && actionInitialAttributes && actionInitialAttributes.id == sn_nb_action.Constants.TBL_DECISION_TREE && gs.nil(attributes)) {
this.nextBestActionDAO.setActionAttribute(actionDetailRecord, actionInitialAttributes.attributes);
}
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionDetailRecord)) {
if (!gs.nil(actionDetailRecord[sn_nb_action.Constants.COL_RULE]))
this.nextBestActionDAO.updateActionDetailOnUpgrade(actionDetailRecord);
var actionDetailOrders = this.nextBestActionDAO.getActionDetailOrders(actionDetailRecord);
var actionDetObj = sn_nb_action.ActionDetail.createFromRecord(actionDetailRecord, actionDetailOrders);
var state = sn_nb_action.Constants.STATE_SKIPPED;
if (actionDetailRecord.state == sn_nb_action.Constants.STATE_IN_ERROR) {
state = sn_nb_action.Constants.STATE_ERROR_SKIPPED;
}
return this._changeState(actionDetailRecord, state);
} else
this._log.warn("Could not find action detail for action " + actionSysId);
return false;
},
completeAction: function(contextRecord, actionSysId, actionDetailSysId, actionDetails, actionInitialAttributes) {
var actionDetailRecord;
if (gs.nil(actionDetailSysId))
actionDetailRecord = this.nextBestActionDAO.getActionDetail(contextRecord, actionSysId);
else
actionDetailRecord = this.nextBestActionDAO.getActionDetailBySysId(actionDetailSysId);
if (actionDetailRecord.state != sn_nb_action.Constants.STATE_SKIPPED && actionInitialAttributes && actionInitialAttributes.id == sn_nb_action.Constants.TBL_DECISION_TREE && gs.nil(actionDetailRecord.getValue(sn_nb_action.Constants.COL_ATTRIBUTE)))
this.nextBestActionDAO.setActionAttribute(actionDetailRecord, actionInitialAttributes.attributes);
var attributes = JSON.parse(actionDetailRecord.getValue('attribute'));
if (actionDetails) {
for (var key in actionDetails)
attributes[key] = actionDetails[key];
attributes = JSON.stringify(attributes);
actionDetailRecord.setValue('attribute', attributes);
actionDetailRecord.update();
}
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionDetailRecord)) {
if (!gs.nil(actionDetailRecord[sn_nb_action.Constants.COL_RULE]))
this.nextBestActionDAO.updateActionDetailOnUpgrade(actionDetailRecord);
var actionDetailOrders = this.nextBestActionDAO.getActionDetailOrders(actionDetailRecord);
var actionDetObj = sn_nb_action.ActionDetail.createFromRecord(actionDetailRecord, actionDetailOrders);
return this._changeState(actionDetailRecord, sn_nb_action.Constants.STATE_COMPLETED);
} else
this._log.warn("Could not find action detail for action " + actionSysId);
return false;
},
progressAction: function(actionDetailSysId) {
var actionDetailRecord = this.nextBestActionDAO.getActionDetailBySysId(actionDetailSysId);
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionDetailRecord)) {
if (!gs.nil(actionDetailRecord[sn_nb_action.Constants.COL_RULE]))
this.nextBestActionDAO.updateActionDetailOnUpgrade(actionDetailRecord);
return this._changeState(actionDetailRecord, sn_nb_action.Constants.STATE_IN_PROGRESS);
} else
this._log.warn("Could not find action detail for action " + actionSysId + " when trying to set RA in_progress");
return false;
},
_changeState: function(actionDetailRecord, state) {
var currentState = actionDetailRecord.getValue(sn_nb_action.Constants.COL_STATE);
if (currentState == sn_nb_action.Constants.STATE_NEW &&
(state != sn_nb_action.Constants.STATE_IN_PROGRESS &&
state != sn_nb_action.Constants.STATE_IGNORED &&
state != sn_nb_action.Constants.STATE_SKIPPED &&
state != sn_nb_action.Constants.STATE_COMPLETED &&
state != sn_nb_action.Constants.STATE_IN_ERROR)) {
this._log.error("Action state is new, it cannot be changed to " + state);
return false;
}
if (currentState == sn_nb_action.Constants.STATE_IN_PROGRESS &&
(state != sn_nb_action.Constants.STATE_SKIPPED &&
state != sn_nb_action.Constants.STATE_COMPLETED &&
state != sn_nb_action.Constants.STATE_IN_ERROR)) {
this._log.error("Action state is in use, it cannot be changed to " + state);
return false;
}
if (currentState == sn_nb_action.Constants.STATE_IGNORED ||
currentState == sn_nb_action.Constants.STATE_SKIPPED ||
currentState == sn_nb_action.Constants.STATE_COMPLETED) {
this._log.error("Action state is " + currentState + ", it cannot be changed");
return false;
}
return this.nextBestActionDAO.setActionState(actionDetailRecord, state);
},
hideRecommendation: function(actionDetailRecord) {
var hash = actionDetailRecord.getValue(sn_nb_action.Constants.COL_PARENT_RA_ID);
//for upgrade scenarios when hash is empty
if (gs.nil(hash))
return false;
var stateAttributesList = this.nextBestActionDAO.getStatesAttributesListFromActionDetails(hash, actionDetailRecord);
var actionHandler = this._getActionHandler(actionDetailRecord);
if (actionHandler) {
var actionRecord = actionDetailRecord[sn_nb_action.Constants.COL_RECOMMENDED].getRefRecord();
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionRecord)) {
try {
if (typeof actionHandler.hideRecommendation === "function") {
var hideAction = actionHandler.hideRecommendation(stateAttributesList, actionRecord);
return hideAction;
}
} catch (ex) {
this._log.error("Failed to get hideAction value of recommended action " + actionRecord.getUniqueValue());
}
}
} else
this._log.error("Could not find implementaion for action type " + actionDetailRecord.getUniqueValue());
},
_getHideActionResponse: function() {
var response = {};
response.actionStatus = sn_nb_action.Constants.STATUS_ERROR;
response.statusCode = sn_nb_action.Constants.ERROR_405;
response.errorMessage = sn_nb_action.Constants.RA_PERFORMED_MESSAGE;
return response;
},
_setCallToActions: function(actionTypeRecord, actionRecord, currentRecord, currentDetail, actionDetailObj) {
var actionHandler = sn_nb_action.NextBestActionUtil.getActionTypeHandler(actionTypeRecord);
if (actionHandler) {
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionRecord)) {
try {
if (typeof actionHandler.getActions === "function") {
var callToActions = actionHandler.getActions(actionRecord);
actionDetailObj.setCallToActions(callToActions);
}
} catch (ex) {
this._log.error("Failed to get call to actions of recommended action " + actionRecord.getUniqueValue());
}
}
} else
this._log.error("Error in implementing _setCallToActions");
},
_addCallToActions: function(currentRecord, actionDetailRecord, actionDetailObj) {
var actionHandler = this._getActionHandler(actionDetailRecord);
if (actionHandler) {
var actionRecord = actionDetailRecord[sn_nb_action.Constants.COL_RECOMMENDED].getRefRecord();
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionRecord)) {
try {
if (typeof actionHandler.getActions === "function") {
var callToActions = actionHandler.getActions(actionRecord);
actionDetailObj.setCallToActions(callToActions);
}
} catch (ex) {
this._log.error("Failed to get call to actions of recommended action " + actionRecord.getUniqueValue());
}
}
} else
this._log.error("Could not find implementaion for action type " + actionDetailRecord.getUniqueValue());
},
_getActionAttributes: function(actionDetailRecord) {
var actionHandler = this._getActionHandler(actionDetailRecord);
if (actionHandler) {
var actionRecord = actionDetailRecord[sn_nb_action.Constants.COL_RECOMMENDED].getRefRecord();
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionRecord)) {
try {
if (typeof actionHandler.getActionAttributes === "function") {
var actionAttributes = actionHandler.getActionAttributes(actionRecord, actionDetailRecord.getValue(sn_nb_action.Constants.COL_ATTRIBUTE));
return actionAttributes;
}
} catch (ex) {
this._log.error("Failed to get action attributes of recommended action " + actionRecord.getUniqueValue());
}
}
} else
this._log.error("Could not find implementaion for action type " + actionDetailRecord.getUniqueValue());
},
_setTitleAndDescription: function(actionTypeRecord, actionRecord, currentRecord, currentDetail, actionDetailObj) {
var actionHandler = sn_nb_action.NextBestActionUtil.getActionTypeHandler(actionTypeRecord);
if (actionHandler) {
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionRecord)) {
try {
if (typeof actionHandler.getTitle === "function") {
title = actionHandler.getTitle(currentRecord, actionRecord, currentDetail.actionInputs);
if (sn_nb_action.NextBestActionUtil.isValidString(title))
actionDetailObj.setTitle(title);
}
if (actionHandler && typeof actionHandler.getDescription === "function") {
desc = actionHandler.getDescription(currentRecord, actionRecord, currentDetail.actionInputs);
if (sn_nb_action.NextBestActionUtil.isValidString(desc))
actionDetailObj.setDescription(desc);
}
} catch (ex) {
this._log.error("Failed to get title/description of action " + actionRecord.getUniqueValue());
}
}
} else
this._log.error("Error in implementing _setTitleAndDescription");
},
_addTitleAndDescription: function(currentRecord, actionDetailRecord, actionDetailObj) {
var actionHandler = this._getActionHandler(actionDetailRecord);
if (actionHandler) {
var actionRecord = actionDetailRecord[sn_nb_action.Constants.COL_RECOMMENDED].getRefRecord();
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionRecord)) {
try {
if (typeof actionHandler.getTitle === "function") {
var title = actionHandler.getTitle(currentRecord, actionRecord, actionDetailRecord[sn_nb_action.Constants.COL_ACTION_INPUTS]);
if (sn_nb_action.NextBestActionUtil.isValidString(title))
actionDetailObj.setTitle(title);
}
if (actionHandler && typeof actionHandler.getDescription === "function") {
var desc = actionHandler.getDescription(currentRecord, actionRecord, actionDetailRecord[sn_nb_action.Constants.COL_ACTION_INPUTS]);
if (sn_nb_action.NextBestActionUtil.isValidString(desc))
actionDetailObj.setDescription(desc);
}
} catch (ex) {
this._log.error("Failed to get title/description of action " + actionRecord.getUniqueValue());
}
}
} else
this._log.error("Could not find implementaion for action type " + actionDetailRecord.getUniqueValue());
},
_addCustomPreviewExpereince: function(currentRecord, actionDetailRecord, actionDetailObj) {
var actionHandler = this._getActionHandler(actionDetailRecord);
if (actionHandler) {
var actionRecord = actionDetailRecord[sn_nb_action.Constants.COL_RECOMMENDED].getRefRecord();
try {
if (typeof actionHandler.getCustomAttributes === "function") {
var previewExpereince = actionHandler.getPreviewExperience(currentRecord, actionRecord);
actionDetailObj.setPreviewExperience(previewExpereince);
}
} catch (ex) {
this._log.error("Failed to get custom preview expereince of action " + actionRecord.getUniqueValue());
}
}
},
_setCustomAttributes: function(actionTypeRecord, actionRecord, currentRecord, currentDetail, actionDetailObj) {
var actionHandler = sn_nb_action.NextBestActionUtil.getActionTypeHandler(actionTypeRecord);
if (actionHandler) {
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionRecord)) {
try {
if (typeof actionHandler.getCustomAttributes === "function") {
var previewFields = actionHandler.getCustomAttributes(currentRecord, actionRecord, currentDetail.actionInputs);
actionDetailObj.setCustomAttribute(previewFields);
}
} catch (ex) {
this._log.error("Failed to get custom attributes of action " + actionRecord.getUniqueValue());
}
}
} else
this._log.error("Could not find implementaion for action type");
},
_addCustomAttributes: function(currentRecord, actionDetailRecord, actionDetailObj) {
var actionHandler = this._getActionHandler(actionDetailRecord);
if (actionHandler) {
var actionRecord = actionDetailRecord[sn_nb_action.Constants.COL_RECOMMENDED].getRefRecord();
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionRecord)) {
try {
if (typeof actionHandler.getCustomAttributes === "function") {
var previewFields = actionHandler.getCustomAttributes(currentRecord, actionRecord,
actionDetailRecord[sn_nb_action.Constants.COL_ACTION_INPUTS]);
actionDetailObj.setCustomAttribute(previewFields);
}
} catch (ex) {
this._log.error("Failed to get custom attributes of action " + actionRecord.getUniqueValue());
}
}
} else
this._log.error("Could not find implementaion for action type " + actionDetailRecord.getUniqueValue());
},
_getActionHandler: function(actionDetailRecord) {
var actionTypeRecord = actionDetailRecord[sn_nb_action.Constants.COL_ACTION_TYPE].getRefRecord();
return sn_nb_action.NextBestActionUtil.getActionTypeHandler(actionTypeRecord);
},
// Called by NextBestActionService to check if action can handle tablename of rule record.
isActionAllowed: function(tableName, actionRecord) {
var actionTableName = actionRecord.getValue(sn_nb_action.Constants.COL_SYS_CLASS_NAME);
var actionHandler = sn_nb_action.NextBestActionUtil.getActionTypeHandlerForTable(actionTableName);
if (actionHandler && typeof actionHandler.isActionAllowed === "function")
return actionHandler.isActionAllowed(tableName, actionRecord);
else
this._log.error("Could not find the handler for action table name" + actionTableName);
return false;
},
_sortByActionScore: function(a, b) {
if (b.actionScore > a.actionScore)
return 1;
if (b.actionScore < a.actionScore)
return -1;
return 0;
},
//Append Action Details
_appendActionDetails: function(actionDetails, actionDetailsNotInUse) {
var length = actionDetailsNotInUse.length;
for (var i = 0; i < length; i++)
actionDetails.push(actionDetailsNotInUse[i]);
return actionDetails;
},
_getRuleOrder: function(currentActions) {
var ruleOrderObj = {};
for (var recommended in currentActions) {
if (currentActions.hasOwnProperty(recommended)) {
var actionDetails = currentActions[recommended];
for (var i = 0; i < actionDetails.length; i++) {
var actionDetail = actionDetails[i];
for (var rule in actionDetail.ruleSysIds) {
if (actionDetail.ruleSysIds.hasOwnProperty(rule)) {
var actionDetailOrder = actionDetail.ruleSysIds[rule];
ruleOrderObj[rule] = actionDetailOrder.interOrder;
}
}
}
}
}
var sortedArray = this._sortProperties(ruleOrderObj);
ruleOrderObj = {};
var length = sortedArray.length;
for (var index = 0; index < length; index++)
ruleOrderObj[sortedArray[index][0]] = sortedArray[index][1];
var order = 1;
for (var key in ruleOrderObj) {
if (ruleOrderObj.hasOwnProperty(key)) {
ruleOrderObj[key] = order;
order = order + 1;
}
}
return ruleOrderObj;
},
/**
* Get all rules sorted on order
*
* @return Object
**/
_getRuleOrderObj: function(contextRecord, states, recommendationType) {
var actionDetailRecords = this.nextBestActionDAO.getAllActionDetails(contextRecord, states, recommendationType);
var ruleOrderObj = {};
while (actionDetailRecords && actionDetailRecords.next()) {
if (!gs.nil(actionDetailRecords[sn_nb_action.Constants.COL_RULE]))
this.nextBestActionDAO.updateActionDetailOnUpgrade(actionDetailRecords);
var actionDetailOrders = this.nextBestActionDAO.getActionDetailOrders(actionDetailRecords, true);
while (actionDetailOrders && actionDetailOrders.next())
ruleOrderObj[actionDetailOrders.getValue('rule')] = actionDetailOrders.getValue('inter_order');
}
var sortedArray = this._sortProperties(ruleOrderObj);
ruleOrderObj = {};
var length = sortedArray.length;
for (var index = 0; index < length; index++)
ruleOrderObj[sortedArray[index][0]] = sortedArray[index][1];
var order = 1;
for (var key in ruleOrderObj) {
if (ruleOrderObj.hasOwnProperty(key)) {
ruleOrderObj[key] = order;
order = order + 1;
}
}
return ruleOrderObj;
},
_sortProperties: function(obj) {
var sortable = [];
for (var key in obj)
if (obj.hasOwnProperty(key))
sortable.push([key, obj[key]]);
sortable.sort(function(a, b) {
return a[1] - b[1];
});
return sortable;
},
_compareByInterOrder: function(a, b) {
if (a.getInterOrder() > b.getInterOrder())
return 1;
if (a.getInterOrder() < b.getInterOrder())
return -1;
return 0;
},
errorOutAction: function(contextRecord, actionSysId, actionDetailSysId, actionInitialAttributes) {
var actionDetailRecord;
if (gs.nil(actionDetailSysId))
actionDetailRecord = this.nextBestActionDAO.getActionDetail(contextRecord, actionSysId);
else
actionDetailRecord = this.nextBestActionDAO.getActionDetailBySysId(actionDetailSysId);
var attributes = actionDetailRecord.getValue('attribute');
if (actionDetailRecord.state != sn_nb_action.Constants.STATE_SKIPPED && actionInitialAttributes && actionInitialAttributes.id == sn_nb_action.Constants.TBL_DECISION_TREE && gs.nil(attributes)) {
this.nextBestActionDAO.setActionAttribute(actionDetailRecord, actionInitialAttributes.attributes);
}
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionDetailRecord)) {
return this._changeState(actionDetailRecord, sn_nb_action.Constants.STATE_IN_ERROR);
} else
this._log.warn("Could not find action detail for action " + actionSysId);
return false;
},
_addErrorMessage: function(actionDetailRecord, actionDetailObj) {
var actionHandler = this._getActionHandler(actionDetailRecord);
if (actionHandler) {
if (sn_nb_action.NextBestActionUtil.isValidRecord(actionDetailRecord)) {
try {
if (typeof actionHandler.getErrorMessage === "function") {
var errorMessage = actionHandler.getErrorMessage(actionDetailRecord.getValue(sn_nb_action.Constants.COL_ATTRIBUTE));
if (sn_nb_action.NextBestActionUtil.isValidString(errorMessage))
actionDetailObj.setErrorMessage(errorMessage);
}
} catch (ex) {
this._log.error("Failed to get error message of action " + actionRecord.getUniqueValue());
}
}
} else
this._log.error("Could not find implementation for action type " + actionDetailRecord.getUniqueValue());
},
type: 'ActionServiceImpl'
};
Sys ID
7ad6f1713b3e1010c24e870044efc4ac