Prevent Delegate From Approving Their Own Requests

jmiskey
Kilo Sage

We recently had a situation which we would like to try to prevent going forward, and are not sure the best way of preventing it.  Many times, a manager will designate someone under them as their delegate (for approvals) while they are out-of-the-office.  Many of our requests require Manager Approval.  We want to prevent a user approving their own requests requiring Manager Approval (as the delegate for their Manager).

 

These are the only approvals we want to prevent this from happening (approval of own request as a delegate).  We have other processes that might require something like a Business Owner approval.  And if the submitter of the request is actually the Business Owner approval, we want to allow them to approve their own requests (since they are approving as themselves, and not as a delegate).

 

Is there a way to prevent an employee from approving their own requests, when approving as a delegate only?  We would need something that works globally, as we do not want to have to update hundreds of individual flows/workflows.

 

Also, one other thing to take into consideration is if the delegate tries approving via email.

 

Thanks

3 REPLIES 3

harishk07
Tera Expert

Hi,

 

You can enforce this with a Business Rule on the approval record, because delegate approvals (via UI or email) ultimately update the same record on sysapproval_approver. A “before” Business Rule that blocks the state change when the approver is acting as a delegate and the approval’s target is the same person.

 

Create a Before Business Rule on sysapproval_approver with a condition like current.state.changes() (and optionally only when moving to approved/rejected and Requestor is same as gs.getUserID()). In the script, detect “delegate acting on behalf of someone else” by checking sys_user_delegate (delegation records are stored there). Then block only when the current user is also the requester/requested_for of the thing being approved.

Example script (adjust the “requester” field mapping to your process):

(function executeRule(current, previous) {

  // Only block when an approval is being actioned
  if (!current.state.changes())
    return;

  var newState = (current.state + '').toLowerCase();
  if (newState !== 'approved' && newState !== 'rejected')
    return;

  // Only relevant when the approver is the current user
  if (current.approver.toString() !== gs.getUserID())
    return;

  // Resolve the record being approved
  var target = current.sysapproval.getRefRecord();
  if (!target || !target.isValidRecord())
    return;

  // Identify who the request is for / who submitted (adjust to your use case)
  var requester = '';
  if (target.isValidField('requested_for') && target.getValue('requested_for'))
    requester = target.getValue('requested_for');
  else if (target.isValidField('opened_by') && target.getValue('opened_by'))
    requester = target.getValue('opened_by');

  // If we cannot determine requester, do nothing
  if (!requester)
    return;

  // Only block "self approval while acting as a delegate"
  // i.e., current user == requester AND current user is a delegate for someone else
  if (requester === gs.getUserID()) {
    var del = new GlideRecord('sys_user_delegate');
    del.addActiveQuery();
    del.addQuery('delegate', gs.getUserID());
    del.addQuery('approvals', true);

    // If you use date-bound delegation, keep this; otherwise remove it
    del.addQuery('starts', '<=', gs.nowDateTime());
    del.addQuery('ends', '>=', gs.nowDateTime());

    del.query();
    if (del.hasNext()) {
      current.setAbortAction(true);
      gs.addErrorMessage('You cannot approve your own request when acting as a delegate.');
    }
  }

})(current, previous);

 

This approach blocks only the delegate scenario and does not prevent “real” approvals where the user is the actual approver.

 

 

Best Regards,
Harish

✔️ Kindly mark as Helpful / Accept Solution if this answered your question

Thanks for replying.  I will try to incorporate this, run some testing, and post back with the results.

Initial testing looks good so far!  Will do some more in-depth testing tomorrow.