You need to sign in to do that
Don't have an account?
Gaurav Sinha 27
Need Help to improve code coverage
Below is the class to merge contacts based on merge criteria defined. Can someone help me in writing a test class for the same. Need to deploy it by EOD.
global class ContactMergeBatch implements Database.Batchable<AggregateResult>, Database.Stateful
{
private String query;
private String dupBy;
private String pastNDays;
private Integer BatchSize;
private Set<ID> accIds;
private Set<String> previousQualifiedIds = new Set<String>();
private Set<String> skipEmails;
private List<String> recipientEmails;
private String CustomerRTId=Schema.SObjectType.Contact.getRecordTypeInfosByName().get('Customer').getRecordTypeId();
private String ConsumerRTId=Schema.SObjectType.Contact.getRecordTypeInfosByName().get('Consumer').getRecordTypeId();
private Map<String,ContactMergeWrappper> mergeDupMap;
private Map<String,DateTime> createdDateMap;
private List<ContactMergeWrappper>MergeStatusList;
Private Integer MergeCount;
global ContactMergeBatch(String pnds,String db,Set<String> pqIds,Map<String,DateTime>cdbm)
{
dupBy=db;
pastNDays=pnds;
previousQualifiedIds=pqIds;
createdDateMap=cdbm;
mergeDupMap = new Map<String,ContactMergeWrappper>();
MergeStatusList=New List<ContactMergeWrappper>();
EMDM_Schedule_Job_Config__c config= EMDM_Schedule_Job_Config__c.getvalues('Contact Merge Batch');
pastNDays=config.Last_N_Days__c;
BatchSize=Integer.Valueof(config.BatchLoad__c);
skipEmails = new Set<String>(config.Skip_Email_List__c.split(','));
recipientEmails= new List<String>(config.Confirmation_Recipient__c.split(','));
if(dupBy == 'PersonId') query = 'Select AccountId from Contact where AccountId !=null and CreatedDate = LAST_N_DAYS:'+pastNDays+' and ( RecordTypeId=\''+CustomerRTId+'\' OR RecordTypeId=\''+ConsumerRTId+'\') and IsActive__c=true GROUP BY AccountId';
else
{
if(previousQualifiedIds.size()>0)
{
String pIds = String.join(new List<String>(previousQualifiedIds), '\',\'');
pIds='(\''+pIds+'\')';
System.debug('pIds==>'+pIds);
query = 'Select AccountId from Contact where ( AccountId !=null and CreatedDate = LAST_N_DAYS:'+pastNDays+' and ( RecordTypeId=\''+CustomerRTId+'\' OR RecordTypeId=\''+ConsumerRTId+'\') and IsActive__c=true ) OR AccountId IN '+pIds+' GROUP BY AccountId';
}
else
{
query = 'Select AccountId from Contact where AccountId !=null and CreatedDate = LAST_N_DAYS:'+pastNDays+' and ( RecordTypeId=\''+CustomerRTId+'\' OR RecordTypeId=\''+ConsumerRTId+'\') and IsActive__c=true GROUP BY AccountId';
}
}
System.debug('mergeBy==>'+dupBy+' pastNDays==>'+pastNDays+ ' query==>'+query);
}
//The batch job starts if(a!=null)
global Iterable<AggregateResult> start(Database.BatchableContext bc)
{
return new AggregateResultIterable(query);
}
global void execute(Database.BatchableContext bc, List<sObject> scope)
{
accIds=new Set<ID>();
for(sObject a : scope) accIds.add((Id)a.get('AccountId'));
System.debug('accIds==>'+accIds.size());
List<Contact>QualifiedContacts=[SELECT id,Accountid,Salutation,FirstName,Second_Name__c,LastName,Phone,Separation_Contact__c,Preferred_Method_of_Contact__c,Preferred_Language__c,IsActive__c,Service_Sales_Contact__c,Phonetic_First_Name__c,Phonetic_Second_Name__c ,Phonetic_Last_Name__c ,First_Name_Local__c,Second_Name_Local__c,Last_Name_Local__c,Title,Standardized_Title__c,Phone__c,Work_Phone_Extension__c,MobilePhone,HomePhone,Email,Key_Contact_to__c,DoNotCall,Left_Company__c,Isolation_Status__c,Isolation_Status_Date__c,GDPR_Governed__c,Isolation_Comment__c,Teleoptin_Required__c,Preferred_Subjects__c,Job_Seniority__c,Lead_Source_Most_Recent__c,Job_Responsibilities__c,MDM_ContactSync_Status__c,Suppress_Marketing__c,Suppression_Start_Date__c,Suppression_End_Date__c,Description,Job_Role__c,Business_Function__c,Industry__c,BU_Lead__c, Lead_Source_Original1__c, HP_Customer_Self_Reported__c, MailingCity, MailingState, MailingCountry, MailingPostalCode, MailingStreet, Fax,MDM_Person_ID__c,MDCP_Last_Sync_Date__c,LeadSource,SFDC_MDCP_Batch_Sync_Flag__c,CreatedDate, RecordTypeId, LastModifiedDate,Isolation_Reason__c, MailingCity__c, MailingCountry__c, MailingPostalCode__c, MailingState__c, MailingStreet__c, Telephone_Access_Code__c, Service_Delivery_Email_Opt_In__c, Email_Quality_Survey_Opt_In__c, Phone_Quality_Survey_Opt_In__c, Department, Lead_Source__c,Case_Closure_Notification_Opt_In__c, Alternate_Preferred_Customer_Language__c, Part_Delivered_Notification_Opt_In__c, VisitOps__LinkedInUrl__c, Previous_MDCP_Contact_Relationship__c, Preferred_Language_Code__c, Preferred_Customer_Language__c, Location_ID__c, Contact_External_Id__c, Customer_Division__c, DPlus_Company_Reference__c, SourceSystemContactID__c FROM Contact where AccountId=:accIds and IsActive__c=true AND EMAIL NOT IN :skipEmails ORDER BY CreatedDate DESC];
System.debug('QualifiedContacts==>'+QualifiedContacts);
Map<ID,List<contact>> SegContactMap = new Map<ID,List<contact>>();
Map<String,ContactMergeWrappper> DupMap = new Map<string,ContactMergeWrappper>();
String dupKey;
//Segregating All Contacts by Account
for(contact c :QualifiedContacts)
{
list<contact> clist=new list<contact>();
if(SegContactMap.get(c.accountid)!=null)
{
clist = SegContactMap.get(c.accountid);
}
clist.add(c);
SegContactMap.put(c.accountid,clist);
}
System.debug('SegContactMap==>'+SegContactMap);
//Finding Duplicate based on Filter Passed
Boolean validKey = true;
for(Id accid : SegContactMap.keySet())
{
for(Contact con : SegContactMap.get(accid))
{
validKey = true;
if(DupBy=='LastNameEmail')
{
if(String.isBlank(con.Email)) validKey = false;
dupKey = con.AccountId+con.LastName+con.Email;
}
else
{
if(String.isBlank(con.MDM_Person_ID__c)) validKey = false;
dupKey = con.AccountId+con.MDM_Person_ID__c;
}
System.debug('dupKey ===>'+dupKey +' ==>'+DupBy);
if(DupMap.get(dupKey)==null && validKey)
{
list<Contact> Dlist = new list<Contact>();
ContactMergeWrappper W = new ContactMergeWrappper(con,Dlist,'Processing');
DupMap.put(dupKey,W);
}
else if(DupMap.get(dupKey)!=null && validKey)
{
ContactMergeWrappper W=DupMap.get(dupKey);
DateTime RTCD,CSCD;
RTCD = createdDateMap.get(con.Id) !=null? createdDateMap.get(con.Id):con.CreatedDate;
CSCD = createdDateMap.get(W.Survivor.Id) !=null? createdDateMap.get(W.Survivor.Id):W.Survivor.CreatedDate;
if(RTCD >= CSCD)
{
W.donors.add(W.Survivor);
W.Survivor=con;
}
else
{
W.donors.add(con);
}
DupMap.put(dupKey,W);
}
}
}
//Filter out records with no Donors
System.debug('DupMap==>'+DupMap.size()+' ===>'+DupMap);
mergeDupMap=New Map<String,ContactMergeWrappper>();
for(String key : DupMap.keySet())
{
ContactMergeWrappper W=DupMap.get(key);
if(W.donors.Size()>0)
{
mergeDupMap.put(W.Survivor.Id,W);
System.debug('The previousQualifiedIds 2' + previousQualifiedIds);
previousQualifiedIds.add(W.Survivor.AccountId);
createdDateMap.put(W.Survivor.Id,W.Survivor.CreatedDate);
}
}
System.debug('mergeDupMap==>'+mergeDupMap.size()+' ===>'+mergeDupMap);
//Merging the Qualified records one by one
for(ID DI:mergeDupMap.keyset())
{
ContactMergeWrappper MergeResult=ContactMergeHelper.ProcessMerge(mergeDupMap.get(DI)) ;
MergeStatusList.add(MergeResult);
System.debug('MergeResult==>'+MergeResult);
}
}
// The batch job finishes
global void finish(Database.BatchableContext bc)
{
String mergeText = 'Donor PersonId,Donor Email,Donor FirstName,Donor LastName,Donor Id,Donor CreatedDate,Survivor PersonId,Survivor Email,Survivor FirstName,Survivor LastName,Survivor Id,Survivor CreatedDate,Status' + '\n';
Integer ErorCount = 0;
for(ContactMergeWrappper mw:MergeStatusList)
{
List<Contact>DonorList = mw.Donors;
Contact Survivor = mw.Survivor;
if(mw.Status=='Processed')
{
for(Contact donor:DonorList)
{
if(mw.MergeStatusMap.get(donor.Id) !='Record Merged Sucessfully'){
mergeText += donor.MDM_Person_ID__c+ ',' +donor.Email+ ','+donor.FirstName+ ',' +donor.LastName+ ',' +donor.Id+ ','+donor.CreatedDate+ ',' +Survivor.MDM_Person_ID__c+ ',' +Survivor.Email+ ',' +Survivor.FirstName+ ',' +Survivor.LastName+ ',' +Survivor.Id+ ',' +Survivor.CreatedDate+ ',' +mw.MergeStatusMap.get(donor.Id) + '\n';
ErorCount++;
}
//DonorList.clear();
MergeCount= mw.MergeStatusMap.size();
}
}
}
mergeText = mergeText.substring(0, mergeText.length() -1 );
If(ErorCount>0){
Messaging.EmailFileAttachment csvAttc = new Messaging.EmailFileAttachment();
blob csvBlob = Blob.valueOf(mergeText);
DateTime d = Date.Today() ;
String dateStr = d.format('dd-MM-yyyy') ;
string csvname= 'Contact_Merge_Status_BY_'+dupBy+' '+dateStr+'.csv';
csvAttc.setFileName(csvname);
csvAttc.setBody(csvBlob);
Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
message.toAddresses = recipientEmails;
message.subject = 'Contact merge Error report '+String.valueof(Date.Today());
//message.plainTextBody = 'Hi, \n Please Find the Status of Merge Performed on'+String.valueof(Date.Today());
message.setFileAttachments(new Messaging.EmailFileAttachment[]{csvAttc});
String bodyStart='<html><body><h3>Contact Merge Failure Report:</h3> <table align="left" border="1" cellpadding="1" cellspacing="1" style="width: 500px;"><tbody><tr><td>Operation</td><td>Contact Merge</td></tr><tr><td>Status</td><td>Merge Failed</td>';
String BodyStarttime='</td></tr><tr><td>Time Processed</td><td>';
String NoOfRecordProssced='</td></tr><tr><td>Number of Duplicate records Processed</td><td>';
String errorCounts='</td></tr><tr><td>Number of records Faield to Merge</td><td>';
String BodyTail='</td></tr></tbody></table><p> </p><p> </p><p> </p><p> </p><p> </p> <p> </p><p>Thank You</p><p>Contact Merging Team</p><body></html>';
String HTMLBody=bodyStart+NoOfRecordProssced+MergeCount+errorCounts+ErorCount+BodyStarttime+string.valueof(system.now())+BodyTail;
message.setHtmlBody(HTMLBody);
Messaging.SingleEmailMessage[] messages = new List<Messaging.SingleEmailMessage> {message};
Messaging.SendEmailResult[] results = Messaging.sendEmail(messages);
}
if(dupBy=='PersonId') Id JobId = Database.executeBatch(new ContactMergeBatch(pastNDays,'LastNameEmail',previousQualifiedIds,createdDateMap),BatchSize);
}
}
global class ContactMergeBatch implements Database.Batchable<AggregateResult>, Database.Stateful
{
private String query;
private String dupBy;
private String pastNDays;
private Integer BatchSize;
private Set<ID> accIds;
private Set<String> previousQualifiedIds = new Set<String>();
private Set<String> skipEmails;
private List<String> recipientEmails;
private String CustomerRTId=Schema.SObjectType.Contact.getRecordTypeInfosByName().get('Customer').getRecordTypeId();
private String ConsumerRTId=Schema.SObjectType.Contact.getRecordTypeInfosByName().get('Consumer').getRecordTypeId();
private Map<String,ContactMergeWrappper> mergeDupMap;
private Map<String,DateTime> createdDateMap;
private List<ContactMergeWrappper>MergeStatusList;
Private Integer MergeCount;
global ContactMergeBatch(String pnds,String db,Set<String> pqIds,Map<String,DateTime>cdbm)
{
dupBy=db;
pastNDays=pnds;
previousQualifiedIds=pqIds;
createdDateMap=cdbm;
mergeDupMap = new Map<String,ContactMergeWrappper>();
MergeStatusList=New List<ContactMergeWrappper>();
EMDM_Schedule_Job_Config__c config= EMDM_Schedule_Job_Config__c.getvalues('Contact Merge Batch');
pastNDays=config.Last_N_Days__c;
BatchSize=Integer.Valueof(config.BatchLoad__c);
skipEmails = new Set<String>(config.Skip_Email_List__c.split(','));
recipientEmails= new List<String>(config.Confirmation_Recipient__c.split(','));
if(dupBy == 'PersonId') query = 'Select AccountId from Contact where AccountId !=null and CreatedDate = LAST_N_DAYS:'+pastNDays+' and ( RecordTypeId=\''+CustomerRTId+'\' OR RecordTypeId=\''+ConsumerRTId+'\') and IsActive__c=true GROUP BY AccountId';
else
{
if(previousQualifiedIds.size()>0)
{
String pIds = String.join(new List<String>(previousQualifiedIds), '\',\'');
pIds='(\''+pIds+'\')';
System.debug('pIds==>'+pIds);
query = 'Select AccountId from Contact where ( AccountId !=null and CreatedDate = LAST_N_DAYS:'+pastNDays+' and ( RecordTypeId=\''+CustomerRTId+'\' OR RecordTypeId=\''+ConsumerRTId+'\') and IsActive__c=true ) OR AccountId IN '+pIds+' GROUP BY AccountId';
}
else
{
query = 'Select AccountId from Contact where AccountId !=null and CreatedDate = LAST_N_DAYS:'+pastNDays+' and ( RecordTypeId=\''+CustomerRTId+'\' OR RecordTypeId=\''+ConsumerRTId+'\') and IsActive__c=true GROUP BY AccountId';
}
}
System.debug('mergeBy==>'+dupBy+' pastNDays==>'+pastNDays+ ' query==>'+query);
}
//The batch job starts if(a!=null)
global Iterable<AggregateResult> start(Database.BatchableContext bc)
{
return new AggregateResultIterable(query);
}
global void execute(Database.BatchableContext bc, List<sObject> scope)
{
accIds=new Set<ID>();
for(sObject a : scope) accIds.add((Id)a.get('AccountId'));
System.debug('accIds==>'+accIds.size());
List<Contact>QualifiedContacts=[SELECT id,Accountid,Salutation,FirstName,Second_Name__c,LastName,Phone,Separation_Contact__c,Preferred_Method_of_Contact__c,Preferred_Language__c,IsActive__c,Service_Sales_Contact__c,Phonetic_First_Name__c,Phonetic_Second_Name__c ,Phonetic_Last_Name__c ,First_Name_Local__c,Second_Name_Local__c,Last_Name_Local__c,Title,Standardized_Title__c,Phone__c,Work_Phone_Extension__c,MobilePhone,HomePhone,Email,Key_Contact_to__c,DoNotCall,Left_Company__c,Isolation_Status__c,Isolation_Status_Date__c,GDPR_Governed__c,Isolation_Comment__c,Teleoptin_Required__c,Preferred_Subjects__c,Job_Seniority__c,Lead_Source_Most_Recent__c,Job_Responsibilities__c,MDM_ContactSync_Status__c,Suppress_Marketing__c,Suppression_Start_Date__c,Suppression_End_Date__c,Description,Job_Role__c,Business_Function__c,Industry__c,BU_Lead__c, Lead_Source_Original1__c, HP_Customer_Self_Reported__c, MailingCity, MailingState, MailingCountry, MailingPostalCode, MailingStreet, Fax,MDM_Person_ID__c,MDCP_Last_Sync_Date__c,LeadSource,SFDC_MDCP_Batch_Sync_Flag__c,CreatedDate, RecordTypeId, LastModifiedDate,Isolation_Reason__c, MailingCity__c, MailingCountry__c, MailingPostalCode__c, MailingState__c, MailingStreet__c, Telephone_Access_Code__c, Service_Delivery_Email_Opt_In__c, Email_Quality_Survey_Opt_In__c, Phone_Quality_Survey_Opt_In__c, Department, Lead_Source__c,Case_Closure_Notification_Opt_In__c, Alternate_Preferred_Customer_Language__c, Part_Delivered_Notification_Opt_In__c, VisitOps__LinkedInUrl__c, Previous_MDCP_Contact_Relationship__c, Preferred_Language_Code__c, Preferred_Customer_Language__c, Location_ID__c, Contact_External_Id__c, Customer_Division__c, DPlus_Company_Reference__c, SourceSystemContactID__c FROM Contact where AccountId=:accIds and IsActive__c=true AND EMAIL NOT IN :skipEmails ORDER BY CreatedDate DESC];
System.debug('QualifiedContacts==>'+QualifiedContacts);
Map<ID,List<contact>> SegContactMap = new Map<ID,List<contact>>();
Map<String,ContactMergeWrappper> DupMap = new Map<string,ContactMergeWrappper>();
String dupKey;
//Segregating All Contacts by Account
for(contact c :QualifiedContacts)
{
list<contact> clist=new list<contact>();
if(SegContactMap.get(c.accountid)!=null)
{
clist = SegContactMap.get(c.accountid);
}
clist.add(c);
SegContactMap.put(c.accountid,clist);
}
System.debug('SegContactMap==>'+SegContactMap);
//Finding Duplicate based on Filter Passed
Boolean validKey = true;
for(Id accid : SegContactMap.keySet())
{
for(Contact con : SegContactMap.get(accid))
{
validKey = true;
if(DupBy=='LastNameEmail')
{
if(String.isBlank(con.Email)) validKey = false;
dupKey = con.AccountId+con.LastName+con.Email;
}
else
{
if(String.isBlank(con.MDM_Person_ID__c)) validKey = false;
dupKey = con.AccountId+con.MDM_Person_ID__c;
}
System.debug('dupKey ===>'+dupKey +' ==>'+DupBy);
if(DupMap.get(dupKey)==null && validKey)
{
list<Contact> Dlist = new list<Contact>();
ContactMergeWrappper W = new ContactMergeWrappper(con,Dlist,'Processing');
DupMap.put(dupKey,W);
}
else if(DupMap.get(dupKey)!=null && validKey)
{
ContactMergeWrappper W=DupMap.get(dupKey);
DateTime RTCD,CSCD;
RTCD = createdDateMap.get(con.Id) !=null? createdDateMap.get(con.Id):con.CreatedDate;
CSCD = createdDateMap.get(W.Survivor.Id) !=null? createdDateMap.get(W.Survivor.Id):W.Survivor.CreatedDate;
if(RTCD >= CSCD)
{
W.donors.add(W.Survivor);
W.Survivor=con;
}
else
{
W.donors.add(con);
}
DupMap.put(dupKey,W);
}
}
}
//Filter out records with no Donors
System.debug('DupMap==>'+DupMap.size()+' ===>'+DupMap);
mergeDupMap=New Map<String,ContactMergeWrappper>();
for(String key : DupMap.keySet())
{
ContactMergeWrappper W=DupMap.get(key);
if(W.donors.Size()>0)
{
mergeDupMap.put(W.Survivor.Id,W);
System.debug('The previousQualifiedIds 2' + previousQualifiedIds);
previousQualifiedIds.add(W.Survivor.AccountId);
createdDateMap.put(W.Survivor.Id,W.Survivor.CreatedDate);
}
}
System.debug('mergeDupMap==>'+mergeDupMap.size()+' ===>'+mergeDupMap);
//Merging the Qualified records one by one
for(ID DI:mergeDupMap.keyset())
{
ContactMergeWrappper MergeResult=ContactMergeHelper.ProcessMerge(mergeDupMap.get(DI)) ;
MergeStatusList.add(MergeResult);
System.debug('MergeResult==>'+MergeResult);
}
}
// The batch job finishes
global void finish(Database.BatchableContext bc)
{
String mergeText = 'Donor PersonId,Donor Email,Donor FirstName,Donor LastName,Donor Id,Donor CreatedDate,Survivor PersonId,Survivor Email,Survivor FirstName,Survivor LastName,Survivor Id,Survivor CreatedDate,Status' + '\n';
Integer ErorCount = 0;
for(ContactMergeWrappper mw:MergeStatusList)
{
List<Contact>DonorList = mw.Donors;
Contact Survivor = mw.Survivor;
if(mw.Status=='Processed')
{
for(Contact donor:DonorList)
{
if(mw.MergeStatusMap.get(donor.Id) !='Record Merged Sucessfully'){
mergeText += donor.MDM_Person_ID__c+ ',' +donor.Email+ ','+donor.FirstName+ ',' +donor.LastName+ ',' +donor.Id+ ','+donor.CreatedDate+ ',' +Survivor.MDM_Person_ID__c+ ',' +Survivor.Email+ ',' +Survivor.FirstName+ ',' +Survivor.LastName+ ',' +Survivor.Id+ ',' +Survivor.CreatedDate+ ',' +mw.MergeStatusMap.get(donor.Id) + '\n';
ErorCount++;
}
//DonorList.clear();
MergeCount= mw.MergeStatusMap.size();
}
}
}
mergeText = mergeText.substring(0, mergeText.length() -1 );
If(ErorCount>0){
Messaging.EmailFileAttachment csvAttc = new Messaging.EmailFileAttachment();
blob csvBlob = Blob.valueOf(mergeText);
DateTime d = Date.Today() ;
String dateStr = d.format('dd-MM-yyyy') ;
string csvname= 'Contact_Merge_Status_BY_'+dupBy+' '+dateStr+'.csv';
csvAttc.setFileName(csvname);
csvAttc.setBody(csvBlob);
Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
message.toAddresses = recipientEmails;
message.subject = 'Contact merge Error report '+String.valueof(Date.Today());
//message.plainTextBody = 'Hi, \n Please Find the Status of Merge Performed on'+String.valueof(Date.Today());
message.setFileAttachments(new Messaging.EmailFileAttachment[]{csvAttc});
String bodyStart='<html><body><h3>Contact Merge Failure Report:</h3> <table align="left" border="1" cellpadding="1" cellspacing="1" style="width: 500px;"><tbody><tr><td>Operation</td><td>Contact Merge</td></tr><tr><td>Status</td><td>Merge Failed</td>';
String BodyStarttime='</td></tr><tr><td>Time Processed</td><td>';
String NoOfRecordProssced='</td></tr><tr><td>Number of Duplicate records Processed</td><td>';
String errorCounts='</td></tr><tr><td>Number of records Faield to Merge</td><td>';
String BodyTail='</td></tr></tbody></table><p> </p><p> </p><p> </p><p> </p><p> </p> <p> </p><p>Thank You</p><p>Contact Merging Team</p><body></html>';
String HTMLBody=bodyStart+NoOfRecordProssced+MergeCount+errorCounts+ErorCount+BodyStarttime+string.valueof(system.now())+BodyTail;
message.setHtmlBody(HTMLBody);
Messaging.SingleEmailMessage[] messages = new List<Messaging.SingleEmailMessage> {message};
Messaging.SendEmailResult[] results = Messaging.sendEmail(messages);
}
if(dupBy=='PersonId') Id JobId = Database.executeBatch(new ContactMergeBatch(pastNDays,'LastNameEmail',previousQualifiedIds,createdDateMap),BatchSize);
}
}