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).
| Field | Type | Reference |
|---|---|---|
| u_current_ale | Currency | |
| u_current_aro | Currency | |
| u_current_sle | Currency | |
| u_current_impact | Reference | Risk Criteria |
| u_current_likelihood | Reference | Risk Criteria |
| u_current_score | Reference | Risk 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 Overviewwidget and rename toCustom Risk Overview. - Add a new tab named “Current Scoring”
- Click on
Savebutton 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 Heatmapwidget by clickingInsert and Staymenu action. - Name: Current Risk Heatmap
- Click on
Savebutton to save the change.
Script
- Copy and paste below
Scriptin 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_heatmapUI page by clickingInsert and Staymenu action. - Name: current_heatmap
- Click on
Savebutton to save the change.
Endpoint
- Copy and paste below
Endpointin UI page section
sn_risk_current_heatmap.do
Body HTML template
- Copy and paste below
HTML Codein 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 Scriptin Processing Script Section
// empty
- Click on
Savebutton 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
Scriptin 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
Savebutton 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
Scriptin 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
Savebutton 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.

