logo

NJP

Create Current Scoring for Risk Management

NOWJedi · Feb 04, 2024 · article

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 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" ?>


<br> <style><br> #currentRiskHighChartContainer text tspan {<br> stroke-width: 1px;<br> }<br> </style></p> <pre><code>&lt;g2:evaluate var=&quot;jvar_riskHighChartData&quot;&gt; var risk = new sn_risk.RiskHeatmap().getRiskHeatmapData(&#39;current&#39;, &#39;&#39;, true); new global.JSON().encode(risk); &lt;/g2:evaluate&gt; &lt;g2:evaluate var=&quot;jvar_riskXAxisCategories&quot;&gt; var xAxis = new sn_risk.RiskHeatmap().getRiskHeatmapXAxisCategories(); new global.JSON().encode(xAxis); &lt;/g2:evaluate&gt; &lt;g2:evaluate var=&quot;jvar_riskYAxisCategories&quot;&gt; var yAxis = new sn_risk.RiskHeatmap().getRiskHeatmapYAxisCategories(); new global.JSON().encode(yAxis); &lt;/g2:evaluate&gt; &lt;div id=&quot;currentRiskHighChartContainer&quot; name=&quot;currentRiskHighChartContainer&quot; style=&quot;min-width: 310px; height: 400px; max-width: 600px; margin: 0 auto&quot;&gt; &lt;/div&gt; </code></pre> <p><a href="/j:jelly" target="_blank" rel="noopener">/j:jelly</a></p> <p><u><strong>Client script</strong></u></p> <ul> <li>Copy and Paste below script in Client Script Section</li> </ul> <p>(function($){<br> var chart;</p> <pre><code>chart = new Highcharts.Chart({ chart: { renderTo: &quot;currentRiskHighChartContainer&quot;, type: &#39;heatmap&#39;, marginTop: 12, marginBottom: 60, plotBackgroundColor: &#39;none&#39;, 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:&#39;center&#39;, text: &#39;&#39;, style: { color: &#39;black&#39;, fontSize: &#39;12pt&#39; } }, xAxis: { categories: JSON.parse(&#39;$[HTML, JS:jvar_riskXAxisCategories]&#39;), title: { enabled: true, text: &#39;&lt;span&gt;Impact&lt;/span&gt;&#39; } }, yAxis: { categories: JSON.parse(&#39;$[HTML, JS:jvar_riskYAxisCategories]&#39;), title: { enabled: true, text: &#39;&lt;span&gt;Likelihood&lt;/span&gt;&#39; } }, tooltip: { formatter: function () { var msg = new GwtMessage().getMessage(&#39;Count: {0}&#39;, this.point.value) + &#39;&lt;br&gt;&#39; + new GwtMessage().getMessage(&#39;Impact: {0}&#39;, this.series.yAxis.categories[this.point.y]) + &#39;&lt;br&gt;&#39; + new GwtMessage().getMessage(&#39;Likelihood: {0}&#39;, this.series.xAxis.categories[this.point.x]); return msg; } }, credits: { enabled: false }, /*want to make this part dynamically populated*/ series:[{ data:[], cursor: &#39;pointer&#39;, showInLegend: false, dataLabels: { enabled: true, color: &#39;black&#39;, type: &#39;heatmap&#39;, backgroundColor: &#39;none&#39;, style: { textShadow: &#39;none&#39; } } }] }); sn_risk.RiskHeatmapUtils.updateHeatmap(chart, &#39;current&#39;, true); CustomEvent.on(&#39;dashboard_filter.removed&#39;, function(filterMessage){ sn_risk.RiskHeatmapUtils.onRemoveEvent(chart, filterMessage, &#39;current&#39;, true); }); CustomEvent.on(&#39;dashboard_filter.added&#39;, function(filterMessage){ sn_risk.RiskHeatmapUtils.onAddEvent(chart, filterMessage, &#39;current&#39;, true); }); </code></pre> <p>})(jQuery);</p> <p><u><strong>Processing Script</strong></u></p> <ul> <li>Copy and Paste below <code>Server-Side Script</code> in Processing Script Section</li> </ul> <p>// empty</p> <ul> <li>Click on <code>Save</code> button to save the change.</li> </ul> <h2>Step 5: Scripting – Edit RiskHeatMap<a href="https://gist.github.com/rafzk/40a819bed8950c6233364aa6232f6a77#step-5-scripting---edit-riskheatmap" target="_blank" rel="noopener"></a></h2> <p><u><strong>Go to System Definition &gt; Script Include</strong></u></p> <ul> <li>Search for <code>RiskHeatMap</code>and open the record.</li> <li>Copy and Paste below <code>Script</code> in Script Include Script Section</li> </ul> <p>var RiskHeatmap = Class.create();<br> RiskHeatmap.prototype = Object.extendsObject(RiskHeatmapBase, {</p> <pre><code>// Overwrite current method to include current as heatmapType _getRiskHeatmapData: function(heatmapType, filter, includeColor){ var riskData = []; var riskImpactFieldName = &#39;&#39;; var riskLikelihoodFieldName = &#39;&#39;; if (heatmapType == &#39;inherent&#39;){ riskImpactFieldName = &#39;impact&#39;; riskLikelihoodFieldName = &#39;likelihood&#39;; } else if(heatmapType == &#39;residual&#39;){ riskImpactFieldName = &#39;residual_impact&#39;; riskLikelihoodFieldName = &#39;residual_likelihood&#39;; } else if(heatmapType == &#39;current&#39;){ riskImpactFieldName = &#39;u_current_impact&#39;; riskLikelihoodFieldName = &#39;u_current_likelihood&#39;; } else return riskData; var likelihood = new GlideRecord(&#39;sn_risk_criteria&#39;); likelihood.addQuery(&#39;type&#39;, &#39;likelihood&#39;); likelihood.orderByDesc(&#39;order&#39;); likelihood.query(); for(var i = 0; i &lt; likelihood.getRowCount(); i++){ likelihood.next(); var impact = new GlideRecord(&#39;sn_risk_criteria&#39;); impact.addQuery(&#39;type&#39;, &#39;impact&#39;); impact.orderByDesc(&#39;order&#39;); impact.query(); for(var j = 0; j &lt; impact.getRowCount(); j++){ impact.next(); var risk = new GlideAggregate(&#39;sn_risk_risk&#39;); var count = 0; risk.addQuery(riskImpactFieldName, impact.getUniqueValue()); risk.addQuery(riskLikelihoodFieldName, likelihood.getUniqueValue()); if (filter) risk.addEncodedQuery(filter); risk.addAggregate(&#39;COUNT&#39;); risk.query(); if (risk.next()) count = risk.getAggregate(&#39;COUNT&#39;); var riskColor = this._getRiskColor(impact.getUniqueValue(), likelihood.getUniqueValue()); var riskUrl = &#39;sn_risk_risk_list.do?sysparm_query=&#39; + riskImpactFieldName + &#39;%3D&#39; + impact.getUniqueValue() + &#39;%5E&#39; + riskLikelihoodFieldName + &#39;%3D&#39; + likelihood.getUniqueValue(); if (filter) riskUrl += &#39;%5E&#39; + 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: &#39;RiskHeatmap&#39; </code></pre> <p>});</p> <ul> <li>Click on <code>Save</code> button to save the change.</li> </ul> <h2>Step 6: Scripting – Create new RiskFormUtils<a href="https://gist.github.com/rafzk/40a819bed8950c6233364aa6232f6a77#step-6-scripting---create-new-riskformutils" target="_blank" rel="noopener"></a></h2> <p><u><strong>Go to System UI &gt; UI Scripts &gt; Click New</strong></u></p> <ul> <li>Id: WR_RiskFormUtilsV2</li> <li>Copy and Paste below <code>Script</code> in UI Script Script Section</li> </ul> <p>var sn_risk = sn_risk || {};</p> <p>sn_risk.WR_RiskFormUtilsV2 = (function() {<br> &quot;use strict&quot;;</p> <p>return {</p> <pre><code>calculateALE: function(currency) { var resALE = g_form.getValue(&#39;sys_readonly.sn_risk_risk.residual_ale&#39;); var inALE = g_form.getValue(&#39;sys_readonly.sn_risk_risk.inherent_ale&#39;); var ccr = g_form.getValue(&#39;calculated_risk_factor&#39;); resALE = parseFloat(resALE.replace(/[^\d\.]/g,&#39;&#39;)); inALE = parseFloat(inALE.replace(/[^\d\.]/g,&#39;&#39;)); var calcALE = parseFloat(resALE + ((inALE - resALE) * (ccr / 100))); calcALE = calcALE.toFixed(2); calcALE = currency + calcALE; g_form.setValue(&#39;calculated_ale&#39;, calcALE.toString()); }, synchSymbol: function(fromSLE, toSLE, tableName){ var toSLESymbol = g_form.getValue(toSLE + &#39;.currency&#39;); var fromSLESymbol = g_form.getValue(fromSLE + &#39;.currency&#39;); if (toSLESymbol == fromSLESymbol) return; var val = g_form.getValue(toSLE + &#39;.display&#39;); // Strip any special characters in the value val = val.replace(new RegExp(g_user_grouping_separator, &quot;g&quot;), &quot;&quot;); var newSLEVal = fromSLESymbol + &#39;;&#39; + val; g_form.setValue(toSLE + &quot;.currency&quot;, fromSLESymbol); g_form.setValue(toSLE + &quot;.display&quot;, val); g_form.setValue(toSLE, newSLEVal); var id = tableName + &#39;.&#39; + 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&#39;t save the currenct var sleElement= document.getElementById(id); sleElement.value = newSLEVal; }, hideQualitativeFields: function(hideQualitativeFields) { var fieldsToHide = []; if (hideQualitativeFields) { fieldsToHide = [&#39;significance&#39;, &#39;residual_significance&#39;, &#39;likelihood&#39;, &#39;residual_likelihood&#39;, &#39;score&#39;, &#39;residual_score&#39;, &#39;calculated_score&#39; ]; } else { fieldsToHide = [&#39;inherent_sle&#39;, &#39;residual_sle&#39;, &#39;inherent_aro&#39;, &#39;residual_aro&#39;, &#39;inherent_ale&#39;, &#39;residual_ale&#39;, &#39;calculated_ale&#39;, &#39;default_inherent_sle&#39;, &#39;default_residual_sle&#39;, &#39;default_inherent_aro&#39;, &#39;default_residual_aro&#39; ]; } for (var i = 0; i &lt; fieldsToHide.length; i++) g_form.setDisplay(fieldsToHide[i], false); },   updateRiskScore: function(scoreType, fieldName, fieldType, value) {             var setFieldName, impactField, likelihooField;             var ga = new GlideAjax(&#39;RiskUtilsAJAXV2&#39;);             switch(fieldName) {                 case &#39;u_current_impact&#39;:                     setFieldName = &#39;u_current_sle&#39;;                     ga.addParam(&#39;sysparm_name&#39;, &#39;usingQualitative&#39;);                     ga.addParam(&#39;sysparm_prop_name&#39;, &#39;sn_risk.qualitative_impact&#39;);                     ga.getXML(setFields);                     break;                 case &#39;u_current_likelihood&#39;:                     setFieldName = &#39;u_current_aro&#39;;                     ga.addParam(&#39;sysparm_name&#39;, &#39;usingQualitative&#39;);                     ga.addParam(&#39;sysparm_prop_name&#39;, &#39;sn_risk.qualitative_likelihood&#39;);                     ga.getXML(setFields);             }             function setFields(response) {                 var answer = response.responseXML.documentElement.getAttribute(&quot;answer&quot;);                 if(answer == &#39;true&#39;) {                     ga = new GlideAjax(&#39;RiskUtilsAJAXV2&#39;);                     ga.addParam(&#39;sysparm_name&#39;, &#39;getRiskCriteria&#39;);                     ga.addParam(&#39;sysparm_field_type&#39;, fieldType);                     ga.addParam(&#39;sysparm_field_value&#39;, value);                     ga.getXMLAnswer(function(answer) {                         if(answer != false || answer == &#39;0&#39;)                             g_form.setValue(setFieldName, answer);                     });                     ga = new GlideAjax(&#39;RiskUtilsAJAXV2&#39;);                     ga.addParam(&#39;sysparm_name&#39;, &#39;getRiskScore&#39;);                     ga.addParam(&#39;sysparm_impact&#39;, g_form.getValue(&#39;u_current_impact&#39;));                     ga.addParam(&#39;sysparm_likelihood&#39;, g_form.getValue(&#39;u_current_likelihood&#39;));                     ga.getXMLAnswer(function(answer) {                         g_form.setValue(&#39;u_current_score&#39;, answer);                     });                 }             }         }, useQualitativeImpact: function(useQualitativeImpact) { jslog(&quot;Calling use qualitative impact &quot; + useQualitativeImpact); if(useQualitativeImpact) { g_form.setDisplay(&#39;inherent_sle&#39;, false); g_form.setDisplay(&#39;residual_sle&#39;, false); g_form.setDisplay(&#39;default_inherent_sle&#39;, false); g_form.setDisplay(&#39;default_residual_sle&#39;, false); } else { g_form.setDisplay(&#39;impact&#39;, false); g_form.setDisplay(&#39;residual_impact&#39;, false); } }, useQualitativeLikelihood: function(useQualitativeLikelihood) { jslog(&quot;Calling use qualitative likelihood &quot; + useQualitativeLikelihood); if(useQualitativeLikelihood) { g_form.setDisplay(&#39;inherent_aro&#39;, false); g_form.setDisplay(&#39;residual_aro&#39;, false); g_form.setDisplay(&#39;default_inherent_aro&#39;, false); g_form.setDisplay(&#39;default_residual_aro&#39;, false); } else { g_form.setDisplay(&#39;likelihood&#39;, false); g_form.setDisplay(&#39;residual_likelihood&#39;, false); } }, validateRisk: function(fieldType) { jslog(&quot;Started: &quot; + fieldType); fieldType = fieldType + &#39;&#39;; var isDefault = false; var fieldArr = fieldType.split(&#39;_&#39;); if(fieldArr[0] == &#39;default&#39;) isDefault = true; var inherentField; var residualField; var inherent; var residual; switch(fieldType) { case &#39;likelihood&#39;: case &#39;impact&#39;: residualField = &#39;residual_&#39; + fieldType; inherentField = fieldType; setQualitativeValues(inherentField, residualField); break; case &#39;residual_likelihood&#39;: case &#39;residual_impact&#39;: residualField = fieldType; inherentField = fieldArr[1]; setQualitativeValues(inherentField, residualField); break; case &#39;default_inherent_sle&#39;: case &#39;inherent_sle&#39;: setInherentQuantitativeValues(fieldType, fieldArr); setQuantitativeValues(inherentField, residualField); doCheck(); break; case &#39;default_inherent_aro&#39;: case &#39;inherent_aro&#39;: setInherentQuantitativeValues(fieldType, fieldArr); setAROValues(inherentField, residualField); break; case &#39;default_residual_sle&#39;: case &#39;residual_sle&#39;: setResidualQuantitativeValues(fieldType, fieldArr); setQuantitativeValues(inherentField, residualField); doCheck(); break; case &#39;default_residual_aro&#39;: case &#39;residual_aro&#39;: 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 = &#39;default_residual_&#39; + fieldArr[2]; else residualField = &#39;residual_&#39; + fieldArr[1]; hideErrorBoxes(inherentField, residualField); } function setResidualQuantitativeValues(fieldType, fieldArr) { if(isDefault) inherentField = &#39;default_inherent_&#39; + fieldArr[2]; else inherentField = &#39;inherent_&#39; + fieldArr[1]; residualField = fieldType; hideErrorBoxes(inherentField, residualField); } function setQuantitativeValues(inherentField, residualField) { var rawInherent = g_form.getValue(inherentField); var inherentArray = rawInherent.split(&#39;;&#39;); inherent = parseFloat(inherentArray[1].replace(/,/g , &#39;&#39;)); var rawResidual = g_form.getValue(residualField); var residualArray = rawResidual.split(&#39;;&#39;); residual = parseFloat(residualArray[1].replace(/,/g , &#39;&#39;)); } function setQualitativeValues(inherentField, residualField) { hideErrorBoxes(inherentField, residualField); inherent = false; residual = false; if(g_form.getValue(inherentField) == &#39;&#39;) { 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 == &#39;likelihood&#39;) inherent = criteria.percentage_max_value; else inherent = parseInt(criteria.currency_max_value); doCheck(); } function setResidual(criteria) { if(criteria.type == &#39;likelihood&#39;) residual = criteria.percentage_max_value; else residual = parseInt(criteria.currency_max_value); doCheck(); } function doCheck() { if(inherent !== false &amp;&amp; residual !== false &amp;&amp; (parseFloat(residual)) &gt; parseFloat(inherent)) { switch(fieldType) { case &#39;likelihood&#39; : g_form.showErrorBox(inherentField,getMessage(&#39;sn_risk_likelihood_inherent_lower_than_residual&#39;)); break; case &#39;residual_likelihood&#39; : g_form.showErrorBox(residualField,getMessage(&#39;sn_risk_likelihood_residual_higher_than_inherent&#39;)); break; case &#39;impact&#39; : g_form.showErrorBox(inherentField,getMessage(&#39;sn_risk_impact_inherent_lower_than_residual&#39;)); break; case &#39;residual_impact&#39; : g_form.showErrorBox(residualField,getMessage(&#39;sn_risk_impact_residual_higher_than_inherent&#39;)); break; case &#39;inherent_sle&#39; : g_form.showErrorBox(&#39;inherent_sle&#39;, getMessage(&#39;sn_risk_sle_inherent_lower_than_residual&#39;)); break; case &#39;default_inherent_sle&#39; : g_form.showErrorBox(&#39;default_inherent_sle&#39;, getMessage(&#39;sn_risk_sle_inherent_lower_than_residual&#39;)); break; case &#39;residual_sle&#39; : g_form.showErrorBox(&#39;residual_sle&#39;, getMessage(&#39;sn_risk_sle_residual_higher_than_inherent&#39;)); break; case &#39;default_residual_sle&#39; : g_form.showErrorBox(&#39;default_residual_sle&#39;, getMessage(&#39;sn_risk_sle_residual_higher_than_inherent&#39;)); break; case &#39;inherent_aro&#39; : g_form.showErrorBox(&#39;inherent_aro&#39;, getMessage(&#39;sn_risk_aro_inherent_lower_than_residual&#39;)); break; case &#39;default_inherent_aro&#39; : g_form.showErrorBox(&#39;default_inherent_aro&#39;, getMessage(&#39;sn_risk_aro_inherent_lower_than_residual&#39;)); break; case &#39;residual_aro&#39; : g_form.showErrorBox(&#39;residual_aro&#39;, getMessage(&#39;sn_risk_aro_residual_higher_than_inherent&#39;)); break; case &#39;default_residual_aro&#39; : g_form.showErrorBox(&#39;default_residual_aro&#39;, getMessage(&#39;sn_risk_aro_residual_higher_than_inherent&#39;)); break; } return false; } else return true; } }, type: &#39;WR_RiskFormUtilsV2&#39; </code></pre> <p>};<br> })();</p> <ul> <li>Click on <code>Save</code> button to save the change.</li> </ul> <h2>Step 7: Edit Custom Risk Overview dashboard</h2> <p><a href="https://gist.github.com/rafzk/40a819bed8950c6233364aa6232f6a77#step-7-edit-custom-risk-overview-dashboard" target="_blank" rel="noopener"></a></p> <p><u><strong>Go to Service Portal &gt; Page &gt; Click New</strong></u></p> <p>Adapt the dashboard according to your taste.<a href="https://gist.github.com/rafzk/40a819bed8950c6233364aa6232f6a77#create-current-scoring-for-risk-management" target="_blank" rel="noopener"></a></p> <p>Search for <code>Custom Risk Overview</code> dashboard.</p> <p>In the “Current Scoring” tab search for widget current and add to the dashboard.</p> <p>The post <a href="https://nowjedi.com/2024/02/04/create-current-scoring-for-risk-management/" target="_blank" rel="noopener">Create Current Scoring for Risk Management</a> appeared first on <a href="https://nowjedi.com" target="_blank" rel="noopener">NOWJedi</a>.</p>

View original source

https://nowjedi.com/2024/02/04/create-current-scoring-for-risk-management/