Assign Records to Owners Using an Assignment Plan

The AssignRecords() Apex method assigns records to users automatically using rules specified in an assignment plan. For example, suppose that you use a web-to-lead generation form to generate inbound leads in Salesforce. You use the AssignRecords() method to assign those leads to sales reps as soon as the lead records are created, reducing the time for sales reps to contact leads.

Signature

String, List<sObject> maps.API.AssignRecords(String, List<sObject>)
Where,
  • maps is the namespace that's available after you install Salesforce Maps.
  • API is the class that contains the global methods exposed to developers.
  • AssignRecords() is the method.

Sample Code

This code assigns accounts to reps based on an existing assignment plan. The AssignRecords() method returns a List<sObject> containing the records that were assigned to an assignment plan, the plan ID, and the records that weren't assigned to an assignment plan.

The AssignRecords() global method uses the last record cache to assign records. As a best practice, schedule assignment of records frequently in a batch to keep the cache up to date. For more information, see Salesforce Help: Schedule and Run Record Assignments.

If you invoke methods within a flow, process builder, or trigger, avoid uncommitted work errors when you perform one of the following.

  • Call the methods through a future method
  • Call the methods as queueable

Different processes refresh the token, such as plotting a route or schedule. The refresh process is almost immediate after each qualifying action occurs.

Warning

Example

// Get the record ID of the assignment plan.
maps__AssignmentPlan__c plan = [SELECT Id FROM maps__AssignmentPlan__c];

// Get a list of records you want to assign.
// This query includes all fields mapped in the plan.
List<Account> accs = [SELECT Id, BillingLatitude, BillingLongitude FROM Account];

// Call the AssignRecords method with the plan ID and list of account records.
maps.API.AssignRecords(plan.Id, accs);

// Log the record assignment output in JSON format.
Map<String, Object> response = maps.API.AssignRecords(plan.Id, accs);
system.debug(JSON.serialize(response));

Invocable Example

public class InvocableTest {
    
    @future(callout=true)
    public static void testInvocableFuture(List<Id> accIds) {
    // This query includes all fields mapped in the plan.
        List<Account> accs = [SELECT Id, BillingLatitude, BillingLongitude, Description, maps__AssignmentRule__c FROM Account WHERE Id IN :accIds];

        // Call the AssignRecords method with the plan ID and list of account records.
        maps.API.AssignRecords('a0L54000007oHXqEAM', accs);

        // Log the record assignment output in JSON format.
        Map<String, Object> response = maps.API.AssignRecords(plan.Id, accs);
        system.debug(JSON.serialize(response));
    }

    public with sharing class testInvocableQueueable implements Queueable, Database.AllowsCallouts {
        List<Id> accIds;

        public testInvocableQueueable(List<Id> accIds) {
            this.accIds = accIds;
        }

        public void execute(QueueableContext qc) {
            // This query includes all fields mapped in the plan.
            List<Account> accs = [SELECT Id, BillingLatitude, BillingLongitude, Description, maps__AssignmentRule__c FROM Account WHERE Id IN :accIds];

            // Call the AssignRecords method with the plan ID and list of account records.
            maps.API.AssignRecords('a0L54000007oHXqEAM', accs);

            // Log the record assignment output in JSON format.
            Map<String, Object> response = maps.API.AssignRecords(plan.Id, accs);
            system.debug(JSON.serialize(response));
        }
    }

    @InvocableMethod(label='test invocable' description='test auto assign' callout=true)
    public static void testInvocable(List<Id> accIds) {
        
        // CALLING A FUTURE METHOD WORKS.
        //testInvocableFuture(accIds);
        
        // CALLING A QUEUEABLE METHOD WORKS.
        //System.enqueueJob(new testInvocableQueueable(accIds));
        
        // THIS WON’T WORK AS AN INVOCABLE METHOD. A CALLOUT INSIDE OF A RECORD UPDATE OR INSERT RESULTS IN AN UNCOMMITTED WORK ERROR.
        // INSTEAD, SEPARATE THE TRANSACTION INTO A FUTURE OR QUEUEABLE METHOD.
        //List<Account> accs = [SELECT Id, BillingLatitude, BillingLongitude, Description, maps__AssignmentRule__c FROM Account WHERE Id IN :accIds];
        //maps.API.AssignRecords('a0L54000007oHXqEAM', accs);
    }
}

Trigger Example

// FOR INSERTS, AFTER WORKS BETTER THAN BEFORE BECAUSE THE ID DOESN’T EXIST IN THE BEFORE CHECK.
trigger AccountTrigger on Account (after insert, after update) {
    
    List<Id> accIds = new List<Id>();

    for (Account acc : Trigger.new) {
        if (acc.maps__AssignmentRule__c == null) {
            accIds.add(acc.Id);
        }
    }
    
    // CALLING A QUEUEABLE METHOD WORKS.
    //if (!accIds.isEmpty()) {
        //System.enqueueJob(new AccountTriggerHelper.testTriggerQueueable(accIds));
    //}
    
    // THIS WON’T WORK AS A TRIGGER.
    //List<Account> accs = [SELECT Id, BillingLatitude, BillingLongitude, Description, maps__AssignmentRule__c FROM Account WHERE Id IN :accIds];
    //maps.API.AssignRecords('a0L54000007oHXqEAM', accs);
    
    // CALLING A FUTURE METHOD WON’T WORK.
    //AccountTriggerHelper.testTriggerFuture(accIds);
    
}
public class AccountTriggerHelper {
    
    @future(callout=true)
    public static void testTriggerFuture(List<Id> accIds) {
    //  This query includes all fields mapped in the plan.
        List<Account> accs = [SELECT Id, BillingLatitude, BillingLongitude, Description, maps__AssignmentRule__c FROM Account WHERE Id IN :accIds];
        // Call the AssignRecords method with the plan ID and list of account records.
        maps.API.AssignRecords('a0L54000007oHXqEAM', accs);
    }

    public with sharing class testTriggerQueueable implements Queueable, Database.AllowsCallouts {
        List<Id> accIds;

        public testTriggerQueueable(List<Id> accIds) {
            this.accIds = accIds;
        }

        public void execute(QueueableContext qc) {
        // This query includes all fields mapped in the plan.
            List<Account> accs = [SELECT Id, BillingLatitude, BillingLongitude, Description, maps__AssignmentRule__c FROM Account WHERE Id IN :accIds];
            // Call the AssignRecords method with the plan ID and list of account records.
            maps.API.AssignRecords('a0L54000007oHXqEAM', accs);

        // Log the record assignment output in JSON format.
        Map<String, Object> response = maps.API.AssignRecords(plan.Id, accs);
        system.debug(JSON.serialize(response));
        }
    }

}

Sample Response

This method returns an Apex Map<String, Object> object that contains the records assigned, the plan ID, and records not assigned. This JSON response illustrates the essential data returned.

{
    assigned: [
        {
            id="0011700001LTxzwAAD", // ID of record assigned.
            rule="0021700001LTxzwAAD", // ID of rule used for assignment.
            user="0031700001LTxzwAAD" // ID of user assigned to the matched rule.
        },
        {
            id="0011700001LTxzwAAG",
            rule="0021700001LTxzwAAD",
            user="0031700001LTxzwAAD"
        }
    ],
    plan: "a0L54000007oHXqEAM", // Assignment plan ID
    unassigned: ["0011700001LTxzwAAE", "0011700001LTxzwAAF"] // List of record IDs not assigned.
}