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
speedforcespeedforce 

batch apex to update mass accounts and contacts

I am new to Salesforce development and I am struggling in few things. I have to write a batch apex which will update few fields in all the contacts and accounts. There are few mappings which will be done cross object - like few fields from contacts will update theie value to a field in accounts object for that record. Here is what I have tried so far:
global class UpdateContactFields implements Database.Batchable<SObject>{
    global String query;
    global final String Entity;
    global final String email;
 
    global UpdateContactFields(String q, String e){
        query=q;
        Entity=e;
    }

    global Database.QueryLocator start(Database.BatchableContext BC){
        query = 'SELECT * FROM Contact LIMIT 10';
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<Contact> scope){
        List<Contact> contcts = new List<Contact>();
        //List<Account> accounts = new List<Account>();
        for(Contact c : scope){
            Contact cnt = (Contact)c;
            cnt.Pardot_End_Date_180_Prior__c       = cnt.End_Date_180_Prior__c;
            cnt.Pardot_Professional_Status__c     = cnt.Professional_Status__c;

            //need a way to pull the corresponding account here because of the field mapping to be done below
            //cnt.Pardot_Related_C_Account__c    = account.Related_C_Account__c ; //Pardot_Related_C_Account__c is in contacts and Related_C_Account__c is in accounts object

            contcts.add(cnt);
        }
        update contcts;
    }
    
    global void finish(Database.BatchableContext BC) {
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.setToAddresses(new String[] {email});
        mail.setReplyTo('****@****.org');
        mail.setSenderDisplayName('Account and Contacts Batch Processing');
        mail.setSubject('Batch Process Completed - Salesforce');
        mail.setPlainTextBody('Batch Process has completed');
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
    }
}
I dont know how to pull the corresponding account and do the field value assignment from account to contacts. Can someone please guide me through this. This is quite critical and I am stuck in it from sometime. Thank you.
Ajeet28augAjeet28aug
List<Contact> contactUpdate = new List<Contact>();
Set<Id> accId = new Set<Id>();
for(Contact c : scope){

//Update contact field.

if(c.AccountId != NULL)
accId.add(c.AccountId);

contactUpdate.add(c);
}

List<Account> updateAccount = [Select Id, Name from Account where Id In: accId];

//Loop over this account list and update the record accordingly.

Thanks & Best Regards
Ajeet
speedforcespeedforce
Hi @Ajeet28aug, I have done it this way:
global Database.QueryLocator start(Database.BatchableContext BC){
        query = 'SELECT End_Date_180_Prior__c, Pardot_End_Date_180_Prior__c, Professional_Status__c, Pardot_Professional_Status__c, Pardot_Related_C_Account__c, AccountId, Email FROM contact WHERE AccountId != null LIMIT 10';
        return Database.getQueryLocator(query);
    }

global void execute(Database.BatchableContext BC, List<Contact> scope){
List<Contact> contcts = [select End_Date_180_Prior__c, Professional_Status__c, AccountId, Days_of_Member_Tenure__c, Pardot_Days_of_Member_Tenure__c from contact where id = :scope];
Map<Id, Account> accts = new Map<id, Account>([
    SELECT Related_C_Account__c FROM Account
    WHERE Id IN (SELECT AccountId FROM Contact WHERE Id = :scope)
]);
for(Contact c : contcts){
    Account a = accts.get(c.AccountId);
    c.Pardot_End_Date_180_Prior__c       = c.End_Date_180_Prior__c;
    c.Pardot_Professional_Status__c     = c.Professional_Status__c;
    c.Pardot_Related_C_Account__c    = a.Related_C_Account__c ;     
    a.Pardot_Days_of_Member_Tenure__c = a.Days_of_Member_Tenure__c;
}
update contcts;
update accts.values(); // save changes to the accounts
}


Doing this, is updating my contacts well, however I am getting this error on account - FIELD_FILTER_VALIDATION_EXCEPTION, Sector Owner can only be on of the Strategic Account Owners.: [Sector_Owner__c] . I have one mandatory lookup field as Sector_Owner__c on account object and its filter criteria should match this - Sector Owner: Username EQUALS rmsprd@company.org . Any suggestions on why I should be getting this? Much appreciate your help. Thank you.
Ajeet28augAjeet28aug
Hi @speedforce

That's great you are getting an error because that's something towards your workaround. Now, you have to provide value to this mandatory field according to the lookup filter i.e [Sector Owner: Username EQUALS rmsprd@company.org] and then update the values. That will definitely resolve your error. 

Mark, it solved, if it resolves your error.

Thanks & Best Regards
Ajeet