P-Rudenko-SN
ServiceNow Employee
ServiceNow Employee

Dear Community,

I've recently faced a requirement to develop the custom risk assessment for the change request in addition to the standard one. The point is to create a new field (let's call it 'Security Risk'), that must be populated based on the answers to the custom risk assessment. Similar questions were earlier raised on Community, however, I could not find a clear and detailed solution, therefore decided to post mine here, which might be helpful for others in the future. This implementation is specifically done for the change management, but the same approach can be applied for any other task record and field. 

The following elements were created/modified:

1) Custom Survey ('asmt_metric_type' record + metric category + assessment metrics (questions) + assessment metric definitions (answer options))

2) UI Action to run the custom security risk assessment (survey)

Name: Fill Out Security Risk Assessment

Condition: new Custom_SecChgRisk().checkAsmt(current.sys_id) && current.state == '-4' && current.u_security_classification != '' && current.type !== 'standard' (when the assessment is complete, I don't need the UI action to be shown)

var typeSysID = gs.getProperty('custom.asmt.sys_id'); //sys_id of custom survey to be called 
var createAssessmentOutput = (new SNC.AssessmentCreation()).createAssessments(typeSysID , '', gs.getUserID());
var assessmentDetailsArray = createAssessmentOutput.split(',');
var assessmentInstanceSysId = assessmentDetailsArray[0];
if (assessmentDetailsArray.length >= 3) {

   var grAsmtInstance = new GlideRecord('asmt_assessment_instance');
       grAsmtInstance.get(createAssessmentOutput.split(",")[0]);
       grAsmtInstance.trigger_table = current.getTableName();
       grAsmtInstance.task_id = current.getValue('sys_id'); 
       grAsmtInstance.trigger_id = current.getValue('sys_id');
       grAsmtInstance.update();
   
   var url = '/assessment_take3.do?sysparm_assessable_type=' + typeSysID;
   action.setRedirectURL(url);

}

3) Script include to check whether the assessment is complete (required for the UI action condition):

(function executeRule(current, previous /*null when async*/) {

var grAsmtRes = new GlideRecord('asmt_metric_result');
var score = 0;
grAsmtRes.addQuery('instance', current.sys_id);
grAsmtRes.query();
while(grAsmtRes.next()){		
           score += parseFloat(grAsmtRes.getValue('actual_value')); //'actual_value' is a decimal field
	}
 var grChg = new GlideRecord('change_request');
     grChg.addQuery('sys_id', current.task_id);
     grChg.query();
  if(grChg.next()){
     //defining the risk calculation
     //I've created the system properties of score for medium and major risk (in my case it's 14 and 24)
	if(score <= gs.getProperty('custom.asmt.risk_med')) grChg.setValue('u_security_risk', 'Minor');
        if((score <= gs.getProperty('custom.asmt.risk_maj')) && (score > gs.getProperty('custom.asmt.risk_med')))  grChg.setValue('u_security_risk', 'Medium'); 
        if(score > gs.getProperty('custom.asmt.risk_maj')) grChg.setValue('u_security_risk', 'Major');
           grChg.update();
		}		
	
})(current, previous);

4) Business Rule to calculate the assessment score and populate the custom risk field based on it.

Table: asmt_assessment_instance

Insert and Update

When: after (as we need to make sure all the related answers are inserted)

Filter conditions: {Metric Type} IS {Your custom Survey}

                         {State} IS {Complete}

                         {Percent answered} IS {100}

(function executeRule(current, previous /*null when async*/) {

	var grAsmtRes = new GlideRecord('asmt_metric_result');
	var score = 0;
	grAsmtRes.addQuery('instance', current.sys_id);
	grAsmtRes.query();
	while(grAsmtRes.next()){		
		score += parseFloat(grAsmtRes.getValue('actual_value')); //decided to use 'parseFloat' as 'actual_value' is a decimal field
	}
	var grChg = new GlideRecord('change_request');
	    grChg.addQuery('sys_id', current.task_id);
	    grChg.query();
	 if(grChg.next()){
//defining the risk calculation 
//I've created the system properties of score for medium and major risk (in my case it's 14 and 24) for better maintainability
	    
         if(score <= gs.getProperty('custom.asmt.risk_med')) grChg.setValue('u_security_risk', 'Minor');
         if((score <= gs.getProperty('custom.asmt.risk_maj')) && (score > gs.getProperty('custom.asmt.risk_med'))) grChg.setValue('u_security_risk', 'Medium'); 
         if(score > gs.getProperty('custom.asmt.risk_maj')) grChg.setValue('u_security_risk', 'Major');
         grChg.update();
						
		}		
	
})(current, previous);

5) Custom UI Page: after the assessment answers are submitted, I need the user to be redirected to the current change record, therefore I had to do some tiny adjustments to the 'assessment_take2' UI page processing script. Again for better maintainability I copied this page and named the new one as 'assessment_take3' (Captain Obvious here :)). The following code was adjusted for the processing script (lines 259-274):

var type = new GlideRecord("asmt_metric_type");
    type.get(type_sysID);
var inst = new GlideRecord("asmt_assessment_instance");
    inst.get(instance_sysID);
var chgID = inst.task_id;

var url = ''; 
    if(typeof sysparm_return_url!== 'undefined')
	url = GlideStringUtil.unEscapeHTML(sysparm_return_url);
	if (selection_result == 'submit') {
	    if (type.url != '')
		url = type.url;
	         else if (url == '') {
		  url = '/change_request.do?sys_id=' + chgID;
		}
	}

This is pretty much it. I hope the solution will be helpful to anyone who would have a similar requirement. At the same time, I'm happy to see any suggestions on how to improve it. Many thanks!

 

Regards,

Pavlo

Comments
Petal Lobban1
Tera Explorer

could you provide the script include; it appears to be the BR.

HK11
Tera Contributor

Hi there, can you please help with condition to achieve below on a change form?

 

We want to hide the Request for Approval UI Button until Risk Assessment for that change is completed.

If Risk Assessment was completed then display the Request For Approval UI button.

 

Thanks

Hiren

 

 

nishakumari1
Tera Contributor

can you please provide script include. In place of script include you have shared BR.

Version history
Last update:
‎03-15-2021 08:35 AM
Updated by: