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
Ramya DeshpandeRamya Deshpande 

Apex class to check for Process instance steps (related to custom object), with the status pending and delayed for approval for more than 24hrs

Batch Apex Class on custom object containing approval process,  to send an email to the approvers logged into the approval history related history of the custom object records ,
If at all the approval process status of the record is pending more than 24 hours
    We need 3 different email templates based on time delay, different email template should be triggered
a.    If Delayed between 24hrs and 48hrs – Email template for 24hr delay
b.    If Delayed between 48hrs and 72hrs – Email template for 48hr delay
c.    If Delayed more than 72hrs – Email template for 72hr delay
Below is the code written to achieve the above result .

global class FreightApprovalProcessBatch implements Database.Batchable<sobject>,Database.Stateful {
      
    List<Id> userList24 = new List<Id>();
    List<Id> userList48 = new List<Id>();
    List<Id> userList72 = new List<Id>();
        
    global Database.QueryLocator start(Database.BatchableContext bc)
    {        
        return 
            Database.getQueryLocator('SELECT ActorId,ElapsedTimeInHours, ProcessInstance.TargetObjectId,ProcessInstance.TargetObject.Name FROM ProcessInstanceWorkitem WHERE ElapsedTimeInHours > 24 AND ProcessInstanceId IN (SELECT Id FROM ProcessInstance WHERE Status = \'Pending\')');                         
    }   
    
    global void execute(Database.BatchableContext bc, List<ProcessInstanceWorkitem> scope)
    {        
        for(ProcessInstanceWorkitem p : scope)           
        {           
            Schema.SObjectType objectType = p.ProcessInstance.TargetObjectId.getSobjectType();
            if(objectType.getDescribe().getName().equals('Custom Object'))
            {              
                if(p.ElapsedTimeInHours >= 24 && p.ElapsedTimeInHours < 48 )
                {
                    userList24.add(p.ActorId);                 
                }
                
                else if(p.ElapsedTimeInHours >= 48 && p.ElapsedTimeInHours < 72)
                {
                    userList48.add(p.ActorId);                 
                }
                
                else if(p.ElapsedTimeInHours >= 72)
                {
                    userList72.add(p.ActorId); 
                }
            }             
        }
    }
    global void finish(Database.BatchableContext bc)
    {
        
        List <EmailTemplate> listTemplate = [Select id,name from EmailTemplate where name = 'Email Template 1' OR name = 'Email Template 2' OR name = 'Email Template 3'];   
        Id templateId24;
        Id templateId48;
        Id templateId72;
        for(EmailTemplate objEmailTemplate : listTemplate){
            
            if(objEmailTemplate.name == 'Email Template 1')
            {
                templateId24 = objEmailTemplate.Id;                
            }
            
            else if(objEmailTemplate.name == 'Email Template 2')
            {
                templateId48 = objEmailTemplate.Id;
            }
            
            else if(objEmailTemplate.name == 'Email Template 3')
            {
                templateId72 = objEmailTemplate.Id;
            }          
        }
              
        Messaging.MassEmailMessage emails24=new Messaging.MassEmailMessage(); 
        emails24.setTargetObjectIds(UserList24);       
        emails24.setTemplateID(templateId24);
        emails24.setSaveAsActivity(false);
        Messaging.SendEmail(New Messaging.MassEmailMessage[]{emails24}); 
                   
        Messaging.MassEmailMessage emails48=new Messaging.MassEmailMessage(); 
        emails48.setTargetObjectIds(UserList48);
        emails48.setTemplateID(templateId48);
        emails48.setSaveAsActivity(false);       
        Messaging.SendEmail(New Messaging.MassEmailMessage[]{emails48});
        
        Messaging.MassEmailMessage emails72=new Messaging.MassEmailMessage(); 
        emails72.setTargetObjectIds(UserList72);
        emails72.setTemplateID(templateId72);
        emails72.setSaveAsActivity(false);       
        Messaging.SendEmail(New Messaging.MassEmailMessage[]{emails72});   
    }    
}
Now, when I will run my above batch class in execute anonymous window, it is running successfully , even I am getting all those records to whom the email should be triggered.
Also, tried passing the hardcode userid's , then  I am able to receive an email .

But, when the batch is executed , I am not receiving any mails to my inbox.
So, please, let me know if some part of code is missing in the mass email messaging methods .
Also, we have created the different HTML email templates with the merge field in it, the merge fields are not populated in the received mails .
Also, let me know, how we should go and write test class for the same above class.