Name

sn_ci_analytics.CAProcessor

Description

No description available

Script

var CAProcessor = Class.create();
CAProcessor.prototype = {
  initialize: function() {
      this.logger = CIAnalyticsLogger.getLogger({
          source: "CAProcessor",
      });
      this.config = new CAConfig();
      this.isBroadcastAllowed = this.config.isBroadcastAllowed();
      this.jobMaxConversationCount = this.config.getJobMaxConversationCount();
      this.payloadSizeCalculator = new CAPayloadSizeCalculator();
      this.payloadBuilder = new CAPayloadBuilder();
      this.evaluator = new GlideScopedEvaluator();
      this.validConversationFn = this._validationFormula();
      this.isError = false;
      this.logger.info("Configuration Details {0}", new global.JSON().encode(this.config.getDetails()));
      this.CORRECT_INTENT = this.payloadBuilder.getIntentName(this.payloadBuilder.INTENT_CORRECT);
      this.AUTO_SELECTED = this.payloadBuilder.getIntentName(this.payloadBuilder.INTENT_AUTO_SELECTED);
      this.conversationIds = [];
  	this.UNSUPPORTED_INTENT = this.payloadBuilder.getIntentName(this.payloadBuilder.INTENT_UNSUPPORT);
  },

  process: function() {
      try {
          var batchProcessor = new CABatchProcessor();
          var oobEventProcessor = new CAOOBEventProcessor();
          this.clickMetricsEventProcessor = new CAClickMetricsCustomEventProcessor();
          var isError = false;
          var caConversationGr = this._queryCAConversation();
          var lastOpenUser = "";
          while (!this.isError && caConversationGr.next()) {
              var conversationId = caConversationGr.conversation.sys_id;
              var notificationGr = this._queryNotification(conversationId);
              if (this.isBroadcastAllowed != 'true' && caConversationGr.conversation.conversation_type == 'notification'){
                  this.conversationIds.push(caConversationGr.conversation.sys_id);
                  continue;
              }
              if (this._canIgnoreConversation(caConversationGr, notificationGr, lastOpenUser)) {
                  var params = [conversationId, CABatchProcessor.batchId, caConversationGr.conversation.state, caConversationGr.conversation.consumer.name];
                  this.logger.info("Conversation:{0}, BatchId:{1}, Conversation State:{2}, Conversation Consumer: {3}", params);
                  lastOpenUser = caConversationGr.conversation.consumer;
                  continue;
              }
              this.payloadBuilder.initConversation(conversationId);
              this._processOverrides(conversationId);
              if (!this._processConversation(caConversationGr, notificationGr))
                  continue;

              this._processEvents(conversationId, oobEventProcessor);
              isError = !batchProcessor.queueOrSend(this.payloadBuilder.getConversation());
              if (isError)
                  return;
          }
          if (!isError)
              batchProcessor.sendAll();
          if (this.isBroadcastAllowed != 'true')
              batchProcessor._updateTableWithStatus(this.conversationIds,'ignored','Filtered out the "notification" type conversation due to system property "allow_broadcast" disabled');
      } catch (err) {
          var message = "CI analytics processor job failed:" + err.message;
          if (err.stack)
              message = message + "\n" + err.stack;
          this.logger.error(message);
      }
  },

  _validConversation: function(caConversationGr, interactionGr, notificationGr) {
      if (!this.validConversationFn) {
          return true;
      }
      this.evaluator.putVariable('convGr', caConversationGr);
      this.evaluator.putVariable('interactionGr', interactionGr);
      this.evaluator.putVariable('notificationGr', notificationGr);
      return this.evaluator.evaluateScript(this.validConversationFn, "value_script", null);
  },

  _validationFormula: function() {
      var gr = new GlideRecord('sn_ci_analytics_formula_override');
      gr.addQuery('key', 'Active Conversation');
      gr.addQuery('type', 'eligibilitycriteria');
      gr.addQuery('active', true);
      gr.query();
      if (gr.next()) {
          return gr;
      }
      return null;
  },

  _queryNotification: function(conversationId) {
      var notificationGr = new GlideRecord('sys_cs_notification');
      notificationGr.addQuery('conversation', conversationId);
      notificationGr.query();
      return notificationGr;
  },

  _queryCAConversation: function() {
      var caConversationGr = new GlideRecord('sn_ci_analytics_conversation');
      caConversationGr.addQuery('status', 'new').addOrCondition('status', 'onHold');
      caConversationGr.orderBy('consumer');
      caConversationGr.orderBy('sys_created_on');
      if (this.jobMaxConversationCount > 0)
          caConversationGr.setLimit(this.jobMaxConversationCount);
      caConversationGr.query();
      return caConversationGr;
  },

  _canIgnoreConversation: function(caConversationGr, notificationGr, lastOpenUser) {
      var currentRecordUser = caConversationGr.conversation.consumer;
      var conversationId = caConversationGr.conversation.sys_id;
      var state = caConversationGr.conversation.state;
      var status = caConversationGr.status;
      while (notificationGr.next()) {
          var notificationState = notificationGr.state;
          if (notificationState == 'pending' || notificationState == 'sent') {
              var params = [conversationId, CABatchProcessor.batchId, notificationState, caConversationGr.conversation.consumer.name];
              this.logger.info("Conversation:{0}, BatchId:{1}, Notification State: {2}, Conversation Consumer: {3}", params);
              return true;
          }
      }
      if (state == 'open' || state == 'chatInProgress' || status == 'onHold')
          return true;
      return currentRecordUser == lastOpenUser;
  },

  _updateConversationStateAsIgnored: function(caConversationGr, reason) {
      caConversationGr.setValue('status', 'ignored');
      caConversationGr.setValue('reason', reason);
      caConversationGr.update();
      this.logger.info('Conversation ignored from formula override: {0}', [caConversationGr.conversation]);
  },

  _processConversation: function(caConversationGr, notificationGr) {
      var conversationId = caConversationGr.conversation.sys_id;
      var interactionGr = this._queryInteraction(conversationId);
      if (!this._validConversation(caConversationGr, interactionGr, notificationGr)) {
          this._updateConversationStateAsIgnored(caConversationGr, 'Filtered out from the "Active Conversation" formula override');
          return false;
      }
      this.payloadBuilder.buildConversation(caConversationGr, interactionGr);
      this.payloadBuilder.addUser(caConversationGr);
      var conversationTask = this.payloadBuilder.queryConversationTask(conversationId);
      var intentPrediction = {
          isCorrectPrediction: false,
          isAutoSelected: false,
  		isUnsupportedPrediction: false,
      };
      var nluIntents = [];
      var taskIds = [];
      while (conversationTask.next()) {
          var topicName = conversationTask.topic_type.name;
          taskIds.push(conversationTask.getValue('sys_id'));
          if (this._isPreviewedConversation(topicName)) {
              var params = [conversationTask.getValue('sys_id'), topicName];
              this._updateConversationStateAsIgnored(caConversationGr, 'Previewed Conversation');
              this._logDebug('ConversationTask: {2}, Previwed topic found {3}, conversation ignored.', conversationId, params);
              return false;
          }

          if (this._filterInternalTopicBlock(conversationTask))
              continue;

          if (topicName)
              this.payloadBuilder.addTopic(conversationTask);
          this._processIntents(conversationTask, conversationId, nluIntents, intentPrediction);
          this.payloadBuilder.addTopicNodes(conversationTask);
      }
      this._modifyIntentEvents(nluIntents, intentPrediction);
      this.payloadBuilder.addIntentsToConversation(nluIntents);
      this.payloadBuilder.updateDeflectionCount(taskIds);
      return true;
  },

  _filterInternalTopicBlock: function(taskGr) {
      if (taskGr.topic_type.type == 'TOPIC_BLOCK' && taskGr.calling_task.topic_type.type == 'SETUP_TOPIC')
          return true;
      return false;
  },

  _isPreviewedConversation: function(topicName) {
      if (!gs.nil(topicName) && topicName.startsWith('_PRVW_'))
          return true;

      return false;
  },

  _queryInteraction: function(conversationId) {
      var interactionGr = new GlideRecord('interaction');
      interactionGr.addQuery('channel_metadata_document', conversationId);
      interactionGr.addQuery('channel_metadata_table', 'sys_cs_conversation');
      interactionGr.query();
      interactionGr.next();
      return interactionGr;
  },

  _processIntents: function(conversationTask, conversationId, nluIntents, intentPrediction) {
      var openNluIntentFeedbackGr = new GlideRecord('open_nlu_predict_intent_feedback');
      openNluIntentFeedbackGr.addQuery('app_document_table', 'sys_cs_conversation_task');
      openNluIntentFeedbackGr.addQuery('app_document', conversationTask.sys_id);
      //openNluIntentFeedbackGr.addQuery('mapped', true);
      //openNluIntentFeedbackGr.addNotNullQuery('prediction');
      openNluIntentFeedbackGr.query();
  	if(openNluIntentFeedbackGr.getRowCount() > 1) {
  		this.payloadBuilder.updateMutiplePredictionsCount();
  	}
      while (openNluIntentFeedbackGr.next()) {
          var prediction = openNluIntentFeedbackGr.prediction;
          var nluIntentGr = new GlideRecord('sys_nlu_intent');
          nluIntentGr.addQuery('name', prediction);
          nluIntentGr.query();
          if (!nluIntentGr.next())
              this._logDebug("Nlu intent not found in sys_nlu_intent table for predication: {2}", conversationId, [prediction]);
          var topicLangGr = new GlideRecord('sys_cs_topic_language');
          topicLangGr.addQuery('nlu_intent', prediction);
          topicLangGr.query();
          if (!topicLangGr.next())
              this._logDebug("Topic not found in sys_cs_topic_language table for nlu intent: {2}", conversationId, [prediction]);
          var intentEvent = this.payloadBuilder.buildIntentEvent(openNluIntentFeedbackGr, nluIntentGr, topicLangGr);
  		if(intentEvent['Name'] == this.UNSUPPORTED_INTENT) {
  			intentPrediction.isUnsupportedPrediction = true;
  		}
          if (intentEvent['Name'] == this.CORRECT_INTENT)
              intentPrediction.isCorrectPrediction = true;

          if (intentEvent['Name'] == this.AUTO_SELECTED)
              intentPrediction.isAutoSelected = true;

          nluIntents.push(intentEvent);
      }
  },

  _modifyIntentEvents: function(nluIntents, intentPrediction) {
      var correctName;
  	if (intentPrediction.isUnsupportedPrediction)
  		correctName = this.UNSUPPORTED_INTENT;
      else if (intentPrediction.isCorrectPrediction)
          correctName = this.CORRECT_INTENT;
      else if (intentPrediction.isAutoSelected)
          correctName = this.AUTO_SELECTED;
      else
          return;

      nluIntents.forEach(function(event) {
          event['Name'] = correctName;
      });
  },

  _processEvents: function(conversationId, oobEventProcessor) {
      oobEventProcessor.process(this.payloadBuilder);
      this.clickMetricsEventProcessor.process(this.payloadBuilder);
      var eventsGr = new GlideRecord('sn_ci_analytics_event');
      eventsGr.addQuery('active', true);
      eventsGr.query();
      while (eventsGr.next()) {
          var queryTable = eventsGr.source_table;
          var condition = eventsGr.source_table_filter;
          var conversationMappingField = eventsGr.conversation_mapping_field;
          this.payloadBuilder.preProcessCustomEvent(eventsGr);

          var sourceGr = new GlideRecord(queryTable);
          if (sourceGr.isValid()) {
              var query = conversationMappingField + "=" + conversationId;
              if (!(condition == null || condition == ''))
                  query = query + "^" + condition;
              sourceGr.addEncodedQuery(query);
              sourceGr.query();
              while (sourceGr.next())
                  this.payloadBuilder.addCustomEvent(sourceGr, eventsGr);
          }
      }
  },

  _processOverrides: function(conversationId) {
      var overridesGr = new GlideRecord('sn_ci_analytics_formula_override');
      overridesGr.addQuery('type', '!=', 'eligibilitycriteria');
      overridesGr.addQuery('active', true);
      overridesGr.query();
      while (overridesGr.next())
          this.payloadBuilder.processOverride(overridesGr, conversationId);
  },

  _logDebug: function(msg_template, conversationId, params) {
      if (this.logger.isDebugEnabled()) {
          var arrayUtil = new global.ArrayUtil();
          var defaultParams = [conversationId, CABatchProcessor.batchId];
          var argParams = arrayUtil.convertArray(params);
          var mergedArray = arrayUtil.union(defaultParams, argParams);
          msg_temp = "Conversation:{0}, BatchId:{1}, " + msg_template;
          this.logger.debug(msg_temp, mergedArray);
      }
  },

  type: 'CAProcessor'
};

Sys ID

854fefe4733210107d804c9885f6a7bd

Offical Documentation

Official Docs: