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
Shruthi MN 88Shruthi MN 88 

Batchable apex

1- Write a batch class to update leads status as closed lost if no activity has been performed for last 30 days and send notification to manager
I am getting the attached wrrorUser-added image
global class UpdateLeadStatusBatch implements Database.Batchable<sObject> {

    global Database.QueryLocator start(Database.BatchableContext BC) {
        DateTime thirtyDaysAgo = System.now().addDays(-30);
        String query = 'SELECT Id, OwnerId, Owner.ManagerId__c FROM Lead WHERE LastActivityDate <= :thirtyDaysAgo AND Status != \'Closed - Lost\'';
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<sObject> scope) {
        List<Lead> leadsToUpdate = new List<Lead>();
        Set<Id> managerIds = new Set<Id>();

        for (sObject s : scope) {
            Lead lead = (Lead) s;
            lead.Status = 'Closed - Lost';
            leadsToUpdate.add(lead);

            // Access the manager's Id through the custom field
            Id managerId = (Id)lead.get('Owner.ManagerId__c');
            if (managerId != null) {
                managerIds.add(managerId);
            }
        }

        update leadsToUpdate;

        // Send Notification to Managers
        // Using Email Services to send email notifications
        if (!managerIds.isEmpty()) {
            List<Messaging.SingleEmailMessage> emailMessages = new List<Messaging.SingleEmailMessage>();

            for (Id managerId : managerIds) {
                // Construct and send email to the manager
                User managerUser = [SELECT Id, Email FROM User WHERE Id = :managerId LIMIT 1];

                if (managerUser != null && !String.isBlank(managerUser.Email)) {
                    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
                    email.setSubject('Lead Status Update');
                    email.setHtmlBody('<p>Hello, ' + managerUser.Name + ',</p>' +
                                      '<p>The status of some leads has been updated to "Closed - Lost" due to inactivity.</p>' +
                                      '<p>Thank you!</p>');
                    email.setTargetObjectId(managerUser.Id);
                    email.setSaveAsActivity(false);
                    emailMessages.add(email);
                }
            }

            if (!emailMessages.isEmpty()) {
                List<Messaging.SendEmailResult> sendResults = Messaging.sendEmail(emailMessages);
                for (Messaging.SendEmailResult result : sendResults) {
                    if (!result.isSuccess()) {
                        System.debug('Failed to send email: ' + result.getErrors()[0].getMessage());
                    }
                }
            }
        }
    }

    global void finish(Database.BatchableContext BC) {
        // Any logic you want to execute after the batch finishes
    }
}
 
CharuDuttCharuDutt
Hii Shruthi 
Try Below Code 
global class UpdateLeadStatusBatch implements Database.Batchable<sObject> {

    global Database.QueryLocator start(Database.BatchableContext BC) {
        //DateTime thirtyDaysAgo = System.now().addDays(-30);
        String query = 'SELECT Id, OwnerId FROM Lead WHERE LastActivityDate <= N_DAYS_AGO:30 AND Status != \'Closed - Lost\'';
        system.debug(query);
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<Lead> scope) {
        List<Messaging.SingleEmailMessage> emailMessages = new List<Messaging.SingleEmailMessage>();
        List<Lead> leadsToUpdate = new List<Lead>();
        map<Id,Lead> managerIds = new map<Id,Lead>();

        for (Lead olead : scope) {
            olead.Status = 'Closed - Lost';
            leadsToUpdate.add(olead);
            if (olead.OwnerId!= null) {
                managerIds.put(olead.OwnerId,oLead);
            }
        }

        update leadsToUpdate;

        // Send Notification to Managers
        // Using Email Services to send email notifications
        if (!managerIds.isEmpty()) {
            list<User> lstmanagerUser = [SELECT Id, Email, ManagerId, Manager.email, Manager.Name FROM User WHERE Id In :managerIds.KeySet()];
            
            for(User managerUser : lstmanagerUser){

                // Construct and send email to the manager
                if (managerUser != null && !String.isBlank(managerUser.Email)) {
                    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
                    email.setSubject('Lead Status Update');
                    email.setHtmlBody('<p>Hello, ' + managerUser.Manager.Name + ',</p>' +
                                      '<p>The status of some leads has been updated to "Closed - Lost" due to inactivity.</p>' +
                                      '<p>Thank you!</p>');
                    email.setTargetObjectId(managerUser.Id);
                    email.setToAddresses(new list<String>{managerUser.Manager.email});
                    email.setSaveAsActivity(false);
                    emailMessages.add(email);
                }
            }
        }

            if (!emailMessages.isEmpty()) {
                List<Messaging.SendEmailResult> sendResults = Messaging.sendEmail(emailMessages);
                for (Messaging.SendEmailResult result : sendResults) {
                    if (!result.isSuccess()) {
                        System.debug('Failed to send email: ' + result.getErrors()[0].getMessage());
                    }
                }
            }
    }

    global void finish(Database.BatchableContext BC) {
        // Any logic you want to execute after the batch finishes
    }
}
 
Please Mark It As best Answer If it Helps
Thank You!
Shruthi MN 88Shruthi MN 88
The batch ran but I didnt recieve any email
CharuDuttCharuDutt
Hii Shruthi Coz the record owner don't have any manager
Shruthi MN 88Shruthi MN 88
I am not getting any debug statements 

global class UpdateLeadStatusBatch implements Database.Batchable<sObject> {

    global Database.QueryLocator start(Database.BatchableContext BC) {
        //DateTime thirtyDaysAgo = System.now().addDays(-25);
        String query = 'SELECT Id, OwnerId FROM Lead WHERE LastActivityDate <= N_DAYS_AGO:25 AND Status != \'closed lost\'';
        system.debug(query);
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<Lead> scope) {
        List<Messaging.SingleEmailMessage> emailMessages = new List<Messaging.SingleEmailMessage>();
        List<Lead> leadsToUpdate = new List<Lead>();
        map<Id,Lead> managerIds = new map<Id,Lead>();

        for (Lead olead : scope) {
            olead.Status = 'closed lost';
            leadsToUpdate.add(olead);
            if (olead.OwnerId!= null) {
                managerIds.put(olead.OwnerId,oLead);
            }
        }

        update leadsToUpdate;

        // Send Notification to Managers
        // Using Email Services to send email notifications
        if (!managerIds.isEmpty()) {
            list<User> lstmanagerUser = [SELECT Id, Email, ManagerId, Manager.email, Manager.Name FROM User WHERE Id In :managerIds.KeySet()];
            system.debug('Manager' +lstmanagerUser);
            for(User managerUser : lstmanagerUser){

                // Construct and send email to the manager
                if (managerUser != null && !String.isBlank(managerUser.Email)) {
                    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
                    email.setSubject('Lead Status Update');
                    email.setHtmlBody('<p>Hello, ' + managerUser.Manager.Name + ',</p>' +
                                      '<p>The status of some leads has been updated to "Closed - Lost" due to inactivity.</p>' +
                                      '<p>Thank you!</p>');
                    email.setTargetObjectId(managerUser.Id);
                    email.setToAddresses(new list<String>{managerUser.Manager.email});
                    email.setSaveAsActivity(false);
                    emailMessages.add(email);
                }
            }
        }

            if (!emailMessages.isEmpty()) {
                List<Messaging.SendEmailResult> sendResults = Messaging.sendEmail(emailMessages);
                for (Messaging.SendEmailResult result : sendResults) {
                    if (!result.isSuccess()) {
                        System.debug('Failed to send email: ' + result.getErrors()[0].getMessage());
                    }
                }
            }
    }

    global void finish(Database.BatchableContext BC) {
        // Any logic you want to execute after the batch finishes
    }
}
CharuDuttCharuDutt
Hi Shruthi
in Anonymous Window Exceute this Database.Execute(new UpdateLeadStatusBatch()) Check open log check box and click execute highlighted the log will auto open check debugs in that log
Shruthi MN 88Shruthi MN 88
I am executing this and its only displaying line number 6 
UpdateLeadStatusBatch ub = new UpdateLeadStatusBatch();
Id batchId = Database.executeBatch(ub);
Class:
global class UpdateLeadStatusBatch implements Database.Batchable<sObject> {

    global Database.QueryLocator start(Database.BatchableContext BC) {
        //DateTime thirtyDaysAgo = System.now().addDays(-2);
        String query = 'SELECT Id, OwnerId FROM Lead WHERE LastModified <= N_DAYS_AGO:24 AND Status != \'closed lost\'';
        system.debug(query);
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<Lead> scope) {
        List<Messaging.SingleEmailMessage> emailMessages = new List<Messaging.SingleEmailMessage>();
        List<Lead> leadsToUpdate = new List<Lead>();
        map<Id,Lead> managerIds = new map<Id,Lead>();
 System.debug('Number of leads to update: ' + leadsToUpdate.size());
        for (Lead olead : scope) {
            olead.Status = 'closed lost';
            leadsToUpdate.add(olead);
            if (olead.OwnerId!= null) {
                managerIds.put(olead.OwnerId,oLead);
               
            }
        }

        update leadsToUpdate;

        // Send Notification to Managers
        // Using Email Services to send email notifications
        if (!managerIds.isEmpty()) {
            list<User> lstmanagerUser = [SELECT Id, Email, ManagerId, Manager.email, Manager.Name FROM User WHERE Id In :managerIds.KeySet()];
            system.debug('Manager' +lstmanagerUser);
            for(User managerUser : lstmanagerUser){

                // Construct and send email to the manager
                if (managerUser != null && !String.isBlank(managerUser.Email)) {
                    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
                    email.setSubject('Lead Status Update');
                    email.setHtmlBody('<p>Hello, ' + managerUser.Manager.Name + ',</p>' +
                                      '<p>The status of some leads has been updated to "Closed - Lost" due to inactivity.</p>' +
                                      '<p>Thank you!</p>');
                    email.setTargetObjectId(managerUser.Id);
                    email.setToAddresses(new list<String>{managerUser.Manager.email});
                    email.setSaveAsActivity(false);
                    emailMessages.add(email);
                }
            }
        }

            if (!emailMessages.isEmpty()) {
                List<Messaging.SendEmailResult> sendResults = Messaging.sendEmail(emailMessages);
                for (Messaging.SendEmailResult result : sendResults) {
                    if (!result.isSuccess()) {
                        System.debug('Failed to send email: ' + result.getErrors()[0].getMessage());
                    }
                }
            }
    }

    global void finish(Database.BatchableContext BC) {
        // Any logic you want to execute after the batch finishes
    }
}
CharuDuttCharuDutt
Hii Shruthi  You're getting line no.6 debug only because there are no records matching that filter Try To Run The Query Tha's in Batch In Query Editor And See If You Have Any Record
Shruthi MN 88Shruthi MN 88
I am getting 0 records
CharuDuttCharuDutt
Then how you will get other debugs other than line 6 if there record exist then only it will enter execute method in batch then only you will get other debugs you can try and exceute the batch class after removing query filter just for test
 
global class UpdateLeadStatusBatch implements Database.Batchable<sObject> {

    global Database.QueryLocator start(Database.BatchableContext BC) {
        DateTime thirtyDaysAgo = System.now().addDays(-30);
        String query = 'SELECT Id, OwnerId FROM Lead WHERE LastActivityDate <= N_DAYS_AGO:30 AND Status != \'Closed - Lost\'';
        system.debug(query);
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<Lead> scope) {
        System.debug('Number of leads to update: ' + scope.size());
        List<Messaging.SingleEmailMessage> emailMessages = new List<Messaging.SingleEmailMessage>();
        List<Lead> leadsToUpdate = new List<Lead>();
        map<Id,Lead> managerIds = new map<Id,Lead>();

        for (Lead olead : scope) {
            olead.Status = 'Closed - Lost';
            leadsToUpdate.add(olead);
            if (olead.OwnerId!= null) {
                managerIds.put(olead.OwnerId,oLead);
            }
        }

        update leadsToUpdate;

        // Send Notification to Managers
        // Using Email Services to send email notifications
        if (!managerIds.isEmpty()) {
            list<User> lstmanagerUser = [SELECT Id, Email, ManagerId, Manager.email, Manager.Name FROM User WHERE Id In :managerIds.KeySet()];
            
            for(User managerUser : lstmanagerUser){

                // Construct and send email to the manager
                if (managerUser.ManagerId != null) {
                    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
                    email.setSubject('Lead Status Update');
                    email.setHtmlBody('<p>Hello, ' + managerUser.Manager.Name + ',</p>' +
                                      '<p>The status of some leads has been updated to "Closed - Lost" due to inactivity.</p>' +
                                      '<p>Thank you!</p>');
                    email.setTargetObjectId(managerUser.Id);
                    email.setToAddresses(new list<String>{managerUser.Manager.email});
                    email.setSaveAsActivity(false);
                    emailMessages.add(email);
                }
            }
        }

            if (!emailMessages.isEmpty()) {
                List<Messaging.SendEmailResult> sendResults = Messaging.sendEmail(emailMessages);
                for (Messaging.SendEmailResult result : sendResults) {
                    if (!result.isSuccess()) {
                        System.debug('Failed to send email: ' + result.getErrors()[0].getMessage());
                    }
                }
            }
    }

    global void finish(Database.BatchableContext BC) {
        // Any logic you want to execute after the batch finishes
    }
}
Please Mark It As best Answer If it Helps
Thank You!