Use PDIs? Take our 5-minute survey to help shape the PDI roadmap.

Script include's 'activeAnything' query is not passing through the OOB query BR

Shraddha17
Tera Contributor

Hi,

 

There's an OOB BR which prevents itil users to see disabled user records. To bypass this, we have added a condition in this BR to check if the current query contains 'Active Anything' flag as we just need to bypass this one catalog item's reference qualifier.

 

This script is not working for itil users and they are still unable to see disabled user records. What am I missing here ?

 

Here is the BR,

(function executeRule(current, previous /*null when async*/ ) {
    var query = current.getEncodedQuery();
    if (gs.getSession().isInteractive() && !query.includes('activeANYTHING')) {
        current.addActiveQuery();
    }
})(current, previous);
 
 
Here is the advanced reference qualifier,
javascript: new ReferenceQualifiers().test();
 
Here is the script include,
a1: function(_lastUpdatedHoursStr) {
        // gs.log('Ref Inactive _lastUpdatedHoursStr ' + _lastUpdatedHoursStr);

        var queryString = 'activeANYTHING^active=false';

        var userIdArr = [];
        var userGr = new GlideRecord('sys_user');
        userGr.addQuery('active', 'false');
        userGr.addQuery('user_name', 'NOT LIKE', 'ad%');
        userGr.addQuery('user_name', 'NOT LIKE', 'bd%');
        userGr.addQuery('name', 'DOES NOT CONTAIN', 'test');
        userGr.addQuery('u_checktype_type', 'DOES NOT CONTAIN', 'vvv');
        userGr.addNotNullQuery('employee_number');
        userGr.addNotNullQuery('u_num');
        if (_lastUpdatedHoursStr != undefined) {
            var lastUpdatedQueryStr = 'sys_updated_onRELATIVEGT@hour@ago@' + _lastUpdatedHoursStr;
            userGr.addEncodedQuery(lastUpdatedQueryStr);
        }
        userGr.query();
        while (userGr.next()) {
            userIdArr.push(String(userGr.sys_id));
        }

        return queryString + '^sys_idIN' + userIdArr;
    },
 
    b1: function() {

        var userIdArr = [];
        var userGr = new GlideRecord('sys_user');
        userGr.addActiveQuery();
        userGr.addQuery('user_name', 'NOT LIKE', 'ad%');
        userGr.addQuery('user_name', 'NOT LIKE', 'bd%');
        userGr.addQuery('name', 'DOES NOT CONTAIN', 'test');
        userGr.addQuery('u_checktype_type', 'DOES NOT CONTAIN', 'vvv');
        userGr.addNotNullQuery('employee_number');
        userGr.addNotNullQuery('u_num');
        userGr.query();
        while (userGr.next()) {
            userIdArr.push(String(userGr.sys_id));
        }

        return 'active=true^sys_idIN' + userIdArr;
    },
 
    test: function() {

        var userIdArr = [];
        var queryAllStr = '';
        var queryActiveStr = '';
        var queryInactiveStr = '';
        if (this.b1().length > 0) {
            queryActiveStr = String(this.b1());
        }

        if (this.a1('96').length > 0) {
            queryInactiveStr = String(this.a1('96'));
        }

        if (JSUtil.notNil(queryInactiveStr) && JSUtil.notNil(queryActiveStr)) {
            queryAllStr = queryActiveStr + '^NQ' + queryInactiveStr;
        }

        return queryAllStr;
    },
 
3 REPLIES 3

drbob
Tera Guru

I've done this before (with the same choice of "activeANYTHING"). Don't have access now but can confirm it _should_ work.

Have you logged the value of "query" in your BR to make sure the "activeANYTHING" is making it through ? Also, log the result of query.includes('...') - in case there's something wacky going on there (I can't recall but isn't the inclusion of "includes()" a newer thing - maybe query BRs don't understand that - have you tried seeing if query.indexOf('...') is "-1" ?

drbob
Tera Guru

Also, just try it in list view as a user with the itil role. If they can add the "active is ANYTHNG" filter can they see inactive users there ?

 

If so then there's something up with your "test" function (probably "b1" being called instead of "a1" - check that too by logging when the functions are entered).

If not then it's the BR.

boteeuwen
Tera Expert

In your Script Include's test function, you are building an encoded query using the ^NQ operator:
queryAllStr = queryActiveStr + '^NQ' + queryInactiveStr;
When a reference qualifier uses ^NQ, ServiceNow splits the execution into two entirely independent database queries.
When the User Query Business Rule runs, it intercepts the execution context. However, current.getEncodedQuery() evaluates only the first branch of the query string (queryActiveStr) unless you iterate through the subqueries. Because activeANYTHING is embedded inside the second branch (queryInactiveStr), your Business Rule reads the first query part, fails to see the keyword, and forcefully injects current.addActiveQuery() across the board. This effectively overrides your second query branch...


Furthermore, I saw another error:

Inside your script include function a1(), you perform a server-side query on the exact same table:

var userGr = new GlideRecord('sys_user');
...
userGr.query();

When userGr.query() triggers, it fires the User Query Business Rule again recursively. During this internal a1() query execution, current.getEncodedQuery() is looking at the query structure of userGr (which does not contain the activeANYTHING string).The Business Rule sees no flag, hits the else block, and appends active=true to your internal lookup.
As a result, userGr returns zero inactive users, rendering userIdArr empty.

 

Check if this works (this script is generated with AI):

SCRIPT INCLUDE:

a1: function(_lastUpdatedHoursStr) {
var userIdArr = [];
var userGr = new GlideRecord('sys_user');

// CRITICAL: Temporarily disable business rules on this internal lookup
// to prevent the User Query BR from filtering out inactive users here!
userGr.setWorkflow(false);

userGr.addQuery('active', 'false');
userGr.addQuery('user_name', 'NOT LIKE', 'ad%');
userGr.addQuery('user_name', 'NOT LIKE', 'bd%');
userGr.addQuery('name', 'DOES NOT CONTAIN', 'test');
userGr.addQuery('u_checktype_type', 'DOES NOT CONTAIN', 'vvv');
userGr.addNotNullQuery('employee_number');
userGr.addNotNullQuery('u_num');

if (_lastUpdatedHoursStr != undefined) {
var lastUpdatedQueryStr = 'sys_updated_onRELATIVEGT@hour@ago@' + _lastUpdatedHoursStr;
userGr.addEncodedQuery(lastUpdatedQueryStr);
}
userGr.query();
while (userGr.next()) {
userIdArr.push(userGr.getUniqueValue());
}

// Return only the raw sys_ids here
return 'sys_idIN' + userIdArr.join(',');
},

b1: function() {
var userIdArr = [];
var userGr = new GlideRecord('sys_user');
userGr.setWorkflow(false); // Keep workflow disabled for consistency

userGr.addActiveQuery();
userGr.addQuery('user_name', 'NOT LIKE', 'ad%');
userGr.addQuery('user_name', 'NOT LIKE', 'bd%');
userGr.addQuery('name', 'DOES NOT CONTAIN', 'test');
userGr.addQuery('u_checktype_type', 'DOES NOT CONTAIN', 'vvv');
userGr.addNotNullQuery('employee_number');
userGr.addNotNullQuery('u_num');
userGr.query();
while (userGr.next()) {
userIdArr.push(userGr.getUniqueValue());
}

return 'sys_idIN' + userIdArr.join(',');
},

test: function() {
var queryActiveStr = this.b1();
var queryInactiveStr = this.a1('96');
var queryAllStr = '';

if (queryActiveStr && queryInactiveStr) {
// CRITICAL: Put the activeANYTHING flag at the absolute front of the total string
queryAllStr = 'activeANYTHING^' + queryActiveStr + '^NQ' + queryInactiveStr;
} else if (queryActiveStr) {
queryAllStr = 'activeANYTHING^' + queryActiveStr;
} else if (queryInactiveStr) {
queryAllStr = 'activeANYTHING^' + queryInactiveStr;
}

return queryAllStr;
},


BUSINESS RULE:
(function executeRule(current, previous /*null when async*/ ) {
var query = current.getEncodedQuery();

// Check if the interactive session query contains our flag anywhere in the text string
if (gs.getSession().isInteractive() && query.indexOf('activeANYTHING') == -1) {
current.addActiveQuery();
}
})(current, previous);