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
devrequirementdevrequirement 

Compile error: Batch Apex for Email Opt Out field update in duplicate Contacts

Hi All,

 

Following are the two approaches to find the contacts with same email value as the contact record that was latest updated and provide the duplicate contacts the same Email Opt Out field value as in the latest updated contact.

 

Both approaches are giving compiling error. Any help will be greatly appreciated.

 

Thank you!!!!

 

Error are pointed to the lines in red texts.

 

APPROACH 1

 Error: Compile Error: Initial term of field expression must be a concrete SObject: LIST<Contact> at line 34 column 4

 

global Class UpdateEmailOptOutFieldBatchable implements Database.Batchable<Contact>{
// declaring the variable
global final String query;

/* Constructor method to fetch contacts from the database*/

global UpdateEmailOptOutFieldBatchable(){
query = 'SELECT Id, Name, Email, HasOptedOutOfEmail, LastModifiedDate from CONTACT';
}

/*Start method to be invoked*/
global Database.QueryLocator start(Database.BatchableContext BC){
return Database.getQueryLocator(query);
}

global void execute(Database.BatchableContext BC, List<Contact> allContactList)
{
// declaring the variables
List <Contact> ContactsToUpdate = new List<Contact>();
Set <String> ContactIDsToUpdate = new Set<String>();
//Gathering the records, with same email address and different ID, in the list
for(Contact C1: allContactList)
{
List <Contact> emailgroupContactList = new List <Contact> ();
emailgroupContactList.add(C1);
for(Contact C2: allContactList)
{
If (C1.email == C2.email && C1.Id != C2.Id)
{
emailgroupContactList.add(C2);
}
}
// Sorting the groupContactList in terms of Last Modified Date such that the Contact with recent modified date will be at the top.
if(emailgroupContactList.isEmpty == False)
{
for(integer i=0; i<emailgroupContactList.size()-1; i++)
{
for(integer j=0; j<emailgroupContactList.size()-1; j++)
{
If (emailgroupContactList[j].Id != emailgroupContactList[j+1].Id && emailgroupContactList[j].LastModifiedDate < emailgroupContactList[j+1].LastModifiedDate)
{
Contact Temp = new Contact();
Temp = emailgroupContactList[j];
emailgroupContactList[j] = emailgroupContactList[j+1];
emailgroupContactList[j+1] = Temp;
}
}
}
// take HasOptOut Field value of the top most record and update it to the rest of duplicate records in emailgroupContactList
// And then update it to ContactsToUpdate

for(integer i=1; i<emailgroupContactList.size()-1; i++)
{
emailgroupContactList[i].HasOptedOutOfEmail = emailgroupContactList[0].HasOptedOutOfEmail;
if(ContactIDsToUpdate.contains(emailgroupContactList[i].Id)==False)
{
ContactIDsToUpdate.add(emailgroupContactList[i].Id);
ContactsToUpdate.add(emailgroupContactList[i]);
}
}
}
}
If (ContactsToUpdate.isempty==False)
{
update ContactsToUpdate;
}
}

global void finish(Database.BatchableContext BC){
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddress(new String[]{'rk@gmail.com'});
mail.setReplyTo('rk@gmail.com');
mail.setSenderDisplayName('Batch Processing');
mail.setSubject('Batch Process Completed');
mail.setPlainTextBody('Batch Process of Email Opt Out field update for duplicate contact records has completed');
Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});
}
}

 

APPROACH 2

Error: Compile Error: Initial term of field expression must be a concrete SObject: LIST<Contact> at line 33 column 21

 

global Class UpdateEmailOptOutFieldBatchable implements Database.Batchable<Contact>{
// declaring the variable
global final String query;

/* Constructor method to fetch contacts from the database*/

global UpdateEmailOptOutFieldBatchable(){
query = 'SELECT Id, Name, Email, HasOptedOutOfEmail, LastModifiedDate from CONTACT ORDER BY LastModifiedDate DESC';
}

/*Start method to be invoked*/
global Database.QueryLocator start(Database.BatchableContext BC){
return Database.getQueryLocator(query);
}

global void execute(Database.BatchableContext BC, List<Contact> allContactList)
{
// declaring the variables
List <Contact> ContactsToUpdate = new List<Contact>();
Set <String> ContactIDsToUpdate = new Set<String>();
for(integer i=0; i<allContactList.size()-1; i++)
{
for(integer j=i+1; j<allContactList.size()-1; j++)
{
If (allContactList[i].email == allContactList[j].email && ContactIDsToUpdate.contains(allContactList[j].Id)==False)
{
ContactIDsToUpdate.add(allContactList[j].Id);
allContactList[j].HasOptedOutOfEmail=allContactList[i].HasOptedOutOfEmail;
ContactsToUpdate.add(allContactList[j]);
}
}
}
If (ContactsToUpdate.isempty==False)
{
update ContactsToUpdate;
}
}
global void finish(Database.BatchableContext BC){
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddress(new String[]{'rk@gmail.com'});
mail.setReplyTo('rk@gmail.com');
mail.setSenderDisplayName('Batch Processing');
mail.setSubject('Batch Process Completed');
mail.setPlainTextBody('Batch Process of Email Opt Out field update for duplicate contact records has completed');
Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});
}
}

 

Rahul SharmaRahul Sharma

devrequirement,

List.isEmpty is not a property.

Its a method so for accessing it you need to write:

//It is like checking if(false == false) which is not correct way of doing it.
if(emailgroupContactList.isEmpty() == False)

or 

//We normally use it like this as it returns false
if(!emailgroupContactList.isEmpty())

 Refer this link for more help.

devrequirementdevrequirement

Thanks for reply Rahul!!

Made the change and few other trivial changes and the code compiles fine.

 

Now, please correct and guide me if I am wrong.

To test the code based on 2nd approach, we can either:

 

1. Database.executeBatch(new UpdateEmailOptOutFieldBatchable()); in developer console.

    Once the batch job is done check the duplicate contacts and if the field has been updated or not.

 

OR

 

2. Test Class. Could someone provide me examples to write the test class for this (kind of) particular batch apex?

 

Cheers!

DR