Name

sn_risk.RiskUtilsBaseV2

Description

Risk utility base for Risk V2

Script

var RiskUtilsBaseV2 = Class.create();
RiskUtilsBaseV2.prototype = {
  initialize: function() {
  },
  
  calculateScores: function(risk) {
  	return this._calculateScores(risk);
  },
  
  getCalculatedScore: function(grInherentScore, grResidualScore, percent_pass, total_tests) {
  	return this._getCalculatedScore(grInherentScore, grResidualScore, percent_pass, total_tests);
  },
  
  getRiskCriteria: function(type, value) {
  	return this._getRiskCriteria(type, value);
  },
  
  getRiskScore: function(significance, likelihood) {
  	return this._getRiskScore(significance, likelihood);
  },
  
  getValidRisksForRelationships: function(profile, stream, risk) {
  	return this._getValidRisksForRelationships(profile, stream, risk);
  },
  
  isValidRiskRelationship: function(relationship) {
  		return this._isValidRiskRelationship(relationship);
  },
  
  setRiskFromDefinition: function(riskID, statementID) {
  	return this._setRiskFromStatement(riskID, statementID);
  },
  
  showRiskRelationshipAddButton: function(risk, profile, stream) {
  	return this._showRiskRelationshipAddButton(risk, profile, stream);
  },
  
  syncRiskQualitativeFields: function(risk) {
  	return this._syncRiskQualitativeFields(risk);
  },
  
  syncRiskStatementQualitativeFields: function(riskStatement) {
  	return this._syncRiskStatementQualitativeFields(riskStatement);
  },
  
  syncQualitativeFields: function(current) {
  	return this._syncQualitativeFields(risk);
  },
  
  updateCalculatedRiskFactor: function(risk) {
  	return this._updateCalculatedRiskFactor(risk);
  },
  
  updateIndicatorFailureFactor: function(risk) {
  	return this._updateIndicatorFailureFactor(risk);
  },
  
  updateControlFailureFactor: function(risk) {
  	return this._updateControlFailureFactor(risk);
  },
  
  updateQuantitativeFields: function(sysID, value, type, isRisk, selectField) {
  	return this._updateQuantitativeFields(sysID, value, type, isRisk, selectField);
  },
  
  updateQualitativeFields: function(sysID, newMaxVal, type, isRisk, selectField) {
  	return this._updateQualitativeFields(sysID, newMaxVal, type, isRisk, selectField);
  },
  
  updateScoreFields: function(sysID, newVal) {
  	return this._updateScoreFields(sysID, newVal);
  },

  updateImpactOnInsert: function(type, newVal, isRisk, selectField) {
  	return this._updateImpactOnInsert(type, newVal, isRisk, selectField);
  },
  
  updateScoreOnInsert: function(newVal) {
  	return this._updateRiskScore(newVal);
  },
  
  updateQuantitativeOnCriteriaDelete: function(type, isRisk, selectField) {
  	return this._updateQuantitativeFields("", '0', type, isRisk, selectField);
  },
  
  updateScoreOnDelete: function(newVal) {
  	return this._updateRiskScore(newVal);
  },
  
  isLeaf: function(riskStatement){
  	return this._isLeaf(riskStatement);
  },
  
  deleteRecord: function(table, sysIds){
  	return this._deleteRecord(table, sysIds);
  },
  
  _isLeaf: function(riskStatement){
  	return (typeof(riskStatement.leaf) === 'undefined' || (typeof(riskStatement.leaf) !== 'undefined' && riskStatement.leaf));
  },
  
  _calculateScores: function(risk) {
  	var crit, currencyCode, val;
  	currencyCode =  risk.inherent_sle.getCurrencyCode();
  	val = risk.inherent_sle.getCurrencyValue();
  	risk.inherent_ale = currencyCode + ";" + val * risk.inherent_aro;
  	crit = this._getRiskCriteria('score', risk.inherent_ale.getReferenceValue());

  	if(crit != false)
  		risk.setValue('score', crit.getUniqueValue());

  	currencyCode =  risk.residual_sle.getCurrencyCode();
  	val = risk.residual_sle.getCurrencyValue();
  	risk.residual_ale = currencyCode + ";" + val * risk.residual_aro;

  	crit = this._getRiskCriteria('score', risk.residual_ale.getReferenceValue());

  	if(crit != false)
  		risk.setValue('residual_score', crit.getUniqueValue());
  },
  
  _getCalculatedScore: function(grInherentScore, grResidualScore, percent_pass, total_tests) {
  	if(!total_tests || total_tests === 0) {
  		//No controls. Use Residual Score if it is set. If not, use Inherent score
  		if(grResidualScore) {
  			return grResidualScore;
  		} else {
  			return grInherentScore;
  		}
  	}
  	
  	if(!percent_pass) {
  		//Treat null or undefined as 0% compliance.
  		percent_pass = 0;
  	}

  	//Make sure we can calculate a score. If not, use Inherent score (even if empty)
  	if(!grInherentScore || !grResidualScore || percent_pass === 0) {
  		return grInherentScore;
  	}

  	var compliance = percent_pass / 100;
  	var inherent = grInherentScore.currency_max_value.getReferenceValue();
  	var residual = grResidualScore.currency_max_value.getReferenceValue();
  	var calculated = Math.round((inherent - residual) * (1 - compliance) + residual);

  	return this._getRiskCriteria('score', calculated);
  },
  
  _getRiskCriteria: function(type, value) {
  	//Returns the GlideRecord for a Risk Criteria record for a given type or weighting
  	
  	if(value.toString() == 'null')
  		return '';
  	
  	value = parseFloat(value);
  	var queryField;
  	if(type.equals('likelihood'))
  		queryField = 'percentage_max_value';
  	else // type is score or impact
  		queryField = 'currency_max_value';
  	var crit = new GlideRecord('sn_risk_criteria');
  	crit.addQuery(queryField, '>=', value);
  	crit.addQuery('type', type);
  	crit.orderBy(queryField);
  	crit.setLimit(1);
  	crit.query();
  	crit.next();

  	if(crit.getRowCount() == 0) {
  		var maxCrit = new GlideRecord('sn_risk_criteria');
  		maxCrit.addQuery('type', type);
  		maxCrit.orderByDesc(queryField);
  		maxCrit.setLimit(1);
  		maxCrit.query();
  		maxCrit.next();
  		return maxCrit;
  	}
  	else if(crit.getRowCount() == 1) {
  		return crit;
  	}
  	else
  		return false;
  },
  
  _getRiskScore: function(significance, likelihood) {
  	//Calculates a score from significance and likelihood and returns the associated Risk Criteria threshold for the score
  	var score = parseFloat(significance) * parseFloat(likelihood);
  	score = score.toFixed(2);
  	return this._getRiskCriteria('score', score);
  },
  
  _setRiskFromStatement : function(riskID, statementID) {
  	var grRisk = new GlideRecord('sn_risk_risk');
  	if(!grRisk.get(riskID)) return false;
  	
  	var grDef = new GlideRecord('sn_risk_definition');
  	if(!grDef.get(statementID)) return false;
  	
  	var updated = false;
  	var fields = [
  		'additional_information',
  		'category',
  		'description',
  		'likelihood',
  		'residual_likelihood',
  		'impact',
  		'residual_impact'
  		
  	];
  	
  	for(var i in fields) {
  		var field = fields[i];
  		if(grRisk[field] + '' == grDef[field] + '') continue;
  		grRisk[field] = grDef[field];
  		updated = true;
  	}
  	
  	if(grRisk.name.nil()) {
  		grRisk.name = grDef.name;
  		updated = true;
  	}
  	
  	var currencyCode='';
  	if (grRisk.inherent_sle != grDef.default_inherent_sle) {
  		currencyCode = grDef.default_inherent_sle.getCurrencyCode();
  		grRisk.inherent_sle = currencyCode+";"+grDef.default_inherent_sle.getCurrencyValue();
  		
  		if (parseFloat(grRisk.inherent_sle) < parseFloat(grRisk.residual_sle))
  			grRisk.residual_sle = currencyCode+";"+grRisk.inherent_sle.getCurrencyValue();
  		
  		updated = true;
  	}
  	
  	if (grRisk.residual_sle != grDef.default_residual_sle) {
  		currencyCode = grDef.default_residual_sle.getCurrencyCode();
  		grRisk.residual_sle = currencyCode+";"+grDef.default_residual_sle.getCurrencyValue();
  		
  		if (parseFloat(grRisk.inherent_sle) < parseFloat(grRisk.residual_sle))
  			grRisk.residual_sle = currencyCode+";"+grRisk.inherent_sle.getCurrencyValue();
  		
  		updated = true;
  	}
  	
  	if (grRisk.inherent_aro != grDef.default_inherent_aro) {
  		grRisk.inherent_aro = grDef.default_inherent_aro;
  		
  		if (grRisk.inherent_aro.value < grRisk.residual_aro.value )
  			grRisk.residual_aro = grRisk.inherent_aro;
  		
  		updated = true;
  	}		
  	
  	if (grRisk.residual_aro != grDef.default_residual_aro) {
  		grRisk.residual_aro = grDef.default_residual_aro;
  		
  		if (grRisk.inherent_aro.value < grRisk.residual_aro.value )
  			grRisk.residual_aro = grRisk.inherent_aro;
  		
  		updated = true;
  	}		
  	
  	if(updated)	grRisk.update();
  	
  	return updated;
  },
  
  _syncRiskQualitativeFields: function(risk) {
  		return this._syncQualitativeFields(risk, true);
  },
  
  _syncRiskStatementQualitativeFields: function(riskStatement) {
  		return this._syncQualitativeFields(riskStatement, false);
  },
  
  _syncQualitativeFields: function(current, isRisk) {
  	var isQualImpact = (gs.getProperty('sn_risk.qualitative_impact') == 'true');
  	var isQualLikelihood = (gs.getProperty('sn_risk.qualitative_likelihood') == 'true');
  	var crit;
  
  	if(isQualImpact) {
  		var currencyCode, val;
  		if(isRisk) {
  			
  			if (current.impact == ""){
  				current.inherent_sle = '0';
  			}else {
  				currencyCode =  current.impact.currency_max_value.getCurrencyCode();
  				val = current.impact.currency_max_value.getCurrencyValue();
  				
  				current.inherent_sle = currencyCode + ";" + val;
  			}
  			
  			if (current.residual_impact == ""){
  				current.residual_sle = '0';
  			}else {

  				currencyCode =  current.residual_impact.currency_max_value.getCurrencyCode();
  				val = current.residual_impact.currency_max_value.getCurrencyValue();
  				current.residual_sle = currencyCode + ";" + val;
  			}				
  		}
  		else {
  			
  			if (current.impact == ""){
  				current.default_inherent_sle = '0';
  			}else {
  				currencyCode =  current.impact.currency_max_value.getCurrencyCode();
  				val = current.impact.currency_max_value.getCurrencyValue();
  				
  				current.default_inherent_sle = currencyCode + ";" + val;
  			}
  			
  			if (current.residual_impact == ""){
  				current.default_residual_sle = '0';
  			}else {

  				currencyCode =  current.residual_impact.currency_max_value.getCurrencyCode();
  				val = current.residual_impact.currency_max_value.getCurrencyValue();
  				current.default_residual_sle = currencyCode + ";" + val;
  			}			
  		}
  	}
  	else {
  		var inherentCritValue, residualCritValue;
  		if(isRisk) {
  			inherentCritValue = current.inherent_sle.getReferenceValue();
  			residualCritValue = current.residual_sle.getReferenceValue();
  		}
  		else {
  			inherentCritValue = current.default_inherent_sle.getReferenceValue();
  			residualCritValue = current.default_residual_sle.getReferenceValue();
  		}
  		
  		crit = this._getRiskCriteria('impact', inherentCritValue);
  		current.setValue('impact', crit.getUniqueValue());
  		
  		crit = this._getRiskCriteria('impact', residualCritValue);
  		current.setValue('residual_impact', crit.getUniqueValue());

  	}
  	
  	if(isQualLikelihood) {
  		
  		if(isRisk) {
  			current.inherent_aro = (current.likelihood == "") ? '0' : current.likelihood.percentage_max_value;
  			current.residual_aro = (current.residual_likelihood == "") ? '0' : current.residual_likelihood.percentage_max_value;
  		}
  		else {
  			current.default_inherent_aro = (current.likelihood == "") ? '0' : current.likelihood.percentage_max_value;
  			current.default_residual_aro = (current.residual_likelihood == "") ? '0' : current.residual_likelihood.percentage_max_value;
  		}
  	}
  	else {
  		
  		var inherentCritValue, residualCritValue;
  		if(isRisk) {
  			inherentCritValue = current.inherent_aro;
  			residualCritValue = current.residual_aro;
  		}
  		else {
  			inherentCritValue = current.default_inherent_aro;
  			residualCritValue = current.default_residual_aro;
  		}
  		
  		crit = this._getRiskCriteria('likelihood', inherentCritValue);
  		current.setValue('likelihood', crit.getUniqueValue());
  		
  		crit = this._getRiskCriteria('likelihood', residualCritValue);
  		current.setValue('residual_likelihood', crit.getUniqueValue());			
  	}
  },
  
  _updateCalculatedRiskFactor: function(risk) {
  	var calculatedRiskFactor = 0;
  	var currencyCode =  risk.inherent_sle.getCurrencyCode();
  	
  	var indicatorFailureFactor = parseFloat(risk.indicator_failure_factor);
  	var controlFailureFactor = parseFloat(risk.control_failure_factor);
  	var resALE = parseFloat(risk.residual_ale.getCurrencyValue());
  	var inALE = parseFloat(risk.inherent_ale.getCurrencyValue());

  	if(controlFailureFactor == 0 || indicatorFailureFactor == 0)
  		calculatedRiskFactor = controlFailureFactor + indicatorFailureFactor;
  	else {
  		var ccr = (indicatorFailureFactor + controlFailureFactor) / 2;
  		calculatedRiskFactor = ccr;
  	}
  	
  	var calcALE = resALE + ((inALE - resALE) * (calculatedRiskFactor / 100));
  	calcALE = calcALE.toFixed(2);
  	risk.calculated_ale = currencyCode + ';' + calcALE;
  	var calculatedScore = this._getRiskCriteria('score', risk.calculated_ale.getReferenceValue());
  	risk.calculated_risk_factor = calculatedRiskFactor;
  	risk.calculated_score = calculatedScore.sys_id;
  },
  
  _updateControlFailureFactor: function(risk) {
  	var controlFailureFactor = 0;
  	var numTotalControls = 0;
  	var numFailedControls = 0;
  			
  	var relatedControl = new GlideRecord('sn_risk_m2m_risk_control');
  	relatedControl.addQuery('sn_risk_risk', risk.sys_id);
  	relatedControl.query();
  	
  	if (relatedControl.getRowCount() > 0) {
  		var totalControlsWeighting = 0;
  		var failedControlsWeighting = 0;
  		
  		while(relatedControl.next()) {
  			if (!relatedControl.sn_compliance_control.nil() && relatedControl.sn_compliance_control.state + '' != "retired") {
  				totalControlsWeighting += parseInt(relatedControl.sn_compliance_control.weighting + '');
  				numTotalControls++;
  				
  				if((relatedControl.sn_compliance_control.status + '') == 'non_compliant' || relatedControl.sn_compliance_control.exempt) {
  					failedControlsWeighting += parseInt(relatedControl.sn_compliance_control.weighting + '');
  					numFailedControls++;
  				}
  			}
  		}
  		if (totalControlsWeighting <= 0)
  			controlFailureFactor = 0;
  		else
  			controlFailureFactor = (failedControlsWeighting / totalControlsWeighting) * 100;
  	}
  	
  	if (numTotalControls > 0) {
  		risk.percent_pass = ((numTotalControls - numFailedControls) / numTotalControls) * 100;
  		risk.percent_fail = (numFailedControls / numTotalControls) * 100;
  	}
  	else {
  		risk.percent_pass = 0;
  		risk.percent_fail = 0;
  	}
  	
  	risk.control_failure_factor = controlFailureFactor;
  },
  
  _updateIndicatorFailureFactor: function(risk) {
  	var indicatorFailureFactor = 0;
  	var indicators = new GlideRecord('sn_grc_indicator');
  	indicators.addQuery('item', risk.sys_id);
  	indicators.addActiveQuery();
  	indicators.query();

  	var totalIndicators = indicators.getRowCount();
  	var failedIndicators = 0;
  	
  	if(totalIndicators > 0)
  		while(indicators.next())
  			if(indicators.last_result_passed.toString() == 'false')
  				failedIndicators++;
  	
  	indicators = new GlideRecord("sn_grc_pa_m2m_item_pa_indicator");
  	if (indicators.isValid()) {
  		indicators.addQuery('sn_grc_item', risk.sys_id);
  		indicators.addActiveQuery();
  		indicators.query();
  	
  		var totalPAIndicators = indicators.getRowCount();
  		totalIndicators += totalPAIndicators;
  	
  		if(totalPAIndicators > 0)
  			while(indicators.next())
  				if(indicators.breach_counter != 0)
  					failedIndicators++;
  	}
  	
  	if (totalIndicators != 0)
  		risk.indicator_failure_factor = (failedIndicators / totalIndicators) * 100;
  	else
  		risk.indicator_failure_factor = 0;
  },
  
  /* When in qualitative and risk criteria's max value is changed, update the SLE / ARO fields accordingly */
  _updateQuantitativeFields: function(sysID, value, type, isRisk, selectField) {
  	var resType = "residual_" + type;
  	var inherentField, residualField;
  	if (selectField == "QualImpact") {
  		inherentField = "inherent_sle";
  		residualField = "residual_sle";
  	}
  	if (selectField == "QualLikelihood") {
  		inherentField = "inherent_aro";
  		residualField = "residual_aro";
  	}
  	
  	if (inherentField && residualField) {
  		var defaultInherent = "default_" + inherentField;
  		var defaultResidual = "default_" + residualField;
  		var tableName = (isRisk) ? "sn_risk_risk" : "sn_risk_definition";
  		
  		var riskTable = new GlideRecord(tableName);
  		if (sysID == "")
  			riskTable.addEncodedQuery(type + "ISEMPTY^OR" + resType + "ISEMPTY");
  		else {
  			var or = riskTable.addQuery(type, "=", sysID);
  			or.addOrCondition(resType, "=", sysID);
  		}
  		riskTable.query();
  		while(riskTable.next()) {
  			if (isRisk) {
  				if (riskTable[type] == sysID) 
  					riskTable.setValue(inherentField, value);
  				if (riskTable[resType] == sysID)
  					riskTable.setValue(residualField, value);
  			} else {
  				if (riskTable[type] == sysID)
  					riskTable.setValue(defaultInherent, value);
  				if (riskTable[resType] == sysID)
  					riskTable.setValue(defaultResidual, value);
  			}
  			riskTable.update();	
  		}
  	}
  },
  
  /* Get the number immediatly lower than and immediately higher than the parameter newVal from risk criteria of the given type
  params: type - is the type in risk criteria (impact, score, likelihood)
  */
  _getLowMaxValue: function(type, newVal) {
  	var maxField = (type == "likelihood") ? "percentage_max_value" : "currency_max_value";
  	var arr = [];
  	var lowCurrMax = new GlideRecord("sn_risk_criteria");
  	lowCurrMax.addQuery("type", type);
  	lowCurrMax.orderBy(maxField);
  	lowCurrMax.query();
  	while(lowCurrMax.next()){
  		if(maxField == "currency_max_value"){
  			arr.push(Number(lowCurrMax[maxField].getReferenceValue()));	
  		}else{
  			arr.push(Number(lowCurrMax[maxField]));	
  		}
  	}
  	
  	var num = newVal;
  	var low = (num < arr[0]) ? num : arr[0];
  	var high = (num > arr[0]) ? num : arr[0];
  	
  	for (var i=0;i<arr.length;i++) {
  		if (arr[i] < num && low < arr[i])
  			low = arr[i];
  		if (arr[i] > num && high <= arr[i]){
  			high = arr[i];
  			break;
  		}
  	}
  	return [low, high];
  },
  
  /* Find the records with inherent / residual fields in the range of low and high and update the SLE / ARO values */
  _updateQuantitativeFieldsInRange: function(tableName, type, resType, inherentField, residualField, low, high, newVal) {
  	/* if newVal is either the lowest or highest in the range, then we need find records less than highest or record greater than lowest respectively
  	   if newVal == low
  		   field <= high
  	   if newVal == high
  	       field >= low
  	*/
  	var riskSLE = new GlideRecord(tableName);
  	var field = riskSLE.addNotNullQuery();
  	if (newVal != low) {
  		field.addOrCondition(inherentField, ">=", low);
  		field.addOrCondition(residualField, ">=", low);
  	}
  	if (newVal != high) {
  		field.addOrCondition(inherentField, "<=", high);	
  		field.addOrCondition(residualField, "<=", high);
  	}
  	riskSLE.query();
  			
  	while(riskSLE.next()) {
  		var risKCri2;
  		var inherentValue, residualValue;
  		var inherentElement = riskSLE[inherentField];
  		var residualElement = riskSLE[residualField];
  		
  		if(inherentElement.getED().getInternalType() == "currency"){
  			inherentValue = inherentElement.getReferenceValue();
  		}else{
  			inherentValue = inherentElement;
  		}
  		
  		if(residualElement.getED().getInternalType() == "currency"){
  			residualValue = residualElement.getReferenceValue();
  		}else{
  			residualValue = residualElement;
  		}
  			
  		
  		if (newVal == low) {
  			if (riskSLE[inherentField] <= high) {
  				risKCri2 = this._getRiskCriteria(type, inherentValue);
  				riskSLE.setValue(type, risKCri2.sys_id);
  			}
  			if (riskSLE[residualField] <= high) {
  				risKCri2 = this._getRiskCriteria(type, residualValue);
  				riskSLE.setValue(resType, risKCri2.sys_id);
  			}
  		}
  		if (newVal == high) {
  			if (riskSLE[inherentField] >= low) {
  				risKCri2 = this._getRiskCriteria(type, inherentValue);
  				riskSLE.setValue(type, risKCri2.sys_id);
  			}
  			if (riskSLE[residualField] >= low) {
  				risKCri2 = this._getRiskCriteria(type, residualValue);
  				riskSLE.setValue(resType, risKCri2.sys_id);
  			}
  		}
  		if (newVal != low && newVal != high && inherentValue >= low && inherentValue <= high) {
  			risKCri2 = this._getRiskCriteria(type, inherentValue);
  			riskSLE.setValue(type, risKCri2.sys_id);
  		} 
  		if (newVal != low && newVal != high && residualValue >= low && residualValue <= high) {
  			risKCri2 = this._getRiskCriteria(type, residualValue);
  			riskSLE.setValue(resType, risKCri2.sys_id);
  		}
  		riskSLE.update();
  	}		
  },
  
  /* Risk criteria record of type score is updated, any record using this score should be updated */
  _updateRiskScore: function(newVal) {
  	var lowMax = this._getLowMaxValue("score", newVal);
  	var low = lowMax[0];
  	var high = lowMax[1];
  	/* if newVal is either the lowest or highest in the range, then we need find records less than highest or record greater than lowest respectively
  	   if newVal == low
  		   field <= high
  	   if newVal == high
  	       field >= low
  	*/
  	
  	var riskALE = new GlideRecord("sn_risk_risk");
  	var field = riskALE.addNotNullQuery();
  	if (newVal != low) {
  		field.addOrCondition("inherent_ale", ">=", low);
  		field.addOrCondition("residual_ale", ">=", low);
  		field.addOrCondition("calculated_ale", ">=", low);
  	}
  	if (newVal != high) {
  		field.addOrCondition("inherent_ale", "<=", high);		
  		field.addOrCondition("residual_ale", "<=", high);		
  		field.addOrCondition("calculated_ale", "<=", high);
  	}
  	riskALE.query();
  		
  	while(riskALE.next()) {
  		var risKCri2;
  		var riskInherentALERefVal = riskALE.inherent_ale.getReferenceValue();
  		var riskResidualALERefVal = riskALE.residual_ale.getReferenceValue();
  		var riskCalculatedALERefVal = riskALE.calculated_ale.getReferenceValue();
  		
  		if (newVal == low) {
  			if (riskInherentALERefVal <= high) {
  				risKCri2 = this._getRiskCriteria("score", riskInherentALERefVal);
  				riskALE.setValue("score", risKCri2.sys_id);
  			} 
  			if (riskResidualALERefVal <= high) {
  				risKCri2 = this._getRiskCriteria("score", riskResidualALERefVal);
  				riskALE.setValue("residual_score", risKCri2.sys_id);
  			}
  			if (riskCalculatedALERefVal <= high) {
  				risKCri2 = this._getRiskCriteria("score", riskCalculatedALERefVal);
  				riskALE.setValue("calculated_score", risKCri2.sys_id);
  			}
  		}
  		if (newVal == high) {
  			if (riskInherentALERefVal >= low) {
  				risKCri2 = this._getRiskCriteria("score", riskInherentALERefVal);
  				riskALE.setValue("score", risKCri2.sys_id);
  			} 
  			if (riskResidualALERefVal >= low) {
  				risKCri2 = this._getRiskCriteria("score", riskResidualALERefVal);
  				riskALE.setValue("residual_score", risKCri2.sys_id);
  			}
  			if (riskCalculatedALERefVal >= low) {
  				risKCri2 = this._getRiskCriteria("score", riskCalculatedALERefVal);
  				riskALE.setValue("calculated_score", risKCri2.sys_id);
  			}
  		}
  		if (newVal != low && newVal != high && riskInherentALERefVal >= low && riskInherentALERefVal <= high) {
  			risKCri2 = this._getRiskCriteria("score", riskInherentALERefVal);
  			riskALE.setValue("score", risKCri2.sys_id);
  		} 
  		if (newVal != low && newVal != high && riskResidualALERefVal >= low && riskResidualALERefVal <= high) {
  			risKCri2 = this._getRiskCriteria("score", riskResidualALERefVal);
  			riskALE.setValue("residual_score", risKCri2.sys_id);
  		}
  		if (newVal != low && newVal != high && riskCalculatedALERefVal >= low && riskCalculatedALERefVal <= high) {
  			risKCri2 = this._getRiskCriteria("score", riskCalculatedALERefVal);
  			riskALE.setValue("calculated_score", risKCri2.sys_id);
  		}
  		riskALE.update();
  	}
  },
  
  _updateQualitativeFields: function(sysID, newMaxVal, type, isRisk, selectField) {
  	var resType = "residual_" + type;
  	var tableName = (isRisk) ? "sn_risk_risk" : "sn_risk_definition";
  	
  	// reset impact / likelihood of risks / risk statements when criteria is changed when quantitative
  	var oldRisk = new GlideRecord(tableName);
  	var o = oldRisk.addQuery(type, sysID);
  	o.addOrCondition(resType, sysID);
  	oldRisk.query();
  	while(oldRisk.next()) {
  		var fieldName;
  		if (isRisk) {
  			if (type == "likelihood" && selectField == "QuanLikelihood")
  				fieldName = "residual_aro";
  			else if (type == "impact" && selectField == "QuanImpact")
  				fieldName = "inherent_sle";
  		} else {
  			if (type == "likelihood" && selectField == "QuanLikelihood")
  				fieldName = "default_residual_aro";
  			else if (type == "impact" && selectField == "QuanImpact")
  				fieldName = "default_inherent_sle";
  		}
  		if (fieldName) {
  			var risKCri = "";
  			if(oldRisk[fieldName].getED().getInternalType() == "currency"){
  				risKCri = this._getRiskCriteria(type, oldRisk[fieldName].getReferenceValue());
  			}else{
  				risKCri = this._getRiskCriteria(type, oldRisk.getValue(fieldName));
  			}

  			if (oldRisk[type] == sysID)
  				oldRisk.setValue(type, risKCri.sys_id);
  			if (oldRisk[resType] == sysID)
  				oldRisk.setValue(resType, risKCri.sys_id);

  			oldRisk.update();
  		}
  	}		
  	
  	// get the currency max value less than and greater than the new currency max value
  	var lowHigh = this._getLowMaxValue(type, newMaxVal);
  	var low = lowHigh[0];
  	var high = lowHigh[1];
  	var inherentField, residualField;
  	
  	if (isRisk) {
  		if (type == "likelihood") {
  			inherentField = "inherent_aro";
  			residualField = "residual_aro";
  		} else {
  			inherentField = "inherent_sle";
  			residualField = "residual_sle";
  		}
  	} else {
  		if (type == "likelihood") {
  			inherentField = "default_inherent_aro";
  			residualField = "default_residual_aro";
  		} else {
  			inherentField = "default_inherent_sle";
  			residualField = "default_residual_sle";
  		}
  	} 
  	
  	//Fetch all the risks and risk statements with SLE / ARO in the range of low and high determined above
  	this._updateQuantitativeFieldsInRange(tableName, type, resType, inherentField, residualField, low, high, newMaxVal);
  	
  },
  
  _updateScoreFields: function(sysID, newVal) {
  	// update all risks with old score to the updated scoring display value
  	var risk = new GlideRecord("sn_risk_risk");
  	var or = risk.addQuery("score", sysID);
  	or.addOrCondition("residual_score", sysID);
  	or.addOrCondition("calculated_score", sysID);
  	risk.query();
  	while(risk.next()) {
  		var riskCri;
  		if (risk.score == sysID) {
  			riskCri = this._getRiskCriteria("score", risk.inherent_ale.getReferenceValue());
  			risk.setValue("score", riskCri.sys_id);
  		}
  		if (risk.residual_score == sysID) {
  			riskCri = this._getRiskCriteria("score", risk.residual_ale.getReferenceValue());
  			risk.setValue("residual_score", riskCri.sys_id);
  		}
  		if (risk.calculated_score == sysID) {
  			riskCri = this._getRiskCriteria("score", risk.calculated_ale.getReferenceValue());
  			risk.setValue("calculated_score", riskCri.sys_id);
  		}
  		risk.update();
  	}
  	
  	this._updateRiskScore(newVal);
  },
  
  _updateImpactOnInsert: function(type, newVal, isRisk, selectField) {
  	var resType = "residual_" + type;
  	var lowMax = this._getLowMaxValue(type, newVal);
  	var low = lowMax[0];
  	var high = lowMax[1];
  	var inherentField, residualField;
  	var tableName = (isRisk) ? "sn_risk_risk" : "sn_risk_definition";
  	if (isRisk) {
  		if (type == "likelihood" && selectField == "QuanLikelihood") {
  			inherentField = "inherent_aro";
  			residualField = "residual_aro";
  		} else if (type == "impact" && selectField == "QuanImpact"){
  			inherentField = "inherent_sle";
  			residualField = "residual_sle";
  		}
  	} else {
  		if (type == "likelihood" && selectField == "QuanLikelihood") {
  			inherentField = "default_inherent_aro";
  			residualField = "default_residual_aro";
  		} else if (type == "impact" && selectField == "QuanImpact"){
  			inherentField = "default_inherent_sle";
  			residualField = "default_residual_sle";
  		}
  	} 

  	//Fetch all the risks and risk statements with SLE / ARO in the range of low and high determined above
  	if (inherentField && residualField) 
  		this._updateQuantitativeFieldsInRange(tableName, type, resType, inherentField, residualField, low, high, newVal);
  },
  
  _showRiskRelationshipAddButton: function(risk, profile, relationship) {
  	var prof = new GlideRecord("sn_grc_profile");
  	if(prof.get(profile)) {
  		var stream;
  	
  		if(relationship.getEncodedQuery().indexOf("downstream_risk=" + risk.sys_id + '') != -1)
  			stream = "upstream";
  		else
  			stream = "downstream";

  		var riskList = this._getValidRisksForRelationships(prof, stream, risk.sys_id + '');
  		if(riskList.length > 0)
  			return true;
  		else
  			return false;
  	}
  	else
  		return false;	
  },
  
  _getValidRisksForRelationships: function(profile, stream, currentRiskID) {
  	var grcUtils = new sn_grc.GRCUtils();
  	var query = "sys_idIN" +  grcUtils.getProfileListFromProfileClassModel(profile, stream, true);
  	
  	var profiles = new GlideRecord('sn_grc_profile');
  	profiles.addEncodedQuery(query);
  	profiles.query();
  	
  	var riskList = [];
  	var risk;
  	
  	while(profiles.next()) {
  		risk = new GlideRecord('sn_risk_risk');
  		risk.addQuery('state', '!=', 'retired');
  		risk.addQuery('profile', profiles.sys_id + '');
  		risk.query();
  		
  		while(risk.next()) {
  			var m2m = new GlideRecord('sn_risk_m2m_risk_risk');
  			if(stream == 'upstream'){
  				m2m.addQuery('upstream_risk', risk.sys_id + '');
  				m2m.addQuery('downstream_risk', currentRiskID);
  			}
  			else {
  				m2m.addQuery('upstream_risk', currentRiskID);
  				m2m.addQuery('downstream_risk', risk.sys_id + '');
  			}
  			
  			m2m.query();
  			if(!m2m.next())
  				riskList.push(risk.getUniqueValue());
  		}
  	}
  	return riskList;
  	
  },
  
  _isValidRiskRelationship: function(relationship) {
  	var profile1 = new GlideRecord("sn_grc_profile");
  	var profile2 =  new GlideRecord("sn_grc_profile");
  	
  	if(profile1.get(relationship.upstream_risk.profile) && profile2.get(relationship.downstream_risk.profile)) {
  		var riskList = this._getValidRisksForRelationships(profile1, "downstream", relationship.upstream_risk.sys_id);
  		var isInList = false;
  		
  		for(var i = 0; i < riskList.length; i++) {
  			if(relationship.downstream_risk.sys_id == riskList[i])
  				isInList = true;
  		}
  		
  		return isInList;
  	}
  	else
  	   return false;
  },
  
  _deleteRecord: function(table, sysIds) {
  	for (var i=0; i<sysIds.length; i++) {
  		var gr = new GlideRecord(table);
  		if (gr.get(sysIds[i]))
  			gr.deleteRecord();
  	}
  },
  
  type: 'RiskUtilsBaseV2'
};

Sys ID

a475f670d7030200bbc783e80e61034d

Offical Documentation

Official Docs: