Scripted Audit Creating the Same Task Multiple Times
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎04-26-2023 04:28 PM
Hello all. I have a scripted audit where it records service offerings for compliance, and in the code below, it checks whether the Business Contact field of the TSO is valid and if the user is active.
One of my requirements is to create a task where if the audit result is failed, I am to create a task for that audit.
I've added the following code before the certification processing of the audit:
var followOnTask = new SNC.CertificationProcessing().createFollowOnTask(current.sys_id, sysId, assignToUser, '', taskMsg);
but the problem is that this code would generate the same task every time the audit has been ran.
Is there a way I could manipulate the code to make it so that they won't have to create a duplicate task when it is already generated and still in open state?
I've tried one of the system properties that the documentation mentioned to set to false to prohibit the creation of the same task, but it didn't work.
This is just a part of the scripted audit for reference.
var certProcessor;
if (gs.getCurrentScopeName().includes("global"))
certProcessor = new SNC.CertificationProcessing();
else {
certProcessor = new CertificationProcessing();
}
// API call to retrieve records based on the filter
var gr = new SNC.CertificationProcessing().getFilterRecords(current.filter);
// Loop over all records defined by the filter
while (gr.next()) {
var pass = true;
var columnNameSpace = '';
var hasAvailability = false;
var userGr = new GlideRecord('sys_user');
var soCommitmentGr = new GlideRecord('service_offering_commitment');
var sysId = gr.getValue('sys_id'); // Sys ID of audited record
var businessContact = gr.getValue('business_contact'); //is not null or blank and user is active
var serviceOwner = gr.getValue('owned_by'); //is not null or blank and user is active
var serviceManager = gr.getValue('managed_by'); //is not null or blank and user is active
var deliveryOwner = gr.getValue('delivery_manager'); //is not null or blank and user is active
var primaryContact = gr.getValue('supported_by'); //is not null or blank and user is active
var primarySPG = gr.getValue('support_group'); //is not null or blank
var platformName = gr.getValue('u_es_organisational_platform'); //is not null or blank
var description = gr.getValue('description'); //at least 15 characters
var approvalGroup = gr.getValue('change_control'); //is not null or blank
var environment = gr.getValue('environment'); //is not null or blank
var arcAvailabilityTier = gr.getValue('u_cba_availability_tier'); //is not null or blank
var arcRecoverabilityTier = gr.getValue('u_cba_arc_recoverability_tier'); //is not null or blank
var arcCyberSecurityTier = gr.getValue('u_cba_cyber_security_tier'); //is not null or blank
var arcOverallTier = gr.getValue('u_cba_overall_tier'); //is not null or blank
var costcenter = gr.getValue('cost_center'); //is not null or blank
var company = gr.getValue('company'); //is not null or blank
var availability = ''; //Service comitment record exists of type 'Availability' and is not empty
// Determine if businessContact not null or blank and user is active
if (!businessContact) {
columnNameSpace = gr.business_contact.getLabel(); // String value of column audited against
// Call log failed result API
// Params:
// auditId - Sys id of audit record executed
// auditedRecordId - Sys id of the record audited
// followOnTask - Sys id of the follow on task associated with the audited record(@see auditedRecordId). Can be empty
// columnDisplayName - Label of the column audited(ex. Disk space (GB)). Can be empty
// operatorLabel - Label of the operator used to audit the column(ex. is not empty, greater than). Can be empty
// desiredValue - Desired value of the column. Can be empty
// discrepancyValue - Discrepancy value. Can be empty
// isCI - True, if audited record is a CI. False, otherwise.
// domainToUse - Sys domain of the "cert_audit" record. Can be empty
new SNC.CertificationProcessing().logAuditResultFail(current.sys_id, sysId, '', columnNameSpace, 'not null', '', gr.getDisplayValue('business_contact'), true);
pass = false;
} else {
//Check user is active
userGr = new GlideRecord('sys_user');
userGr.get(businessContact);
if (userGr.isValidRecord()) {
if (userGr.getValue('active') == 0) {
columnNameSpace = gr.business_contact.getLabel(); // String value of column audited against
new SNC.CertificationProcessing().logAuditResultFail(current.sys_id, sysId, '', columnNameSpace, 'active user', '', gr.getDisplayValue('business_contact'), true);
pass = false;
}
}
}
Any help is much appreciated!
- Labels:
-
Data Acquisition
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎04-26-2023 04:55 PM
It's a great question, and one worth pursuing a good answer for, IMO. I have run into this before and basically come up with the answer that I'd have to write a lot of potentially unpleasant code for this or create a more enhanced auditing framework on top of something that is already a bit convoluted in some ways, and have landed on this: if you want methods to track health on a more frequent basis than you are willing to deal with the creation of new, possibly duplicate audit tasks, you might be better off handling this through other means than audits. And if you're going to be actually creating tasks for audits, those tasks should have some weight to them. They should have SLAs and governance, and reporting to show whether they are being addressed. They shouldn't be just another way to look at how we're doing with our data completeness/correctness. And if looking at it like that makes you (or your customers!) cringe at the thought of having all of these tasks land in their plate "on top of all the other work they have to do" maybe also consider narrowing the criteria of your audit so that at least you are only selecting the "top offenders" or most critical business impact areas as a target for your scripted audits.
The opinions expressed here are the opinions of the author, and are not endorsed by ServiceNow or any other employer, company, or entity.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎04-26-2023 04:59 PM - edited ‎04-26-2023 05:04 PM
Another thing you could consider doing is to assign these tasks to a CMDB Remediation Workflow that will modify your data automatically (e.g. walk up the management hierarchy as managers may be able to assume accountability for assigning responsibility for previously active direct reports) and then complement the auto-reassignment of those roles with notifications: "ACTION REQUIRED: You have been assigned the following things for the following reasons... make sure these items are properly assigned to the right people"
That said, based on a quick review of your code, I don't know whether getValue('active') == 0 is actually the right logical test for that condition. I could be wrong though. And also the !businessContact test looks suspect, because getValue() might not return an actual null, but rather an empty string. I would use gs.nil(businessContact) for this test instead to be sure.
The opinions expressed here are the opinions of the author, and are not endorsed by ServiceNow or any other employer, company, or entity.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎04-26-2023 07:15 PM
Thanks so much for your inputs! I do agree on all of your inputs to be honest. What is the actual best practice to tackle this sort of solution?
Truth be told, we have about 2,000 CIs that are detected by this audit of ours and from each errors per CI, a task has to be generated, which would probably bloat the instance with information.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Checkout glide.allow.new.cert_follow_on_task
Source: https://www.servicenow.com/docs/bundle/yokohama-servicenow-platform/page/product/compliance/concept/...