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
RICARDO PALMARICARDO PALMA 

Error runing a Batch process: Apex CPU time limit exceeded

global class EvergreenOppoRevenueScheduleBatch implements Database.Batchable<sObject> {
String query;
id firstId = null;    
global Database.QueryLocator start(Database.BatchableContext BC) {
    /*This SOQL gets all the records (Evergreen Opportunities) on the sObject (OpportunityLineItemSchedule)
    WHERE OpportunityLineItem.Opportunity.StageName = 'Contract Executed' 
    and OpportunityLineItem.Opportunity.TFBA__c =  True 
    and OpportunityLineItem.Opportunity.Contract_Status__c <> 'Cancelled' 
    and OpportunityLineItem.Opportunity.Contract_Status__c <> 'Renewed'  
    and OpportunityLineItem.Cancellation_Date__c = null  
    and  OpportunityLineItem.HasRevenueSchedule = True 
    and  OpportunityLineItem.PricebookEntry.Product2.Media__r.Automatic_Revenue_Schedule__c  = True 
    This query can get up to 50,000,000 records 
     */
     
return Database.getQueryLocator([SELECT OpportunityLineItemId, ScheduleDate, OpportunityLineItem.Number_of_Billings__c, OpportunityLineItem.Discounted_Rate__c  From OpportunityLineItemSchedule Where OpportunityLineItem.Opportunity.StageName = 'Contract Executed' and OpportunityLineItem.Opportunity.TFBA__c =  True and OpportunityLineItem.Opportunity.Contract_Status__c <> 'Cancelled' and OpportunityLineItem.Opportunity.Contract_Status__c <> 'Renewed'  and OpportunityLineItem.Cancellation_Date__c = null  and  OpportunityLineItem.HasRevenueSchedule = True and  OpportunityLineItem.PricebookEntry.Product2.Media__r.Automatic_Revenue_Schedule__c  = True Order By OpportunityLineItemId DESC]);
}
 
List<OpportunityLineItemSchedule> addrecs = new List<OpportunityLineItemSchedule>();   
    
/*This is the Loop for the Query scope*/    
global void execute(Database.BatchableContext BC, List<OpportunityLineItemSchedule> scope) {

/*Creating a unique ID Set of the all Opportunities*/
Set<ID> oppProductId = new Set<ID>();
  For (OpportunityLineItemSchedule recuni : scope)  {
     oppProductId.add(recuni.OpportunityLineItemId );   
 }

/*Creating a list of all Max Date for each opportunity line item Ids product from the OpportunityLineItemSchedule sObject using the unique list */    
AggregateResult[] groupedResults = [SELECT Max(ScheduleDate) MaxDate, OpportunityLineItemId oppid FROM OpportunityLineItemSchedule Where OpportunityLineItemId in :oppProductId Group By OpportunityLineItemId Order By OpportunityLineItemId];

   
/*Looping through all the unique Ids to get the Discounted Rate and Number of  Billings */
For (OpportunityLineItem opprec : [Select id , Discounted_Rate__c, Number_of_Billings__c From OpportunityLineItem where id in :oppProductId Order By Id]) {   
       Date maxDatevar;
       String stridLineItem;
       Id idLineItem;
   
 /*For each record now go throught the following loop find the Max Date. When the Max Date is found get out to the loop */
       For (AggregateResult ar :groupedResults) {
           
            stridLineItem = String.ValueOf(ar.get('oppid'));
            idLineItem = Id.ValueOf(stridLineItem);
            If (opprec.Id ==  idLineItem) {
            maxDatevar = Date.valueOf(ar.get('MaxDate'));
                      
            if (date.today() >=  MaxDatevar){
                Integer Days = 0;
                Date oldServiDate = MaxDatevar;
                Days =  Date.daysInMonth(oldServiDate.year(), oldServiDate.month());
                oldServiDate = oldServiDate + Days;

                for (Integer countBillings = 1 ; countBillings <= opprec.Number_of_Billings__c; countBillings++  ){
                OpportunityLineItemSchedule oppS = new OpportunityLineItemSchedule();
                oppS.OpportunityLineItemId = idLineItem;
                oppS.Type = 'Revenue';
                oppS.ScheduleDate = oldServiDate;
                oppS.Revenue = opprec.Discounted_Rate__c;
                Days =  Date.daysInMonth(oldServiDate.year(), oldServiDate.month());
                oldServiDate = oldServiDate + Days;
                addrecs.add(oppS);
                }  
            }
          break; /*Exit the loop after the record is found.*/
              
          }
           
        }
}
 

  Insert addrecs; /*Insert all the records on the OpportunityLineItemSchedule*/

}
    

global void finish(Database.BatchableContext BC) {
}
}
I think problem is my nested loop, base on the info that I found online. Any ideas how to fix this issue?
Thanks.
Best Answer chosen by RICARDO PALMA
Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri
Try to reduce the batch size.

All Answers

Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri
Try to reduce the batch size.
This was selected as the best answer
RICARDO PALMARICARDO PALMA
Thank you Bhaswanthnaga.