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
Dustin Moore 22Dustin Moore 22 

Assistance with creating a batched Apex class to run nightly

Hello, 

I am needing some assistnace writing a batched apex class that will update contacts meeting certin criteria, and update a picklist based on a date field. 

Example:

Get all contacts where record type id = XXXXXXX & Latest_Service_Date__c != (not equal) NULL

If Latest_Service_Date__c is ≥ Date(TODAY - 90) update Picklist_Field__c = TRUE

else If Latest_Service_Date__c is < Date(TODAY - 90) update Picklist_Field__c = FALSE


Date(TODAY - 90) meaning if the Latest_Service_Date__c is in the past 90 days. 

Would be glad to read through any articles or material, I just have not been successful in finding anything helpful thus far. 
Best Answer chosen by Dustin Moore 22
PRAKASH JADA 13PRAKASH JADA 13
Batch class:
--------------------------------
global class UpdateContactBatch implements Database.Batchable<sobject>, Schedulable {
    
    // Constructor
    global UpdateContactBatch() {
        
    }
    
    // Start Method
    global  Database.QueryLocator start(Database.BatchableContext BC) {
        Id recordTypeId = Schema.SObjectType.Contact.RecordTypeInfosByName.get('Test').RecordTypeId;
        String query = 'SELECT ID, Latest_Service_Date__c, RecordTypeId '+  
                            ' FROM Contact ' + 
                            ' WHERE RecordTypeId = : recordTypeId ' + 
                            'AND Latest_Service_Date__c != NULL';
        return Database.getQueryLocator(query);
    }
    
    // Execute Method
    global  void execute(Database.BatchableContext BC, List<Contact> contacts) {
        // Loop to iterate over the list of Contacts
        for(Contact contact : contacts) {
            if(contact.Latest_Service_Date__c > Date.today()-90) {
                contact.Picklist_Field__c = true;
            } else {
                contact.Picklist_Field__c  = false;
            }
        }
        
        // Performing the DML operation
        if(contacts.size() > 0) {
            update contacts;
        }
    }
    
    // Finish method
    global void finish(Database.BatchableContext info) {
        
    }
    
    global void execute(System.SchedulableContext SC) {
        Database.executeBatch(new UpdateContactBatch(), 200);
    }
}

Test class:
-----------------

@isTest
public class UpdateContactBatchTest {
    @testSetUp static void prepareTestData() {
        Id recordTypeId = Schema.SObjectType.Contact.RecordTypeInfosByName.get('Test').RecordTypeId;
        List<Account> accounts = new List<Account>();
        
        Account account1 = new Account(Name = 'Test Account1');
        Account account2 = new Account(Name = 'Test Account2');
        
        accounts.add(account1);
        accounts.add(account2);
        insert accounts;
        
        List<Contact> contacts = new List<Contact>();
        contact contact1 = new Contact(LastName = 'Test LastName', FirstName = 'Test FirstName', RecordTypeId = recordTypeId,
                                       AccountId = account1.Id, Latest_Service_Date__c = Date.today() - 90);
        contact contact2 = new Contact(LastName = 'Test LastName', FirstName = 'Test FirstName',  RecordTypeId = recordTypeId,
                                       AccountId = account2.Id, Latest_Service_Date__c = Date.today());
        contacts.add(contact1);
        contacts.add(contact2);
        insert contacts;
    }
    @isTest static void testMethod1() {
        Account account = [SELECT ID, NAME FROM Account WHERE NAME = 'Test Account1'];
        Contact contact = [Select Id FROM Contact where AccountId = :account.Id];
        Test.startTest();
        UpdateContactBatch batch1 = new UpdateContactBatch();
        String sch = '0 0 2 * * ?';
        System.Schedule('Testing the batch class', sch, batch1);
        Test.stopTest();
    }
}

All Answers

PRAKASH JADA 13PRAKASH JADA 13
Batch class:
--------------------------------
global class UpdateContactBatch implements Database.Batchable<sobject>, Schedulable {
    
    // Constructor
    global UpdateContactBatch() {
        
    }
    
    // Start Method
    global  Database.QueryLocator start(Database.BatchableContext BC) {
        Id recordTypeId = Schema.SObjectType.Contact.RecordTypeInfosByName.get('Test').RecordTypeId;
        String query = 'SELECT ID, Latest_Service_Date__c, RecordTypeId '+  
                            ' FROM Contact ' + 
                            ' WHERE RecordTypeId = : recordTypeId ' + 
                            'AND Latest_Service_Date__c != NULL';
        return Database.getQueryLocator(query);
    }
    
    // Execute Method
    global  void execute(Database.BatchableContext BC, List<Contact> contacts) {
        // Loop to iterate over the list of Contacts
        for(Contact contact : contacts) {
            if(contact.Latest_Service_Date__c > Date.today()-90) {
                contact.Picklist_Field__c = true;
            } else {
                contact.Picklist_Field__c  = false;
            }
        }
        
        // Performing the DML operation
        if(contacts.size() > 0) {
            update contacts;
        }
    }
    
    // Finish method
    global void finish(Database.BatchableContext info) {
        
    }
    
    global void execute(System.SchedulableContext SC) {
        Database.executeBatch(new UpdateContactBatch(), 200);
    }
}

Test class:
-----------------

@isTest
public class UpdateContactBatchTest {
    @testSetUp static void prepareTestData() {
        Id recordTypeId = Schema.SObjectType.Contact.RecordTypeInfosByName.get('Test').RecordTypeId;
        List<Account> accounts = new List<Account>();
        
        Account account1 = new Account(Name = 'Test Account1');
        Account account2 = new Account(Name = 'Test Account2');
        
        accounts.add(account1);
        accounts.add(account2);
        insert accounts;
        
        List<Contact> contacts = new List<Contact>();
        contact contact1 = new Contact(LastName = 'Test LastName', FirstName = 'Test FirstName', RecordTypeId = recordTypeId,
                                       AccountId = account1.Id, Latest_Service_Date__c = Date.today() - 90);
        contact contact2 = new Contact(LastName = 'Test LastName', FirstName = 'Test FirstName',  RecordTypeId = recordTypeId,
                                       AccountId = account2.Id, Latest_Service_Date__c = Date.today());
        contacts.add(contact1);
        contacts.add(contact2);
        insert contacts;
    }
    @isTest static void testMethod1() {
        Account account = [SELECT ID, NAME FROM Account WHERE NAME = 'Test Account1'];
        Contact contact = [Select Id FROM Contact where AccountId = :account.Id];
        Test.startTest();
        UpdateContactBatch batch1 = new UpdateContactBatch();
        String sch = '0 0 2 * * ?';
        System.Schedule('Testing the batch class', sch, batch1);
        Test.stopTest();
    }
}
This was selected as the best answer
Dustin Moore 22Dustin Moore 22
This is fantastic, thank you so much! class is at 100% coverage, and all seems to be working great!
Deepali KulshresthaDeepali Kulshrestha
Hi Dustin,

Please refer to the code below for your problem. 

I have used the exact names of the fields that you have mentioned so change them accordingly.
global class UpdatePicklist implements 
Database.Batchable<sObject> {
    
    global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator('SELECT ID, Latest_Service_Date__c, Picklist_Field__c'+
                                        'FROM Contact'+            
                                        'WHERE  Latest_Service_Date__c!= Null'
                                       );
    }
    global void execute(Database.BatchableContext bc, List<Contact> contact_List){
        date d1 = system.today()-90;
        
        // process each batch of records
        List<Contact> contacts = new List<Contact>();
        for(Contact con : contact_List){
            if(con.Latest_Service_Date__c >= d1){
                con.Picklist_Field__c='true';
                contacts.add(con);
            }
            else
                if(con.Latest_Service_Date__c < d1){
                    con.Picklist_Field__c='false';
                    contacts.add(con);
                }
        }
        
        update contacts;
    }
    global void finish(Database.BatchableContext bc){
        
    }
    
}


To execute the batch class from Execute Anonymous Window, write :


UpdatePicklist obj1 = new UpdatePicklist();
Id batchId = Database.executeBatch(obj1);


Use this Id to monitor the progress

For any query related to batch class please follow this link:

https://trailhead.salesforce.com/en/content/learn/modules/asynchronous_apex


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

Thanks and Regards,
Deepali Kulshrestha
www.kdeepali.com