Dynamically Creating Workflow Approvals for Multiple Users

jmiskey
Kilo Sage

I need to dynamically create multiple approvals for multiple approvers.  Here is some background.

I have a table named "u_packages_approvers", which has the following fields:

u_package_name - unique package name

u_type - set to either "approval_needed" or "general_use"

u_approver - primary approver (all records with "u_type" set to "approval_needed" have a user entry here)

u_backup_approver - secondary approver (not required, only some records populated here)

Then, on my Catalog Item, we have a list collector variable named "packages_access" where they can select as many packages that they like.  I have come up with a Run Script action that currently loops through all the items in my list collector, looks lto see if they require approval, and if so, it creates an approval for the primary approver, and includes the package name in the approval type field ("u_approval_type").  My code is posted below:

//capture packages selected from variable
var pkgList = current.variables.packages_access.toString();

//loop through all packages
var pkgArray = pkgList.split(',');
for (var i = 0; i < pkgArray.length; i++) {
	var pkg = pkgArray[i];
	var gr = new GlideRecord('u_packages_approvers');
	gr.addQuery('sys_id', pkg);
	gr.query();

	//create approvals
	if (gr.next()){
		if (gr.u_type == 'approval_needed'){
			var appr1 = gr.u_approver;
			var appr2 = gr.u_backup_approver;
			var pkg_name = gr.u_package_name;

			//create approval
			var approval = new GlideRecord('sysapproval_approver');
			approval.initialize();
			approval.state = 'requested';
			approval.approver = appr1;
			approval.u_approval_type = pkg_name + ' Approval';
			approval.sysapproval = current.sys_id;   //Current is record that requires approval
			approval.insert();

		}
	}

}

That part all works fine.  Now, the tricky part is I want to add the "backup approvers".  So it should be a situation where if a single package has multiple approvers (primary and backup), an approval is created for each of them, but only one needs to accept/reject the approval (then the other one is unnecessary). 

I am not sure how to amend my code how to do that, especially since I am creating multiple approval records at once (for the various packages selected).  Obviously, some approvals will need to be related to each other (primary/backup for a single package), while others are not (approvals for the different packages).

Does that make sense?  Does anyone have any ideas on how to amend my code to do that?

Thanks

1 ACCEPTED SOLUTION

Coleton
Kilo Guru

You'd want to have  a BR that looks at the 'sysapproval_approver' table which runs when the state changes and the item they're approving is the item for this process (so a little dotwalking from the approval record to get the item name). When that state changes, query for records with the same 'document_id' and set the state to "No Longer Required".

That behavior will essentially be, "if one person approves this ticket, find the other approval records for this ticket and mark them as no longer needed". If you are having multiple packages selectable, which do not share approvers, this won't work. You would have to make a custom field on the approval table which allows you to relate primary/backup approvers. Then you could use that field to determine which approval records to set No Longer Required.

If you need assistance with writing the BR, just reply. Let me know if this answers your question by marking it as correct.

View solution in original post

8 REPLIES 8

Coleton
Kilo Guru

You'd want to have  a BR that looks at the 'sysapproval_approver' table which runs when the state changes and the item they're approving is the item for this process (so a little dotwalking from the approval record to get the item name). When that state changes, query for records with the same 'document_id' and set the state to "No Longer Required".

That behavior will essentially be, "if one person approves this ticket, find the other approval records for this ticket and mark them as no longer needed". If you are having multiple packages selectable, which do not share approvers, this won't work. You would have to make a custom field on the approval table which allows you to relate primary/backup approvers. Then you could use that field to determine which approval records to set No Longer Required.

If you need assistance with writing the BR, just reply. Let me know if this answers your question by marking it as correct.

Thanks for the reply.  I like that idea, but where is this "document_id" field that you are matching on?

In my situation, I think we can determine which records needs to be associated with one another by looking at a combination of the RITM number (sysapproval) and Approval Type (u_approval_type) fields.

I think I may need assistance in creating that rule.

It should be the record that's being approved:

find_real_file.png

This is an out-of-the-box field on the 'sysapproval_approver' table. It should be the field you have on your approval records which has a reference to the record being approved.

OK, so I actually followed your advice of using a Business Rule, I just did it a little bit different than you suggested.  I matched on the fields I mentioned.  So my Business Rule looks like this:

find_real_file.png

find_real_file.png

I also updated my Run Script to run approvals for the backup approvers, like this:

//capture packages selected from variable
var pkgList = current.variables.packages_access.toString();

//loop through all packages
var pkgArray = pkgList.split(',');
for (var i = 0; i < pkgArray.length; i++) {
	var pkg = pkgArray[i];
	var gr = new GlideRecord('u_packages_approvers');
	gr.addQuery('sys_id', pkg);
	gr.query();

	//create approvals
	if (gr.next()){
		if (gr.u_type == 'approval_needed'){
			var appr1 = gr.u_approver;
			var appr2 = gr.u_backup_approver;
			var pkg_name = gr.u_package_name;

			//create array of approvers
			var apps = [];
			apps.push(appr1);
			if (appr2 != '') {
				apps.push(appr2);
			}

			//loop through approvers
			for (var j = 0; j < apps.length; j++) {
				var app = apps[j];

				//create approval
				var approval = new GlideRecord('sysapproval_approver');
				approval.initialize();
				approval.state = 'requested';
				approval.approver = app;
				approval.u_approval_type = 'Cognos: ' + pkg_name + ' Approval';
				approval.sysapproval = current.sys_id;   //Current is record that requires approval
				approval.insert();
			}
		}
	}

}

All appears to be working fine now.  Thanks for all the help!