[SalesForce] Lead assignment rule in a trigger

The objective is to have assignment rules fired on a Lead record creation. It seems the rule can be assigned only when using "update" DML in an "after insert" trigger. Why does another DML must be executed after insert to have lead assignment rule assigned?

//Does not work
trigger LeadTrigger on Lead (before insert) {    
    for (Lead l : Trigger.new) {        
        Database.DMLOptions dmo = new Database.DMLOptions();
        dmo.assignmentRuleHeader.useDefaultRule = true;
        so.setOptions(dmo);
    }
}


//Works: Records must be *updated* in after insert trigger in order to have the rule assigned
trigger LeadTrigger on Lead (after insert) {
    List<Lead> ls = new List<Lead>();

    for (Lead l : Trigger.new) {
        ls.add(new Lead(id = l.id));
    }

    Database.DMLOptions dmo = new Database.DMLOptions();
    dmo.assignmentRuleHeader.useDefaultRule = true;
    Database.update(ls, dmo);
}

Moreover, testing of the rule assignment fails even though the rule has been assigned to the Lead. We cannot test assignment rule outcome (ownerId=defaultQueueId for example) since the rule will change on PROD eventually.

//Test method failing for a lead *having* rule assigned:    
public static void assertDefaultAssignmentRules(SObject sobj) {
    Database.DMLOptions dmo = sobj.getOptions();

    System.assertNotEquals(null, dmo, 'DMLOption is null');
    System.assert(dmo.assignmentRuleHeader.useDefaultRule, dmo);
}

Best Answer

Lead reassignment within a trigger can be done with future methods such as the following. Your after insert / after update trigger will need to collect up a set of lead ids that qualify for reassignment and then once all other afterinsert/afterupdate operations are complete, call the future method below:

Note use of DmlOptions:

@future
public static void futureLeadReassign(Set<ID> lIdReassignSet) { 
    
    List<Lead> lUpdList = [SELECT Id FROM Lead WHERE Id IN: lIdReassignSet];
    Database.DMLOptions dmo = new Database.DMLOptions();
    dmo.assignmentRuleHeader.useDefaultRule = true;         
    for (Lead l:lUpdList) {
        // use leadAssignment rules when updating
        l.setOptions(dmo);
    }
    
    try {update(lUpdList);}
    catch (DmlException e) {/* do something here like send email to sysad with error */}
}
Related Topic