0

Create Current Scoring for Risk Management

In this snippet you will create a current scoring (similar to inherent or residual) using same functions and logic.

Step 1: Create the following fields in Risk table

Go to sn_risk_risk.config > Dictionary entries > Click New

Make sure you have the update in the correct application. (GRC: Risk Management).

FieldTypeReference
u_current_aleCurrency
u_current_aroCurrency
u_current_sleCurrency
u_current_impactReferenceRisk Criteria
u_current_likelihoodReferenceRisk Criteria
u_current_scoreReferenceRisk Criteria

Step 2: Reporting – Clone Risk Overview dashboard

Go to pa_dashboard and get ready to clone a out of the box record

Make sure you have the update in the correct application. (GRC: Risk Management).

  • Clone Risk Overview widget and rename to Custom Risk Overview.
  • Add a new tab named “Current Scoring”
  • Click on Save button to save the change.

Step 3: Reporting – Clone inherent_heatmap UI page

Go to sys_widgets and get ready to clone a out of the box record

Make sure you have the update in the correct application. (GRC: Risk Management).

  • Clone Inherent Heatmap widget by clicking Insert and Stay menu action.
  • Name: Current Risk Heatmap
  • Click on Save button to save the change.

Script

  • Copy and paste below Script in Widget’s Script section
function sections() {
    return {
		'Current Risk Heatmap' : { 'name' : 'current_heatmap' }
    };
}

function render() {
	return renderer.getRenderedPage( 'sn_risk_current_heatmap');  
}

function getEditLink() {
	return "sys_ui_page.do?sysparm_query=name=current_heatmap";
}

Step 4: Reporting – Clone inherent_heatmap UI page

Go to sys_ui_page and get ready to clone a out of the box record

Make sure you have the update in the correct application. (GRC: Risk Management).

  • Clone inherent_heatmap UI page by clicking Insert and Stay menu action.
  • Name: current_heatmap
  • Click on Save button to save the change.

Endpoint

  • Copy and paste below Endpoint in UI page section
sn_risk_current_heatmap.do

Body HTML template

  • Copy and paste below HTML Code in Widget’s HTML Template section
<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
	<g:requires name="styles/heisenberg/heisenberg_all.css" includes="true" />
	<script language="javascript" src="sn_risk.RiskHeatmapUtils.jsdbx" />
	<style>
		#currentRiskHighChartContainer text tspan {
			stroke-width: 1px;
		}
	</style>
	
	<g2:evaluate var="jvar_riskHighChartData">
		var risk = new sn_risk.RiskHeatmap().getRiskHeatmapData('current', '', true); 
		new global.JSON().encode(risk);
	</g2:evaluate>
	<g2:evaluate var="jvar_riskXAxisCategories">
		var xAxis = new sn_risk.RiskHeatmap().getRiskHeatmapXAxisCategories();  
		new global.JSON().encode(xAxis);
	</g2:evaluate>
	<g2:evaluate var="jvar_riskYAxisCategories">
		var yAxis = new sn_risk.RiskHeatmap().getRiskHeatmapYAxisCategories(); 
		new global.JSON().encode(yAxis);
	</g2:evaluate>
	
    <div id="currentRiskHighChartContainer" name="currentRiskHighChartContainer" style="min-width: 310px; height: 400px; max-width: 600px; margin: 0 auto"> 
    </div>
	
   
</j:jelly>

Client script

  • Copy and Paste below script in Client Script Section
(function($){
	var chart;

	chart = new Highcharts.Chart({
		chart: {
			renderTo: "currentRiskHighChartContainer",
			type: 'heatmap',
			marginTop: 12,
			marginBottom: 60,
			plotBackgroundColor: 'none',
			events:{
				load:function() {
					var points = this.series[0].data,
					lenY = this.yAxis[0].tickPositions.length - 1,
					lenX = this.xAxis[0].tickPositions.length - 1,
					x = lenX,
					tmpX = 0,
					y = 0,
					j = 0;
					
					$.each(points, function(i, p){
						var color = p.color;
						p.update({
							color: color
						},false);
					});
					
					this.isDirty = true;
					this.redraw();
				}
			}
		},
		plotOptions: {
			series: {
				events: {
					click: function (event) {
						document.location.href = event.point.url;
					}
				}
			}
		},
		title: {
			align:'center',
			text: '',
			
			style: {
				color: 'black',
				fontSize: '12pt'
			}
			
		},
		
		xAxis: {
			categories: JSON.parse('$[HTML, JS:jvar_riskXAxisCategories]'),
			title: {
				enabled: true,
				text: '<span>Impact</span>'
			}
		},
		
		yAxis: {
			categories: JSON.parse('$[HTML, JS:jvar_riskYAxisCategories]'),
			title: {
				enabled: true,
				text: '<span>Likelihood</span>'
			}
		},
		
		tooltip: {
			formatter: function () {
				var msg = new GwtMessage().getMessage('Count: {0}', this.point.value)
				+ '<br>' + 
				new GwtMessage().getMessage('Impact: {0}', this.series.yAxis.categories[this.point.y])
				+ '<br>' + 
				new GwtMessage().getMessage('Likelihood: {0}', this.series.xAxis.categories[this.point.x]);
				return msg;
			}
		},
		credits: {
			enabled: false
		},
		/*want to make this part dynamically populated*/
		series:[{
			data:[],
			cursor: 'pointer',
			showInLegend: false,			
			dataLabels: {
				enabled: true,
				color: 'black',
				type: 'heatmap',
				backgroundColor: 'none',
				style: {
					textShadow: 'none'
				}
			}
			
		}]
		
	});
	
	sn_risk.RiskHeatmapUtils.updateHeatmap(chart, 'current', true);
	
	CustomEvent.on('dashboard_filter.removed', function(filterMessage){	
		sn_risk.RiskHeatmapUtils.onRemoveEvent(chart, filterMessage, 'current', true);		
	});
	
	CustomEvent.on('dashboard_filter.added', function(filterMessage){
		sn_risk.RiskHeatmapUtils.onAddEvent(chart, filterMessage, 'current', true);
	});	
	
})(jQuery);

Processing Script

  • Copy and Paste below Server-Side Script in Processing Script Section
// empty
  • Click on Save button to save the change.

Step 5: Scripting – Edit RiskHeatMap

Go to System Definition > Script Include

  • Search for RiskHeatMapand open the record.
  • Copy and Paste below Script in Script Include Script Section
var RiskHeatmap = Class.create();
RiskHeatmap.prototype = Object.extendsObject(RiskHeatmapBase, {

    // Overwrite current method to include current as heatmapType
	_getRiskHeatmapData: function(heatmapType, filter, includeColor){
		var riskData = [];
		var riskImpactFieldName = '';
		var riskLikelihoodFieldName = '';
		
		if (heatmapType == 'inherent'){
			riskImpactFieldName = 'impact';
			riskLikelihoodFieldName = 'likelihood';
		}
		else if(heatmapType == 'residual'){
			riskImpactFieldName = 'residual_impact';
			riskLikelihoodFieldName = 'residual_likelihood';
		} else if(heatmapType == 'current'){
			riskImpactFieldName = 'u_current_impact';
			riskLikelihoodFieldName = 'u_current_likelihood';
		} else
		return riskData;
		
		var likelihood =  new GlideRecord('sn_risk_criteria');
		likelihood.addQuery('type', 'likelihood');
		likelihood.orderByDesc('order');
		
		likelihood.query();
		
		for(var i = 0; i < likelihood.getRowCount(); i++){
			likelihood.next();
			
			var impact =  new GlideRecord('sn_risk_criteria');
			impact.addQuery('type', 'impact');
			impact.orderByDesc('order');
			
			impact.query();
			for(var j = 0; j < impact.getRowCount(); j++){
				
				impact.next();
				var risk = new GlideAggregate('sn_risk_risk');
				var count = 0;
				risk.addQuery(riskImpactFieldName, impact.getUniqueValue());
				risk.addQuery(riskLikelihoodFieldName, likelihood.getUniqueValue());
				
				if (filter)				
					risk.addEncodedQuery(filter);

				risk.addAggregate('COUNT');
				risk.query();
				if (risk.next())
					count = risk.getAggregate('COUNT');
				
				var riskColor = this._getRiskColor(impact.getUniqueValue(), likelihood.getUniqueValue());
				var riskUrl = 'sn_risk_risk_list.do?sysparm_query=' + riskImpactFieldName + '%3D' + impact.getUniqueValue()
				+ '%5E' + riskLikelihoodFieldName + '%3D' + likelihood.getUniqueValue();
				
				if (filter)
					riskUrl += '%5E' + filter;
				if (includeColor)
					riskData.push({x:i, y:j, value:count, color: riskColor, url:riskUrl});
				else
					riskData.push({x:i, y:j, value:count, url:riskUrl});
				}
			}
			
			return riskData;
		},





    /** Override base class functions here **/

    type: 'RiskHeatmap'
});
  • Click on Save button to save the change.

Step 6: Scripting – Create new RiskFormUtils

Go to System UI > UI Scripts > Click New

  • Id: WR_RiskFormUtilsV2
  • Copy and Paste below Script in UI Script Script Section
var sn_risk = sn_risk || {};

sn_risk.WR_RiskFormUtilsV2 = (function() {
"use strict";

return {

	calculateALE: function(currency) {

		var resALE = g_form.getValue('sys_readonly.sn_risk_risk.residual_ale');
		var inALE = g_form.getValue('sys_readonly.sn_risk_risk.inherent_ale');
		var ccr = g_form.getValue('calculated_risk_factor');

		resALE = parseFloat(resALE.replace(/[^\d\.]/g,''));
		inALE = parseFloat(inALE.replace(/[^\d\.]/g,''));

		var calcALE = parseFloat(resALE + ((inALE - resALE) * (ccr / 100)));

		calcALE = calcALE.toFixed(2);
		calcALE = currency + calcALE;

		g_form.setValue('calculated_ale', calcALE.toString());
	},

	synchSymbol: function(fromSLE, toSLE, tableName){	
		var toSLESymbol = g_form.getValue(toSLE + '.currency');
		var fromSLESymbol = g_form.getValue(fromSLE + '.currency');  
		if (toSLESymbol == fromSLESymbol)
			return;

		var val = g_form.getValue(toSLE + '.display');	
		// Strip any special characters in the value
		val = val.replace(new RegExp(g_user_grouping_separator, "g"), "");

		var newSLEVal = fromSLESymbol + ';' + val;
		g_form.setValue(toSLE + ".currency", fromSLESymbol);
		g_form.setValue(toSLE + ".display", val);
		g_form.setValue(toSLE, newSLEVal);

		var id = tableName + '.' + toSLE;
		// these two lines are used to set the right currency value, like GBP;100.00
		// Otherwise the value is set to be 100.00, which won't save the currenct
		var sleElement= document.getElementById(id);
		sleElement.value = newSLEVal;			

	},	

	hideQualitativeFields: function(hideQualitativeFields) {
		var fieldsToHide = [];
		if (hideQualitativeFields) {
			fieldsToHide = ['significance', 'residual_significance', 
							'likelihood', 'residual_likelihood',
							'score', 'residual_score',
							'calculated_score'
							];
		}
		else {
			fieldsToHide = ['inherent_sle', 'residual_sle',
							'inherent_aro', 'residual_aro',
							'inherent_ale', 'residual_ale',
							'calculated_ale',

							'default_inherent_sle', 'default_residual_sle',
							'default_inherent_aro', 'default_residual_aro'
							];
		}
		for (var i = 0; i < fieldsToHide.length; i++)
			g_form.setDisplay(fieldsToHide[i], false);
	}, 

	  updateRiskScore: function(scoreType, fieldName, fieldType, value) {

		            var setFieldName, impactField, likelihooField;
		            var ga = new GlideAjax('RiskUtilsAJAXV2');
		
		            switch(fieldName) {
		
		                case 'u_current_impact':
		                    setFieldName = 'u_current_sle';
		                    ga.addParam('sysparm_name', 'usingQualitative');
		                    ga.addParam('sysparm_prop_name', 'sn_risk.qualitative_impact');
		                    ga.getXML(setFields);
		                    break;
		
		                case 'u_current_likelihood':
		                    setFieldName = 'u_current_aro';
		                    ga.addParam('sysparm_name', 'usingQualitative');
		                    ga.addParam('sysparm_prop_name', 'sn_risk.qualitative_likelihood');
		                    ga.getXML(setFields);
		            }
		
		            function setFields(response) {
		                var answer = response.responseXML.documentElement.getAttribute("answer");
		                if(answer == 'true') {
		
		                    ga = new GlideAjax('RiskUtilsAJAXV2');
		                    ga.addParam('sysparm_name', 'getRiskCriteria');
		                    ga.addParam('sysparm_field_type', fieldType);
		                    ga.addParam('sysparm_field_value', value);
		                    ga.getXMLAnswer(function(answer) {
		
		                        if(answer != false || answer == '0')
		                            g_form.setValue(setFieldName, answer);
		                    });
		
		                    ga = new GlideAjax('RiskUtilsAJAXV2');
		                    ga.addParam('sysparm_name', 'getRiskScore');
		                    ga.addParam('sysparm_impact', g_form.getValue('u_current_impact'));
		                    ga.addParam('sysparm_likelihood', g_form.getValue('u_current_likelihood'));
		                    ga.getXMLAnswer(function(answer) {
		                        g_form.setValue('u_current_score', answer);
		                    });
		                }
		            }
		        },
	
	useQualitativeImpact: function(useQualitativeImpact) {
		jslog("Calling use qualitative impact " + useQualitativeImpact);
		if(useQualitativeImpact) {
			g_form.setDisplay('inherent_sle', false);
			g_form.setDisplay('residual_sle', false);
			g_form.setDisplay('default_inherent_sle', false);
			g_form.setDisplay('default_residual_sle', false);
		}
		else {
			g_form.setDisplay('impact', false);
			g_form.setDisplay('residual_impact', false);
		}
	},

	useQualitativeLikelihood: function(useQualitativeLikelihood) {
		jslog("Calling use qualitative likelihood " + useQualitativeLikelihood);
		if(useQualitativeLikelihood) {
			g_form.setDisplay('inherent_aro', false);
			g_form.setDisplay('residual_aro', false);
			g_form.setDisplay('default_inherent_aro', false);
			g_form.setDisplay('default_residual_aro', false);
		}
		else {
			g_form.setDisplay('likelihood', false);
			g_form.setDisplay('residual_likelihood', false);
		}
	},

	validateRisk: function(fieldType) {
		jslog("Started: " + fieldType);
		fieldType = fieldType + '';
		var isDefault = false;
		var fieldArr = fieldType.split('_');

		if(fieldArr[0] == 'default')
			isDefault = true;

		var inherentField;
		var residualField;
		var inherent; 
		var residual;

		switch(fieldType) {
			case 'likelihood':
			case 'impact':
				residualField = 'residual_' + fieldType;
				inherentField = fieldType;
				setQualitativeValues(inherentField, residualField);
				break;

			case 'residual_likelihood':
			case 'residual_impact':
				residualField = fieldType;
				inherentField = fieldArr[1];
				setQualitativeValues(inherentField, residualField);
				break;

			case 'default_inherent_sle':
			case 'inherent_sle':
				setInherentQuantitativeValues(fieldType, fieldArr);
				setQuantitativeValues(inherentField, residualField);
				doCheck();
				break;

			case 'default_inherent_aro':
			case 'inherent_aro':
				setInherentQuantitativeValues(fieldType, fieldArr);
				setAROValues(inherentField, residualField);
				break;

			case 'default_residual_sle':
			case 'residual_sle':
				setResidualQuantitativeValues(fieldType, fieldArr);
				setQuantitativeValues(inherentField, residualField);
				doCheck();
				break;
			case 'default_residual_aro':
			case 'residual_aro':
				setResidualQuantitativeValues(fieldType, fieldArr);
				setAROValues(inherentField, residualField);
				break;
		}

		function hideErrorBoxes(inherentField, residualField) {
			g_form.hideErrorBox(inherentField);
			g_form.hideErrorBox(residualField);
		}

		function setInherentQuantitativeValues(fieldType, fieldArr) {
			inherentField = fieldType;
			if(isDefault)
				residualField = 'default_residual_' + fieldArr[2];
			else
				residualField = 'residual_' + fieldArr[1];
			hideErrorBoxes(inherentField, residualField);
		}

		function setResidualQuantitativeValues(fieldType, fieldArr) {
			if(isDefault)
				inherentField = 'default_inherent_' + fieldArr[2];
			else
				inherentField = 'inherent_' + fieldArr[1];
			residualField = fieldType;
			hideErrorBoxes(inherentField, residualField);
		}

		function setQuantitativeValues(inherentField, residualField) {
			var rawInherent = g_form.getValue(inherentField);
			var inherentArray = rawInherent.split(';');
			inherent = parseFloat(inherentArray[1].replace(/,/g , ''));
			var rawResidual = g_form.getValue(residualField);
			var residualArray = rawResidual.split(';');
			residual = parseFloat(residualArray[1].replace(/,/g , ''));
		}

		function setQualitativeValues(inherentField, residualField) {
			hideErrorBoxes(inherentField, residualField);
			inherent = false;
			residual = false;
			if(g_form.getValue(inherentField) == '') {
				inherent = 0;
			}
			else {
				g_form.getReference(inherentField, setInherent);
			}
			g_form.getReference(residualField, setResidual);
		}

		function setAROValues(inherentField, residualField) {
			hideErrorBoxes(inherentField, residualField);
			inherent = g_form.getValue(inherentField);
			residual = g_form.getValue(residualField);
			doCheck();
		}

		function setInherent(criteria) {
			if(criteria.type == 'likelihood')
				inherent = criteria.percentage_max_value;
			else 
				inherent = parseInt(criteria.currency_max_value);
			doCheck();
		}

		function setResidual(criteria) {
			if(criteria.type == 'likelihood')
				residual = criteria.percentage_max_value;
			else
				residual = parseInt(criteria.currency_max_value);	
			doCheck();
		}

		function doCheck() {
			if(inherent !== false && residual !== false && (parseFloat(residual)) > parseFloat(inherent)) {
				switch(fieldType) {
					case 'likelihood' :
						g_form.showErrorBox(inherentField,getMessage('sn_risk_likelihood_inherent_lower_than_residual'));
						break;
					case 'residual_likelihood' :
						g_form.showErrorBox(residualField,getMessage('sn_risk_likelihood_residual_higher_than_inherent'));
						break;
					case 'impact' :
						g_form.showErrorBox(inherentField,getMessage('sn_risk_impact_inherent_lower_than_residual'));
						break;
					case 'residual_impact' :
						g_form.showErrorBox(residualField,getMessage('sn_risk_impact_residual_higher_than_inherent'));
						break;
					case 'inherent_sle' : 
						g_form.showErrorBox('inherent_sle', getMessage('sn_risk_sle_inherent_lower_than_residual'));
						break;
					case 'default_inherent_sle' :
						g_form.showErrorBox('default_inherent_sle', getMessage('sn_risk_sle_inherent_lower_than_residual'));
						break;
					case 'residual_sle' : 
						g_form.showErrorBox('residual_sle', getMessage('sn_risk_sle_residual_higher_than_inherent'));
						break;
					case 'default_residual_sle' : 
						g_form.showErrorBox('default_residual_sle', getMessage('sn_risk_sle_residual_higher_than_inherent'));
						break;
					case 'inherent_aro' : 
						g_form.showErrorBox('inherent_aro', getMessage('sn_risk_aro_inherent_lower_than_residual'));
						break;
					case 'default_inherent_aro' : 
						g_form.showErrorBox('default_inherent_aro', getMessage('sn_risk_aro_inherent_lower_than_residual'));
						break;
					case 'residual_aro' : 
						g_form.showErrorBox('residual_aro', getMessage('sn_risk_aro_residual_higher_than_inherent'));
						break;
					case 'default_residual_aro' : 
						g_form.showErrorBox('default_residual_aro', getMessage('sn_risk_aro_residual_higher_than_inherent'));
						break;
				}
				return false;
			}
			else
				return true;
		}
	},

	type: 'WR_RiskFormUtilsV2'
};
})();
  • Click on Save button to save the change.

Step 7: Edit Custom Risk Overview dashboard

Go to Service Portal > Page > Click New

Adapt the dashboard according to your taste.

Search for Custom Risk Overview dashboard.

In the “Current Scoring” tab search for widget current and add to the dashboard.

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Rafael

Leave a Reply

Your email address will not be published. Required fields are marked *