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
alaschgarialaschgari 

OpportunityTeamMember data is deleted, if I change opportunity owner

Hey folks,

 

I experience a OpportunityTeamMember data deletion, if I change the owner of the opportunity.

How can I prevent this? Even with a new owner I want to keep the opportunity team!

 

Thank you ver much

Josh :-)

sfdcfoxsfdcfox

That's the default behavior. I believe you'd have to use an asynchronous call to load those team members back in after they are deleted, but I haven't specifically experimented with this.

alaschgarialaschgari

Hey sfdcfox,

thanks for the reply. I found a solution.

I got inspired by another board post where the post creator described the same behavior with OpportunityShare objects:

The Opportunity Team Members are stored in a text field and after the update a parser reads the text field and rebuilds the objects.

 

Here's my adapted solution:

 

	if(trigger.isBefore)
	{
		if(trigger.isUpdate)
		{
			//Execute methods
hlpr_Opportunity.storeOppTeamMembers(trigger.oldMap, trigger.newMap); } } if(trigger.isAfter) { if(trigger.isInsert) { hlpr_Opportunity.setOppTeamMembers(null, trigger.newMap); } if(trigger.isUpdate) { hlpr_Opportunity.setOppTeamMembers(trigger.oldMap, trigger.newMap); } }

 

 

	public static void storeOppTeamMembers(map<Id, Opportunity> oldMap, map<Id, Opportunity> newMap)
	{
		if(oldMap != null && newMap != null)
		{
			Id oId;
			
			map<Id, list<OpportunityTeamMember>> mapOTMs = new map<Id, list<OpportunityTeamMember>>();
			list<OpportunityTeamMember> lstOTMs = new list<OpportunityTeamMember>();
	                 						 
			hlpr.debug('## hlpr_Opportunity storeOppTeamMembers lstOTMs: ' + lstOTMs);
			
	        for(OpportunityTeamMember otm : [SELECT o.UserId, o.OpportunityId, o.OpportunityAccessLevel, o.Provision__c
	                 						 FROM OpportunityTeamMember o
	                 						 WHERE o.OpportunityId =: newMap.keySet()
	                 						 ORDER BY OpportunityId])
			{
				if(oId == null)
					oId = otm.OpportunityId;
					
				if(oId == otm.OpportunityId)
					lstOTMs.add(otm);
				else
				{
					mapOTMS.put(oId, lstOTMs);
					oId = otm.OpportunityId;
					lstOTMs = new list<OpportunityTeamMember>();
					lstOTMs.add(otm);
				}
			}
			
			if(!lstOTMs.isEmpty())
				mapOTMS.put(oId, lstOTMS);
			
			hlpr.debug('## hlpr_Opportunity storeOppTeamMembers mapOTMS: ' + mapOTMS);
			
			for (Opportunity Opp : newMap.values())
			{
	            if (oldMap.get(Opp.id).OwnerId != Opp.OwnerId)
	                Opp.OpportunityTeamMembers__c = String.valueOf(mapOTMs.get(Opp.Id));
	                
				hlpr.debug('## hlpr_Opportunity storeOppTeamMembers Opp.OpportunityTeamMembers__c: ' + Opp.OpportunityTeamMembers__c);
			}
		}
	}
	
	public static void setOppTeamMembers(map<Id, Opportunity> mapOppsOld, map<Id, Opportunity> mapOppsNew)
	{
  		OpportunityTeamMember otm;
  		
  		list<OpportunityTeamMember> lstOTMs = new list<OpportunityTeamMember>();
		list<Schema.PicklistEntry> lstPickVals = hlpr.getPicklistValuesFromObjectField('OpportunityTeamMember', 'TeamMemberRole');
		String tmRole = lstPickVals[0].getValue();
  		
  		if(mapOppsOld != null)
  		{
	  		//Insert old team members
	  		for (Opportunity Opp : mapOppsNew.values())
	  		{
	            // Only if the record owner changed
	            if (mapOppsOld.get(Opp.id).OwnerId != Opp.OwnerId)
				{            	
	                hlpr.debug('## hlpr_Opportunity setOppOwnerTeamMember Opp.OpportunityTeamMembers__c: ' + Opp.OpportunityTeamMembers__c);
	                // Get all the opp team members in a string
	                String lstElements = Opp.OpportunityTeamMembers__c != null ? Opp.OpportunityTeamMembers__c : '';
	                // Work on the string to keep only the pertinent info
	                String regex = 'OpportunityTeamMember\\:\\{';
	                String[] lstElementsTab = lstElements.split(regex);
	                    
	                for(Integer j = 1; j<lstElementsTab.size(); j++)
	                {
	                    // Create the new opp team member with the stored data
	                    otm  = new OpportunityTeamMember();
	                    String[] elements = lstElementsTab[j].trim().split('\\,');
	
	                    for(Integer k = 0; k<elements.size(); k++)
	                    {
	                        if(elements[k].contains('OpportunityId')){
	                            otm.OpportunityId = (Id)elements[k].split('\\=')[1].trim();
	                        }
	                        if(elements[k].contains('UserId')){
	                            otm.UserId = (Id)elements[k].split('\\=')[1].trim().substring(0,15);
	                        }
	                        if(elements[k].contains('Provision__c')){
	                            otm.Provision__c = Decimal.valueOf(elements[k].split('\\=')[1].trim());
	                        }
	                    }
	                    
	                    lstOTMs.add(otm);
					}
	  			}
	  		}
		}
		
		hlpr.debug('## hlpr_Opportunity setOppTeamMembers lstOTMs: ' + lstOTMs);
	  		
		for(Opportunity o : mapOppsNew.values())
		{
			otm = new OpportunityTeamMember();
			otm.UserId = o.OwnerId;
			otm.OpportunityId = o.Id;
			otm.Provision__c = lstOTMs.isEmpty() ? 100 : 0;
			otm.TeamMemberRole = tmRole;
			lstOTMs.add(otm);
		}
		
		hlpr.debug('## hlpr_Opportunity setOppTeamMembers lstOTMs: ' + lstOTMs);
		
		if(!lstOTMs.isEmpty())
			insert lstOTMs;
	}

 

Have fun!

Josh :-)

sfdcfoxsfdcfox

Well, as long as it's all happening in the same transaction, you wouldn't need a field to store this information; a simple static map would suffice, as they survive across triggers within the same transaction, but nevertheless, I like it.

alaschgarialaschgari

Really?

I didn't know that. I will check that out soon! Thanks!!!

sfdcChi2sfdcChi2
hello alaschgari,

will the above code work in my org as is or is there something i will need to change to get it to work? i am facing the exact same issue and would like to keep the old opportunity team members even when the opportunity owner is changed
sfadmin 131sfadmin 131
Can anyone confirm this trigger works in any org as is? This is driving me crazy!
Sulabh KapoorSulabh Kapoor
I was facing the same issue and worked with Salesforce on this. There is an idea - https://success.salesforce.com/ideaView?id=08730000000l2tQAAQ which you can vote. I have implemented this using asynchronous job (using queueable).
Vinutha GP 6Vinutha GP 6
Hi @Sulabh Kapoor, how did you implement this using synchronous job?