Name
sn_rf.RFActionService
Description
Class for sn_rf_recommendation_action table utility functions.
Script
var RFActionService = Class.create();
RFActionService.serializeEvaluationOutput = function(evaluationOutputs) {
var ruleOutputs = {};
// Serialize the rule outputs for generating recommendations
var evaluationOutputsKeys = evaluationOutputs ? Object.keys(evaluationOutputs) : {};
for (var idx1 = 0; idx1 < evaluationOutputsKeys.length; idx1++) {
var output = {};
var key = evaluationOutputsKeys[idx1];
var value = evaluationOutputs[key];
if (value && value.isValidRecord) {
output[RFConstants.TYPE] = RFConstants.evaluationOutputTypes.REFERENCE;
output[RFConstants.REFERENCE_TYPE] = value.getTableName();
output[RFConstants.VALUE] = value.getValue(RFConstants.fields.SYS_ID);
} else {
output[RFConstants.TYPE] = RFConstants.evaluationOutputTypes.STRING;
output[RFConstants.VALUE] = value;
}
ruleOutputs[key] = output;
}
return JSON.stringify(ruleOutputs);
};
RFActionService.createObjectFromRuleOutputs = function(ruleOutputsString) {
var ruleOutputsObject = {};
var ruleOutputsObjectDetails = {
isAccessible: true,
ruleOutputsObject: ruleOutputsObject
};
try {
var ruleOutputs = JSON.parse(ruleOutputsString);
var hiddenKeys = ruleOutputs[RFConstants.evaluatorVariable.HIDDEN_INTERNAL] &&
ruleOutputs[RFConstants.evaluatorVariable.HIDDEN_INTERNAL][RFConstants.VALUE] || [];
var keys = Object.keys(ruleOutputs);
for (var idx1 = 0; idx1 < keys.length; idx1++) {
var ruleOutput = ruleOutputs[keys[idx1]];
var value = ruleOutput[RFConstants.VALUE];
if (ruleOutput[RFConstants.TYPE] == RFConstants.evaluationOutputTypes.REFERENCE) {
var table = ruleOutput[RFConstants.REFERENCE_TYPE];
//Check if the record is accessible to logged-in user. Skip ACLs check if the schema element is hidden.
if (hiddenKeys.indexOf(keys[idx1]) != -1) {
var gr = new GlideRecord(table);
} else {
gr = new GlideRecordSecure(table);
}
if (gr.isValid() && gr.get(value)) {
ruleOutputsObject[keys[idx1]] = gr;
} else {
ruleOutputsObjectDetails.isAccessible = false;
ruleOutputsObject[keys[idx1]] = value;
}
} else {
ruleOutputsObject[keys[idx1]] = value;
}
}
} catch (e) {
new RFLogger("RFActionService - createObjectFromRuleOutputs").logError(e);
return ruleOutputsObjectDetails;
}
return ruleOutputsObjectDetails;
};
RFActionService.discardRecommendation = function(contextRecord, ruleOutputsString, options) {
var result = {};
var ruleOutputs = RFActionService.createObjectFromRuleOutputs(ruleOutputsString).ruleOutputsObject;
var historyId = RFActionService._addInHistory(contextRecord, ruleOutputs, ruleOutputsString, RFConstants.historyStatus.DISCARDED, options.experienceId, RFConstants.actionType.DISCARD);
if (historyId) {
result[RFConstants.experienceDetails.MESSAGE] = RFConstants.DISCARD_SUCCESS_MESSAGE;
} else {
result[RFConstants.ERROR_CODE] = 40001;
result[RFConstants.ERROR_MESSAGE] = RFConstants.DISCARD_ERROR_MESSAGE;
new RFLogger("RFActionService - discardRecommendation").logError(result[RFConstants.ERROR_MESSAGE]);
}
return result;
};
RFActionService._addInHistory = function(contextRecord, ruleOutputs, ruleOutputsString, status, experienceId, actionID) {
var experience = new RFExperienceService(experienceId);
return RFHistoryService.create(contextRecord, experienceId, actionID, experience.getPrimaryActionId() == actionID, status, ruleOutputs, ruleOutputsString);
};
RFActionService.prototype = {
tableName: RFConstants.tables.SN_RF_RECOMMENDATION_ACTION,
initialize: function(grOrSysId) {
this.rfLogger = new RFLogger("RFActionService");
if (grOrSysId && grOrSysId.sys_class_name == this.tableName) {
this.currentRecord = grOrSysId;
} else if (grOrSysId) {
var actionGr = new GlideRecord(this.tableName);
if (actionGr.get(grOrSysId)) {
this.currentRecord = actionGr;
}
}
},
hasValidRecord: function() {
return this.currentRecord && this.currentRecord.sys_class_name == this.tableName;
},
isActive: function() {
return this.currentRecord.getValue(RFConstants.fields.SN_RF_RECOMMENDATION_ACTION_ACTIVE);
},
getLabel: function() {
return this.currentRecord.getDisplayValue(RFConstants.fields.SN_RF_RECOMMENDATION_ACTION_LABEL);
},
getSysId: function() {
return this.currentRecord.getValue(RFConstants.fields.SYS_ID);
},
getUndoActionSysId: function() {
return this.currentRecord.getValue(RFConstants.fields.SN_RF_RECOMMENDATION_ACTION_UNDO_ACTION);
},
getUndoAction: function() {
var undoActionId = this.getUndoActionSysId();
if (undoActionId) {
var action = new RFActionService(undoActionId);
if (action.hasValidRecord()) {
return action;
}
}
},
getType: function() {
return this.currentRecord.getValue(RFConstants.fields.SN_RF_RECOMMENDATION_ACTION_TYPE);
},
isServerScript: function() {
return this.getType() == RFConstants.actionType.SERVER_SCRIPT;
},
isSubflow: function() {
return this.getType() == RFConstants.actionType.SUBFLOW;
},
isUXFClientAction: function() {
return this.getType() == RFConstants.actionType.UXF_CLIENT_ACTION;
},
getServerScript: function() {
return this.currentRecord.getValue(RFConstants.fields.SN_RF_RECOMMENDATION_ACTION_SERVER_SCRIPT);
},
getSubflow: function() {
return this.currentRecord[RFConstants.fields.SN_RF_RECOMMENDATION_ACTION_SUBFLOW].getRefRecord();
},
getActionKey: function() {
return this.currentRecord.getValue(RFConstants.fields.SN_RF_RECOMMENDATION_ACTION_ACTION_KEY);
},
getActionClientPayload: function() {
return this.currentRecord.getValue(RFConstants.fields.SN_RF_RECOMMENDATION_ACTION_CLIENT_PAYLOAD);
},
markCompleteOrRevert: function(contextRecord, ruleOutputsString, isUndo, options) {
var ruleOutputs = RFActionService.createObjectFromRuleOutputs(ruleOutputsString).ruleOutputsObject;
var historyId = this._updateHistory(contextRecord, ruleOutputs, ruleOutputsString, isUndo, options);
if (historyId) {
return {
message: RFConstants.EMPTY_STRING
};
} else {
if (isUndo) {
var exception = new RFExceptionManager("MARK_REVERT_FAILED");
} else {
exception = new RFExceptionManager("MARK_COMPLETE_FAILED");
}
this.rfLogger.logError(exception.getMessage(), "RFActionService - markCompleteOrRevert");
return exception.getJSON();
}
},
performAction: function(contextRecord, ruleOutputsString, isUndo, options) {
var ruleOutputs = RFActionService.createObjectFromRuleOutputs(ruleOutputsString).ruleOutputsObject;
var errorCode, errorMessage, message;
var result = {};
result[RFConstants.STATUS] = RFConstants.INITIALIZED;
if (this.isServerScript()) {
var evaluator = new GlideScopedEvaluator();
evaluator.putVariable(RFConstants.actionVars.CURRENT, contextRecord);
evaluator.putVariable(RFConstants.actionVars.RULE_OUTPUTS, ruleOutputs);
result = evaluator.evaluateScript(this.currentRecord, RFConstants.fields.SN_RF_RECOMMENDATION_ACTION_SERVER_SCRIPT);
} else if (this.isSubflow()) {
var subflow = this.getSubflow();
try {
var inputs = {};
inputs[RFConstants.actionVars.CURRENT] = contextRecord;
inputs[RFConstants.actionVars.RULE_OUTPUTS_SUBFLOW] = ruleOutputs;
var internalName = subflow.getValue(RFConstants.actionVars.INTERNAL_NAME);
var scopeSysId = subflow.getValue(RFConstants.actionVars.SCOPE);
var scope = (scopeSysId === RFConstants.actionVars.GLOBAL) ? scopeSysId : subflow.sys_scope.scope;
var subflowName = scope + RFConstants.actionVars.DOT + internalName;
var output = sn_fd.FlowAPI.getRunner().subflow(subflowName).inForeground().withInputs(inputs).run();
result = output.getOutputs();
this._convertActionResultToCamelCase(result);
} catch (e) {
this.rfLogger.logError("Error occured while executing performAction for subflow " + subflow.sys_id + ". Error: " + e);
}
}
if (result && result.status == RFConstants.SUCCESS) {
this._updateHistory(contextRecord, ruleOutputs, ruleOutputsString, isUndo, options);
return {
"message": result.message || RFConstants.DEFAULT_ACTION_SUCCESS_MESSAGE
};
} else {
errorMessage = (result && result.errorMessage) || RFConstants.DEFAULT_ACTION_ERROR_MESSAGE;
errorCode = result && result.errorCode;
}
if (!errorCode) {
var exception = new RFExceptionManager("UNKNOWN_ERROR");
errorCode = exception.getCode();
errorMessage = exception.getMessage();
}
this.rfLogger.logError("Error occurred while performing action " + this.getSysId() +
". Error: " + errorMessage, "RFActionService - performAction");
return {
"errorCode": errorCode,
"errorMessage": errorMessage
};
},
getDetails: function(contextRecord, evaluationOutputs, experienceId, needUndo) {
var details;
try {
if (needUndo && this.hasValidRecord()) {
var undoAction = this.getUndoAction();
if (undoAction) {
details = undoAction._getDetails(contextRecord, evaluationOutputs, experienceId, true, this.getSysId());
} else {
details = {};
details[RFConstants.actionDetails.TYPE] = RFConstants.actionType.DISABLED;
details[RFConstants.actionDetails.ACTION_SYS_ID] = this.getSysId();
details[RFConstants.actionDetails.LABEL] = this.getLabel();
}
} else if (!needUndo && this.hasValidRecord()) {
details = this._getDetails(contextRecord, evaluationOutputs, experienceId, false);
}
} catch (e) {
this.rfLogger.logError("Error occurred while getting details for action " + this.getSysId() +
". Error: " + e, "RFActionService - getDetails");
}
return details;
},
_getDetails: function(contextRecord, evaluationOutputs, experienceId, isUndo, undoOf) {
var details = {};
details[RFConstants.actionDetails.TYPE] = this.getType();
details[RFConstants.actionDetails.ACTION_SYS_ID] = this.getSysId();
details[RFConstants.actionDetails.LABEL] = this.getLabel();
details[RFConstants.actionDetails.IS_UNDO] = isUndo;
details[RFConstants.actionDetails.ADDITIONALPARAMETERS] = {};
if (isUndo) {
details[RFConstants.actionDetails.ADDITIONALPARAMETERS][RFConstants.actionDetails.UNDO_OF] = undoOf;
}
details[RFConstants.actionDetails.RULE_OUTPUTS] = RFActionService.serializeEvaluationOutput(evaluationOutputs);
details[RFConstants.actionDetails.ADDITIONALPARAMETERS][RFConstants.actionDetails.EXPERIENCE_ID] = experienceId;
if (this.isUXFClientAction()) {
details[RFConstants.actionDetails.ACTION_KEY] = this.getActionKey();
details[RFConstants.actionDetails.CLIENT_PAYLOAD] = new RFPillParserUtils().getParsedValue(this.getActionClientPayload(), contextRecord, evaluationOutputs);
}
details[RFConstants.actionDetails.ADDITIONALPARAMETERS] = JSON.stringify(details[RFConstants.actionDetails.ADDITIONALPARAMETERS]);
return details;
},
_convertActionResultToCamelCase: function(result) {
if (!result) {
return;
}
result.errorCode = result.error_code;
result.errorMessage = result.error_message;
},
_updateHistory: function(contextRecord, ruleOutputs, ruleOutputsString, isUndo, options) {
if (isUndo) {
var historyId = RFHistoryService.markReverted(contextRecord, options.experienceId, options.undoOf, ruleOutputs);
} else {
historyId = RFActionService._addInHistory(contextRecord, ruleOutputs, ruleOutputsString, RFConstants.historyStatus.COMPLETED, options.experienceId, this.getSysId());
}
return historyId;
},
type: "RFActionService"
};
Sys ID
09d6be32c7433010dd7ab6c427c2602e