GlideRecord query in Condition field for BR or UI Action?

bdr529
Mega Contributor

Hello,

On our Change, Release and Features forms I have UI Action form buttons that will apply an Approve or Reject for anyone in the Approvers related list for that item. What I was hoping to do is to only show those form buttons for the users who actually have an approval for that item at that time, just like the isApprovalMine() function does on the sysapproval_approver table.

Admittedly, I was surprised that one Business Rule actually does have a GlideRecord query in its condition line (Update Config on MID) but I'm not sure if I'm able to modify that to make use of the isApprovalMine() function, which I think would be ideal for this scenario!
That Business Rule's condition is: new GlideRecord("ecc_agent").get(current.ecc_agent)

Does anyone have a suggestion or have maybe done something like this before?

Not a big deal, I know, but I'd like to reduce confusion and polish this up a bit!

Thanks for your thoughts,
Tim

5 REPLIES 5

bdr529
Mega Contributor

I think I figured it out! Thanks to the UI Action called Calculate Risk, which also uses the GlideRecord query. This is the condition I now use in my UI Action which makes the form button appear only when the person viewing the form has an awaiting approval:

var conds = new GlideRecord('sysapproval_approver');conds.addQuery('sysapproval', current.sys_id);conds.addQuery('state', '=', 'requested');conds.addQuery('approver', '=', gs.getUserID());conds.query();conds.hasNext()


I didn't realize you could string together the commands separated by semi-colons, which is really useful. Apparently, though, you have to *start* the condition line with the "var conds..." and not begin it with a parenthesis or other conditions. I could end the condition with other items, though. I might be wrong about this, but in my quick testing it appears to be the case.

Enjoy! 😃
Tim


THANK YOU!!!!!!!!!!!!


bdr529
Mega Contributor

One last note about the condition string I came up with... as written above, it takes up a lot of characters (217) which doesn't leave a lot of room for additional conditions in a 254 character field.
I rewrote it this way which trims it down to 167 characters!

var gr=new GlideRecord('sysapproval_approver');gr.addQuery('sysapproval',current.sys_id);gr.addQuery('approver', "javascript:getMyApprovals()");gr.query();gr.hasNext()


CapaJC
ServiceNow Employee
ServiceNow Employee

Nice technique! I'll tack on three thoughts.

1) If condition length is a concern, you can put that script into a global function (either in a Script Include or a global Business Rule), have the function return gr.hasNext(), and simply have your condition call the function.

2) Any time you only care whether there is at least one record returned from a query, you should add a gr.setLimit(1); to the script before doing the gs.query(). This makes sure that if there are, say, 16 million records that match your query, you won't consume resources by retrieving more than you need. gr.setLimit(1); ensures that at most one record will be returned in your GlideRecord object.

3) It's slightly more script, but using GlideAggregate vs. GlideRecord to simply check for the presence of records does less overall work. For a high traffic script, it could be meaningful.

e.g., in your case, the script could look like the following:

Condition: hasRelevantApprovals()

The following function could be placed in a global business rule, or in a single function Script Include:



function hasRelevantApprovals() {
var ga = new GlideAggregate('sysapproval_approver');
ga.addAggregate("COUNT");
ga.addQuery('sysapproval', current.sys_id);
ga.addQuery('state', 'requested');
ga.addQuery('approver', gs.getUserID());
ga.query();
var total = 0;
if (ga.next())
total = ga.getAggregate("COUNT");
return total > 0;
}