- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-06-2025 10:22 PM
Dear experts,
My client would like to have a bulk attest button just like the bulk approve button in the approval table where they can select multiple records in the list then in the list menu they have an approve button to approve all the things required in servicenow. So their requirements are without going into the attestation form and fill in the attestation form which only have two fields
1. Is the control implemented (Yes or No) - Mandatory
2. Explanation
They would like to have the ui action in the list menu which is approve where when click approve it will help them fill in the first question is yes and the explanation field is just leave it blank then changed the state of attestation form to complete. I have tried my own approach to create a new approve ui action list menu and a script include below:
UI Action Script:
function onBulkApprove() {
var selectedRecords = g_list.getChecked();
if (selectedRecords.length === 0) {
alert("Please select at least one record.");
return;
}
var ga = new GlideAjax('global.BulkAttestationProcessor');
ga.addParam('sysparm_name', 'processBulkAttestation');
ga.addParam('sysparm_sys_ids', selectedRecords.join(','));
ga.getXMLAnswer(function(response) {
alert(response); // Show confirmation
g_list.refresh(); // Refresh list
});
}
Script Include:
var BulkAttestationProcessor = Class.create();
BulkAttestationProcessor.prototype = Object.extendsObject(AbstractAjaxProcessor, {
processBulkAttestation: function() {
var sysIds = this.getParameter('sysparm_sys_ids').split(',');
var count = 0;
// Get the metric sys_id for the "Is the control implemented?" question
var metricGr = new GlideRecord('asmt_metric');
metricGr.addQuery('name', 'Is the control implemented?');
metricGr.query();
if (!metricGr.next()) {
return 'Metric "Is the control implemented?" not found.';
}
var metricSysId = metricGr.getUniqueValue();
for (var i = 0; i < sysIds.length; i++) {
var instanceId = sysIds[i];
var instanceGr = new GlideRecord('asmt_assessment_instance');
if (!instanceGr.get(instanceId)) continue;
// Check if metric result already exists
var resultGr = new GlideRecord('asmt_metric_result');
resultGr.addQuery('metric', metricSysId);
resultGr.addQuery('instance', instanceId);
resultGr.query();
var resultExists = false;
while (resultGr.next()) {
resultExists = true;
resultGr.setValue('actual_value', 1);
resultGr.update();
count++;
}
// If no result exists, create one manually
if (!resultExists) {
var newResult = new GlideRecord('asmt_metric_result');
newResult.initialize();
newResult.setValue('metric', metricSysId);
newResult.setValue('instance', instanceId);
newResult.setValue('actual_value', 1);
newResult.insert();
count++;
}
// Mark the instance as complete
instanceGr.setValue('state', 'complete');
instanceGr.update();
}
return count + " attestation(s) approved.";
}
});
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-06-2025 11:48 PM
Hi @ChuanYanF
You need to set the survey reponse in "asmt_assessment_instance_question" table.
I've modified your script and tested it in my PDI. It's working as expected. Please review and modify as required.
UI action:
function onBulkApprove() {
var selectedRecords = g_list.getChecked();
if (selectedRecords.length === 0) {
alert("Please select at least one record.");
return;
} else {
var ga = new GlideAjax('BulkAttestationProcessor');
ga.addParam('sysparm_name', 'processBulkAttestation');
ga.addParam('sysparm_sys_ids', selectedRecords);
ga.getXMLAnswer(function(response) {
alert(response); // Show confirmation
g_list.refresh(); // Refresh list
});
}
}
Script include:
var BulkAttestationProcessor = Class.create();
BulkAttestationProcessor.prototype = Object.extendsObject(AbstractAjaxProcessor, {
processBulkAttestation: function() {
var sysIds = this.getParameter('sysparm_sys_ids').split(',');
var count = 0;
// Get the metric sys_id for the "Is the control implemented?" question
var metricGr = new GlideRecord('asmt_metric');
metricGr.addQuery('name', 'Is the control implemented?');
metricGr.query();
if (!metricGr.next()) {
return 'Metric "Is the control implemented?" not found.';
} else {
var metricSysId = metricGr.getUniqueValue();
}
for (var i = 0; i < sysIds.length; i++) {
var instanceId = sysIds[i];
var instanceGr = new GlideRecord('asmt_assessment_instance');
if (!instanceGr.get(instanceId)) continue;
// Check if metric result already exists
var resultGr = new GlideRecord('asmt_assessment_instance_question'); //UPDATED
resultGr.addQuery('metric', metricSysId);
resultGr.addQuery('instance', instanceId);
resultGr.query();
var resultExists = false;
while (resultGr.next()) {
resultExists = true;
resultGr.setValue('value', 1);
resultGr.update();
count++;
}
// Mark the instance as complete
instanceGr.setValue('state', 'complete');
instanceGr.update();
}
return count + " attestation(s) approved.";
},
type: 'BulkAttestationProcessor'
});
Regards,
Siva
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-07-2025 12:54 AM
ensure UI action and script both are in GRC scope
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-07-2025 12:59 AM
Hi Ankur,
I have recreated the script include and the ui action both in scope grc but this error still appears:
Error MessageAbstractAjaxProcessor undefined, maybe missing global qualifier