function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion

Before Insert Opportunity Trigger issues with lead conversion

***Let me start off by saying Enforce Validation and Triggers from Lead Convert setting is already set for our organization.


Moving forward...


I have a trigger that is supposed to set 3 custom lookup fields on an Opportunity when an opportunity is created. The value of these fields is based on the owner of the opportunity record.


The trigger functions properly in all use cases except when a lead is converted. For some reason the OwnerId of the Opportunity is the running user when the trigger executes instead of the Id set in the LeadConvert obj. This really perplexes me as I specifically set the OwnerId via the setOwnerId() method in my unitTest before calling the convertLead method.


Could anyone shed some light on to why the ownerId's are not being properly set?



trigger SetOpportunityOwnerManager on Opportunity (before insert, before update) 
//Create unique set of ownerId's
Set<ID> ownerIds = new Set<ID>();
for(Opportunity o :
system.debug('OWNERID: ' + o.OwnerId);

//Business logic to run ONLY on Insert
//Create map of OwnerId's to their corresponding manager's
Map<ID, User> userMap = new Map<ID, User>([SELECT Id, Name, ManagerId, Processor__c, InterchangeDirector__c FROM User WHERE Id IN :ownerIds]);

//Set the manager field on the list of opportunities
for(Opportunity o :
system.debug('***updating ' + o.Name);
o.OwnerManager__c = userMap.get(o.OwnerId).ManagerId;
o.Processor__c = userMap.get(o.OwnerId).Processor__c;
o.InterchangeDirector__c = userMap.get(o.OwnerId).InterchangeDirector__c;


Here is my unit test:


//create lead
Lead l = new Lead();
l.OwnerId = RAM.Id;
l.Status = 'Fresh';
l.Company = 'Test Co.';
l.FirstName = 'Jonny';
l.LastName = 'Quest';
l.Phone = '(480) 123-4567';
insert l;

//start testing

//verify lead owner information
Lead lTest = [SELECT Id, OwnerId FROM Lead WHERE Id=:l.Id];
system.assertEquals(RAM.Id, lTest.OwnerId); //PASSED

//convert lead
Database.Leadconvert lc = new database.Leadconvert();
lc.setConvertedStatus('QC Verified');

Database.Leadconvertresult lcr = database.convertLead(lc);

//verify lead successfully converted
system.assert(lcr.isSuccess()); //PASSED

//verify manager, icd, & processor fields were populated on the created opportunity
Opportunity o = [SELECT Id, OwnerId, OwnerManager__c, InterchangeDirector__c, Processor__c FROM Opportunity WHERE Id=:lcr.getOpportunityId()];
system.assertEquals(RAM.Id, o.OwnerId); //PASSED
system.assertEquals(ISM.Id, o.OwnerManager__c); //FAILED
system.assertEquals(icd.Id, o.InterchangeDirector__c);
system.assertEquals(Processor.Id, o.Processor__c);

//end testing



Thanks in advance!


What happens if you move the test.stopTest(); directly after the lead conversion, before your assertions? Maybe there is some post processing stuff that hasn't run yet.


EDIT: does the trigger work when you convert through the normal UI or is just your test failing?


Both my testing and the UI fail. It uses the information of the running user instead of the record owner.


Did some more digging and I have confirmed the behavior you describe. In my testing I did get this error message once when I set the owner Id to a user that did not have opp access:


System.DmlException: ConvertLead failed. First exception on row 0; first error: TRANSFER_REQUIRES_READ, The new owner must have read permission: []


The wording of this error message makes me think that the records are created with the current user and then the ownership is transferred. This appears to be happening outside the context of all before and after insert triggers.


I think if you move the trigger logic to an asynchrounous @future method everrything should work ok.




We've been seeing the same thing as well.  That is the Owner during opportunity triggers is the running user and NOT the assigned owner of the lead convert process.


I've not found this documented anywhere.  Where do we log it as a bug? ;o)