# How to create uneven Round Robin assignment rules

These are even (as the name RR states).

I have other requirements, we want to split the assignment unevenly between reps So, from certain region, reps will get different % of assigned leads Rep A - 18% Rep B - 18% Rep C - 32% Rep D - 32%

• One option I thought was to put Rep A twice in the assignment rules (like Rep # 1, and Rep #2) so he will have 2 assigned values from the formula. But I need something more robust, manageable, and it's not the correct % that are asked for.

Any ideas?

A code/coding solution is also acceptable. As long as managing the split-% will be done outside of the code (label, meta data, etc)

• Round robin, by definition, implies fair split between the reps and hence, it works on sequential assignment strategy for most part. With uneven split requirement, you are deviating from this strategy. But definitions apart, could you clarify few things? (1) Did you mean this uneven split assignment should happen only for specific set of reps or all reps? (2) Did you mean leads from specific regions are only to be considered for this uneven split? In other words, what is your criteria to identify the list of assignable reps for a given lead?
– arut
Nov 26, 2020 at 16:20
• Both of your assumptions are correct. If we can solve the uneven distribution for one set of users/region, we can do it for all. Nov 29, 2020 at 7:02
• Check if the posted answer helps. Sorry about the lengthy answer, but I wanted to explain as much as I could.
– arut
Nov 29, 2020 at 19:12
• If you don't want to go to the lengths outlined in the answers, use an AppExchange tool built for exactly this scenario: SuperRoundRobin Dec 23, 2021 at 13:59

Implementing a completely declarative solution for this requirement is not possible, but a hybrid solution using declarative configuration data & apex code should be the apt approach.

Note that uneven percentage distribution works well only when you have the requirement to split and assign decimal numbers; for example, distribution of currency value (revenue, commission etc.) since there is usually no need to round them off to the nearest whole number. So, in your case at least 50% of the time, the # of leads assigned to at the least one of the reps will have a negligible deviation from the actual percentage intended. The difference in the actual # of leads assigned to this rep will be mostly by 1 and will get adjusted when new leads are being created and assigned. This does occur with evenly split round robin distribution too, but that can be easily explained to the reps. However, in case of uneven distribution, it gets a bit tricky since the distribution itself would be based on slightly complex criteria.

This proposed solution is based on the following assumptions and disclaimers:

• Leads are to be distributed among 4 sales reps (Rep 1, 2, 3 & 4). But, this solution can be leveraged for more reps or queues.
• All lead assignments are going to handled programmatically, so default Lead assignment rules are disabled. If not, then appropriate action has been taken to exclude lead records (that needs to follow specific business requirements) from being processed by the default assignment rules. Explaining how to implement this part is beyond the scope of this post.
• Apex code logic mentioned in the final step of this solution needs to be bulkified, optimized and exception handled appropriately.
• The solution detailed here is only the idea and high level steps that would work for any # of reps and complex criteria with uneven percentage distribution. You will need to improve the design based on your business requirement and do a lot of additional testing.
• Providing the source code sample for this solution is beyond the scope of this post and hence, only high level solution is given in favor of brevity.
• Initial configuration should consider and accommodate already existing assigned leads. Some amount of manual calculation and effort would be required in the initial set-up for this approach to work.
• Different variations of this solution is possible with the underlying concept remaining the same.
• I've used similar logic for other requirements in the past, but not for lead assignment. I have no doubt that this would work.

Solution:

Step 1: Create a custom metadata type to store all of the individual lead assignment criteria. Let's call this as `Lead Assignment Criteria` and should have the following fields:

``````+---+------------------+----------------+------------+--------------------------------------------+
|   | Field Label      | Field API Name | Field Type | Description                                |
+---+------------------+----------------+------------+--------------------------------------------+
| 1 | Lead Assignment  | Name           | Name       | To store Lead object field’s developer     |
|   | Criteria Name    |                |            | name. For lookup field, merge syntax       |
|   |                  |                |            | along with developer name should be used.  |
| 2 | Operator         | Operator__c    | Picklist   | Picklist values should be:                 |
|   |                  |                |            |      Equals                                |
|   |                  |                |            |      Not equals                            |
|   |                  |                |            |      Like                                  |
|   |                  |                |            |      Greater than                          |
|   |                  |                |            |      Lesser than                           |
|   |                  |                |            | Other possible operators can also be       |
|   |                  |                |            | included in this picklist                  |
| 3 | Value            | Value__c       | Text       | To store the possible filter value         |
|   |                  |                |            | such as TODAY, YESTERDAY, Lead’s region    |
|   |                  |                |            | etc. This can be any value required for    |
|   |                  |                |            | filtering the leads.                       |
| 4 | CriterionID      | CriterionID__c | Number     | Unique num to identify a single criterion  |
+---+------------------+----------------+------------+--------------------------------------------+
``````

For example, if you have to specify a criterion for all leads from east US region, it should be similar to the sample shown below.

``````+------------+----------------+------------+----------------+
| Name       | Operator__c    | Value__c   | CriterionID__c |
+------------+----------------+------------+----------------+
| Region__c  | Equals         | East US    | 1              |
+------------+----------------+------------+----------------+
``````

Note that `Region__c` is a field from Lead object and there will be many records in this custom metadata for each criterion that is going to be used for lead assignment.

Step 2: Create a custom metadata type to collate different assignment criteria (that were created in the custom metadata type from step 1) to form the required filter criteria for each of your business requirement. Let's call this as `Lead Assignment Rules` and should have the following fields:

``````+---+------------------+----------------+------------+--------------------------------------------+
|   | Field Label      | Field API Name | Field Type | Description                                |
+---+------------------+----------------+------------+--------------------------------------------+
| 1 | Lead Assignment  | Name           | Name       | Give a meaningful name which can be        |
|   | Rule Name        |                |            | related against the business requirement.  |
| 2 | Filter           | Filter__c      | Text       | Specify the filter using the criterionID   |
|   |                  |                |            | value from the other custom metadata (Lead |
|   |                  |                |            | Assignment Criteria).                      |
|   |                  |                |            | For example, (1 AND 2) OR (3 AND 4)        |
| 3 | Percentage       | Percentage__c  | Number     | Specify the percentage split value here    |
| 4 | Assignee         | Assignee__c    | Text       | Specify Lead Owner, Queue name etc. here   |
+---+------------------+----------------+------------+--------------------------------------------+
``````

Example record for this custom metadata type would similar to the sample shown below:

``````+---------+------------+---------------+-------------+
| Name    | Filter__c  | Percentage__c | Assignee__c |
+---------+------------+---------------+-------------+
| East-US | (1 AND 2)  | 20            | Rep 1       |
| East-US | (1 AND 2)  | 80            | Rep 2       |
+---------+------------+---------------+-------------+
``````

Note that the numbers specified in the field `Filter__c` should correspond to a `criterionID__c` from `Lead Assignment Criteria` metadata records. Using the 2 custom metadata type records, SOQL filter condition string can be dynamically created in apex and used to query required records or the filter conditions can be used to dynamically filter already queried records in apex. `Assignee__c` field should be used to specify a sales rep username or display name or the developer name of a queue.

Step 3: Create a custom object to capture lead assignment data. Let's call this as `Lead Assignment Statistics` and should have the following fields:

``````+---+------------------+----------------+------------+--------------------------------------------+
|   | Field Label      | Field API Name | Field Type | Description                                |
+---+------------------+----------------+------------+--------------------------------------------+
| 1 | Lead Assignment  | Name           | Name       | Specify value as either 'Total Leads' or   |
|   | Statistics Name  |                |            | value of the 'Lead Assignment Rule' custom |
|   |                  |                |            | metadata name. There will be one record    |
|   |                  |                |            | corresponding to each custom metadata      |
|   |                  |                |            | record (Lead Assignment Rule)              |
| 2 | Value            | Value__c       | Text       | To store total # of lead records processed |
|   |                  |                |            | against as specific rule.                  |
+---+------------------+----------------+------------+--------------------------------------------+
``````

Records in this custom object would be similar as shown below:

``````+---+--------------+----------+
|   | Name         | Value__c |
+---+--------------+----------+
| 1 | Total Leads  | 100      |
| 2 | East-US      | 20       |
+---+--------------+----------+
``````

First record 'Total Leads' shows the actual number of processed leads present (i.e., excluding deleted leads). Second record 'East-US' shows the actual number of processed leads corresponding to the custom metadata record with the same name. There would be additional records for each custom metadata (from step 2) record. Note that in the custom metadata there are multiple records for 'East-US' that corresponds to each rep assignment, but only one corresponding record in the sobject that indicates the count of all processed records for this specific rule.

Step 4: Create a custom field in Lead object as `AssignmentProcessed__c` (Field type: Boolean & Default value: false). This field should be toggled to true by apex code after the lead assignment is performed successfully. Additional fields can be created if there is a need to mark certain lead records for re-processing.

Step 5: Write apex (before insert trigger or async future or apex scheduler) code to do the following:

• Query the lead records to be processed based on the `AssignmentProcessed__c` field value or trigger context variables.
• Fetch all the records from the custom metadata `Lead Assignment Rules` & `Lead Assignment Criteria`.
• For each `Lead Assignment Rules` record, get the corresponding `Lead Assignment Criteria` records using the criterionID specified in its value field and dynamically create a SOQL WHERE clause. Using this dynamically constructed WHERE clause, fetch the lead records to be processed. Or, if processing in trigger, use them to filter the required data. In this step, note down other details such as % of leads that needs to be assigned to a sales rep or queue.
• Query the sobject `Lead Assignment Statistics` records. Using the number specified against 'Total Leads' & other records (corresponding to `Lead Assignment Rules` record name), perform the math (by including records being currently processed) to determine whom to assign a lead record and process the assignment on leads fetched in previous step.
• Toggle the `AssignmentProcessed__c` field to true on assigned lead records and update the `Value__c` on Lead Assignment Statistics sobject to reflect the latest processed numbers.
• Additionally, in delete apex trigger (or relevant apex code), if an assigned lead is deleted (or to be excluded), decrement the corresponding record values in the `Lead Assignment Statistics` sobject to maintain the functional integrity of this solution.

• Instead of custom metadata type mentioned in steps 1 & 2, you may choose to use custom sobject if you developing this solution for internal company usage only and if there are designated lead managers who would regularly update the assignment criteria.

• Managing assignment criteria and rules creation (regardless of custom metadata type or custom object) can be developed and exposed as a lighting web component, making this a better solution and easier to train users.

• Great answer @arut, thanks. I wonder if I can use a before flow as well, instead of the Before Trigger to make the solution Codeless. You win the points, as your solution really opened my eyes for a great flow. Dec 1, 2020 at 13:52
• You might want to have a look at these consideration for record triggered flows to identify any limitations with the approach.
– arut
Dec 1, 2020 at 16:53
• You could use record triggered flows too. However (as mentioned in the assumptions), if you decide to use a mix of default assignment rules and the proposed solution, test various lead assignment scenarios thoroughly (you might already know that Out-of-the-box assignment rules are not run during recursive save). For most case, you might not run into any problem, but there could be few corner cases (since it sounds like your business requirement might have or grow into complex criteria based assignment)
– arut
Dec 1, 2020 at 16:56

This is a tough requirement.

Unfortunately, I don't think a declarative approach could be used here. You'd need to be able to query the current levels for each rep in order to allocate the next lead.

I'd recommend using an apex trigger for this. One tip: you can have the trigger set a background field, then use Lead Assignment rules to allocate, similar to the standard round-robin approach in the documentation.

Important tip: you'll need to be able to thoroughly test and report on why a specific lead went to a specific rep. I did this type of project once, and 70% of the work was explaining why Rep C got a lead and Rep D didn't. People get emotional when commissions are involved.

Assuming the reps and percentages will change regularly, you may also need a custom field on User with the percentages.

Also check the appexchange for an app that meets this need. And make sure the business team knows that this requirement isn't very easy to implement. They may decide to work around it with manual assignment from queues.

Good luck!