- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 07-04-2021 07:21 AM
Part 1
| Part 2 | Part 3 |
Overview of all Approval Requests (parent & child records)
Approvals are one of the oldest features in ServiceNow and yet there is so much to improve regarding their experience. For this reason, I would like to dedicate a separate series of articles to this topic, in which I will present smaller enhancements and optimizations from my latest customer projects.
In this first article of a series, I want to demonstrate how to keep the individual approvals of all child records together in one overview.
So what is the situation?
There are some task types which have dedicated child task records, for example Change Tasks (change_task) for Change Requests (change_request) or Catalog Tasks (sc_task) for Requested Items (sc_req_item).
The whole thing is further complicated if individual approval requests have been created for these child tasks. In this case, you can no longer see the status of all the approval requests at a glance in the parent record, and would therefore have to click through each individual child task.
Solution
As often, the solution is an individual Relationship, which can be displayed as a Related List in the parent record. And basically, Relationships are not rocket science, however, there is a small challenge here that needs to be mastered.
The problem is that the reference field "Approval for" (sysapproval) at table Approval (sysapproval_approver) is of type "Task" but the field "Parent" (parent) is often not filled at the target record. Instead, there are many times individual parent-child references. For example, for Change Tasks, the relationship to the parent record is stored in the field "Change Request" (change_request), which is not known in the "Task" table.
So, how can we implement a dot-walk to the Change Request field? The answer is an inserted cast to the target table in the notation:
ref_<TABLE NAME>
In our example, the dot-walk looks like this:
sysapproval.ref_change_task.change_request
The complete configuration of a Relationship "All Approvers" for Change Requests and their corresponding Change Tasks can be realized as follows:
Notes:
- Via the OR-condition (line 5), the possibly existing Approval Requests of the parent record were also included, so that the OOTB Related List "Approvers" can be completely replaced with the custom variant "All Approvers".
- Unfortunately, this specific notation means that it is not possible to implement a generic solution that applies equally to all parent-child relationships. Instead, you have to create the "All Approvers" Relationship for all parent task types individually.
The final result for a Change Request could look like this:
- 2,223 Views

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Great Article!
As an FYI, you can make a global approvals list with a little pre-work.
- Create a system property called approval_parent_fields, mine contains the value parent,change_request,parent_incident
- Create a sys_relationship and set the Applies to table to Global and Advanced to true
- Set the following in the Apply to script.
//Focusing on task, but there is no reason this couldn't just be
//answer = true
//To work for all tables
answer = GlideDBObjectManager.get().getAbsoluteBase(table_name) == 'task';
- Use the following script in the Query with
(function refineQuery(current, parent) {
var potentialRecords = [parent.sys_id];
var parentFields = gs.getProperty('approval_parent_fields' , 'parent');
parentFields.split(",").forEach(function(field){
if(parent.isValidField(field)){
potentialRecords.push(parent.getValue(field));
}
});
current.addQuery('document_id', 'IN' , potentialRecords);
})(current, parent);
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi
thanks for your reply.
I'm a bit irritated as I never saw a Change Task with a referenced RITM at "Parent" field.
And it seems that in your solution you are looking bottom up (child to parent) whereas I wanted to look bottom down (parent to child)
Or am I missing something?
Kind regards
Maik
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
The necessity of this also points to messed up, complicated, hard to follow processes. The gain would be much higher if the processes themselves would be cleaned up necessitating a single container for approvals. So when it comes to executing a Change Task or a Catalog Task or a whatever task, it is not longer a question whether that should be executed or not, whether further approvals are needed or awaiting somewhere or not.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Irritated? hmmm.
Yes my solution looks bottom up as that, from an approval process, makes more sense. Why would a child dictate a parent; in both life and servicenow?
None the less, the logic can be flipped to do what you want. You could query the sys_dictionary table to find all reference fields that reference the table (i.e change_request,task) but that might be rather intensive and it's likely you only want / have approvals on a certain number of tables.
- Create a new property approval_child_tables which houses the tables we're bothered about. i.e task,incident,change,change_task,change_phase,sc_req_item
- Use the following script in the Query with
(function refineQuery(current, parent) {
var tables = gs.getProperty('approval_child_tables');
var fields = gs.getProperty('approval_parent_fields', 'parent');
var potentialRecords = [];
tables.split(",").forEach(function(table){
fields.split(",").forEach(function(field){
var tableGR = new GlideRecord(table);
if(tableGR.isValidField(field)){
tableGR.addQuery(field , parent.sys_id);
tableGR.query();
while(tableGR.next()){
potentialRecords.push(tableGR.getUniqueValue());
}
}
});
});
current.addQuery('document_id', 'IN', potentialRecords);
})(current, parent);