1

I understand that I need to use batch apex to do something like this and I have used it before as well, but not in the right way. I ended up making a list using an soql query for all the records and then, sent the records from the list 200 records at a time(due to some third party constraints) into the batch apex class. But thats probably not how its supposed to be used.

Here is my Apex class:

That first SOQL query is supposed to return over 10000 records. But I am guessing we need to cap that and send it into batch apex in an iterative way. I just not sure how to do that. Any help will be great.

public class StackEx {
    
    public static void check(){
        
        Map<ID,hed__Program_Enrollment__c> program_Enrollments = new Map<ID,hed__Program_Enrollment__c>([Select Id, Name, hed__Enrollment_Status__c,hed__Program_Plan__r.hed__Version__c,Program_Version__c, hed__Contact__r.Id, hed__Program_Plan__r.Name, hed__GPA__c, Non_OLMP_Final_Course__c From hed__Program_Enrollment__c Where hed__Program_Plan__r.Name IN ('Air Command and Staff College','Squadron Officer School','Air War College','Air Command and Staff College Supplemental') AND hed__Enrollment_Status__c = 'Active' ]);
        Set<ID> program_Enrollment_ID_Set = new Set<ID>();
        
        Map<hed__Program_Enrollment__c, List<hed__Course_Enrollment__c>> map_Of_PE_To_CC_List = new Map<hed__Program_Enrollment__c, List<hed__Course_Enrollment__c>>();
        for(hed__Program_Enrollment__c pe: program_Enrollments.values()){
            program_Enrollment_ID_Set.add(pe.Id); 
        }
        
        
        List<hed__Course_Enrollment__c> courseConnections = [SELECT Name, hed__Program_Enrollment__r.hed__Program_Plan__r.Name,hed__Program_Enrollment__r.Name, Course_ID__c,
                                                             Id, Cloud_Course__c, hed__Status__c, hed__Course_Offering__r.hed__Course__r.Course_Type__c, hed__Program_Enrollment__r.hed__Enrollment_Status__c, Current_Seminar__c, hed__Course_Offering__r.hed__Course__r.hed__Course_ID__c, hed__Credits_Attempted__c, Common_Course__c , hed__Credits_Earned__c, hed__Program_Enrollment__r.Id, hed__Contact__r.Id FROM hed__Course_Enrollment__c WHERE hed__Program_Enrollment__r.Id IN :program_Enrollment_ID_Set AND Course_ID__c != 'GSS-502A' AND (hed__Status__c = 'Former' OR hed__Status__c = 'Current')  ];
        
        if(courseConnections.size() != 0){
            for(hed__Course_Enrollment__c cc: courseConnections) {
                if(program_Enrollments.containsKey(cc.hed__Program_Enrollment__r.Id)) {
                    if(!map_Of_PE_To_CC_List.containsKey(program_Enrollments.get(cc.hed__Program_Enrollment__r.Id))) {
                        map_Of_PE_To_CC_List.put(program_Enrollments.get(cc.hed__Program_Enrollment__r.Id), new List<hed__Course_Enrollment__c>());
                    } 
                    map_Of_PE_To_CC_List.get(program_Enrollments.get(cc.hed__Program_Enrollment__r.Id)).add(cc);
                }
            }
            
            
            List<hed__Program_Enrollment__c> listOfProgramEnrollmentsToUpdate = new List<hed__Program_Enrollment__c>();
            
            for(hed__Program_Enrollment__c pe : map_Of_PE_To_CC_List.keySet()) {
                Double foundationalUnits = 0.0;
                Double focusedUnits = 0.0;
                Integer facilitatedCourses = 0;
                for(hed__Course_Enrollment__c cc: map_Of_PE_To_CC_List.get(pe)){
                    if(cc.Cloud_Course__c == false){
                        if(cc.hed__Status__c == 'Former' && cc.hed__Credits_Attempted__c == cc.hed__Credits_Earned__c){
                            if(cc.hed__Credits_Earned__c != null){
                                foundationalUnits = foundationalUnits + cc.hed__Credits_Earned__c;
                            }
                            
                        } 
                        
                        else if(cc.hed__Status__c == 'Current'){
                            if(cc.hed__Course_Offering__r.hed__Course__r.Course_Type__c == 'Self-paced' && cc.hed__Credits_Attempted__c != null ){
                                foundationalUnits = foundationalUnits + cc.hed__Credits_Attempted__c;
                            }
                            
                            else if(cc.hed__Credits_Attempted__c != null  && cc.Current_Seminar__c == true){
                                foundationalUnits = foundationalUnits + cc.hed__Credits_Attempted__c;
                                system.debug('Current focused Course name: '+ cc.Name);
                                
                            }
                        }
                    } 
                    else if(cc.Cloud_Course__c == true){
                        if(cc.hed__Course_Offering__r.hed__Course__r.Course_Type__c == 'facilitated'){
                            facilitatedCourses = facilitatedCourses + 1;
                            system.debug('Focused Facilitated Course name: '+ cc.Name);
                        }
                        
                        if(cc.hed__Status__c == 'Former' && cc.hed__Credits_Attempted__c == cc.hed__Credits_Earned__c){
                            if(cc.hed__Credits_Earned__c != null){
                                focusedUnits = focusedUnits + cc.hed__Credits_Earned__c;
                                system.debug('Former focused Course name: '+ cc.Name);
                            }
                        } 
                        else if(cc.hed__Status__c == 'Current'){
                            if(cc.hed__Course_Offering__r.hed__Course__r.Course_Type__c == 'Self-paced' && cc.hed__Credits_Attempted__c != null ){
                                focusedUnits = focusedUnits + cc.hed__Credits_Attempted__c;
                            }
                            
                            else if(cc.hed__Credits_Attempted__c != null  && cc.Current_Seminar__c == true){
                                focusedUnits = focusedUnits + cc.hed__Credits_Attempted__c;
                                system.debug('Current focused Course name: '+ cc.Name);
                                
                            }
                        }
                    } 
                }
                System.debug('PROGRAM ENROLLMENT: '+ pe.Name);
                System.debug('PROGRAM Plan: '+ pe.hed__Program_Plan__r.Name);
                
                System.debug('FoundationalUnits: '+ foundationalUnits);
                System.debug('FocusedUnits: '+ focusedUnits);
                System.debug('Facilitated: '+ facilitatedCourses);
                
                
                if(pe.hed__Program_Plan__r.Name == 'Air Command and Staff College' && foundationalUnits == 43.0  && focusedUnits >= 9.0 && facilitatedCourses == 1 ){
                    pe.Non_OLMP_Final_Course__c = true;
                    listOfProgramEnrollmentsToUpdate.add(pe);
                }
                else if(pe.hed__Program_Plan__r.Name == 'Air War College'  ) {
                    if(pe.Program_Version__c == '18' && foundationalUnits == 30.0  && focusedUnits >= 9.0 && facilitatedCourses == 1){
                        pe.Non_OLMP_Final_Course__c = true;
                        listOfProgramEnrollmentsToUpdate.add(pe);
                        
                        
                    } else if(pe.Program_Version__c == '19' && foundationalUnits == 31.0  && focusedUnits >= 9.0 && facilitatedCourses == 1){
                        pe.Non_OLMP_Final_Course__c = true;
                        listOfProgramEnrollmentsToUpdate.add(pe);
                    }
                }  
                else if(pe.hed__Program_Plan__r.Name == 'Air Command and Staff College Supplemental' && foundationalUnits == 31) {
                    pe.Non_OLMP_Final_Course__c = true;
                    listOfProgramEnrollmentsToUpdate.add(pe);
                }  
                
                else if(pe.hed__Program_Plan__r.Name == 'Squadron Officer School' && foundationalUnits == 27.0  && focusedUnits >= 9.0 && facilitatedCourses == 1 ) {
                    pe.Non_OLMP_Final_Course__c = true;
                    listOfProgramEnrollmentsToUpdate.add(pe);
                }       
            }
            if(listOfProgramEnrollmentsToUpdate.size() != 0){
                System.debug('ListOfPE to Update: '+ listOfProgramEnrollmentsToUpdate );
                Update listOfProgramEnrollmentsToUpdate;
                
            } 
        }
    }
}

2 Answers 2

3

Your current code is not correct for batch execution. It simply retrieves and starts processing those records itself.

Batch apex allows you to create a batchable apex class (need to use interface) with three methods, which allows Salesforce to:

  1. identify work, that is, no. of records to be divided into multiple batches (Start method)
  2. execute each batch (Execute method)
  3. execute steps after all batches are processes (Finish method)

Suggest reading about batch apex to learn best practices to use it. Read more here: https://trailhead.salesforce.com/en/content/learn/modules/asynchronous_apex/async_apex_batch

2
  • I get what you are saying. Your answer is very generic. I need a legit example as to how to go about this. The first Query itself has more than 50K records. Any help will be apprecitated
    – manb
    Commented Mar 17, 2021 at 23:26
  • For more than 50K records, you may want to design the process to flag records to be processed or which are already processed. In your batch job you can pull a subset of records say first 20K records to be processed. In Finish method you can requeue batch job, if there are more records to be processed. So, in this way, your batch job will keep looping until all records are processed.
    – Anshul
    Commented Mar 18, 2021 at 22:01
0

I think that what you've got there, to my eye, lends itself more to Queueable Apex

If you're happy with everything except for the update statement blowing the limit you could make an QueueableUpdater class that just takes a List<SObject> and runs the update, following the Chaining Jobs example in the link to allow it to process anything beyond the DML row limit in subsequent queueables.

Once that was set you could just replace your update line with something like:

new QueueableUpdater( listOfProgramEnrollmentsToUpdate ).execute();

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .