- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎01-15-2015 11:31 AM
Wondering if anyone has done anything with regards to dynamically handling the number of approvals in a single workflow. The idea is that something needs to go through a series of inline approvals, meaning each approval is created after the previous one has been approved, yet the number of approvals is dynamic based on various conditions of what's being requested.
So, one request may require two approvals yet another request may require four approvals. Again, the approvals must be inline so I don't believe I can use a group-type approval activity since all approvals would be sent at the same time.
My idea so far is to add several approval activities to the workflow and use them as placeholders. For example, I would add 10 approval activities to the workflow but only use two of them if the request required two approvals, or use four of them if the request required four approvals. The drawback to this approach is if the request required more approvals than there are placeholders.
Any other ideas?
Thanks,
Michael
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎01-19-2015 08:51 AM
I appreciate all the replies buy my issue is not dynamically adding one or more approvers to a single Approval workflow activity. What I'm looking for is a way to dynamically add sequential approvals. That is, approval #1 must be approved before approval #2 is sent, and #2 must be approved before #3 is sent and so on. The key is the number of approvals must be dynamic, for example, one request may only require 2 approvals whereas another request may require four approvals - again, in sequence not in parallel.
So I turned to a ServiceNow friend, Dave (Super Dave) Knight and he pointed me to the ServiceNow Document Management Application (requires a plugin activation) which already has this dynamic sequential approval feature in place.
Here's how it works (courtesy of Super Dave):
There is a list of approvers at the bottom of the form, arbitrary length. There is also a field on each approver called 'Sequence'. If you are #1, you approve first. If you are #2, second, and so on. Better yet, if two people are at #2, they approve in parallel, after #1 approvers, and before #3. You get the picture.
There is a workflow built to handle that. It is designed to iterate approvals through that list. It is called 'Document Management Default', illustrated below. It uses a standard Approval activity (scripted of course), and a loop. I've included the code in the key activities marked 1, 2 and 3 below (in case you do not have the document management plugin installed).
Activity #1 (Run Script): Basically goes to the list of records in the DB and remembers the who and sequence number for each value in RAM (the scratchpad). The code that gets the list out of the DB is in DocumentManagementDB, but as you will see, all it does is create an array of approvers, where each object has the name and sequence number of the approver.
current.approval = 'requested';
var db = new DocumentManagementDB();
var approvers = db.getApprovers(current.document);
workflow.scratchpad.approvers = approvers;
if(approvers.length>0){
workflow.scratchpad.current_sequence = approvers[0].sequence;
} else {
workflow.scratchpad.current_sequence = 0;
}
Activity #2 (Approval — User, Additional approvers script): This just gets the array of all approvers at the current sequence number …
answer = [];
var currentSequence = workflow.scratchpad.current_sequence;
var approvers = workflow.scratchpad.approvers;
for(var i=0; i<approvers.length; i++){
if(approvers[i].sequence == currentSequence) {
if(approvers[i].user){
answer.push(approvers[i].user);
} else {
answer.push(approvers[i].group);
}
}
}
Activty #3 (If, Script):
answer = isThereANextSequence();
function isThereANextSequence() {
var currentSequence = workflow.scratchpad.current_sequence;
var approvers = workflow.scratchpad.approvers;
var nextSequence = getNextSequence(approvers, currentSequence);
if (nextSequence>0) {
workflow.scratchpad.current_sequence = parseInt(nextSequence);
return 'yes';
}
return 'no';
}
function getNextSequence(approvers, currentSequence){
for(var i=0; i<approvers.length; i++){
if(approvers[i].sequence>currentSequence){
return approvers[i].sequence;
}
}
//We went through all the sequences
return 0;
}
I know I'm going to find many uses for this functionality and I hope others find it useful as well.
Once again, many, many thanks to Dave Knight for this information.
Michael
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-11-2020 06:28 AM
Actually, for the project from original post, I opted to created my own approval_sequence table. I replicated the out of the box approval_sequence table exactly.
For my "Activity 1", I get my approvers from a custom script include:
var approvers = new pxd_PurchaseRequestUtils().getApprovers(current.sys_id.toString());
workflow.scratchpad.approvers = approvers;
if(approvers.length > 0){
workflow.scratchpad.current_sequence = approvers[0].u_sequence;
} else {
workflow.scratchpad.current_sequence = 0;
}
Here's the method in the script include:
/*
* Returns the approvers and their approval sequence for a specific Purchase Request
*
* Parameters:
* poSysID = the sys_id of the Purchase Request
*
* Output:
* Returns an array where each element of the array is an object with the following
* attributes:
* Object[u_user] = User sys_id of the approver
* Object[u_sequence] = the approval sequence of the approver (integer)
*
* Notes:
* The sequence numbering returned is based on the iteration of the approvers in the
* PO Approver Sequence table. We cannot completely rely on the u_sequence field of
* the PO Approver Sequence table as there could be different approvers with the same
* sequence number. By manually setting the sequence number here, we ensure a unique
* sequence.
*/
getApprovers: function(poSysID) {
poSysID = (JSUtil.notNil(poSysID)) ? poSysID : current.sys_id.toString();
if (JSUtil.nil(poSysID))
return;
var seq = 1;
var approvers = [];
var approverGR = new GlideRecord('u_po_approval_sequence');
approverGR.addQuery('u_document_id', poSysID);
approverGR.addQuery('u_table_name', 'u_ast_po');
approverGR.orderBy('u_sequence'); // first order by sequence number
approverGR.orderBy('sys_created_on'); // then sort by created date/time
approverGR.query();
while(approverGR.next()){
var obj = {};
obj.u_sequence = seq;
obj.u_user = approverGR.getValue('u_user');
obj.u_sys_id = approverGR.getUniqueValue();
approvers.push(obj);
seq++;
}
return approvers;
},
Hope this helps,
Michael
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎03-04-2020 05:00 AM
Hello ,
The solution you have implemented is awesome . But I got stuck at one point I didn't find 'ServiceNow Document Management Application (requires a plugin activation)' Plugin in the store.
How to deal with it.?
Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎03-04-2020 05:43 AM
Sorry, I can't answer to the availability of that plugin. But, you don't need the plugin to build out this dynamic approval framework.
Your framework simply needs to:
- Gather your approvers
- Set an approver based on a sequence
- Check for additional approvers
Michael

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-17-2020 12:33 PM
The only issue i am facing with this is, once approver1 approves, it deletes the approver1 record from approval record and create approver2. But I want to keep approver 1 and approver2 should be shown
Please mark this response as correct or helpful if it assisted you with your question.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-20-2020 02:51 AM
Hi Sanjiv,
I am facing the same issue. Have u able to resolve this issue.