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
Gaurav Sinha 27Gaurav 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>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>&nbsp;<p>&nbsp;</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);

    }
}