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
34213421 

List out of bounds exception

I am trying to change the Opportunity Line Item schedule when a custom field is changed. The schedule works fine when the field is eneterd, but when I edit the custom field it throws the exception

Here is the trigger and the class

Trigger
 
trigger OpportunityReScheduling on Opportunity (after update, before update, after insert) 
    {
        for (Opportunity o: Trigger.new)
        {
            if (Trigger.isBefore)
            {
                if(o.Category__c == 'Solutions'){
                Opportunity prevOpportunity = Trigger.oldMap.get(o.ID);
                    if(o.Effective_Date__c <> null){
                if (o.Effective_Date__c != prevOpportunity.Effective_Date__c) 
                {
                    Integer DayDiff = prevOpportunity.Effective_Date__c.daysBetween(o.Effective_Date__c);

                    OpportunitySchedulingHandler.ScheduleDateUpdate(o.id, DayDiff);
                }
            }
            }
            }
        }
    }

CLass
public with sharing class OpportunitySchedulingHandler {

     //Update LineItemSchedule dates for all scheduling dates

    public static void ScheduleDateUpdate(String oppid, Integer DayDiff) 
    {
       List<OpportunityLineItem> idval = [SELECT id FROM OpportunityLineItem WHERE OpportunityId=:oppid];
       List<OpportunityLineItemSchedule> datelist = new List<OpportunityLineItemSchedule>();
       for (Integer i = 0; i < idval.size(); i++)
       {
           datelist = [SELECT ScheduleDate FROM OpportunityLineItemSchedule WHERE OpportunityLineItemId =:idval[i].id];
           Date firstDate = datelist[0].ScheduleDate.addDays(DayDiff);
           datelist[0].ScheduleDate = firstDate;

           Integer day = firstDate.day();
           Integer month = firstDate.month();
           Integer year = firstDate.year();

           for (Integer k = 1; k < datelist.size(); k++)
           {
               Integer nYear = year;
               Integer nMonth = month + k;
               Integer nDay = day;

               if (nMonth > 12) {
                   nMonth = nMonth - 12;
                   nYear = nYear + 1;
               }

               Set<Integer> longMonths = new Set<Integer> {1,3,5,7,8,10,12};

               if (nDay == 31 && ! longMonths.contains(nMonth)) {
                   nDay = 30;
               }

               if (nDay > 28 && nMonth == 2) {
                   nDay = 28;
               }

               Date mydate = date.newInstance(nYear,nMonth,nDay);
               datelist[k].ScheduleDate = mydate;
           }
           if(!datelist.isEmpty())
           {
                update datelist;
           }
        }
    }    
}
I did try null check for list but that is messing up the schedules
Abdul KhatriAbdul Khatri
Can you please share the logs to check the exact line number you are getting the issue on.
Amit Chaudhary 8Amit Chaudhary 8
update your code like below
public with sharing class OpportunitySchedulingHandler {

     //Update LineItemSchedule dates for all scheduling dates

    public static void ScheduleDateUpdate(String oppid, Integer DayDiff) 
    {
       List<OpportunityLineItem> idval = [SELECT id FROM OpportunityLineItem WHERE OpportunityId=:oppid];
       List<OpportunityLineItemSchedule> datelist = new List<OpportunityLineItemSchedule>();
       for (Integer i = 0; i < idval.size(); i++)
       {
		   	
           datelist = [SELECT ScheduleDate FROM OpportunityLineItemSchedule WHERE OpportunityLineItemId =:idval[i].id];
           if(datelist.size() >0 ){
			   Date firstDate = datelist[0].ScheduleDate.addDays(DayDiff);
			   datelist[0].ScheduleDate = firstDate;

			   Integer day = firstDate.day();
			   Integer month = firstDate.month();
			   Integer year = firstDate.year();

			   for (Integer k = 1; k < datelist.size(); k++)
			   {
				   Integer nYear = year;
				   Integer nMonth = month + k;
				   Integer nDay = day;

				   if (nMonth > 12) {
					   nMonth = nMonth - 12;
					   nYear = nYear + 1;
				   }

				   Set<Integer> longMonths = new Set<Integer> {1,3,5,7,8,10,12};

				   if (nDay == 31 && ! longMonths.contains(nMonth)) {
					   nDay = 30;
				   }

				   if (nDay > 28 && nMonth == 2) {
					   nDay = 28;
				   }

				   Date mydate = date.newInstance(nYear,nMonth,nDay);
				   datelist[k].ScheduleDate = mydate;
			   }
			   if(!datelist.isEmpty())
			   {
					update datelist;
			   }
			}   
        }
    }    
}

NOTE: try to remove SOQL and DML from loop
Abdul KhatriAbdul Khatri
Gosh overlook that SOQL part, good catch.