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
Eric Blaxton.ax1862Eric Blaxton.ax1862 

Trigger help with Opportunity and Opportunity team members

Hi and thank you in advance.

 

 

The situation:

 

I have a 2 custom  fields on opportunity object.  I want to populate these 2 fields with information from the Opportunity Team Member object...Names of the users that fall under a particular role.

 

I think im tired, but this is not making sense to me.  Can you point me in the right direction?

 

 

Best Answer chosen by Admin (Salesforce Developers) 
Eric Blaxton.ax1862Eric Blaxton.ax1862

In case someone needs this the code that works and was implemented (Thanks Maros)

 

trigger

InsertOppTeam2QuoteRequest onOpportunityTeamMember (afterinsert, afterupdate) {

//Using set to be able to work with setOpp and setOTM SETS

set<Id> setOpp = newset<Id>();

set<Id> setOTM = newset<Id>();

 

 

for (OpportunityTeamMember oppTeam : trigger.new) {

  setOpp.add(oppTeam.OpportunityId);

  setOTM.add(oppTeam.id);

  }

//Loop through opportunity team members and grab Users who have these roles 'Primary TA' or 'Inside Sales Support'.

 

list<OpportunityTeamMember> listOTM  = newlist<OpportunityTeamMember>     

    ([

SELECT Id, UserId, OpportunityId,  TeamMemberRole, User.NameFROMOpportunityTeamMemberWHERE Id in :setOTM AND

                         (TeamMemberRole =

'yyy' OR TeamMemberRole = 'xxx') ]);

 

                                                    

// Create a map that grabs the Opportunity Id being worked with

  Map<Id,

Opportunity> mapOpps = newmap<Id, Opportunity>([SELECT Id FROMOpportunityWhere Id = :setOpp ]) ;

  

Opportunity tempOpp;

 

   

//Load the ID's

for(OpportunityTeamMember otm : listOTM ){

        tempOpp = mapOpps.

get(otm.OpportunityId);

         

if(otm.TeamMemberRole == 'yyy') {

              tempOpp.Inside_Sales__c = otm.UserId;

          }

elseif(otm.TeamMemberRole == 'xxx') {

              tempOpp.Technical_Architect__c = otm.UserId;

             }

 

         }      

  

// Load values

  

update mapOpps.values();

}

 

Thanks again to Maros

All Answers

Maros SitkoMaros Sitko
Have you try workflow? Put workflow on Opp team member object, and if user has your role, copy name to opportunity fields. But when you add new opp team member with the same role, fields on Opportunity will be rewritten with the new values. If you do not want it, you must create trigger, with logic when to rewrite your fields (or append names)
Eric Blaxton.ax1862Eric Blaxton.ax1862
Thank you, I will definitely set this up.

For my learning, can you provide the trigger for how to rewrite these fields?
Maros SitkoMaros Sitko
I am sorry, but it will take more time for me, because I don't want to publish trigger which is not perfect for 100%. But here is some points:
- trigger for before/after insert and update on Opp Team member object
- if update, check if role on OTM was changed - if not, you do not need to run trigger
- go throw OTMs and put into map all OTM which has your role
- select Opportunities, which you will update based on previous map
- update list of opportunities
- done
- DO NOT forget to make trigger for working in BULK!
Eric Blaxton.ax1862Eric Blaxton.ax1862
That is great. Concerning the previous question...I don't see how I can update the Opportunity object from a workflow on the Opportunity Team Member object... I only see the options to allow for updating of fields on the same object the workflow is on.
Maros SitkoMaros Sitko
wired. I don't see other fields too. So you must create trigger :(
Eric Blaxton.ax1862Eric Blaxton.ax1862

Ok. i will write a trigger based on your suggestions.  Thanks again and I will repost the trigger in a little bit.

Eric Blaxton.ax1862Eric Blaxton.ax1862

Here is my UNFINISHED code:  I am having trouble with understanding how to get the name of the OpportunityTeamMember into the actual fields on the Opportunity.

 

trigger

InsertOppTeam onOpportunityTeamMember (afterinsert, afterupdate) {

Map<Id,

OpportunityTeamMember> otmMap = new Map<Id, OpportunityTeamMember>

   ([

SELECT Id, UserId FROMOpportunityTeamMemberWHERE TeamMemberRole = 'Primary TA'OR TeamMemberRole = 'Inside Sales Support' ]);

 

     

for (OpportunityTeamMember oppTeam : trigger.new) {           

           

Opportunity opp = [SELECT Id  FROMOpportunityWhere Id = :oppTeam.OpportunityId ] ;          

                  

          

           opp.Inside_Sales__c = otmMap.  ;

            }

          

}

Maros SitkoMaros Sitko

you can put user.Name into your select

SELECT Id, UserId, User.Name FROMOpportunityTeamMemberWHERE TeamMemberRole = 'Primary TA'OR TeamMemberRole = 'Inside Sales Support' ]);

but your trigger is not good.

 

This is better, but be carefull it's only quick written trigger, there can be mistakes, and there is no check if you need change Inside_Sales__c field, if you have more OTM on one Opp there is no rule which should be in your fields, ect....

 

trigger InsertOppTeam onOpportunityTeamMember (afterinsert, afterupdate) {

	set<Id> setOpp = new set<Id>();
	set<Id> setOTM = new set<setOTM>();
	for (OpportunityTeamMember oppTeam : trigger.new) { 
		setOpp.add(oppTeam.OpportunityId);
		setOTM.add(oppTeam.id);
	}          

	list<OpportunityTeamMember> lstOTM = new list<OpportunityTeamMember>([SELECT Id, UserId, OpportunityId, User.Name FROM OpportunityTeamMember WHERE Id in :setOTM AND (TeamMemberRole = 'Primary TA'OR TeamMemberRole = 'Inside Sales Support') ]);

	Map<Id,Opportunity> mapOpps = new map<Id, Opportunity>([SELECT Id FROM OpportunityWhere Id = :setOpp ]) ;          
	Opportunity tempOpp;
	for(OpportunityTeamMember otm : lstOTM ){
		tempOpp = mapOpps.get(otm.OpportunityId);
		tempOpp.Inside_Sales__c = otm.Name;
	}
	update mapOpps.values();  

} 

 

If you need more explanation, you can contact me

 

Eric Blaxton.ax1862Eric Blaxton.ax1862

Once again...thanks for your help.

 

There is a problem that lies with this line of code:  set<Id> setOTM = new set<setOTM>();

 

The compiler does not like the <setOTM> part. 

 

I changed the line to: set <Id> setOTM = newset<Id>();

 

then this line of code did not work because it is not an actual field on the Opportunity Team Member object. 

 

tempOpp.Inside_Sales__c = otm.Name;

 

Let me know if I need to clarify.

 

Eric Blaxton.ax1862Eric Blaxton.ax1862

Hi Maros,

 

I have been able to make this work, except if there are different person for the 'Inside Sales Support' and 'Primary TA' role.

 

Do I need to add the results into an Array and then interate through it?

 

or

 

How would you accomplish this?

 

Eric

Maros SitkoMaros Sitko
I am sorry about my mistakes, it was quick written in notepad :D
You are great if you solve it.
You must insert logic in it to loop 'for(OpportunityTeamMember otm : lstOTM ){' for decide who should be copied. I do not know how you want do it. Do you want both? or only Primary TA? what if you have more Primary TA? ect..
Eric Blaxton.ax1862Eric Blaxton.ax1862

I don't see any mistakes my friend....I am very grateful.

 

Yes, I am wanting to insert the Primary TA and the Inside Sales Support for each opp team.

 

Thanks again,

Maros SitkoMaros Sitko

If you want add both names (or all) this should help, replace
tempOpp.Inside_Sales__c = otm.Name; (or corrected version tempOpp.Inside_Sales__c = otm.User.Name;)
with
tempOpp.Inside_Sales__c = tempOpp.Inside_Sales__c + ',' + otm.User.Name;

and before loop 'for(OpportunityTeamMember otm : lstOTM ){' add one more loop for cleaning Inside_Sales__c fields. (it helps to synchronize list, if you remove some OTM, or to prevent have one name more time)
for(OpportunityTeamMember otm : lstOTM ){
   tempOpp.Inside_Sales__c = null;
}

so it will be

for(OpportunityTeamMember otm : lstOTM ){
   tempOpp.Inside_Sales__c = null;
}

for(OpportunityTeamMember otm : lstOTM ){
        tempOpp = mapOpps.get(otm.OpportunityId);
        tempOpp.Inside_Sales__c = tempOpp.Inside_Sales__c + ',' + otm.User.Name;
}

 

if you need more help with your development, you can directly contact me on maros.sitko@cassacloud.com

 

Eric Blaxton.ax1862Eric Blaxton.ax1862

In case someone needs this the code that works and was implemented (Thanks Maros)

 

trigger

InsertOppTeam2QuoteRequest onOpportunityTeamMember (afterinsert, afterupdate) {

//Using set to be able to work with setOpp and setOTM SETS

set<Id> setOpp = newset<Id>();

set<Id> setOTM = newset<Id>();

 

 

for (OpportunityTeamMember oppTeam : trigger.new) {

  setOpp.add(oppTeam.OpportunityId);

  setOTM.add(oppTeam.id);

  }

//Loop through opportunity team members and grab Users who have these roles 'Primary TA' or 'Inside Sales Support'.

 

list<OpportunityTeamMember> listOTM  = newlist<OpportunityTeamMember>     

    ([

SELECT Id, UserId, OpportunityId,  TeamMemberRole, User.NameFROMOpportunityTeamMemberWHERE Id in :setOTM AND

                         (TeamMemberRole =

'yyy' OR TeamMemberRole = 'xxx') ]);

 

                                                    

// Create a map that grabs the Opportunity Id being worked with

  Map<Id,

Opportunity> mapOpps = newmap<Id, Opportunity>([SELECT Id FROMOpportunityWhere Id = :setOpp ]) ;

  

Opportunity tempOpp;

 

   

//Load the ID's

for(OpportunityTeamMember otm : listOTM ){

        tempOpp = mapOpps.

get(otm.OpportunityId);

         

if(otm.TeamMemberRole == 'yyy') {

              tempOpp.Inside_Sales__c = otm.UserId;

          }

elseif(otm.TeamMemberRole == 'xxx') {

              tempOpp.Technical_Architect__c = otm.UserId;

             }

 

         }      

  

// Load values

  

update mapOpps.values();

}

 

Thanks again to Maros

This was selected as the best answer