Validating Before Update Business Rules with UI Action

Output:


I want to share my experience related to a specific business requirement in ServiceNow HR.
To complete any HR task, you expect the "Effective Date" to be populated first. For such cases, we typically write a "Before Update" business rule with current.setAbort(true);

The HR Task table has an out-of-the-box UI action called "Closed Complete" However, if you have any "Before Update" business rules to validate specific conditions, this out-of-the-box UI action will validate the business rules, but it will not show any error messages.

To provide a practical example, let’s assume an "Effective Date" field exists in the HR case.

To ensure that the "Closed Complete" button validates all business rules before proceeding with the form update, I customized the UI action "Closed Complete." The customized action will evaluate all the business rules, and if they pass, it will proceed with the update; otherwise, it will display errors from the rules.

A. Here is a Business Rule validation example:




B. Here is my customized "Closed Complete" UI action script:

function closeComplete() {
var sysId = typeof rowSysId == 'undefined' || rowSysId == null ? g_form.getUniqueValue() : rowSysId;
/* Customization Starts Here */
/* Purpose: Validate the Before Update Business Rules First */
validateAndSubmit();
function validateAndSubmit() {
// Check if form validation flag is already set to true, if yes, allow submission
if (g_scratchpad.isFormValid) {
return true;
}
var ga = new GlideAjax('sn_hr_core.positionUtils');
ga.addParam('sysparm_name', 'validateTask');
ga.addParam('sys_id', sysId);
ga.getXMLAnswer(function(response) {
console.log('HR Task Validation Response ----'+response);
if (response != 'pass') {
g_scratchpad.isFormValid = false;
return false;
} else {
g_scratchpad.isFormValid = true;
showModalDialog();
}
});
return false; // Prevent default form submission
}
/* Customization Ends Here */
function showModalDialog() { //Custom
//OOB Code (Out of the box):
ScriptLoader.getScripts('sn_hr_core.utils_ui.jsdbx', function() {
getGlideRecord("sn_hr_core_task", sysId, promptDialog);
});
function promptDialog(taskGr) {
var dialogClass = GlideModal ? GlideModal : GlideDialogWindow;
var dialog = new dialogClass('sn_hr_core_HR Task Comment Dialog');
dialog.setTitle(getMessage('Provide a summary of the work performed'));
dialog.setPreference('sysparm_task_sys_id', sysId);
dialog.setPreference('sysparm_ok_method_name', 'closeCompleteTask');
dialog.setPreference('sysparm_is_comment', 'false');
dialog.setPreference('sysparm_task_table', 'sn_hr_core_task');
dialog.on('hrTaskComentDialogSucess', function() {
dialog.destroy();
gsftSubmit(null, g_form.getFormElement(), 'sysverb_update');
});
dialog.render();
return;
}
}
}

//OOB Code (Out of the box)
if (typeof window == 'undefined')
serverClose();

//OOB Code (Out of the box)
function serverClose() {
if (current.work_end.nil())
current.work_end = new GlideDateTime().getDisplayValue();
current.state = 3;
current.update();
action.setRedirectURL(current);
}


C. Here is my newly written script to include:
The method to evaluate business rules when the "Closed Complete" action is triggered:


var positionUtils = Class.create();
positionUtils.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
validateTask: function() {
var result = 'pass'; // Default to 'pass'
var hasFalseEvaluatorResult = false; // Flag to track if any evaluator result is false
var sysId = this.getParameter('sys_id');
var grHRTask = new GlideRecord('sn_hr_core_task');
if (grHRTask.get(sysId)) {
var errors = [];
var brs = new GlideRecord('sys_script');
brs.addEncodedQuery("active=true^collection=sn_hr_core_task^when=before^action_update=true^filter_conditionLIKEstateCHANGESTO3");
brs.query();
while (brs.next()) {
// gs.info('Business Rule Validation----' + brs.getValue('name'));
try {

var script = brs.script;
// gs.info(script);

var evaluator = new GlideScopedEvaluator();
evaluator.putVariable('current', grHRTask);
var evaluatorResult = evaluator.evaluateScript(brs, 'script', script);
gs.info('Business Rule' + brs.getValue('name') + 'Validation Result-----' + evaluatorResult);
if (evaluatorResult == 'false') { // Check if the evaluator result is false
hasFalseEvaluatorResult = true;
}
} catch (e) {
errors.push(e.message);
}
}
if (errors.length > 0) {
result = errors.join(', ');
}
}
gs.info('hasFalseEvaluatorResult------' + hasFalseEvaluatorResult)

// Set the final result based on the flag
if (hasFalseEvaluatorResult) {
result = 'fail';
}
return result;
},
type: 'positionUtils'
});