Name
global.AutoResolutionProcessor
Description
No description available
Script
var AutoResolutionProcessor = Class.create();
AutoResolutionProcessor.prototype = {
initialize: function() {
this.WORKING_ON_TASK_MSG = gs.getMessage("I'm working on this task.");
this.INTENT_TOPIC_PLEASE_RESPOND_MSG = gs.getMessage("To get immediate assistance on this task, please respond to the notification from the Virtual Agent chat widget.");
this.RECOMMENDATIONS_PLEASE_RESPOND_MSG = gs.getMessage("We found some recommendations that may speed up the process of resolving your request. Please respond to the notification from the Virtual Agent chat widget.");
this.NO_TASK_MSG = gs.getMessage('No task record found.');
this.INVALID_CONFIG = gs.getMessage("Auto-Resolution configuration is invalid, unassigning myself from the task for an agent to pick it up.");
this.INVALID_CONTEXT = gs.getMessage("Auto-Resolution context is invalid, unassigning myself from the task for an agent to pick it up.");
this.NOT_ASSIGNED_TO_BOT_USER = gs.getMessage("Task is no longer assigned to bot user.");
this.UNASSIGN_TASK_MSG = gs.getMessage("An agent can better assist you with this task. I'm unassigning myself from the task for an agent to pick it up.");
this.taskHelper = new AutoResolutionTaskHelper();
this.contextHelper = new AutoResolutionContextHelper();
},
process: function(taskSysId, taskTableName) {
var stageSW = new GlideStopWatch();
var totalSW = new GlideStopWatch();
totalSW.start();
var logMessages = [
'Auto-Resolution Task processing summary',
'Start time: ' + new GlideDateTime()
];
this.LOGGING_UTILS = new AutoResolutionLoggingUtils()
.withName(this.type)
.withTaskValues(taskSysId, taskTableName)
// The next context keys will be filled in dynamically, when available
.withLanguage('')
.withContextId('')
.withConfiguration('');
this.LOGGER = this.LOGGING_UTILS.createLogger();
// Perform initial validations and un-assign task if something is not right
stageSW.start();
var validationResponse = this._doInitialValidations(taskSysId, taskTableName);
stageSW.end();
logMessages.push(this._buildLogMessage("AutoResolutionValidationStage", stageSW));
// Set values from validation response
var taskGr = validationResponse.task_gr;
var contextGr = validationResponse.context_gr;
var configGr = validationResponse.config_gr;
var languageCode = validationResponse.language_code;
if (!validationResponse.validation_passed) {
this.unassignAndUpdateContext(taskGr, contextGr, validationResponse.reason, validationResponse.reason,
AutoResolutionConstants.TASK_PROCESSING_STATE.VALIDATION);
logMessages = this._addEndLogMessages(logMessages, totalSW);
this.LOGGER.info(logMessages.join('\n'));
return;
}
var taskProcessingStages = [
new AutoResolutionLanguageXStage(contextGr, configGr, taskGr, languageCode),
new AutoResolutionExitConditionStage(contextGr, configGr, taskGr, languageCode),
new AutoResolutionIntentProcessingStage(contextGr, configGr, taskGr, languageCode),
new AutoResolutionAISearchStage(contextGr, configGr, taskGr, languageCode),
new AutoResolutionNotificationStage(contextGr, configGr, taskGr, languageCode)
];
var loggingContextJSON = this._updateLoggingContext(contextGr.getUniqueValue(), configGr.getUniqueValue(), languageCode);
var loggingContext = new sn_log.GlideLogContext(loggingContextJSON);
var contextFieldValueMap = {};
var contextActive = true;
try {
// Iterate and execute all stages
for (var i=0; i<taskProcessingStages.length; i++) {
stageSW.start();
var stage = taskProcessingStages[i];
this.LOGGER.debug('Executing task processing stage {0} with contextFieldValueMap: {1}', stage.type,
JSON.stringify(contextFieldValueMap));
// Execute the stage
var stageResponse = stage.execute(contextFieldValueMap);
this.LOGGER.debug('Task processing stage {0} is complete with response: {1}', stage.type,
JSON.stringify(stageResponse));
// Merge the context from the stage
contextFieldValueMap = this._merge(contextFieldValueMap, stageResponse.contextFieldValueMap);
stageSW.stop();
logMessages.push(this._buildLogMessage(stage.type, stageSW));
// Check if the stage is telling us to stop the process
if (!stageResponse.should_proceed){
contextFieldValueMap.task_processing_state = stage.getStateValue();
contextActive = false;
break;
}
}
} catch (error) {
this.LOGGER.error('Error process task={0} in stage={1} for Auto-Resolution, exception={2}', taskGr.number,
stage.getStateValue(), error);
contextActive = false;
contextFieldValueMap.task_processing_state = stage.getStateValue();
var reasonMessage = "Unexpected error occurred during " + stage.type;
if (gs.nil(contextFieldValueMap.reason))
contextFieldValueMap.reason = reasonMessage;
else
contextFieldValueMap.reason = reasonMessage + ',\n' + contextFieldValueMap.reason;
}
contextFieldValueMap.active = contextActive;
if (contextActive) {
contextFieldValueMap.task_processing_state = AutoResolutionConstants.TASK_PROCESSING_STATE.PROCESSED;
} else {
contextFieldValueMap.sla_state = '';
contextFieldValueMap.notification_state = '';
}
stageSW.start();
this.contextHelper.updateContext(contextGr.getUniqueValue(), contextFieldValueMap);
this.LOGGER.info('Updated IAR Context with field values: {0}', JSON.stringify(contextFieldValueMap));
this.handleTask(taskGr, configGr, contextGr.getUniqueValue(), contextActive, contextFieldValueMap);
stageSW.stop();
logMessages.push(this._buildLogMessage("ContextAndTaskUpdate", stageSW));
logMessages = this._addEndLogMessages(logMessages, totalSW);
this.LOGGER.info(logMessages.join('\n'));
// Clear the dynamic logging context
loggingContext.clear();
},
/**
* Validate task, IAR configuration, IAR context record exists and task is still assigned to bot user
* @param taskSysId
* @param taskTableName
* @returns {{validation_passed = true/false
context_sys_id = <sys Id of the IAR context record>
language_code = <session language identified during task creation
config_sys_id = <sys Id of the IAR configuration record>}}
*/
_doInitialValidations: function(taskSysId, taskTableName) {
this.LOGGER.debug('Auto-Resolution - Task Processing - Initial Validations');
var response = {
validation_passed: false,
reason: '',
language_code: '',
task_gr: null,
context_gr: null,
config_gr: null,
};
try {
var taskGr = AutoResolutionTaskDataBroker.getTaskRecord(taskTableName, taskSysId);
if (gs.nil(taskGr)) {
response.reason = this.NO_TASK_MSG;
this.LOGGER.error('Task record not found for sysId {0} in table {1}', taskSysId, taskTableName);
return response;
}
response.task_gr = taskGr;
var contextGr = this.contextHelper.getContextFromTask(taskGr);
if (gs.nil(contextGr)) {
response.reason = this.INVALID_CONTEXT;
return response;
}
response.context_gr = contextGr;
// Configuration should be valid and active
var configGr = this.contextHelper.getConfigurationGr(contextGr);
if (!configGr || configGr.getValue("active") !== '1') {
response.reason = this.INVALID_CONFIG;
return response;
}
response.config_gr = configGr;
if (!this.taskHelper.isTaskAssignedToBotUser(taskGr)) {
response.reason = this.NOT_ASSIGNED_TO_BOT_USER;
return response;
}
response.language_code = this.contextHelper.getLanguageFromContext(contextGr);
response.validation_passed = true;
return response;
} catch (ex) {
response.reason = 'Unexpected exception during initial validations of task';
this.LOGGER.error(response.reason + ': ' + ex);
return response;
}
},
_addEndLogMessages: function(logMessages, sw) {
var endGDT = new GlideDateTime();
logMessages.push(this._buildLogMessage("Total", sw));
logMessages.push('End time: ' + endGDT);
return logMessages;
},
/**
* Un-assign task and set context inactive
* @param {GlideRecord} taskGr
* @param {GlideRecord} contextGr
* @param {string} workNote
* @param {string} reason
* @param {string} state
*/
unassignAndUpdateContext: function(taskGr, contextGr, workNote, reason, state) {
if (!gs.nil(taskGr))
this.taskHelper.unassignTask(taskGr, workNote);
if (!gs.nil(contextGr)) {
this.contextHelper.setContextInactive(contextGr, reason);
contextGr.setValue('task_processing_state', state);
contextGr.update();
}
this.LOGGER.error(reason);
},
handleTask: function(taskGr, configGr, contextId, contextActive, contextFieldValueMap) {
if (contextActive) {
this.LOGGER.debug('Continuing with Auto-Resolution flow: {0}', taskGr.number);
var vaRespChannelActive = AutoResolutionResponseChannelHelper.checkActiveResponseChannelForConfig(configGr.getUniqueValue(), "Virtual Agent");
var aisTopicSysId = configGr.getValue('ais_topic');
if (gs.nil(contextFieldValueMap.matched_topic) || !vaRespChannelActive)
this.taskHelper.setWorkNotesOnTask(taskGr, this.WORKING_ON_TASK_MSG);
else if (contextFieldValueMap.matched_topic === aisTopicSysId)
this.taskHelper.setCommentsOnTask(taskGr, this.RECOMMENDATIONS_PLEASE_RESPOND_MSG);
else
this.taskHelper.setCommentsOnTask(taskGr, this.INTENT_TOPIC_PLEASE_RESPOND_MSG);
} else {
this.taskHelper.unassignTask(taskGr, this.UNASSIGN_TASK_MSG, configGr.unresolved_task_template.name);
this.LOGGER.warn('IAR flow for task={0} was unable to proceed. See contextId={1}', taskGr.getValue('number'),
contextId);
}
},
_updateLoggingContext: function(contextId, configId, languageCode) {
var context = {};
context[AutoResolutionLoggingUtils.CONTEXT_ID] = contextId;
context[AutoResolutionLoggingUtils.CONFIGURATION] = configId;
context[AutoResolutionLoggingUtils.LANGUAGE] = languageCode;
this.LOGGING_UTILS.withConfiguration(configId);
this.LOGGING_UTILS.withContextId(contextId);
this.LOGGING_UTILS.withLanguage(languageCode);
return context;
},
_merge: function(obj1, obj2) {
for (var attribute in obj2)
obj1[attribute] = obj2[attribute];
return obj1;
},
_buildLogMessage: function(identifier, sw) {
return sw + " - " + identifier;
},
type: 'AutoResolutionProcessor'
};
Sys ID
30bb8fe5532210107a1cddeeff7b1264