Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

Round Robin Business Rule script Question about addQuerry order for multiple custom fields

JGerrity
Tera Contributor

Hello All,

 

I'm attempting to build a round robin business rule script that will need to look at a couple of a custom fields:

 

  • u_roundrobin on the  sys_user_group table as true/false. 
  • "u_out_of_office" (true/false) on the sys_user table

What I want to do with my business rule, is:
1) Query the current.assignment_group to see if u_roundrobin = true

2) If true, query all members of that group and only include those who's u_out_off_office = false

My code so far:

(function executeRule(current, previous /*null when async*/) {

var gMember = new GlideRecord('sys_user_grmember');
gMember.addQuery('group', current.assignment_group);
gs.print("assignmentGroup:"+gMember); 
gs.log("assignmentGroup:"+gMember);
var rrMember = gMember.addQuery('u_roundrobin', true);
gs.print("rrMember:"+rrMember);
gs.log("rrMember:"+rrMember);

if(rrMember == true)
{
var agroup = new GlideRecord('sys_user_grmember');
agroup.addQuery('group', current.assignment_group);
var ooo = agroup.addQuery('u_outlook_out_of_office', true);
agroup.query();
gs.print("ooo:"+ooo);
gs.log("ooo:"+ooo);
if (ooo == true){
if (gMember.next()) {
		current.assigned_to = gMember.user;
	}
}
}
})(current, previous);

I'm struggling with the logic of query group to determine if u_roundrobin is true, then multiple if's or if I can do it all within a query and only reference members of the current assignment group (if it's a member of roundrobin and the user is not outofoffice (ooo).

thoughts?
thank you.

3 ACCEPTED SOLUTIONS

Sandeep Rajput
Tera Patron
Tera Patron

@JGerrity Try if the following works.

(function executeRule(current, previous /*null when async*/) {
var assignedGroup = current.getValue('assignment_group');
var group = new GlideRecord('sys_user_group');
group.addQuery('sys_id', assignedGroup);
if (group.next()) {
	var isMemberRR = group.u_member_of_round_robin;
	gs.print("isMemberRR:" + isMemberRR);
	gs.log("isMemberRR:" + isMemberRR);
	if (isMemberRR == true) {
		var mem = new GlideRecord('sys_user_grmember');
		mem.addQuery('group', group.getValue('sys_id'));
		mem.orderBy('user.u_last_assigned_task_date');
		mem.query();
		if (mem.next() && mem.user.u_outlook_out_of_office != '1') {
			current.assigned_to = mem.user;
		}
	}
}
})(current,previous);

 

View solution in original post

Ankur Bawiskar
Tera Patron
Tera Patron

@JGerrity 

when is the business rule running? on which table and what's the condition?

Your business rule should be Before insert/update.

(function executeRule(current, previous /*null when async*/) {
    // Query the assignment group to check if u_roundrobin is true
    var group = new GlideRecord('sys_user_group');
    if (group.get(current.assignment_group) && group.u_roundrobin) {
        // Query all members of the group who are not out of office
        var gMember = new GlideRecord('sys_user_grmember');
        gMember.addQuery('group', current.assignment_group);
        gMember.addQuery('user.u_out_of_office', false);
        gMember.query();

        // If there are members available, assign the incident to the first one found
        if (gMember.next()) {
            current.assigned_to = gMember.user;
        }
    }
})(current, previous);

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

View solution in original post

@JGerrity 

yes you can use daily scheduled job and handle it

something like this but please enhance

(function() {
    // Step 1: Collect all users in round-robin groups
    var users = [];
    var group = new GlideRecord('sys_user_group');
    group.addQuery('u_roundrobin', true);
    group.query();
    while (group.next()) {
        var gMember = new GlideRecord('sys_user_grmember');
        gMember.addQuery('group', group.sys_id);
        gMember.query();
        while (gMember.next()) {
            users.push(gMember.user.email.toString()); // Collect user email addresses
        }
    }

    // Step 2: Make API call to check AutoReply status
    var requestBody = {
        "requests": users.map(function(email) {
            return {
                "url": "/users/" + email + "/mailboxSettings",
                "method": "GET"
            };
        })
    };

    var request = new sn_ws.RESTMessageV2();
    request.setEndpoint('https://graph.microsoft.com/v1.0/$batch');
    request.setHttpMethod('POST');
    request.setRequestHeader('Content-Type', 'application/json');
    request.setRequestHeader('Authorization', 'Bearer YOUR_ACCESS_TOKEN'); // Replace with your access token
    request.setRequestBody(JSON.stringify(requestBody));

    var response = request.execute();
    var responseBody = JSON.parse(response.getBody());

    // Step 3: Update u_out_of_office status based on API response
    responseBody.responses.forEach(function(res) {
        var email = res.id.split('/')[1];
        var autoReplyStatus = res.body.automaticRepliesStatus;

        var user = new GlideRecord('sys_user');
        user.addQuery('email', email);
        user.query();
        if (user.next()) {
            user.u_out_of_office = (autoReplyStatus === 'enabled');
            user.update();
        }
    });
})();

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

View solution in original post

10 REPLIES 10

@Ankur Bawiskar Wow!  not only a blazingly fast response but exactly what I was looking for.  You even did the coding part for me!  

Greatly appreciated thank you!
Jason

@JGerrity 

Glad to help.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

Hello @Ankur Bawiskar 

Thank you again for this it's a great start!

I noticed that the formatting of MS Graph batching is :

{
  "requests": [
    {
      "id": "1",
   "url": "/users/" + email + "/mailboxSettings/automaticRepliesSetting",
      "method": "GET"
    },
    {
      "id": "2",
      "url": "/users/" + email + "/mailboxSettings/automaticRepliesSetting",
      "method": "GET"
    },
    {
      "id": "3",
      "url": "/users/" + email + "/mailboxSettings/automaticRepliesSetting",
     "method": "GET"
    },
  ]
}


So I'm thinking that the users array should be counted or I'm wondering if it's possible to build the response body inside the 

 while (group.next()) {

loop.

The request body is specific formatting with the combination of { "requests": [
Then each user is within a { }; and ID field is mandatory and then closed within the ]:

As referenced here: https://learn.microsoft.com/en-us/graph/json-batching?tabs=http 

I'm not sure how to write the exact format of the required requestBody with an incremental ID value.

Cheers!

@JGerrity 

then inside the while loop form array of json objects and use it

something like this

(function() {
    // Step 1: Collect all users in round-robin groups
    var users = [];
    var group = new GlideRecord('sys_user_group');
    group.addQuery('u_roundrobin', true);
    group.query();
    while (group.next()) {
        var gMember = new GlideRecord('sys_user_grmember');
        gMember.addQuery('group', group.sys_id);
        gMember.query();
        while (gMember.next()) {
            users.push(gMember.user.email.toString()); // Collect user email addresses
        }
    }

    // Step 2: Make API call to check AutoReply status
    var requestBody = {
        "requests": users.map(function(email, index) {
            return {
                "id": (index + 1).toString(), // Incremental ID value
                "url": "/users/" + email + "/mailboxSettings/automaticRepliesSetting",
                "method": "GET"
            };
        })
    };

    var request = new sn_ws.RESTMessageV2();
    request.setEndpoint('https://graph.microsoft.com/v1.0/$batch');
    request.setHttpMethod('POST');
    request.setRequestHeader('Content-Type', 'application/json');
    request.setRequestHeader('Authorization', 'Bearer YOUR_ACCESS_TOKEN'); // Replace with your access token
    request.setRequestBody(JSON.stringify(requestBody));

    var response = request.execute();
    var responseBody = JSON.parse(response.getBody());

    // Step 3: Update u_out_of_office status based on API response
    responseBody.responses.forEach(function(res) {
        var email = res.id.split('/')[1];
        var autoReplyStatus = res.body.automaticRepliesStatus;

        var user = new GlideRecord('sys_user');
        user.addQuery('email', email);
        user.query();
        if (user.next()) {
            user.u_out_of_office = (autoReplyStatus === 'enabled');
            user.update();
        }
    });
})();

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

JGerrity
Tera Contributor

I want to thank both @Sandeep Rajput  and @Ankur Bawiskar for helping with this.  Sandeep, really appreciate you pointing me in the right direction.

Ankur, your formatting and logic were bang-on!  

Thank you both, greatly appreciated!!
Jason