Name
global.AutoResolutionAPI
Description
This is an external facing Auto Resolution API for invoking IAR and dashboards to get Data points
Script
var AutoResolutionAPI = Class.create();
AutoResolutionAPI.HR_CORE_CASE_TABLE = "sn_hr_core_case";
AutoResolutionAPI.DISABLE_SELF_TUNING_PROPERTY = "glide.platform_ml.disable_agent_zero_self_tuning";
/*
* @param options = {
"tableName" : "incident",
"sysId" : "zzzzzzzz";
}
OR
@param options = {
"taskGr": current
}
OR
@param options = {
"taskGr": taskGr
}
*
* @returns {"status":"","reason":"","iar_enabled":""}
*/
AutoResolutionAPI.invokeIAR = function(options) {
var result = {};
var tableName = options['tableName'] || '';
var sysId = options['sysId'] || '';
var taskGr = options['taskGr'] || '';
var logger = createLogger(sysId, tableName, taskGr);
//check global flag
var isAREnabled = gs.getProperty(AutoResolutionConstants.GLOBAL_AUTO_RESOLUTION_PROPERTY) === 'true';
if (!isAREnabled) {
logger.debug(AutoResolutionConstants.GLOBAL_FLAG_DISABLED_MSG);
return constructFailureResponse(AutoResolutionConstants.GLOBAL_FLAG_DISABLED_MSG, false);
}
var sysIdProvided = false;
if (gs.nil(tableName) && gs.nil(sysId) && gs.nil(taskGr)) {
logger.debug(AutoResolutionConstants.INVALID_SYSID_TABLENAME_MSG);
return constructFailureResponse(AutoResolutionConstants.INVALID_SYSID_TABLENAME_MSG, true);
}
if (!gs.nil(tableName) && !gs.nil(sysId)) {
sysIdProvided = true;
//validate its a task table
if (!AutoResolutionAPIHelper.validateTaskTable(tableName)) {
logger.debug(AutoResolutionConstants.NOT_A_TASKGR_MSG);
return constructFailureResponse(AutoResolutionConstants.NOT_A_TASKGR_MSG, true);
}
//construct taskGr
taskGr = AutoResolutionTaskDataBroker.getTaskRecord(tableName, sysId);
if (gs.nil(taskGr)) {
logger.debug(AutoResolutionConstants.INVALID_SYSID_TABLENAME_MSG);
return constructFailureResponse(AutoResolutionConstants.INVALID_SYSID_TABLENAME_MSG, true);
}
}
if (!sysIdProvided && !taskGr.instanceOf('task')) {
logger.debug(AutoResolutionConstants.NOT_A_TASKGR_MSG);
return constructFailureResponse(AutoResolutionConstants.NOT_A_TASKGR_MSG, true);
}
else
tableName = taskGr.getTableName();
var configFieldNames = [AutoResolutionConstants.CONFIGURATION_TRIGGER_CONDITION_FIELD_NAME, AutoResolutionConstants.SYSID_FIELD_NAME, AutoResolutionConstants.ACTIVE_FIELD_NAME];
var configResults = AutoResolutionUtil.getConfigurationFieldValuesForTaskTable(tableName, configFieldNames);
if (Object.keys(configResults).length === 0) {
logger.debug(AutoResolutionConstants.IAR_CONFIG_NOT_FOUND_MSG, tableName);
return constructFailureResponse(replaceMsgParams(AutoResolutionConstants.IAR_CONFIG_NOT_FOUND_MSG, tableName), true);
}
if (configResults[AutoResolutionConstants.ACTIVE_FIELD_NAME] !== '1') {
logger.debug(AutoResolutionConstants.IAR_CONFIG_INACTIVE_MSG, tableName);
return constructFailureResponse(replaceMsgParams(AutoResolutionConstants.IAR_CONFIG_INACTIVE_MSG, tableName), true);
}
//check if the task condition falls in the condition that we have on config
if (!GlideFilter.checkRecord(taskGr, configResults[AutoResolutionConstants.CONFIGURATION_TRIGGER_CONDITION_FIELD_NAME])) {
logger.debug(AutoResolutionConstants.IAR_TRIGGER_CONDITION_MISMATCH_MSG);
return constructFailureResponse(AutoResolutionConstants.IAR_TRIGGER_CONDITION_MISMATCH_MSG, true);
}
//assign task to bot user and dispatch sysevent
new AutoResolutionTaskHelper().processTask(taskGr, configResults[AutoResolutionConstants.SYSID_FIELD_NAME]);
return constructSuccessResponse();
};
/**
* API for Cases Processed by IAR - Get the total number of cases processed by IAR
* @param {string} tableName - Name of the task table that should have a valid IAR config
* @param {number} numOfDays - Ex: 30, 90 or 120
* @returns {number} numOfCasesProcessed - integer value
*/
AutoResolutionAPI.getCasesProcessedByIAR = function(tableName, numOfDays) {
if (!AutoResolutionAPIHelper.validateInputs(tableName, numOfDays))
return 0;
return AutoResolutionAPIHelper.getCasesProcessedCount(tableName, numOfDays);
};
/**
* API for Deflectable Cases - Get the total number of cases where deflectable is true
* @param {string} tableName - Name of the task table that should have a valid IAR config
* @param {number} numOfDays - Ex: 30, 90 or 120
* @returns {number} numberOfCasesDeflected - integer value
*/
AutoResolutionAPI.getDeflectableCases = function(tableName, numOfDays) {
if (!AutoResolutionAPIHelper.validateInputs(tableName, numOfDays))
return 0;
return AutoResolutionAPIHelper.getDeflectableCaseCount(tableName, numOfDays);
};
/**
* API for Reviewed Cases - Get the total number of cases where solutions have been reviewed by user
* @param {string} tableName - Name of the task table that should have a valid IAR config
* @param {number} numOfDays - Ex: 30, 90 or 120
* @returns {number} numberOfCasesReviewed - integer value
*/
AutoResolutionAPI.getCasesReviewedByUser = function (tableName, numOfDays) {
if (!AutoResolutionAPIHelper.validateInputs(tableName, numOfDays))
return 0;
return AutoResolutionAPIHelper.getReviewedCaseCount(tableName, numOfDays);
};
/**
* API for Cases Auto-resolved - Get the total number of cases where the user requested to close the case
* @param {string} tableName - Name of the task table that should have a valid IAR config
* @param {number} numOfDays - Ex: 30, 90 or 120
* @returns {number} numberOfCasesResolved - integer value
*/
AutoResolutionAPI.getCasesResolvedByIAR = function(tableName, numOfDays) {
if (!AutoResolutionAPIHelper.validateInputs(tableName, numOfDays))
return 0;
return AutoResolutionAPIHelper.getResolvedCaseCount(tableName, numOfDays);
};
/**
* API for Feedback: Return the total number of positive, negative, and no feedback
* @param {string} tableName - Name of the task table that should have a valid IAR config
* @param {number} numOfDays - Ex: 30, 90 or 120
* @returns {{negative: number, no_feedback: number, positive: number}}
*/
AutoResolutionAPI.getFeedbackForCases = function(tableName, numOfDays) {
if (!AutoResolutionAPIHelper.validateInputs(tableName, numOfDays))
return {"positive" : 0, "negative" : 0, "no_feedback" : 0};
return AutoResolutionAPIHelper.getFeedbackCountForCases(tableName, numOfDays);
};
/**
* API for Response channels: Number of notifications delivered on each response channels
* @param {string} tableName - Name of the task table that should have a valid IAR config
* @param {number} numOfDays - Ex: 30, 90 or 120
* @returns {Email: number, SMS: number, "Virtual Agent": number}
*/
AutoResolutionAPI.getNotificationsDeliveredCountPerResponseChannels = function(tableName, numOfDays) {
if (!AutoResolutionAPIHelper.validateInputs(tableName, numOfDays))
return {"Email" : 0, "SMS" : 0, "Virtual Agent" : 0};
return AutoResolutionAPIHelper.getNotificationsDeliveredCountForCases(tableName, numOfDays);
};
/**
* API for Cases with matched intents - Get the number of cases for which intent was found
* @param {string} tableName - Name of the task table that should have a valid IAR config
* @param {number} numOfDays - Ex: 30, 90 or 120
* @returns {number} of Cases with intents which had matched topics
*/
AutoResolutionAPI.getCasesWithMatchedIntents = function(tableName, numOfDays) {
if (!AutoResolutionAPIHelper.validateInputs(tableName, numOfDays))
return 0;
return AutoResolutionAPIHelper.getMatchedIntentsCaseCount(tableName, numOfDays);
};
/**
* API for cases with matched search results
* @param {string} tableName - Name of the task table that should have a valid IAR config
* @param {number} numOfDays - Ex: 30, 90 or 120
* @returns {number} of Cases with matched search results
*/
AutoResolutionAPI.getCasesWithMatchedSearchResults = function (tableName, numOfDays) {
if (!AutoResolutionAPIHelper.validateInputs(tableName, numOfDays))
return 0;
return AutoResolutionAPIHelper.getAISearchResultsCaseCount(tableName, numOfDays);
};
/**
* API for Case with matched intents and topic is not found
* @param {string} tableName - Name of the task table that should have a valid IAR config
* @param {number} numOfDays - Ex: 30, 90 or 120
* @returns {number} of Cases with intents and no matched topics
*/
AutoResolutionAPI.getCasesWithIntentsAndNoTopics = function(tableName, numOfDays) {
if (!AutoResolutionAPIHelper.validateInputs(tableName, numOfDays))
return 0;
return AutoResolutionAPIHelper.getMatchedIntentsWithNoTopicsCaseCount(tableName, numOfDays);
};
/**
* API for number of cases where topic is found and could not be delivered
* @param {string} tableName - Name of the task table that should have a valid IAR config
* @param {number} numOfDays - Ex: 30, 90 or 120
* @returns {number} of cases with topics but notification couldn't be delivered
*/
AutoResolutionAPI.getCasesWithTopicFoundAndNotificationNotDelivered = function(tableName, numOfDays) {
if (!AutoResolutionAPIHelper.validateInputs(tableName, numOfDays))
return 0;
return AutoResolutionAPIHelper.getMatchedTopicsWithNotificationsNotDeliveredCaseCount(tableName, numOfDays);
};
/**
* API for Topics matched: Count of unique topics delivered to users
* @param {string} tableName - Name of the task table that should have a valid IAR config
* @param {number} numOfDays - Ex: 30, 90 or 120
* @returns {number} of unique topics that was delivered to users
*/
AutoResolutionAPI.getTopicsMatchedForIAR = function(tableName, numOfDays) {
if (!AutoResolutionAPIHelper.validateInputs(tableName, numOfDays))
return 0;
return AutoResolutionAPIHelper.getUniqueTopicsCount(tableName, numOfDays);
};
/**
* API to Get the total hours saved by IAR
* @param {string} tableName
* @param {number} numOfDays
* @returns {number} (MTTR * number cases auto-closed by IAR)
*/
AutoResolutionAPI.getHoursSavedByIAR = function(tableName, numOfDays) {
// we support this data point only if it is a HR related case table currently
if (!AutoResolutionAPI.isHRCaseTable(tableName))
return 0;
if (!AutoResolutionAPIHelper.validateInputs(tableName, numOfDays))
return 0;
return AutoResolutionAPIHelper.getHoursSaved(tableName, numOfDays);
};
/**
* API to get Total cost saved by IAR
* @param {string} tableName
* @param {number} numOfDays
* @returns {number} (Hours saved * cost)
*/
AutoResolutionAPI.getCostSavedByIAR = function(tableName, numOfDays) {
// we support this data point only if it is a HR related case table currently
if (!AutoResolutionAPI.isHRCaseTable(tableName))
return 0;
if (!AutoResolutionAPIHelper.validateInputs(tableName, numOfDays))
return 0;
return AutoResolutionAPIHelper.getCostSaved(tableName, numOfDays);
};
/**
* Check if the passed table name is a HR case table or extends HR case table
* @param {string} tableName
*/
AutoResolutionAPI.isHRCaseTable = function(tableName) {
if (tableName === AutoResolutionAPI.HR_CORE_CASE_TABLE)
return true;
var tableList = GlideDBObjectManager.get().getTableExtensions(AutoResolutionAPI.HR_CORE_CASE_TABLE);
return (tableList.indexOf(tableName) >= 0);
}
/**
* Sets the value of Disable self tuning property for agent zero
* @param propertyValue true|false
*/
AutoResolutionAPI.disableSelfTuningProperty = function(propertyValue) {
gs.setProperty(AutoResolutionAPI.DISABLE_SELF_TUNING_PROPERTY, propertyValue);
};
/**
* Returns an array af active response channels for a given IAR configuration
* @param configSysId
* @returns {responseChannel1, ..}
*/
AutoResolutionAPI.getActiveResponseChannels = function(configSysId) {
return AutoResolutionAPIHelper.getActiveResponseChannelsByConfiguration(configSysId);
};
/**
* Given the table name, checks whether a trained workflow solution is available in IAR, if true returns the workflow
* solution name
* @param tableName - incident | sn_hr_core_case
* @param languageCode - 'en' | 'fr' ..
* @returns {"trained_solution": true, "solution_name":"<if trained_solution is true>>"}
*/
AutoResolutionAPI.isTrainedWorkflowSolutionAvailable = function(tableName, languageCode) {
var response = {};
var logger = createLogger();
// check for valid IAR table name
var configSysId = AutoResolutionUtil.getConfigurationForTask(tableName);
if (gs.nil(configSysId)) {
logger.warn("isTrainedWorkflowSolutionAvailable: Not a valid IAR config table {0}", tableName)
response.trained_solution = false;
return response;
}
// check if solution record is created in IAR for given language
var result = AutoResolutionLanguageHelper.getSolutionNameAndVersionForLanguageWithCapability(configSysId,
languageCode || 'en', AutoResolutionConstants.AGENT_ZERO_WORKFLOW_CAPABILITY);
if (Object.keys(result).length === 0) {
logger.warn("isTrainedWorkflowSolutionAvailable: language configuration with workflow solution not found for the given " +
"table: {0} and language: {1}", tableName, languageCode)
response.trained_solution = false;
return response;
}
var mlHelper = new AutoResolutionMLHelper(configSysId);
var activeVersionExists = mlHelper.hasActiveVersion(result.solution_name);
if (!activeVersionExists) {
logger.warn("isTrainedWorkflowSolutionAvailable: there is no trained workflow solution with name {0}", result.solution_name);
response.trained_solution = false;
return response;
}
response.trained_solution = true;
response.solution_name = result.solution_name;
response.solution_version = result.solution_version;
return response;
};
/**
* Given the table name, gets list of active mapped intents from IAR intent to topic map table
* @param tableName
* @returns [intent1, intent2, ..]
*/
AutoResolutionAPI.getActiveMappedIntents = function(tableName) {
var mappedIntents = [];
var logger = createLogger();
var configSysId = AutoResolutionUtil.getConfigurationForTask(tableName);
if (gs.nil(configSysId))
return mappedIntents;
var result = AutoResolutionLanguageHelper.getSolutionNameAndVersionForLanguageWithCapability(configSysId,
'en', AutoResolutionConstants.AGENT_ZERO_WORKFLOW_CAPABILITY);
if (Object.keys(result).length === 0) {
logger.warn("getActiveMappedIntents: there is no workflow solution for given table: {0}, unable to return active intents",
tableName);
return mappedIntents;
}
var mlHelper = new AutoResolutionMLHelper(configSysId);
var activeVersionExists = mlHelper.hasActiveVersion(result.solution_name);
if (!activeVersionExists) {
logger.warn("getActiveMappedIntents: there is no trained workflow solution with name {0}, unable to return active intents", result.solution_name);
return mappedIntents;
}
var intentTopicMapGr = new GlideRecord(AutoResolutionConstants.INTENT_TOPIC_MAP_TABLE_NAME);
intentTopicMapGr.addQuery('ar_configuration.target_table_name', tableName);
intentTopicMapGr.addActiveQuery();
intentTopicMapGr.query();
while (intentTopicMapGr.next())
mappedIntents.push(intentTopicMapGr.getValue("ar_intent"));
return mappedIntents;
};
/**
* Updates the active solution version number for the workflow solution associated to the given table name
* @param tableName
* @param versionNumber
* @param languageCode
* @returns {boolean}
*/
AutoResolutionAPI.updateActiveSolutionVersionNumber = function(tableName, versionNumber, languageCode) {
var logger = createLogger();
var configSysId = AutoResolutionUtil.getConfigurationForTask(tableName);
if (gs.nil(configSysId)) {
logger.warn("updateActiveSolutionVersionNumber: Not a valid IAR config table {0}", tableName);
return false;
}
var result = AutoResolutionLanguageHelper.getSolutionNameAndVersionForLanguageWithCapability(configSysId,
languageCode || 'en', AutoResolutionConstants.AGENT_ZERO_WORKFLOW_CAPABILITY);
if (Object.keys(result).length === 0) {
logger.warn("updateActiveSolutionVersionNumber: unable to find solution for given table: {0} and language: {1}",
tableName, languageCode);
return false;
}
var mlHelper = new AutoResolutionMLHelper(configSysId);
var activeVersionExists = mlHelper.hasActiveVersion(result.solution_name);
if (!activeVersionExists) {
logger.warn("updateActiveSolutionVersionNumber: there is no existing trained version of workflow solution with" +
" name {0}, unable to update version", result.solution_name);
return false;
}
logger.info("updateActiveSolutionVersionNumber: Current workflow solution version for solution:{0} is {1} " +
"and updating it to {2}", result.solution_name, result.solution_version, versionNumber);
AutoResolutionLanguageHelper.setVersionNumberForWorkflowSolution(configSysId, result.solution_name, versionNumber);
return true;
};
/**
* Register an event with name sn_cs.iar.workflow.training.complete when an IAR WF solution completes training
* @param solutionName
* @param solutionVersion
*/
AutoResolutionAPI.createTrainingCompletedEvent = function(solutionName, solutionVersion) {
var logger = createLogger();
if (gs.nil(solutionName) || gs.nil(solutionVersion)) {
logger.debug("createTrainingCompletedEvent: Solution name:{0} or solution version:{1} is invalid", solutionName,
solutionVersion)
return;
}
if (!AutoResolutionLanguageHelper.validConfigExistsForSolutionName(solutionName)) {
logger.debug("createTrainingCompletedEvent: IAR configuration is not available with Solution name:{0} ",
solutionName, solutionVersion)
return;
}
logger.info("createTrainingCompletedEvent: Registering IAR workflow solution training completed event with solution" +
"name: {0} and solution version: {1}", solutionName, solutionVersion);
gs.eventQueue("sn_cs.iar.workflow.training.complete", "", "", solutionName, solutionVersion);
};
function constructFailureResponse(reason, iarEnabled) {
var response = {};
response.status = 'failure';
response.reason = reason;
response.iar_enabled = iarEnabled;
return response;
}
function constructSuccessResponse() {
var response = {};
response.status = 'success';
response.reason = AutoResolutionConstants.IAR_TASK_ASSIGNED_TO_BOT_MSG;
response.iar_enabled = true;
return response;
}
function createLogger(param1, param2, param3) {
var logUtils = new AutoResolutionLoggingUtils()
.withName(this.type);
if (!gs.nil(param1) && !gs.nil(param2))
logUtils.withTaskValues(param1, param2);
else if (!gs.nil(param3))
logUtils.withTaskGr(param3);
return logUtils.createLogger();
}
function replaceMsgParams(param1, param2) {
return param1.replace("{0}", param2);
}
Sys ID
ee9183da77988110f14a24f1cd5a99fc