Round Robin Assignment Using Public Groups in Salesforce

Round Robin Assignment Using Public Groups in Salesforce

Do you like the idea of Omni Channel’s round robin routing but want to assign records to offline users? Well, with Public Groups in Salesforce and a little Apex, you can!

Let’s pretend that when a Contact is created, we need to set the owner of the Contact in a round robin fashion based on picklist field values on the Account.

First, create a Public Group corresponding to each of the possible picklist values. The members of each Public Group can consist of individual users, or of other Public Groups. Members are sorted by name and the round robin assignment will be performed using this sorting.

To make the solution more scalable, create a Custom Metadata Type to map the picklist values to the name of the Public Groups. Note that, if a picklist value is not listed in the Custom Metadata Type, the Contact Owner will not be changed.

In addition, you will need to create a Custom Setting to hold the name of the last user from each Public Group that was assigned in the round robin.

When a Contact is created, the “Before Insert” trigger checks the Account’s picklist value and finds the matching Public Group from the Custom Metadata Type. Once all of the members have been fetched and sorted, the Custom Setting checks to find the name of the last user assigned.

If no name is found in the Custom Setting (a.k.a. this is the first Contact ever being assigned to the Group), a record is created in the Custom Setting to track the Public Group’s first user; that user will be the Contact Owner. If the Custom Setting does contain a name, the next user listed in the Public Group will be set as the Contact Owner, and the Custom Setting record is updated with the name of this user. And around it goes!

In case you’re wondering, here are the Apex methods I used to fetch all the users from a Public Group are below. If you need a little more help on leveraging Round Robin and Public Groups, find out how we can help you with custom development.

 private Set<Id> getGroupUserIds(String groupName)
 {
     Set<Id> setUserId = new Set<Id>();// final list of users
     Set<Id> setGroupId = new Set<Id>(); // member groups
     for(GroupMember gm : [Select GroupId, UserOrGroupId From 
                           GroupMember where Group.Name = :groupName
                           and Group.Type = 'Regular'])
     {
         if(gm.UserOrGroupId.getSObjectType() == User.getSObjectType())
         {
             setUserId.add(gm.UserOrGroupId);
         }
         if(gm.UserOrGroupId.getSObjectType() == 
                                            Group.getSObjectType())
         {
             setGroupId.add(gm.UserOrGroupId);
         }
     }
 
     if(!setGroupId.isEmpty())
     {
          // get users from member groups
          setUserId.addAll(getGroupUserIds(setGroupId)); 
     }

     return setUserId;
 }

 // recursive method to get users from member groups 
 private Set<Id> getGroupUserIds(Set<Id> setGroupId)
 {
     Set<Id> setUserId = new Set<Id>(); // final list of users
     Set<Id> setChildGroupId = new Set<Id>(); // member groups
     for(GroupMember gm : [Select GroupId, UserOrGroupId From     
                            GroupMember where Id in :setGroupId])
     {
         if(gm.UserOrGroupId.getSObjectType() == User.getSObjectType())
         {
             setUserId.add(gm.UserOrGroupId);
         }
         if(gm.UserOrGroupId.getSObjectType() == 
                                          Group.getSObjectType())
         {
             setChildGroupId.add(gm.UserOrGroupId);
         }
     }

     if(!setChildGroupId.isEmpty())
     {
         setUserId.addAll(getGroupUserIds(setChildGroupId));
     }
     return setUserId;
 }