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
Muhammad Jawwad 16Muhammad Jawwad 16 

How to schedule batch apex for the 1st date of every month?

global class LoanOfficerBatch implements Database.Batchable<sObject> {
    public String query = 'SELECT Loan_Officer_1a__c,Loan_Officer_1a__r.Email, ConvertedOpportunityId, Name, Phone,' 
                          +  'Status, Est_Re_Pull_Date__c, Realtor_Name__c ' 
                          +   ' FROM Lead'; 
    public EmailTemplate templateId = [Select Id,HtmlValue,Subject from EmailTemplate where name = 'LoanOfficerRecord' LIMIT 1];

    global Database.QueryLocator start(Database.BatchableContext bc) {

        query += ' WHERE CreatedDate = LAST_MONTH  AND Loan_Officer_1a__c != null';
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, list<Lead> allLeads) {
        
        
         
        List<String> convertedOppId = new List<String>();
         for(Lead l: allLeads){
	         convertedOppId.add(l.ConvertedOpportunityId); 
             }

         Map<Id, Opportunity> opptyMap = new Map<Id, Opportunity>();  
         for(Opportunity o : [SELECT Id,Name,Contact__r.Name,Contact__r.Phone,Starting_Credit_Score__c,Enrolled_On__c,Est_Re_Pull_Date__c,StageName FROM Opportunity WHERE Id IN: convertedOppId]){
	      opptyMap.put(o.Id, o);
          }
        
        
        
        Map<Id,List<Lead>> leadMap = new Map<Id,List<Lead>>();
        List<Messaging.SingleEmailMessage> mails = new List<Messaging.SingleEmailMEssage>();
        if(allLeads != null && allLeads.size() > 0){
            for(Lead l: allLeads){
                if(!leadMap.containsKey(l.Loan_Officer_1a__c)){
                    leadMap.put(l.Loan_Officer_1a__c, new List<lead>());
                }
                leadMap.get(l.Loan_Officer_1a__c).add(l);
            }
        }
        if(leadMap.keySet().size() > 0){
            Map<Id,Contact> officers = new Map<Id,Contact>([SELECT Id,Email,Name FROM Contact WHERE Id IN: leadMap.keySet()]);
            for(Id i: leadMap.keySet()){
                Contact con = officers.get(i);
                System.debug(con);
                if(String.isnOtBlank(con.Email)){
                    Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
                    mail.setToAddresses(new String[]{con.EMail});
                    mail.setSubject(templateId.Subject);
                    String html = templateId.HtmlValue;
                    html = html.replace('||OfficerName||',con.Name);
                    String leadsTable = '<table cellpadding="3" cellspacing="3" width="100%" align="center" border="1" style="border-collapse:collapse;">'+
                        '<tr style="font-weight:bold;"><td>Name</td><td>Phone</td><td>Status</td><td>Est. Re Pull Date</td><td>Realtor Name</td></tr>';
                    
                    for(Lead l: leadMap.get(i))  
                    if(l.ConvertedOpportunityId==null)
                    {                    {
                        
                        
                        leadsTable += '<tr><td>'+l.Name+'</td>'+
                            '<td>'+l.Phone+'</td><td>'+l.Status+'</td>'+
                            '<td>'+l.Est_Re_Pull_Date__c+'</td><td>'+l.Realtor_Name__c+'</td></tr>';
                    }
                                               }
                    leadsTable += '</table>';
                    
                     String opptyTable = '<table cellpadding="3" cellspacing="3" width="100%" align="center" border="1" style="border-collapse:collapse;">'+
                        '<tr style="font-weight:bold;"><td>Name</td><td>Phone</td><td>Starting Credit Score</td><td>Enrolled On</td><td>Estimated Pull Date</td><td>StageName</td></tr>';
                    
                    for(Id idKey: opptyMap.keySet()){
                        Opportunity o = opptyMap.get(idKey);
                        
                        
                        opptyTable += '<tr><td>'+o.Contact__r.Name+'</td><td>'+o.Contact__r.Phone+'</td><td>'+o.Starting_Credit_Score__c+'</td><td>'+o.Enrolled_On__c+'</td>'
                            +'<td>'+o.Est_Re_Pull_Date__c+'</td><td>'+o.StageName+'</td></tr>';
                    }
                    opptyTable += '</table>';
                    html = html.replace('||Leads||',leadsTable);
                    html = html.replace('||Opportunity||',opptyTable);
                    html = html.replace('null',' ');
                    mail.setHTMLBody(html);
                    mails.add(mail);
                }
            }
        }
        if(mails.size() > 0){
            Messaging.sendEmail(mails);
        }
    }

    global void finish(Database.BatchableContext BC) {

    }
   
}
please help
 
Best Answer chosen by Muhammad Jawwad 16
Maharajan CMaharajan C
Hi Mohammad,

First create scheduler class to your batch class. Then only you can run your batch class monthly.

Scheduler Class:

global class LoanOfficerBatchSheduler implements Schedulable {
   global void execute(SchedulableContext sc) {
      LoanOfficerBatch b = new LoanOfficerBatch(); 
      database.executebatch(b);
   }
}

Then there is two way to run this batch class via the Scheduler:

1. Salesforce Standard Out of Box Scheduler : (Cons : you can only scehdule up to next five years)

Setup > Apex Classes > Shedule Apex Button > Then you can lookup the above Sheduler Class. Please refer the below screenshot for further:

User-added image



2. Using CRON and Developer Console:

Developer Console > Debug > Open Execute Anonymous Window > paste the below code > Execute


LoanOfficerBatchSheduler m = new LoanOfficerBatchSheduler();
String sch = '0 0 0 1 * ? *';
String jobID = system.schedule('Merge Job', sch, m);

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_scheduler.htm
http://amitsalesforce.blogspot.com/2017/07/how-to-write-test-class-for-scheduler.html
https://webkul.com/blog/cron-expression-for-scheduling-jobs-in-salesforce/

Thanks,
Maharajan.C

All Answers

Alain CabonAlain Cabon
Hi,

Schedule Apex job: To schedule your batch Apex to run at regular intervals, you also need an Apex class that implements interface Schedulable or all in one class is also possible.

Crontab:
http://www.leftpropeller.com/2018/08/13/schedulable-batch-apex/

or Schedule Apex via user interface
Click “Schedule Apex” button in Setup / Develop / Apex Classes to create a schedule apex job.

https://www.xgeek.net/salesforce/writing-a-schedulable-batch-apex-in-salesforce/
Maharajan CMaharajan C
Hi Mohammad,

First create scheduler class to your batch class. Then only you can run your batch class monthly.

Scheduler Class:

global class LoanOfficerBatchSheduler implements Schedulable {
   global void execute(SchedulableContext sc) {
      LoanOfficerBatch b = new LoanOfficerBatch(); 
      database.executebatch(b);
   }
}

Then there is two way to run this batch class via the Scheduler:

1. Salesforce Standard Out of Box Scheduler : (Cons : you can only scehdule up to next five years)

Setup > Apex Classes > Shedule Apex Button > Then you can lookup the above Sheduler Class. Please refer the below screenshot for further:

User-added image



2. Using CRON and Developer Console:

Developer Console > Debug > Open Execute Anonymous Window > paste the below code > Execute


LoanOfficerBatchSheduler m = new LoanOfficerBatchSheduler();
String sch = '0 0 0 1 * ? *';
String jobID = system.schedule('Merge Job', sch, m);

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_scheduler.htm
http://amitsalesforce.blogspot.com/2017/07/how-to-write-test-class-for-scheduler.html
https://webkul.com/blog/cron-expression-for-scheduling-jobs-in-salesforce/

Thanks,
Maharajan.C
This was selected as the best answer
Ajay K DubediAjay K Dubedi
Hi Muhammad,
Try this:
Firstly make scheduler:
global class BatchScheduerName implements Schedulable {

    global void execute(SchedulableContext ctx) {
        LoanOfficerBatch obj= new LoanOfficerBatch();
        //Batch size is 200, records will be split into batches
        Database.ExecuteBatch(obj, 200);
    }
}
Save it.

Now time to schedule it:
Run this code in Execute Anonymous Window.

BatchScheduerName b = new BatchScheduerName();
String chronJobId = ' 0 0 12 1 1/1 ? *';
System.schedule('BatchSchedule', chronJobId,  b);

I hope you find the above solution helpful. If it does, please mark as Best Answer to help others too.

Thanks,
Ajay Dubedi
uday bhaskar 75uday bhaskar 75
hiii @muhammad i have  a small  doubht in annomoys window 3 rd step . system shedule ( batchshedule) . how can u taken
Saurabh GujjelwarSaurabh Gujjelwar
@Maharajan C can you please tell me that it will automatically call after every month, once we execute above code in annomoys window or we have to call it again again in annomoys window in every month.. Plesae exaplain