[SalesForce] Updating Lead Owner in trigger before lead conversion

I have a use case where I need to update the Lead.OwnerId during lead conversion. I want the resulting Account, Opportunity, Task & email to go to the new owner.

I thought that I would be able to simply create a before update trigger, test if it's converting and then update the lead.OwnerId. I created a very simple proof of concept to test this and got some odd results:

trigger LeadTrigger on Lead (before update, after update) {
    System.debug((Trigger.isBefore ? 'Before' : 'After') +  ' Update');
    System.debug(lead.OwnerId);

    if(trigger.isBefore){
        for(Lead lead : (List<Lead>) trigger.new) {
            if (Lead.IsConverted){
                lead.OwnerId = '0054C000000jHDD';
            }
            System.debug('New Owner: ' + lead.OwnerId);
        }
    }
}

After converting the Account, Opportunity, Task owners are NOT updated to 0054C000000jHDD. The debug output is very strange as System.debug(lead.OwnerId); outputs the string OwnerId instead of a user id.

14:40:58.601 (2611942429)|USER_DEBUG|[15]|DEBUG|Before Update
14:40:58.601 (2612031531)|USER_DEBUG|[16]|DEBUG|OwnerId
14:40:58.601 (2612297809)|USER_DEBUG|[23]|DEBUG|New Owner: 0054C000000jHDDQA2
14:40:58.663 (2665290643)|USER_DEBUG|[15]|DEBUG|After Update
14:40:58.663 (2665365454)|USER_DEBUG|[16]|DEBUG|OwnerId

Best Answer

By the time you're in the Lead After Update trigger logic, the Account, Contact, and Opportunity have already been created. See this question for the gory details behind conversion.

Furthermore, the eventual record owners would have already been fixed, as it is determined at the very moment the Triggers and Order of Execution reaches step 2 (i.e. as soon as the lead has been retrieved from the database), and won't be finalized until step 19 (or whatever the penultimate step is when you read the docs).

You'll want to look at the LeadConvert class (or the related SOAP docs); you'll see the owner can be specified by code or in the UI before conversion, and your trigger won't know what value was selected, as record ownership is fixed up at the last possible second, basically right before the final database commit (step 19 above).

At the trigger level, you have two basic choices, then: (a) block the conversion and tell the user to correct the ownership first, or (b) use a future/queueable method to be called after the final post-commit logic of the first transaction to set the new record owner.

You could build a Visualforce page to override conversion, which would give you more control over the owner, since you could then change it immediately before calling the convertLead method yourself.