Name
sn_nb_action.RuleServiceImpl
Description
A service to manage rules and interact with rule handlers
Script
var RuleServiceImpl = Class.create();
RuleServiceImpl.prototype = {
initialize: function() {
this.nextBestActionDAO = sn_nb_action.NextBestActionUtil.getNextBestActionDAO();
this._log = new global.GSLog(sn_nb_action.Constants.PROP_LOG_LEVEL, this.type);
},
getBestActions: function(currentRecord, actionTypes, recommendationType, fields) {
var rules = {};
if (!actionTypes) {
actionTypes = this.nextBestActionDAO.loadActionTypesByTable();
if (!actionTypes) {
this._log.error("There are no action types defined.");
return false;
}
}
var rulesRecord = this.nextBestActionDAO.getRules(currentRecord, fields);
if (!rulesRecord) {
this._log.error("There are no rules defined or rules are inactive for table " + currentRecord.getTableName());
return false;
}
var currentActions = {};
var hasActions = false;
while (rulesRecord.next()) {
rules[rulesRecord.getUniqueValue()] = true;
var recommendedActionsArr = this._evaluateRule(currentRecord, rulesRecord, recommendationType);
if (recommendedActionsArr) {
var ruleActions = this._processActions(recommendedActionsArr, rulesRecord, currentActions, actionTypes);
if (ruleActions) {
hasActions = true;
currentActions = Object.extend(currentActions, ruleActions);
}
}
}
if (hasActions)
return {
'currentActions': currentActions,
'currentRules': rules
};
return {
'currentActions': false,
'currentRules': rules
};
},
_processActions: function(recommendedActionsArr, ruleRecord, currentActions, actionTypes) {
var ruleActions = {};
var hasActions = false;
for (var i = 0; i < recommendedActionsArr.length; i++) {
var actionRecord = recommendedActionsArr[i].getAction();
if (!sn_nb_action.NextBestActionUtil.isValidRecord(actionRecord))
continue;
var actionSysId = actionRecord.getUniqueValue();
var actionTableName = actionRecord.getTableName();
var actionTypeDetail = actionTypes[actionTableName];
try {
if (actionTypeDetail) {
var newActionDetailObj = sn_nb_action.ActionDetail.createFromRule(ruleRecord, actionTypeDetail, i + 1, recommendedActionsArr[i]);
if (currentActions.hasOwnProperty(actionSysId) || ruleActions.hasOwnProperty(actionSysId))
this._processEvaluatedAction(currentActions, ruleActions, newActionDetailObj, actionSysId, ruleRecord, i + 1, recommendedActionsArr[i]);
else {
ruleActions[actionSysId] = [newActionDetailObj];
hasActions = true;
}
} else
this._log.error("Undefined action type " + [ruleRecord.getUniqueValue(), actionTableName, actionSysId]);
} catch (ex) {
this._log.error("Error processing recommended action: " + recommendedActionsArr[i].getHint() + " " + ex.message);
}
}
if (hasActions)
return ruleActions;
return false;
},
_processEvaluatedAction: function(currentActions, ruleActions, newActionDetailObj, actionSysId, ruleRecord, intraorder, recommendedAction) {
var processedActionDetArray, duplicateActionDetObject;
if (currentActions.hasOwnProperty(actionSysId)) {
processedActionDetArray = currentActions[actionSysId];
duplicateActionDetObject = sn_nb_action.NextBestActionUtil.getDuplicateActionDetail(processedActionDetArray, newActionDetailObj);
if (duplicateActionDetObject) {
//action detail with same action input was recommended by another rule
sn_nb_action.ActionDetail.updateFromRule(duplicateActionDetObject, ruleRecord, intraorder, recommendedAction);
} else
processedActionDetArray.push(newActionDetailObj);
} else { //same rule duplicate recommendation
processedActionDetArray = ruleActions[actionSysId];
duplicateActionDetObject = sn_nb_action.NextBestActionUtil.getDuplicateActionDetail(processedActionDetArray, newActionDetailObj);
if (!duplicateActionDetObject)
processedActionDetArray.push(newActionDetailObj);
else {
// update groups for the existing action from new action
sn_nb_action.ActionDetail.updateFromRule(duplicateActionDetObject, ruleRecord, intraorder, recommendedAction);
}
}
},
_evaluateRule: function(currentRecord, ruleRecord, recommendationType) {
var ruleRoles = ruleRecord.getValue(sn_nb_action.Constants.COL_ROLES);
if (gs.nil(ruleRoles) || gs.hasRole(ruleRoles)) {
var ruleTableName = ruleRecord.getValue(sn_nb_action.Constants.COL_SYS_CLASS_NAME);
var ruleHandler = sn_nb_action.NextBestActionUtil.getRuleTypeHandler(ruleTableName);
if (ruleHandler && typeof ruleHandler.evaluateRule == "function") {
try {
var actualRuleRecord = new GlideRecord(ruleTableName);
if (actualRuleRecord.get(ruleRecord.getUniqueValue())) {
var recommendedActionsArr = ruleHandler.evaluateRule(currentRecord, actualRuleRecord, recommendationType);
if (recommendedActionsArr && Array.isArray(recommendedActionsArr) && recommendedActionsArr.length > 0)
return recommendedActionsArr;
}
} catch (ex) {
this._log.error("Failed to evaluate action(s) for rule " + ruleRecord.getUniqueValue());
}
} else
this._log.error("Could not find implementaion for rule type " + ruleTableName);
}
return false;
},
isValidRule: function(ruleRecord) {
var ruleTableName = ruleRecord.getValue(sn_nb_action.Constants.COL_SYS_CLASS_NAME);
var ruleHandler = sn_nb_action.NextBestActionUtil.getRuleTypeHandler(ruleTableName);
if (ruleHandler && typeof ruleHandler.isValidRule == "function") {
return ruleHandler.isValidRule(ruleRecord);
} else
this._log.error("Could not find implementaion for rule type " + ruleTableName);
return false;
},
type: 'RuleServiceImpl'
};
Sys ID
246f463d3b3e1010c24e870044efc4e4