Name

sn_grc.IndicatorStrategyBase

Description

Shared indicator strategy functionality

Script

var IndicatorStrategyBase = Class.create();
IndicatorStrategyBase.prototype = {
  initialize: function(indicatorRecord) {
  	this.indicatorRecord = indicatorRecord;
  },
  
  run: function() {
  	
  },
  
  isLatestIndicatorResultFlapping: function(result){
  	var resultGR = new GlideRecord('sn_grc_indicator_result');
  	resultGR.addQuery("indicator", this.indicatorRecord.getValue("sys_id"));
  	resultGR.orderByDesc('collection_date');
  	resultGR.setLimit(1);
  	resultGR.query();
  	
  	if (resultGR.next()) {
  		var resultGRPassed = resultGR.passed + '' == 'true';
  		return (result != resultGRPassed);
  	}

  	return true;
  },
  
  updateResult: function(result, value) {
  	var resultGR = new GlideRecord('sn_grc_indicator_result');
  	resultGR.addQuery("indicator", this.indicatorRecord.getValue("sys_id"));
  	resultGR.orderByDesc('collection_date');
  	resultGR.setLimit(1);
  	resultGR.query();
  	
  	if (resultGR.next()){
  		resultGR.collection_date = new GlideDateTime();
  		resultGR.value = value;
  		resultGR.passed = result; 
  		resultGR.update();
  		return resultGR.getUniqueValue();
  	}
  	return null;
  },
  
  addResult: function(passed, valueType, value, taskId, target_type, target) {
      var pr = new sn_grc.GRCUtils().getMessage("profile_lower");
  
  	var indicatorType = this.indicatorRecord.type + '';
  	var result = new GlideRecord('sn_grc_indicator_result');
  	result.addQuery("indicator", this.indicatorRecord.getValue("sys_id"));
  	result.orderByDesc("collection_date");
  	result.setLimit(1);
  	result.query();
  	
  	if (result.next()) {
  		result.is_last_result = false;
  		result.update();
  	}
  	
  	var currentDate = new GlideDateTime();
  	var formattedDate = currentDate.getDisplayValue().split(" "); // [0] - date, [1] - time
  	
  	result = new GlideRecord('sn_grc_indicator_result');
  	result.collection_date = currentDate;
  	result.indicator = this.indicatorRecord.getValue("sys_id");
  	result.passed = passed;
  	result.value_type = valueType;
  	result.value = value;
  	result.is_last_result = true;
  	result.target_type = target_type;
  	result.target = target_type ? target : '';
  	if (indicatorType == 'manual')
  		result.indicator_task = taskId;
  	else if (!result.indicator_task)
  		result.indicator_task = '';
  	
  	if (!this.indicatorRecord.item.nil()) {
  	    
  		if (!this.indicatorRecord.item.content.nil() && !this.indicatorRecord.item.profile.nil())
  			result.label = "Result generated on " + formattedDate[0] + " at " + formattedDate[1]  + " from " + this.indicatorRecord.item.content.name + " (content) and " +  this.indicatorRecord.item.profile.name + " ("+pr+")" ;
  		else {
  			if (!this.indicatorRecord.item.content.nil())
  				result.label = "Result generated on "+ formattedDate[0] + " at " + formattedDate[1]  + " from " + this.indicatorRecord.item.content.name + " (content). No "+ pr+ " available in the item record";
  			else if (!this.indicatorRecord.item.profile.nil())
  				result.label = "Result generated on "+ formattedDate[0] + " at " + formattedDate[1]  + " from " +  this.indicatorRecord.item.profile.name + " ("+pr+"). No content available in the item record";
  			else
  				result.label = "No "+ pr +" and content available in the item record, generated on "+ formattedDate[0] + " at " + formattedDate[1];
  		}
  	}
  	else
  		gs.info("Indicator item is null");

  	if (!this.indicatorRecord.item.profile.nil()) {			
  		var gr = new GlideRecord(this.indicatorRecord.getValue("table"));
  		if(!this.indicatorRecord.item.profile.applies_to.nil()){
  		if (gr.get(this.indicatorRecord.item.profile.applies_to)) {
  			result.owner = this.indicatorRecord.item.owner;
  			result.owning_group = this.indicatorRecord.item.owning_group;
  	}
  	else
  			gs.info("Associated item to profile not found");
  		}
  		else
  			gs.info("Associated record to {0} not found",pr);
  	}
  	else
  		gs.info("Item has no associated "+ pr);

  	if (result.insert() != null) 		
  		return result.getUniqueValue();
  	else {
  		gs.info("Result cannot be inserted");
  		return '';
  	}
  },
  
  collectSupportingData: function(result, task) {
  	var sample = parseInt(this.indicatorRecord.getValue("sample_size"));
  	if (isNaN(sample))
  		sample = 0;

  	// Retrieve the supporting data records
  	var gr = new GlideRecord(this.indicatorRecord.getValue("reference_table"));
  	var criteria = this.indicatorRecord.getValue("criteria");
  	if (criteria != null && criteria != '')
  		gr.addEncodedQuery(criteria);
  	if (this.indicatorRecord.getValue("type") == "basic" && this.indicatorRecord.getValue("target_type") == "percentage") {
  		var additionalCriteria = this.indicatorRecord.getValue("additional_criteria");
  		if (additionalCriteria != null && additionalCriteria != '') {
  			gr.addEncodedQuery(additionalCriteria);
  		}
  	}
  	
  	if (!this.indicatorRecord.item.nil()) {			
  		if (!this.indicatorRecord.item.profile.nil()) {
  			if (this.indicatorRecord.use_reference_field) {
  				gr.addQuery(this.indicatorRecord.getValue("reference_field"), this.indicatorRecord.item.profile.applies_to);
  			}
  		}
  		else {
  			gs.debug("Associated item to "+ pr+" not found during collection data");
  			return;
  		}
  	}
  	else {
  		gs.debug("Indicator has no associated item during collection data");
  		return;
  	}
  	
  	gr.query();
  	
  	var rowCount = gr.getRowCount();
  	 if (rowCount == 0)
  	 	return;		
  	
  	 if ((sample > rowCount) || (sample == 0))
  	 	sample = rowCount;
  	
  	var probability = Math.min(sample / rowCount, 0.95) + 0.05;
  	
  	// Build the supporting data field list. If none are selected, get all table fields
  	var supportingDataFields = this.indicatorRecord.supporting_data_fields;
  	var supportingDataFieldList = [];
  	
  	if (supportingDataFields != '')
  		supportingDataFieldList = supportingDataFields.toString().split(',');
  	else 
  		supportingDataFieldList = this.getAllFields(gr);
  	
  	var numRecordsAdded = 0;
  	while (gr.next() && numRecordsAdded < sample) {
  		if (Math.random() >= probability)
  			continue;
  		
  		// For each supporting data record, store every selected field
  		for(var i = 0; i < supportingDataFieldList.length; i++) {
  			var table = this.indicatorRecord.getValue("reference_table");
  			var fieldName = supportingDataFieldList[i].toString();
  			var fieldValue = gr.getElement(fieldName).getDisplayValue();
  			this.insertSupportingDataRecord(table, gr.getUniqueValue(), gr.getElement(fieldName).getName(), fieldName, fieldValue, result, task);
  		}
  		numRecordsAdded++;
  	}
  },

  insertSupportingDataRecord: function(table, sysId, element, fieldName, fieldValue, resultId, taskId) {
  	resultId = resultId || '';
  	taskId = taskId || '';
  	
  	var date = new GlideDateTime();

  	var supportingData = new GlideRecord('sn_grc_indicator_supporting_data');
  	supportingData.collection_date = date;
  	supportingData.result = resultId;
  	supportingData.task = taskId;
  	supportingData.table = table;
  	supportingData.document = sysId;
  	supportingData.long_document_id = '|' + sysId;
  	supportingData.element = element;
  	supportingData.field_name = fieldName;
  	supportingData.value = fieldValue;
  	supportingData.insert();
  },
  
  getAllFields: function(record) {
  	var elementList = record.getElements();
  		
  	var supportingDataFieldList = [];
  	for(var j = 0; j < elementList.length; j++) 
  		supportingDataFieldList.push(elementList[j].getED().getName());

  	return supportingDataFieldList;
  },

  type: 'IndicatorStrategyBase'
};

Sys ID

451c4a82d7320200d77c83e80e6103e9

Offical Documentation

Official Docs: