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