Name

sn_risk_advanced.AutomatedFactorUtilsBase

Description

No description available

Script

var AutomatedFactorUtilsBase = Class.create();
AutomatedFactorUtilsBase.prototype = {
  initialize: function() {},

  executeAndGetFactorResponse: function(factorResponse) {
      return this._executeAndGetFactorResponse(factorResponse);
  },

  executeAndSetResponsesForFactor: function(factor) {
      this._executeAndSetResponsesForFactor(factor);
  },

  executeAutomatedFactors: function() {
      this._executeAutomatedFactors();
  },

  createCSVAttachment: function(response, csvData) {
      this._createCSVAttachment(response, csvData);
  },

  deleteAttachments: function(tablename, sysIds) {
      this._deleteAttachments(tablename, sysIds);
  },

  _executeAutomatedFactors: function() {
      this._executeAutomatedFactorsWithType('sn_risk_advanced_automated_query_factor');
      this._executeAutomatedFactorsWithType('sn_risk_advanced_automated_scripted_factor');
  },

  executeFactor: function(factorID, entityID, riskID, controlID, objectID) {
      this._executeFactor(factorID, entityID, riskID, controlID, objectID);
  },

  executeFactorsOfAsmtType: function(asmtType, asmt) {
      this._executeFactorsOfAsmtType(asmtType, asmt);
  },

  executeAssessmentResponseFactor: function(assessmentResponse) {
      this._executeAssessmentResponseFactor(assessmentResponse);
  },

  isFactorOptedOut: function(response) {
      return this._isFactorOptedOut(response);
  },

  canRunAutomatedFactors: function(response) {
      return this._canRunAutomatedFactors(response);
  },

  _isFactorOptedOut: function(response) {
      var asmt = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      asmt.get(response.assessment_instance_id);
      var optedOut = false;
      if (response.assessment_type == '2')
          optedOut = asmt.mitigating_controls_to_assess;
      else if (response.assessment_type == '3')
          optedOut = asmt.residual_risk_not_applicable;
      return optedOut;
  },

  _executeAssessmentResponseFactor: function(assessmentResponse) {
      var result = this._executeAndGetFactorResponse(assessmentResponse);
      if (result.error)
          return;

      assessmentResponse.factor_response = result.score;
      assessmentResponse.update();
      //For Scripted factors supporting data creation is done in the script itself. So we have to create it only for query factors.
      if (!gs.nil(result.score) && current.factor.sys_class_name == 'sn_risk_advanced_automated_query_factor') {
          //Creating supporting data attachments in an event to reduce factor execution time.
          gs.eventQueue('sn_risk_advanced.create_supporting_data', null,
              new global.JSON().encode({
                  responseIds: [assessmentResponse.getUniqueValue()]
              }), '', 'automated_factors');
      }
  },

  _executeFactorsOfAsmtType: function(asmtType, asmt) {
      var automatedFactorResponse = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      automatedFactorResponse.addQuery('factor.sys_class_name', 'IN', 'sn_risk_advanced_automated_scripted_factor,sn_risk_advanced_automated_query_factor');
      automatedFactorResponse.addQuery('assessment_instance_id', asmt.getUniqueValue());
      automatedFactorResponse.addQuery('assessment_type', asmtType);
      automatedFactorResponse.query();
      var responseIds = [];
      while (automatedFactorResponse.next()) {
          var result = this.executeAndGetFactorResponse(automatedFactorResponse);
          if (result.error)
              continue;
          automatedFactorResponse.factor_response = result.score;
          automatedFactorResponse.update();
          //For Scripted factors supporting data creation is done in the script itself. So we have to create it only for query factors. 
          if (!gs.nil(result.score) && automatedFactorResponse.factor.sys_class_name == 'sn_risk_advanced_automated_query_factor')
              responseIds.push(automatedFactorResponse.getUniqueValue());
      }
      if (responseIds.length != 0) {
          //Creating supporting data attachments in an event to reduce transition time from one state to another.
          gs.eventQueue('sn_risk_advanced.create_supporting_data', null,
              new global.JSON().encode({
                  responseIds: responseIds
              }), '', 'automated_factors');
      }
  },

  _executeAutomatedFactorsWithType: function(tableName) {
      var factor = new GlideRecord(tableName);
      factor.addQuery('state', '2');
      factor.addNotNullQuery('risk_assessment_methodology');
      factor.addNotNullQuery('next_run_date');
      factor.addQuery('next_run_date', '<=', new GlideDate());
      factor.query();
      var utils = this._getUtilty(tableName);
      while (factor.next()) {
          utils.executeAndSetResponsesForFactor(factor);
  		var freq_value = factor.frequency;
  		var frequencyDetails = {
  			frequency: factor.frequency
  		};
  		if (freq_value == 3 || freq_value == 4 || freq_value == 5 || freq_value == 6)
  			frequencyDetails.day_of_month =factor.day_of_month;
  		if (freq_value == 6)
  			frequencyDetails.month = factor.month;
  		if(freq_value == 2)
  			frequencyDetails.day_of_week = factor.day_of_week;
  		
  		new sn_grc.FrequencyUtils().setNextRunDate(frequencyDetails);
  		factor.next_run_date = frequencyDetails.next_run_date;
  		factor.update();
      }
  },

  _executeAndGetFactorResponse: function(factorResponse) {
      var result = {};
      var factor = factorResponse.getElement('factor').getRefRecord();
      var utils = this._getUtilty(factor.getTableName());
      //Delete existing attachemnt for each resopnse.
      this._deleteAttachments('sn_risk_advanced_risk_assessment_instance_response', [factorResponse.getUniqueValue()]);
      try {
          result = utils.executeAndGetFactorResponse(factorResponse);
      } catch (ex) {
          this._setErrorFromException(result, ex, factor);
      }
      if (factor.getTableName() == 'sn_risk_advanced_automated_query_factor') {
          result.sourceRecordId = factor.getUniqueValue();
          result.table = 'sn_risk_advanced_automated_query_factor';
      } else {
          result.sourceRecordId = factorResponse.getUniqueValue();
          result.table = 'sn_risk_advanced_risk_assessment_instance_response';
      }

      this._handleException(result);
      return result;
  },

  _getUtilty: function(tableName) {
      switch (tableName) {
          case 'sn_risk_advanced_automated_query_factor':
              return new QueryFactorUtils();
          case 'sn_risk_advanced_automated_scripted_factor':
              return new ScriptFactorUtils();
      }
  },

  _getReferenceCurrencyCode: function() {
      var gr = new GlideRecord('sn_risk_advanced_risk_assessment_instance');
      gr.initialize();
      return gr.inherent_computed_ale.getReferenceCurrencyCode();
  },

  _getResponsesToBeAssessed: function(factor) {
      var automatedFactorResponse = new GlideRecord('sn_risk_advanced_risk_assessment_instance_response');
      automatedFactorResponse.addQuery('factor', factor.getUniqueValue());
      automatedFactorResponse.addEncodedQuery('assessment_instance_id.stateNOT IN0,1,8');
      return automatedFactorResponse;
  },

  _executeFactor: function(factorID, entityID, riskID, controlID, objectID) {
      var automatedFactor = new GlideRecord('sn_risk_advanced_base_automated_factor');
      automatedFactor.get(factorID);
      if (automatedFactor.isValidRecord()) {
          var factor = new GlideRecord(automatedFactor.sys_class_name);
          factor.get(factorID);
          var utils = this._getUtilty(factor.getTableName());
          utils.executeFactorFilterResponses(factor, entityID, riskID, controlID, objectID);
      }
  },

  _createCSVAttachment: function(response, csvData, fileName) {
      var attachment = new GlideSysAttachment();
      attachment.write(response, fileName, 'application/csv', csvData);
  },

  _deleteAttachments: function(tableName, sysIds) {
      for (var i = 0; i < sysIds.length; i++) {
          var attachment = new GlideSysAttachment();
          var attachments = attachment.getAttachments(tableName, sysIds[i]);
          while (attachments.next()) {
              attachment.deleteAttachment(attachments.getUniqueValue());
          }
      }
  },

  _handleException: function(result) {
      if (result.error) {
          this._createException(result);
      } else {
          this._markExistingExceptionAsResolved(result);
      }
  },

  _createException: function(result) {
      var exceptionUtils = new sn_grc.GRCExceptionUtils();
      if (result.error) {
          var exception = {};
          exception.table = result.table;
          exception.sourceRecordId = result.sourceRecordId;
          //Runtime Exception
          exception.exceptionCategory = '2';
          exception.exceptionMessage = result.error;
          exception.allowMultipleExceptions = false;
          exception.application = '7443d9ba7373230055e9d8b0caf6a7b0';
          exceptionUtils.createException(exception);
      }
  },

  _markExistingExceptionAsResolved: function(result) {
      new sn_grc.GRCExceptionUtils().updateMatchingExceptions(result.table, result.sourceRecordId, null, 2);
  },

  _setErrorFromException: function(result, ex, factor) {
      if (!gs.nil(ex.error))
          result.error = ex.error;
      else
          result.error = ex;

      if (!gs.nil(ex.resolution))
          result.resolution = ex.resolution;
      this._setError(result, factor);
  },

  _setError: function(result, factor, inputs) {
      var factorName = factor.getValue('name');
      var factorId = factor.getUniqueValue();
      var aggregationType = factor.getValue('aggregation_type');
      var aggregationColumn = factor.getValue('aggregation_column');
      var errorMessages = {};
      errorMessages.queryFactorPrefix = gs.getMessage("Error in execution of automated factor\n\nFactor: {0}\nFactorId: {1}", [factorName, factorId]);
      errorMessages.scriptedFactorPrefix = gs.getMessage("Error in execution of scripted factor\n\nFactor: {0}\nFactorId: {1}", [factorName, factorId]);
      errorMessages.scriptedFactorResolution = "Fix above mentioned error in the script";

      if (!gs.nil(result.score)) {
          if (isNaN(result.score)) {
              if (factor.getTableName() == 'sn_risk_advanced_automated_query_factor') {
                  result.error = gs.getMessage('Selected aggregation ({0}) of column ({1}) is not a number', [aggregationType, aggregationColumn]);
                  result.resolution = gs.getMessage('Select a column whose aggregation gives a number.');
              } else {
                  result.error = gs.getMessage('The value in result.score is not a number.');
                  result.resolution = "Set result.score as a number.";
              }

          } else if (result.score == Infinity) {
              if (factor.getTableName() == 'sn_risk_advanced_automated_query_factor') {
                  result.error = gs.getMessage('Selected aggregation ({0}) of column ({1}) is infinity', [aggregationType, aggregationColumn]);
                  result.resolution = gs.getMessage('Select a column whose aggregation gives a number.');
              } else {
                  result.error = gs.getMessage('The value in result.score is infinity.');
                  result.resolution = "Set result.score as a number.";
              }
          }
      }

      if (result.error) {
          if (factor.getTableName() == 'sn_risk_advanced_automated_query_factor') {
              result.prefix = errorMessages.queryFactorPrefix;
          } else {
              result.prefix = errorMessages.scriptedFactorPrefix;
              if (gs.nil(result.resolution))
                  result.resolution = errorMessages.scriptedFactorResolution;
          }
          result.error = this._construnctErrorMessage(result.prefix, result.error, result.resolution, inputs);
          result.score = '';
      }
  },

  _construnctErrorMessage: function(prefix, error, resolution, inputs) {
      var message = prefix + "\n\nError: " + error;

      if (!gs.nil(inputs))
          message += "\n\nInputs: " + JSON.stringify(inputs);

      if (!gs.nil(resolution))
          message += "\n\nResolution: " + resolution;
      return message;
  },

  _canRunAutomatedFactors: function(response) {
      return (response.factor.sys_class_name == 'sn_risk_advanced_automated_scripted_factor' || response.factor.sys_class_name == 'sn_risk_advanced_automated_query_factor') && (response.assessment_instance_id.state == '3' && response.assessment_instance_id.mitigating_controls_to_assess == false);
  },
  type: 'AutomatedFactorUtilsBase'
};

Sys ID

a2503b72775300102a272f589a106114

Offical Documentation

Official Docs: