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
Linda 98Linda 98 

URGENT!!!!Help with trigger firing twice.Unable to take for inside for loop

I am a trigger which is firing twice so i am able to see four records instead of two in debug log.

below is my code.I am having a for loop inside a for loop which i am not able to avoid.
Please correct me what is my mistake.

Customplan is a custom object which is created when opportunity stage is chnaged to plan ready.Now i wamt to split amount with plans starting from today,I am having four plans with start date -Oct,Nov,dec,jan 
In this case i should update only dec and jan plan by calcuating amount for them.(dec has 26 days,jan has 31 days) 
 
trigger updateplans on Opportunity (after update) 
{
    List<customplan__c> CPList =new List<customplan__c>();
    List<customplan__c> updatedlist =new List<customplan__c>();
    List<id> oppid =new List<id>();
    Integer noOfMonths,dINM,noOfDays,startMonth; 
    Opportunity Oldopp =new opportunity();
    Date eD,endD,endDate;
    Date startDate,strD;
        
  
    for(opportunity O: trigger.new){
            oppid.add(O.id);
            oldOpp = Trigger.oldMap.get(O.Id);
      }
      
  CPList=[select startdate__c,enddate__c from customplan__c where opportunity__c =: oppid and enddate__c  > today];
  
    for(opportunity op:trigger.new){
       if(Op.stagename=='Plan ready' && oldopp.stagename != Op.stagename && (Op.amount__c !=null && Op.amount__c >0))
       {
           if(Op.End__c != null)
               {
                   noOfMonths = system.today().monthsBetween(op.Base_Project_End__c);    
               }   
           if(noOfMonths != Null & noOfMonths > 0)
               {
               startDate = system.today();
               enddate=op.Start__c;      
               } 
            for(Integer i = 0; noOfMonths >= i; i++){
                if(i > 0)
                {
                endD = endDate;
                startDate = endD.addDays(1);
                }
                strD = startDate;
                dINM = date.daysInMonth(startDate.year(), (i < 0?
                (strD.month()+1):startDate.month()));
                endDate = Date.newInstance(startDate.year(), startDate.month(), dINM);
                eD= (i > 0)?(endDate > Op.End__c?
               Op.End__c:endDate):endDate;  
                noOfDays = startDate.daysBetween(ED)+1;    
                /*** this i am unable to get outside. ****/
                for(customplan__c rp: rplist){
                 rp.PlanAmount__c=Op.amount__c/op.Numberofdays__c*noofdays ;     //op.numberofdays__c is a formula field which calculates op.End__c -Today()+1    (total days present)
                 updatedlist.add(rp);            
                }
            }          
       }
    }   
    Update updatedlist ;  
}
Thank you,
 
Marcelo CostaMarcelo Costa

Hi Linda,
What is happening is that you are creating a recursive call to the trigger.
If your requirement is to run the trigger only once, you can create a control class with a static variable to control such scenario.
check this link for salesforce documentation on the subject:
https://help.salesforce.com/articleView?id=000133752&language=en_US&type=1
Another tip, is never to have logic on the trigger itself. best practices states that we should use a trigger handler, and only set the trigger context (in case of multiple trigger context) on the trigger class...
Good Luck.

Linda 98Linda 98
Hi Marcelo,

I tried using this.
https://help.salesforce.com/articleView?id=000133752&language=en_US&type=1
 but still i get same way.
Error is duplicate id .

I am sorry but I didnt get what is your second tip.
 
Linda 98Linda 98
I changed my code like this.
eD= (i > 0)?(endDate > Op.End__c?
               Op.End__c:endDate):endDate; 
                noOfDays = startDate.daysBetween(ED)+1;   
                /*** this i am unable to get outside. ****/
              if(checkRecursion.runOnce())
              {
                for(customplan__c rp: rplist){
                 rp.PlanAmount__c=Op.amount__c/op.Numberofdays__c*noofdays ;     //op.numberofdays__c is a formula field which calculates op.End__c -Today()+1    (total days present)
                 updatedlist.add(rp);           
                }
}
            }         
       }
    }  
    Update updatedlist ; 
}


when i do this,loop is running only once and updating all the records with first value.
Linda 98Linda 98
I also tried to use map in my code.
mymap.putall(updatedlist);


then check size and then update the values.

This doesnt give any error but as i am looping through 2 records,in debug log its showing 4 records.


How can i overcome this?Not able to figure it out where i am making mistake.

please help.