Round-Robin (Auto Assignment of new incidents and tasks)

magoo
Kilo Expert

HI All,

 

I was asked to create a round-robin type approach (Auto Assignment) for any incidents/tasks that come into our two level1 groups. What we are looking for is that if its sent to team A's group it will auto assign to the next team member in line, and same with Team B.   I have searched the forums and found a post back from 2008 but it had been deleted by ServiceNow in 2010.   Our company is new to ServiceNow (a couple months now), and I am guessing this is more of a script that would need to run, but currently do not have much experience in scripting.   Has anyone had any luck with doing something like this?   Any suggestions would be greatly appreciated!

 

Thanks!

1 ACCEPTED SOLUTION

justin_drysdale
Mega Guru

We have this in our instance.   Here's the breakdown:



On sys_user, create a date/time field to track last ticket assigned. Also create a checkbox that will be used to determine if the user can receive a ticket.   This can be your vacation exclusion logic.



1. Make an array (associative, key-value) to contain your users that will receive tickets and their corresponding last ticket assigned timestamp.


2. Find your assignment group, and query it's users.


3. Push those users and timestamp into the user array from 1.   You can conditionalize here with the checkbox to make sure you are only pushing 'active' users into the array.


4. Sort the array by timestamp, return the user that has the oldest timestamp.


4.5. Update the user's timestamp.


5. assigned_to = returned user.



Please let me know if you have any questions.


View solution in original post

102 REPLIES 102

Hello,



Even i am not getting correct ticket count. Is some code missing because i dont have any entries added in Round robin table as i see their is no code written for the same.


Yeah, I too ran into that same issue but fixed it.   Sorry I forgot to post the fix.



Here's my business rule:


gs.sleep(3000); // Sleep statement added to prevent ticket flood being assigned to a single technician.






if (current.assignment_group == '8a4cd5b36fd3d1000fd9122cbb3ee48f') // "Service Desk" group sys_id.


{


      current.assigned_to = resolveTech();


}




function resolveTech()


{


      var tech_arr = [];


      var group = new GlideRecord('sys_user_grmember');


      group.addQuery('group', '8a4cd5b36fd3d1000fd9122cbb3ee48f'); // "Service Desk" group sys_id.


      group.query();


     


      var tech = "";


      var lastAssigned = "";


      var isAssignable = false;


     


      while(group.next())


      {


              isAssignable = group.user.u_round_robin_active;


              tech = group.user.sys_id;


              lastAssigned = group.user.u_last_ticket_assigned + "";


             


              // Only pushing assignable users to array.


              if (isAssignable == true)


              {


                      tech_arr.push({ sys_id: tech, last_assigned: lastAssigned });


              }


      }    




      // Sort on last assigned, return user with.


      tech_arr.sort(function(a, b)


                                  {


                                      return (a.last_assigned < b.last_assigned ? -1:(a.last_assigned > b.last_assigned ? 1:0));


                                  });


      updateDateTime(tech_arr[0].sys_id); // Updating ticket last assigned date


      keepCountOfAssignmentsForTheDay(tech_arr[0].sys_id);


      gs.sleep(2000);


      return (tech_arr[0].sys_id); // Assigned_to technician (sys_id).


}




function updateDateTime(assignedTo_sysID)


{


      var nowdt = gs.nowDateTime();


      var updateDate = new GlideRecord('sys_user');


      updateDate.addQuery('sys_id', assignedTo_sysID);


      updateDate.query();


     


      while(updateDate.next())


      {


              updateDate.u_last_ticket_assigned = nowdt;


              updateDate.update();


      }


}




function keepCountOfAssignmentsForTheDay(assignedTo_sysID)


{


      var gdt = new GlideDateTime();


      var month = gdt.getMonth();


      var year = gdt.getYear();


      var day = gdt.getDayOfMonth();


     


      var gr = new GlideRecord('u_round_robin');


      gr.addQuery('u_user_sys_id', assignedTo_sysID);


      gr.addQuery('u_year', year);


      gr.addQuery('u_month', month);


      gr.addQuery('u_day_of_month', day);


      gr.orderBy('u_timestamp');


      gr.query();


     


      var tog = 0;


      var myVal = 0;


     


      while (gr.next())


      {


              if (tog == 0)


              {


                      myVal = parseInt(gr.u_daily_tickets_assigned.getDisplayValue());


              }


             


              if (!parseInt(myVal))


                      myVal = 0;


             


              tog++;


              gr.u_daily_tickets_assigned = (myVal + 1);


              gr.update();


      }


}

















The key for this fix is the keepCountOfAssignmentsForTheDay() function.


Hello David,



Many Thanks for this. But where are you inserting the values in u_round_robin table and querying it in keepCountOfAssignmentsForTheDay() .



Thanks,


Nidhi


Actually I can! I created a dynamic content block and built everything in it around the sys_id of the technician. Now, since this was my first iteration of this project, I actually ended up building separate content blocks for each Technician in the Service Center group. I quickly realized that was a bad idea since the turnover rate was a little high. My new iteration is run from a table and you simply add or remove a record for a technician and it'll automatically populate in the application. Anywho, to what you were looking for...



<?xml version="1.0" encoding="utf-8" ?>


<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">



<!-- This will create a jelly variable that contains the users login id as well as the sys_id of their record in SN. -->


<j:set var="jvar_testuser" value="a8ad4da46f56250092a4186e6b3ee4e7" />




<!-- GET THE TECHNICIAN NAME -->


<g:evaluate var="jvar_darjohnson_name">


var gr = new GlideRecord('sys_user');


gr.get('sys_id','${jvar_darjohnson}');


var jvar_darjohnson_name = gr.name;


jvar_darjohnson_name;


</g:evaluate>



<!-- THIS IS CHECKING A FLAG ON THEIR USER RECORD TO DETERMINE IF THEY ARE ACTIVE(SCHEDULED TO BE ON THE CLOCK). THAT SCHEDULING FUNCTIONALITY IS RUN ON A SCHEDULED JOB THAT CHECKS THE SCHEDULE TABLE WHERE I CREATED RECORDS OF EVERYONES SCHEDULE AND THEIR MANAGER CAN SIMPLY MODIFY THEIR SCHEDULE OR MARK THEM AS BEING ABSENT AND THE APPLICATION WILL RESPOND ACCORDINGLY BY NOT MARKING THEM AS ACTIVE AND NOT ASSIGNING TICKETS TO THEM. -->


<g2:evaluate var="jvar_darjohnson_status">


var tr = new GlideRecord('sys_user');


tr.get('sys_id','${jvar_darjohnson}');


var jvar_darjohnson_status = tr.u_is_available_;


jvar_darjohnson_status;


</g2:evaluate>



<!-- THIS IS RUNNING A GLIDEAGGREGATE TO ACCOUNT FOR HOW MANY RECORDS ARE ACTIVE AND ASSIGNED TO THIS PARTICULAR TECHNICIAN -->


<g2:evaluate var="jvar_darjohnson_queue">


var qr = new GlideAggregate('task');


qr.addActiveQuery();


qr.addQuery('assigned_to','${jvar_darjohnson}');


qr.addQuery('u_resolved',false);


qr.addAggregate('COUNT');


qr.query();


var darjohnson_items = 0;


if(qr.next()){


darjohnson_items = qr.getAggregate('COUNT');


}


darjohnson_items;


</g2:evaluate>



<!-- THIS IS TAKING THOSE PREVIOUS QUERIES AND CREATING VARIABLES TO HOLD THE CONTENT BEFORE BEING DISPLAYED ON THE SCREEN. -->


<j:set var="jvar_tickets_today" value="$[gr.getValue('u_tickets_assigned_today')]" />


<j:set var="jvar_tickets_week" value="$[gr.getValue('u_tickets_assigned_this_week')]" />


<j:set var="jvar_tickets_month" value="$[gr.getValue('u_tickets_assigned_this_month')]" />



<!-- THIS IS PRESENTING THE STATUS OF THE TECHNICIAN -->


<!-- DECLARE THE OPPOSITE OF THE TECHNICIANS CURRENT STATUS -->


<j2:set var="jvar_darjohnson_opp_status" value="$[!jvar_darjohnson_status]" />




<!-- WRITE THE INFORMATION TO THE SCREEN -->


<div>


<p style="font-size:20px;font-weight:bold;color:#D2CECE;text-align:center">${jvar_darjohnson_name}</p>


<p style="font-size:18px;text-align:center;text-decoration:underline">Available</p>


<p id="darjohnsonStatus" style="text-align:center;font-size:18px;color:blue"> $[jvar_darjohnson_status] </p>


<p style="font-size:18px;text-align:center;">Tickets assigned today :   ${jvar_tickets_today}</p>


<p style="font-size:18px;text-align:center;">Tickets assigned this week :   ${jvar_tickets_week}</p>


<p style="font-size:18px;text-align:center;">Tickets assigned this month :   ${jvar_tickets_month}</p>


<p style="font-size:18px;text-align:center;">Queue : $[jvar_darjohnson_queue]</p>


</div>



<!-- THESE ARE THE BUTTONS THAT ALLOW YOU TO CHANGE THE TECHNICIANS STATUS AND VIEW ALL OF THE ITEMS IN THAT TECHNICIANS QUEUE -->


<div style="text-align:center">


<fieldset>


<legend style="margin-left:auto;margin-right:auto">Change Technician Status</legend>


<j:set var="jvar_button_title" value="Change Status" />


<g:macro_invoke macro="change_darjohnson_status" title="${jvar_button_title}" status="$[jvar_darjohnson_status]" tech="${jvar_darjohnson}" />


<g:macro_invoke macro="view_darjohnson_records" tech="${jvar_darjohnson}" />


</fieldset>


</div>


</j:jelly>


That's the code that's operating the content block for the first version of my application. Since we are planning an upgrade to Geneva in early 2016, I've started working on an upgrade to the application to provide improve how the application operates and provide a few additions. Here is what I currently have in the lab...



find_real_file.png


This provides a more visually pleasing interface to change the status, view the queue, chat with the technician(assuming the plugin is turned on, or send emails directly to the technician related to a specific record. Just a side thing i'm working on. Hope all of that info helps someone.


Hi Cal,



We are also looking into using the On-Call plugin for the same purpose.


Would it be possible for you to share how you managed to set it up? with any scripts/screenshots if possible?



Thanks in advance!



Regards,


Samiul