How to add a check delegate is true condition to an UI Action?

ChuanYanF
Tera Guru

Dear experts,

 

Currently I am toggling with the delegate functions on the latest yokohama fix and for some ui action I have certain conditions only for certain role, I tried to create a script include to call in the condition field for the ui action as below, but the button will still appear after the delegate assigned time is already passed or the delegate record is being deleted. How should I approach this manner? Is my script has some improvements to undergo?
Script include:

var DelegationUtil = Class.create();
DelegationUtil.prototype = {
    initialize: function() {},

    isUserOrDelegate: function(originalUserId) {
        var currentUserId = gs.getUserID();
        if (currentUserId == originalUserId)
            return true;

        var gr = new GlideRecord('sys_user_delegate');
        gr.addActiveQuery();
        gr.addQuery('delegate', currentUserId);
        gr.addQuery('user', originalUserId);
        gr.addQuery('starts', '<=', gs.nowDateTime());
        gr.addQuery('ends', '>=', gs.nowDateTime());
        gr.query();
        return gr.hasNext();
    }
};
UI Action Condition:
(gs.hasRole('sn_risk_advanced.Boost - BU HOD') ||  (new  global.DelegationUtil().isUserOrDelegate)) && (current.state == 1) && (!current.isNewRecord()) && current.canRead() && current.u_submitted == true​
19 REPLIES 19

Roshnee Dash
Tera Guru
  1. Checking Active Delegations:

    • gr.addActiveQuery(); ensures that only active records are retrieved, but it may not account for records that were deleted.

    • Your ends condition (gr.addQuery('ends', '>=', gs.nowDateTime());) checks if the delegation is still valid, but if the ends field is empty or incorrectly handled, it may still return results.

  2. Handling Deleted Records:

    • If a delegate record is deleted, your query won't return results. However, ServiceNow may retain cached data or old results.

  3. Calling the Function in UI Action Condition:

    • You're referencing isUserOrDelegate without properly invoking it ((new global.DelegationUtil().isUserOrDelegate)). This should be corrected to new global.DelegationUtil().isUserOrDelegate(originalUserId).

Suggested Fixes:

Updating Your Script Include

Modify your isUserOrDelegate method to handle delegation records properly and ensure the query properly validates the delegation period:

var DelegationUtil = Class.create();
DelegationUtil.prototype = {
    initialize: function() {},

    isUserOrDelegate: function(originalUserId) {
        var currentUserId = gs.getUserID();
        if (currentUserId == originalUserId)
            return true;

        var gr = new GlideRecord('sys_user_delegate');
        gr.addActiveQuery();
        gr.addQuery('delegate', currentUserId);
        gr.addQuery('user', originalUserId);
        gr.addQuery('starts', '<=', gs.nowDateTime());
        gr.addQuery('ends', '>=', gs.nowDateTime());
        gr.addQuery('active', true);  // Ensure only active delegations are considered
        gr.query();

        return gr.next(); // Using gr.next() instead of gr.hasNext() ensures data integrity
    }
};

This ensures:

  • That only active delegation records are considered.

  • Using .next() rather than .hasNext() ensures you retrieve an actual record, preventing caching issues.

Fixing Your UI Action Condition

You need to properly call the function in the condition field:

(gs.hasRole('sn_risk_advanced.Boost - BU HOD') ||  
    new global.DelegationUtil().isUserOrDelegate(current.user)) && 
    (current.state == 1) && 
    (!current.isNewRecord()) && 
    current.canRead() && 
    current.u_submitted == true

 

Your feedback makes the community stronger! If you found this helpful, marking it as the correct answer helps others.
Stay awesome,
Roshnee Dash

Hi Roshnee, thanks for the reply, but for this part of the query, the delegates table itself does not have the active field, so it is not able to tell if the delegates is still active or not and isit been deleted yet. This does not solve my current situation. Any other approach on this?

        gr.addQuery('active', true);  // Ensure only active delegations are considered

 

Hi ChuanYanF,

I ran into something similar recently and found two main issues that make the “delegate check” always return true:

  1. The UI Action condition wasn’t actually calling the function

  2. We need to be sure that a deleted or expired delegation never matches

Below is a step-by-step fix. It uses only the sys_user_delegate fields user, delegate, starts and ends—no extra “active” field is needed, because once a delegation record is deleted or its end date is in the past, it simply won’t match our date queries.

Try this Script Include:

var DelegationUtil = Class.create();
DelegationUtil.prototype = {
    initialize: function() {},

    /**
     * Returns true if the current user is either the original user
     * (originalUserId) or a valid delegate for them right now.
     */
    isUserOrDelegate: function(originalUserId) {
        var currentUserId = gs.getUserID();
        // 1) If I’m the original user, return true immediately
        if (currentUserId == originalUserId) {
            return true;
        }

        // 2) Otherwise, look for any sys_user_delegate record
        //    where: delegate == me, user == originalUserId,
        //    and starts <= now <= ends
        var gr = new GlideRecord('sys_user_delegate');
        gr.addQuery('delegate', currentUserId);
        gr.addQuery('user', originalUserId);
        gr.addQuery('starts', '<=', gs.nowDateTime());
        gr.addQuery('ends', '>=', gs.nowDateTime());
        gr.query();

        // .next() will advance the record pointer if there’s at least one match
        return gr.next();
    }
};


Also you need to correct the UI Action Condition:
Inside your UI Action’s Condition field, you have to call isUserOrDelegate() and pass in the right “original user” field from the current record. For example, if your record has a field called u_owner that holds the original user’s sys_id, you would do:

(
  gs.hasRole('sn_risk_advanced.boost - bu hod')
  || new global.DelegationUtil().isUserOrDelegate(current.u_owner)
)
&& (current.state == 1)
&& (!current.isNewRecord())
&& current.canRead()
&& current.u_submitted == true

 

Hi Lukasz,

 

Thanks for the reply, but I tried using your script include, but it does not seem to work, so im not sure what is the problem here, I followed exactly your script here but the button is now not visible to the delegate after I implemented the new codes.