Can I programmatically merge Leads to existing Accounts?

Yes, heres a sample from http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_dml_convertLead.htm#leadConvertResult_object

Lead myLead = new Lead(LastName = 'Fry', Company='Fry And Sons');
insert myLead;

Database.LeadConvert lc = new     database.LeadConvert();
lc.setLeadId(myLead.Id)

   lc.setConvertedStatus(convertStatus);
lc.setAccountId(SET ACCOUNT ID);


Database.LeadConvertResult lcr =     Database.convertLead(lc);
System.assert(lcr.isSuccess());

Considerations before implementing merge functionality:

  • Can be used only for Accounts,Contacts and Leads.
  • The values for the fields of the Master record are carried forwarded and any related records from the duplicates are associated with the master.
  • Don't expect salesforce to take care by external ids.
  • Can merge up-to three records only.(if you want to merge more than 3 use the same master record and do multiple merges)

Example code to merge duplicate leads:

trigger WebLead on Lead (After insert) {  

     Map<String,lead>   mapemailleads = new Map<String,lead>();
     List<Lead> leadlistemail = new List<Lead>();
     Map<ID,lead>   mapIdleads = new Map<ID,lead>();

         for(Lead l:Trigger.new)

        {
         mapemailleads.put(l.email,l);
         mapIdleads.put(l.id,l);
        }

        leadlistemail= [select id,Street,City,State,Country,PostalCode,Email,
                               Alternate_Email__c, SSO__c,
                               FirstName,LastName
                               from Lead
                               Where Email  IN:mapemailleads.keySet() 
                               AND isconverted = False
                               NOT IN: mapIdleads.KeySet()];

       for(Lead l:leadlistemail){
         Lead newlead = mapleads.get(l.email);

         /** Merge command takes to arguments first one master record(l in this case)
          * to which child records
          * are merged(new lead in this case).second argument can be a single SObject 
          * or list containing no more than 2 records.
          */          
          merge l newlead;
        }

}

Common Errors or Pitfalls:

  • you should make sure you are not querying the same leads again. (Error thrown:first error: INVALID_ID_FIELD, The master record id appears in the merge id list: )
  • After merge operation the values in the fields of master record or those that are carried forward.if you want to get some values from child records you have to manually do it.
  • Notes or Attachments(contacts or opportunities in the case of accounts) on the child records will be assigned to master.
  • Good idea to always filter converted leads.

Merging Leads with Person Account:

In this scenario let us consider we have to merge leads with a person account based on the email.

    trigger WebLead on Lead (After insert) {  

     Map<String,lead>   mapemailleads = new Map<String,lead>();
     List<Account>  paccountemail = new List<Account>();
     Database.LeadConvert lc = new database.LeadConvert();

         for(Lead l:Trigger.new)

        {
         mapemailleads.put(l.email,l);

        }

       List<Account> paccountemail=[select id,personEmail,Alternate_Email__pc,                                      
                                      from Account 
                                      where recordtype.name='Person Account' 
                                      and (personEmail IN:mapemailleads.keySet() 
                                      OR Alternate_Email__pc IN:mapemailleads.keySet())]; 

       for(Account a:paccountemail){
         Lead newlead = mapemailleads.get(a.email);

              lc.setLeadId(newlead.id);
              lc.setAccountId(a.ID);//converting  into existing account                        
              lc.setDoNotCreateOpportunity(true); //mention weather to create a opportunity or not
              LeadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
              lc.setConvertedStatus(convertStatus.MasterLabel);
              Database.LeadConvertResult lcr = Database.convertLead(lc);                
              System.assert(lcr.isSuccess()); 

        }

}

Field values are updated according to lead field mappings for the conversion process and all the notes and attachments from lead are attached to the account.

Though the answer was same,just thinking a detailed writing from my recent blog post would help some one looking here for the same.