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
Will YeeWill Yee 

Trigger - Inserts new Opp after old Opp changes stage

Currently the trigger is creating 6 duplicate copies of the Opportunity instead of 1. Everything else seems to be working as intended though. 

It looks like its running multiple times through the second loop and adding 6 copies to the list, but shouldn't the "LIMIT 1" in the first section limit the "oppList" size to 1 record and the next 'for' loop only fire for one instance?

trigger insertNewOpp on Opportunity (after update) {

//create list of Opps
List<Opportunity> listOpp = new List<Opportunity>();

for(Opportunity opp : Trigger.new)
{
    //Make a list of all opps where Id is equal to that of the current opp
    List<Opportunity> oppList = [SELECT Id,AccountID,StageName,Primary_Contact__c, LeadSource, ForecastCategoryName, Name, CloseDate, RecordTypeId
        FROM Opportunity
        WHERE ID = :opp.Id
        LIMIT 1];
       
for(Opportunity oppi : oppList){
//if Opp is changed to Closed Won
   if(opp.StageName == 'Closed Won')
       {
           //Create a new opp with the following attributes
          Opportunity oppNew = new Opportunity (AccountID=oppi.AccountID, StageName='Prospecting', Primary_Contact__c=oppi.Primary_Contact__c, LeadSource=oppi.LeadSource, ForecastCategoryName='Omitted', Name=oppi.Name + 'New', CloseDate=oppi.CloseDate, RecordTypeId = '012d0000000SocP'); 
           //Add to the list
          listOpp.add(oppNew);
       }
       }
}
     
     if(listOpp.size() > 0)
     insert listOpp;
}
Best Answer chosen by Will Yee
Deepak RamaDeepak Rama
Could you refactor the trigger to look something like this:

trigger insertNewOpp on Opportunity (after update) {

//create list of Opps
List<Opportunity> listOpp = new List<Opportunity>();

for(Opportunity opp : Trigger.new)
{
// You do not need this as we already have list of opportunity

/*    //Make a list of all opps where Id is equal to that of the current opp
    List<Opportunity> oppList = [SELECT Id,AccountID,StageName,Primary_Contact__c, LeadSource, ForecastCategoryName, Name, CloseDate, RecordTypeId
        FROM Opportunity
        WHERE ID = :opp.Id
        LIMIT 1];*/
       
//if Opp is changed to Closed Won
   if(opp.StageName == 'Closed Won')
       {
           //Create a new opp with the following attributes
          Opportunity oppNew = new Opportunity (AccountID=oppi.AccountID, StageName='Prospecting', Primary_Contact__c=oppi.Primary_Contact__c, LeadSource=oppi.LeadSource, ForecastCategoryName='Omitted', Name=oppi.Name + 'New', CloseDate=oppi.CloseDate, RecordTypeId = '012d0000000SocP'); 
           //Add to the list
          listOpp.add(oppNew);
       }
       }
}
     
     if(listOpp.size() > 0)
     insert listOpp;
}


All Answers

Deepak RamaDeepak Rama
Could you refactor the trigger to look something like this:

trigger insertNewOpp on Opportunity (after update) {

//create list of Opps
List<Opportunity> listOpp = new List<Opportunity>();

for(Opportunity opp : Trigger.new)
{
// You do not need this as we already have list of opportunity

/*    //Make a list of all opps where Id is equal to that of the current opp
    List<Opportunity> oppList = [SELECT Id,AccountID,StageName,Primary_Contact__c, LeadSource, ForecastCategoryName, Name, CloseDate, RecordTypeId
        FROM Opportunity
        WHERE ID = :opp.Id
        LIMIT 1];*/
       
//if Opp is changed to Closed Won
   if(opp.StageName == 'Closed Won')
       {
           //Create a new opp with the following attributes
          Opportunity oppNew = new Opportunity (AccountID=oppi.AccountID, StageName='Prospecting', Primary_Contact__c=oppi.Primary_Contact__c, LeadSource=oppi.LeadSource, ForecastCategoryName='Omitted', Name=oppi.Name + 'New', CloseDate=oppi.CloseDate, RecordTypeId = '012d0000000SocP'); 
           //Add to the list
          listOpp.add(oppNew);
       }
       }
}
     
     if(listOpp.size() > 0)
     insert listOpp;
}


This was selected as the best answer
James LoghryJames Loghry
The killer was you had a loop within a loop.  So essentially you were creating n^2 Opportunities, but also querying inside a loop which would invoke a governor limit.  Deepak's code should help direct you towards a solution to your duplicate issue.
Will YeeWill Yee
I've went and refracted the code so it looks like this now. Still getting the same issue with 6 new duplicate opps.

trigger insertNewOpp2 on Opportunity (after update) {

//create list of Opps
List<Opportunity> listOpp = new List<Opportunity>();

for(Opportunity opp : Trigger.new)
{
       
//if Opp is changed to Closed Won
   if(opp.StageName == 'Closed Won')
       {
           //Create a new opp with the following attributes
          Opportunity oppNew = new Opportunity (AccountID=opp.AccountID, StageName='Prospecting', Primary_Contact__c=opp.Primary_Contact__c, LeadSource=opp.LeadSource, ForecastCategoryName='Omitted', Name=opp.Name + 'New', CloseDate=opp.CloseDate, RecordTypeId = '012d0000000SocP'); 
           //Add to the list
          listOpp.add(oppNew);
       }
       }
     if (listOpp.size() > 0)
     insert listOpp;
}


Deepak RamaDeepak Rama
Seems like there might be other triggers on Opportunity object. Could you verify if this is the case?
Will YeeWill Yee
Deepak, you're correct. I'll have to revist these other triggers before proceeding with this one .Thanks for the help!
Deepak RamaDeepak Rama

Hi Will,

Could you mark this question as resolved and possibly pick best answer.
 

Thanks,
Deepak.