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
LiorGLiorG 

Confusing behavior from trigger

My trigger is this:

 

trigger RBOppClone on Opportunity (after update) {
        
        Set<Opportunity> oppSet = new Set<Opportunity>();
        for (Opportunity oppRec: trigger.new) {
            oppSet.add(oppRec);
        }
        
        for (Opportunity oppRec: oppSet) {
            Opportunity oldOpp = trigger.oldMap.get(oppRec.Id);
            if (oppRec.Product_Sold__c == 'Business Product' &&
               oppRec.StageName == 'Stage 5 - Closed - Won' &&
               oldOpp.StageName != 'Stage 5 - Closed - Won') {
                Opportunity newOpp = oppRec.clone();
                newOpp.StageName = 'Referral Credit - Dummy Stage';
                if (oppRec.Amount == null || oppRec.Amount < 50.00) {
                    newOpp.Amount = 500;
                } else {
                    newOpp.Amount = 1000;
                }
                insert newOpp;
            }
        }

}

 

Sometimes 2 opportunities are inserted instead of one in the same update. Anyone know why this might be happening? Also, I'm aware this trigger isn't bulk-uploads-safe.

Best Answer chosen by Admin (Salesforce Developers) 
sanjaypatidarsanjaypatidar
Trigger RBOppClone on Opportunity (after update) 
{
	List<Opportunity> OpptsList = new List<Opportunity>();
	
	for(Integer i = 0; i < trigger.new.size(); i++)
	{
		if(trigger.new[i].Product_Sold__c == 'Business Product' &&  Trigger.new[i].StageName == 'Stage 5 - Closed - Won' && Trigger.old[i].StageName != 'Stage 5 - Closed - Won')
		{
			Opportunity newOpp = new Opportunity();
			
			newOpp.StageName = 'Referral Credit - Dummy Stage';
                        newOpp.CloseDate = System.today();
                        newOpp.Name = 'TestName';
			
			if (Trigger.new[i].Amount == null || Trigger.new[i].Amount < 50.00) 
			{
				newOpp.Amount = 500;
			} 
			else 
			{
				newOpp.Amount = 1000;
			}
				
			OpptsList.add(newOpp);
		}
	}
	
	insert OpptsList;
}

 You need to have a Name and Close Date as well, while creating an Opp. Added the same.

All Answers

sanjaypatidarsanjaypatidar

You are using both the clone menthod and the insert method. that is the reason for the 2 Oppty creation.

LiorGLiorG

Oh, cloning auto-inserts?

Naidu PothiniNaidu Pothini
Trigger RBOppClone on Opportunity (after update) 
{
	List<Opportunity> OpptsList = new List<Opportunity>();
	
	for(Integer i = 0; i < trigger.new.size(); i++)
	{
		if(trigger.new[i].Product_Sold__c == 'Business Product' &&  Trigger.new[i].StageName == 'Stage 5 - Closed - Won' && Trigger.old[i].StageName != 'Stage 5 - Closed - Won')
		{
			Opportunity newOpp = Trigge.new[i];
			
			newOpp.StageName = 'Referral Credit - Dummy Stage';
			
			if (Trigger.new[i].Amount == null || Trigger.new[i].Amount < 50.00) 
			{
				newOpp.Amount = 500;
			} 
			else 
			{
				newOpp.Amount = 1000;
			}
				
			OpptsList.add(newOpp);
		}
	}
	
	insert OpptsList;
}

 Try this.

sanjaypatidarsanjaypatidar

True, the code above should be able to help you.

LiorGLiorG

There's a problem with your trigger.

 

AfterUpdate caused by: System.FinalException: Record is read-only: Trigger.RBOppClone: line 12, column 1

 

Referring to this line: 

newOpp.StageName = 'Referral Credit - Dummy Stage';
sanjaypatidarsanjaypatidar
Trigger RBOppClone on Opportunity (after update) 
{
	List<Opportunity> OpptsList = new List<Opportunity>();
	
	for(Integer i = 0; i < trigger.new.size(); i++)
	{
		if(trigger.new[i].Product_Sold__c == 'Business Product' &&  Trigger.new[i].StageName == 'Stage 5 - Closed - Won' && Trigger.old[i].StageName != 'Stage 5 - Closed - Won')
		{
			Opportunity newOpp = new Opportunity();
			
			newOpp.StageName = 'Referral Credit - Dummy Stage';
			
			if (Trigger.new[i].Amount == null || Trigger.new[i].Amount < 50.00) 
			{
				newOpp.Amount = 500;
			} 
			else 
			{
				newOpp.Amount = 1000;
			}
				
			OpptsList.add(newOpp);
		}
	}
	
	insert OpptsList;

 Try this

Naidu PothiniNaidu Pothini
Trigger RBOppClone on Opportunity (after update) 
{
	List<Opportunity> OpptsList = new List<Opportunity>();
	
	for(Integer i = 0; i < trigger.new.size(); i++)
	{
		if(trigger.new[i].Product_Sold__c == 'Business Product' &&  Trigger.new[i].StageName == 'Stage 5 - Closed - Won' && Trigger.old[i].StageName != 'Stage 5 - Closed - Won')
		{
			Opportunity newOpp = Trigge.new[i].clone(false,true);
			
			newOpp.StageName = 'Referral Credit - Dummy Stage';
			
			if (Trigger.new[i].Amount == null || Trigger.new[i].Amount < 50.00) 
			{
				newOpp.Amount = 500;
			} 
			else 
			{
				newOpp.Amount = 1000;
			}
				
			OpptsList.add(newOpp);
		}
	}
	
	insert OpptsList;
}

 

Try this.

sanjaypatidarsanjaypatidar
Trigger RBOppClone on Opportunity (after update) 
{
	List<Opportunity> OpptsList = new List<Opportunity>();
	
	for(Integer i = 0; i < trigger.new.size(); i++)
	{
		if(trigger.new[i].Product_Sold__c == 'Business Product' &&  Trigger.new[i].StageName == 'Stage 5 - Closed - Won' && Trigger.old[i].StageName != 'Stage 5 - Closed - Won')
		{
			Opportunity newOpp = new Opportunity();
			
			newOpp.StageName = 'Referral Credit - Dummy Stage';
                        newOpp.CloseDate = System.today();
                        newOpp.Name = 'TestName';
			
			if (Trigger.new[i].Amount == null || Trigger.new[i].Amount < 50.00) 
			{
				newOpp.Amount = 500;
			} 
			else 
			{
				newOpp.Amount = 1000;
			}
				
			OpptsList.add(newOpp);
		}
	}
	
	insert OpptsList;
}

 You need to have a Name and Close Date as well, while creating an Opp. Added the same.

This was selected as the best answer
sanjaypatidarsanjaypatidar

the one by Naidu is even better.  :smileyhappy:

LiorGLiorG

Naidu's didn't work. I had to create the opp like in your trigger. 

Naidu PothiniNaidu Pothini

But you might come up with a problem of having the cloned opportunities with same opportunity name, and in some cases you might not have all the data in the original opportunity in the cloned opportuntiy..

 

and i think, clone() will not insert the record by default.

 

LiorGLiorG

>and i think, clone() will not insert the record by default.

 

Then do you know why my original trigger inserted 2 opps?

Naidu PothiniNaidu Pothini

Did you check the debug log with your code? you might find something. 

 

Can you try once again with your code and check whther it is creating two records and in this case can you paste the debug log?

LiorGLiorG

The problem is intermittent. I haven't been able to reproduce it.