You need to sign in to do that
Don't have an account?
Trigger to create an opportunity team member from lead conversion
I wrote a Trigger on Lead that creates an Opportunity Team Member when a Lead is converted and it has ConvertedOpportunityId. The Opportunity Team Member should have UserId = Lead OwnerId and has a specific role (for example - "Account Manager").
I tested converting a Lead that was owned by me and the Opportunity was created with an Opportunity Team Member = me and role was Account Manager, so I thought the Trigger worked fine. Then I tested converting a Lead that was owned by another user. The Opportunity was created with the same owner as the Lead Owner, but there was no Opportunity Team Member. I added some debug statements to catch if the Opportunity Team Member was really created and it did (at least) in the debug log. One of the debugs showed that the Opportunity Team Member was created from the Trigger and it had me (the person who converted the Lead) as the Member. Another debug showed that I was the Opportunity Owner, but when I checked in the UI, the Opportunity Owner was actually the other user.
Here is my Lead Trigger.
Trigger Lead on Lead (before insert, before update) { if (Trigger.isBefore) { if (Trigger.isUpdate) { Set<Id> setLeadIds = new Set<Id>(); Set<Id> setConvertedOppIds = new Set<Id>(); for (Lead ld : Trigger.new) { // Find all converted Leads with Opportunitiy and add ConvertedOpportunityId to setConvertedOppIds if (ld.isConverted && ld.ConvertedOpportunityId != null && Trigger.oldMap.get(ld.Id).ConvertedOpportunityId != ld.ConvertedOpportunityId) setConvertedOppIds.add(ld.ConvertedOpportunityId); } if (!setConvertedOppIds.isEmpty()) { List<OpportunityTeamMember> lstOppTeams = new List<OpportunityTeamMember>(); // Get Opportunities that created from the Lead conversion List<Opportunity> lstConvertedOpps = [select Id, OwnerId from Opportunity where Id in :setConvertedOppIds]; if (lstConvertedOpps.size() > 0) { for (Opportunity opp : lstConvertedOpps) { OpportunityTeamMember otm = new OpportunityTeamMember( TeamMemberRole = 'Account Manager', OpportunityId = opp.Id, UserId = opp.OwnerId); lstOppTeams.add(otm); } // Insert Opportunity Team if (!lstOppTeams.isEmpty()) { for (Opportunity opp : lstConvertedOpps) { System.debug('===== before inserting OTMs, opp = ' + opp); } System.debug('===== inserting OTMs: ' + lstOppTeams); insert lstOppTeams; for (OpportunityTeamMember otm : [select id, UserId, TeamMemberRole from OpportunityTeamMember where OpportunityId in :setConvertedOppIds]) System.debug('===== OTM after insert: ' + otm); lstConvertedOpps = [select Id, OwnerId from Opportunity where Id in :setConvertedOppIds]; for (Opportunity opp : lstConvertedOpps) { System.debug('===== after inserting OTMs, opp = ' + opp); } } } } } } }
So, I wonder if we can really write a Trigger on Lead that creates an Opportunity Team Member that belongs to a different user?
Also, can we catch what happens during the Lead Conversion, like why there seems to be some opportunity owner changing during that time but we couldn't really see that?
Out of the curiousity, I wrote a Trigger on Opportunity just for debug to see if I could catch the opportunity change. Strangely, I was unable to do that. The debugs only showed that I was the opportunity owner right before Insert and also after insert. Nothing showed that the other user was the opportunity owner until I checked in the UI.
Here is the opportunity Trigger.
Trigger Opportunity on Opportunity (after insert, after update, before insert, before update) { String str = ''; str += (Trigger.isBefore) ? 'Before ' : 'After '; if (Trigger.isInsert) str += 'Insert: '; if (Trigger.isUpdate) str += 'Update: '; for (Opportunity opp : Trigger.new) { System.debug('===== ' + str + ' Opp Id=' + opp.id + ' OwnerId=' + opp.OwnerId); } }
I contacted Salesforce support and he gave me this resolution below:
Resolution:
The Order of operations for Lead Convert is something like this:
• Account created, triggers/workflow fire • Contact created, triggers/workflow fire • Opportunity created, triggers/workflow fire • Owners are reparented
The workaround is to use an @future method for the new opportunity, as @future fires after the correct owner is assigned for the Opportunity.
I updated my code to use the @future method and it worked! A caveat from using @future is we can run into the governor limit that only allows 200 @future method calls per one full license user, per 24 hours.
Class for creating Opportunity Team Member:
Trigger that calls the class above:
I also used static variable to store the state of the trigger processing that prevents recursive future method calls (thanks to Jeff Douglas's blog).
All Answers
Funny, we just finished getting the bugs out of a trigger as well that automatically builds an opportunity team on the opportunity based on a lookup on the opportunity called "Team", which references a custom object I made called "Team" with a child object called "Team Members" where you can create all the team members on your team (each team member record references a user) and that way you can set your team on the lead, and once the opportunity is made, it automatically builds all the members who are a part of your team and sets the access level defined in their Team Member record, along with their default role, etc.
Some advice I should probably give you based on a lot of frustration, is that by default, any Opportunity Team Member records you create will have Read-Only permissions. If you wish to give team members Read/Write permissions, then you need to insert a record in to the OpportunityShare object with an access level of "Edit" for that user. Also, if the opportunity owner also happens to be one of the OpportunityTeamMembers that are getting added, you need to leave out the OpportunityShare record that gets created for that team member or else the trigger will error (because salesforce adds an OpportunityShare record automatically for the opportunity owner, which will conflict with the OpportunityShare record that the trigger tries to create if the Opportunity Owner is also one of the Team Members). It was kind of tricky but eventaully we got all the bugs out.
I don't know if it's of any help, but here's the final trigger we made:
Test Class:
I contacted Salesforce support and he gave me this resolution below:
Resolution:
The Order of operations for Lead Convert is something like this:
• Account created, triggers/workflow fire • Contact created, triggers/workflow fire • Opportunity created, triggers/workflow fire • Owners are reparented
The workaround is to use an @future method for the new opportunity, as @future fires after the correct owner is assigned for the Opportunity.
I updated my code to use the @future method and it worked! A caveat from using @future is we can run into the governor limit that only allows 200 @future method calls per one full license user, per 24 hours.
Class for creating Opportunity Team Member:
Trigger that calls the class above:
I also used static variable to store the state of the trigger processing that prevents recursive future method calls (thanks to Jeff Douglas's blog).