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
Ganesh VinnakotaGanesh Vinnakota 

Apex batch to send Email to users on Leads with their past due leads in an attachment

Hello,
I am trying to build a batch that can be scheduled daily and sends email to all the lead owners if they have any past due date leads.
Each owner should get their own email with an attachment containing only leads assigned to them.
My code below is failing to get an attachment containing only leads assigned to them.
Can any one help me?

global class BatchableLeadEmailAlert  implements Database.Batchable<sObject>, Database.AllowsCallOuts, Database.Stateful {
    global   String  query;
    String YES = 'Yes';   
    //  ---------------------------------------------------------------------
    //  CONSTRUCTOR
    //  ---------------------------------------------------------------------
    global BatchableLeadEmailAlert() {
      query = 'SELECT Id,Name,FirstName,LastName,Phone,Secondary_Lead_Owner__c from Lead where Secondary_Lead_Owner__c != null AND Test_Record__c = \''+YES+'\'';                    
    }    
    //  ---------------------------------------------------------------------
    //  INTERFACE METHOD: start
    //  ---------------------------------------------------------------------
    global Database.QueryLocator start(Database.BatchableContext bc){
        return Database.getQueryLocator(query);
    }
    
    //  ---------------------------------------------------------------------
    //  INTERFACE METHOD: execute 
    //  ---------------------------------------------------------------------
    global void execute(Database.BatchableContext bc, List<sObject> scope) {
    
        Set<Id> userid = new Set<Id>();
        Set<Id> LdId = new Set<Id>();
        for (SObject s: scope) {    
            Lead LdsIds = (Lead) s;  
            LdId.add(LdsIds.Id);
            userid.add(LdsIds.Secondary_Lead_Owner__c);                            
          }     
                    
             List<User> Addresses = new List<User>();
             Addresses = [select Email,LastName from User where Id =: userid];
              List<String> toAddresses = new List<String>();              
              for(User usr: Addresses){
                 toAddresses.add(usr.Email);
              }      
    
          List<Lead> leadlist = [SELECT Id,Name,FirstName,LastName,Phone,Secondary_Lead_Owner__c from Lead where Id =:LdId ORDER BY Secondary_Lead_Owner__c];         
                   
          String header = 'Name, First Name, Last Name, Phone,Secondary_Lead_Owner__c \n';
          String finalstr = header;           
          map<Id, String> userleadsmap = new map<Id, String>();

        for(Lead a: leadlist)
        {                     
               string recordString = a.Name+','+a.FirstName+','+a.LastName+','+a.Phone+','+a.Secondary_Lead_Owner__c+'\n';
               finalstr = finalstr +recordString;               
               userleadsmap.put(a.Secondary_Lead_Owner__c, finalstr);                           
        }             
         List<Messaging.SingleEmailMessage> mails = new List<Messaging.SingleEmailMessage>();
            for(User portalUser :Addresses) {
                    Messaging.EmailFileAttachment csvAttc = new Messaging.EmailFileAttachment();
                    if(userleadsmap.containskey(portalUser.Id)){ 
                    blob csvBlob = Blob.valueOf(userleadsmap.get(portalUser.Id));                    
                    string csvname= 'Lead.csv';
                    csvAttc.setFileName(csvname);
                    csvAttc.setBody(csvBlob);
                    }
                    Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
                    string body = 'Hi '+ portalUser.LastName;
                    String[] ccAddresses = new list<string> {'gvinnakota@ten-x.com'}; 
                    mail.setCcAddresses( ccAddresses );
                    mail.setSubject('Test Subject');
                    mail.setTargetObjectId(portalUser.Id); 
                    mail.setSaveAsActivity(false);
                    mail.setHtmlBody(body); mails.add(mail);
                    mail.setFileAttachments(new Messaging.EmailFileAttachment[]{csvAttc});
               }
            Messaging.sendEmail(mails);
             }

   global void finish(Database.BatchableContext bc){       }
}
 
JSingh9JSingh9
Hi Ganesh, 

I believe this can be best acheived usig two batch class. In the First batch Class Create a Map of User and Lead Ids
Map<String , Set<String>>
 
global class UserLeadEmailCollector implements Database.Batchable<sObject.Data>, Database.Stateful{
    
static Map<String, Set<String>> userWithLeadIds = new map<String, Set<String>>();

     //Considering Due Date as Custom Field
    global Database.QueryLocator start(Database.BatchableContext BC){
     return Database.getQueryLocator([SELECT Id, OwnerId FROM lead WHERE Due_Date__c < TODAY]);;
    } 
    
    global void execute(Database.BatchableContext BC, List<LendioJSON.Data> scope){
       //Create Batch Here
    }
    
    global void finish(Database.BatchableContext BC){
      //Create New batch 
     // If Less Users iterate through map and send email from this batch
}
}

So now u have this map with user Id and corresponding Lead ids, this helps to make sure one user gets only one email with all the pending leads.

Let me know if any further help you may need.

Thanks,
JS


 
Ganesh VinnakotaGanesh Vinnakota
Hi JS,

Thank you. I got this working by adding list map.


global class BatchableLeadEmailAlert  implements Database.Batchable<sObject>, Database.AllowsCallOuts, Database.Stateful {
    global   String  query;
    String YES = 'Yes';
  
    //  ---------------------------------------------------------------------
    //  CONSTRUCTOR
    //  ---------------------------------------------------------------------
    global BatchableLeadEmailAlert() {
      query = 'SELECT Id,Name,FirstName,LastName,Phone,Secondary_Lead_Owner__c from Lead where Secondary_Lead_Owner__c != null AND Test_Record__c = \''+YES+'\'';     
     if(Test.isRunningTest()) {
            query = 'SELECT Id,Name,FirstName,LastName,Phone,Secondary_Lead_Owner__c from Lead where Secondary_Lead_Owner__c != null AND Test_Record__c = \''+YES+'\'';
        }              
    }
   
    //  ---------------------------------------------------------------------
    //  INTERFACE METHOD: start
    //  ---------------------------------------------------------------------
    global Database.QueryLocator start(Database.BatchableContext bc){
        return Database.getQueryLocator(query);
    }
   
    //  ---------------------------------------------------------------------
    //  INTERFACE METHOD: execute
    //  ---------------------------------------------------------------------
    global void execute(Database.BatchableContext bc, List<sObject> scope) {
   
        Set<Id> userid = new Set<Id>();
        Set<Id> LdId = new Set<Id>();
        for (SObject s: scope) {   
            Lead LdsIds = (Lead) s; 
            LdId.add(LdsIds.Id);
            userid.add(LdsIds.Secondary_Lead_Owner__c);                           
          }    
          
                           
             List<User> Addresses = new List<User>();
             Addresses = [select Email,LastName from User where Id =: userid];
              List<String> toAddresses = new List<String>();            
              for(User usr: Addresses){
                 toAddresses.add(usr.Email);
              }     
                     
               List<Lead> leadlist = [SELECT Id,Name,FirstName,LastName,Phone,Secondary_Lead_Owner__c from Lead where Id =:LdId ORDER BY Secondary_Lead_Owner__c];        
                   
     
         
          map<Id, List<Lead>> mapUserIdToLstLead = new map<Id, List<Lead>>();
                    
         for(Lead ld: [SELECT Id,Name,FirstName,LastName,Phone,Secondary_Lead_Owner__c from Lead where Id IN:LdId ORDER BY Secondary_Lead_Owner__c]) {
              if(!mapUserIdToLstLead.containsKey(ld.Secondary_Lead_Owner__c)) {
                          mapUserIdToLstLead.put(ld.Secondary_Lead_Owner__c, new List<Lead>{ld});
                          }
                             else  {
                          mapUserIdToLstLead.get(ld.Secondary_Lead_Owner__c).add(ld);
                          }    
         }   
         
                    system.debug('mapUserIdToLstLead--> ' + mapUserIdToLstLead);
                   
          String header = 'Name, First Name, Last Name, Phone,Secondary_Lead_Owner__c \n';
          String finalstr = header;
          map<Id, String> userleadsmap = new map<Id, String>();
         
        for(Id userIds: mapUserIdToLstLead.keySet())
            {       
                     finalstr = '';     
               for (integer i = 0 ; i < mapUserIdToLstLead.get(userIds).size(); i++) {               
                   string recordString = mapUserIdToLstLead.get(userIds)[i].Name+','+mapUserIdToLstLead.get(userIds)[i].FirstName+','+mapUserIdToLstLead.get(userIds)[i].LastName+','+mapUserIdToLstLead.get(userIds)[i].Phone+','+mapUserIdToLstLead.get(userIds)[i].Secondary_Lead_Owner__c+'\n';
                   finalstr = finalstr + recordString;                 
                  }     
                   userleadsmap.put(userIds, header+finalstr);                
            }
          system.debug('userleadsmap--> ' + userleadsmap);
       
         List<Messaging.SingleEmailMessage> mails = new List<Messaging.SingleEmailMessage>();
            for(User portalUser :Addresses) {
                    Messaging.EmailFileAttachment csvAttc = new Messaging.EmailFileAttachment();
                    if(userleadsmap.containskey(portalUser.Id)){
                    blob csvBlob = Blob.valueOf(userleadsmap.get(portalUser.Id));                    
                    string csvname= 'Lead.csv';
                    csvAttc.setFileName(csvname);
                    csvAttc.setBody(csvBlob);
                    }
                    Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
                    string body = 'Hi '+ portalUser.LastName;
                    String[] ccAddresses = new list<string> {''};
                    mail.setCcAddresses( ccAddresses );
                    mail.setSubject('Test Subject');
                    mail.setTargetObjectId(portalUser.Id);
                    mail.setSaveAsActivity(false);
                    mail.setHtmlBody(body); mails.add(mail);
                    mail.setFileAttachments(new Messaging.EmailFileAttachment[]{csvAttc});
               }
            Messaging.sendEmail(mails);
             }
 
   global void finish(Database.BatchableContext bc){       }