Salesforce Apex Trigger Lead Conversion

In Salesforce, we can convert the Lead to Account, Contact and/or Opportunity with the  “Convert” button from front end. However, this can also be done by using the Database.LeadConvertResult Database method in Apex Class.

Here’s a sample lead conversion trigger scenario:

  • Convert Lead to Contact when the contact value is created or updated.
  • Use Contact email to query the related Lead and then merge them with the Contact

Now, let’s see how the apex trigger code looks like:

  • Create a Map to keep the Contact Object. Use the Contact’s email as the key and Contact object as the value.
  • Create a Set of Contact for query later
Map<String, Contact> contMap = new Map<String, Contact>();
Set contEmailSet = new Set();

for(Contact contObj: trigger.new){
   if(contObj.Email != null){
     contMap.put(contObj.Email, contObj);
     contEmailSet.add(contObj.Email);
   }
}

Once the email Set is created, we can start to query the related Lead and then merge the lead with the contact.

Map<String, Lead> leadMap = new Map<String, Lead>();

        if(contEmailSet.size() > 0){

            for(Lead leadObj: [Select Id, Name, Email, isConverted from Lead Where Email in: contEmailSet]){

                Database.LeadConvert lc = new Database.LeadConvert();

                lc.setLeadId(leadObj.Id);
                lc.setAccountId(contMap.get(leadObj.Email).AccountId);
                lc.setContactId(contMap.get(leadObj.Email).Id);
                lc.setDoNotCreateOpportunity(true);

                LeadStatus convertStatus = [SELECT Id, MasterLabel, IsConverted FROM LeadStatus WHERE IsConverted=true limit 1];
                lc.setConvertedStatus(convertStatus.MasterLabel);

                try{
                    Database.LeadConvertResult lcResults = Database.convertLead(lc);
                }Catch(Exception exp){
                    contMap.get(leadObj.Email).addError(exp.getMessage());
                }
            }
        }
    }

In order to convert the lead we need to provide the following information:

  • Lead Id – Use to identify which lead to convert
  • Contact Id – Use to identify which contact will merge with the lead
  • Account Id – Use to identify which account the lead will be assigned to
  • setConvertedStatus – Use to set the converted lead status

For more information please refer to Salesforce Lead Conversion guide.

Notes:

1. When the lead is converted to Contact, Salesforce will need to update the Contact again for the merging.
2. This will cause the trigger to fire again resulting infinite loop in the trigger
3. We have to create a recursive controller class to prevent infinite loop (Please refer to this blog for more information)

Below is the sample of the recursive control function that will wrap up the implementation for this requirement.

trigger ConvertLeadToAccount on Contact (after insert, after update) {

  //Initial the Map and Set 
  Map<String, Contact> contMap = new Map<String, Contact>();
  Set<String> contSet = new Set<String>();

  //Call the RecursiveTriggerCheck class and check if this is the first run
  if(RecursiveTriggerCheck.getRunTimes() < 1){

    //Get related contact from trigger.new
    for(Contact contObj: trigger.new){

      //check if this record fulfill our requirement
      if(contObj.Email != null && contObj.Merge_Leads__c == true){

        //put the related fulfilled record into the map and set for later uses
        contMap.put(contObj.Email, contObj);
        contSet.add(contObj.Email);
      }
    }

    //set the run time flag
    RecursiveTriggerCheck.setRunTimes();

    //check if there is a lead ready for convert
    if(contSet.size() > 0){

      //get the related lead record(s) from the set(contSet)
      for(Lead leadObj: [Select Id, Name, Email, isConverted from Lead Where Email in: contSet and isConverted = false]){

        Database.LeadConvert lc = new Database.LeadConvert();

        lc.setLeadId(leadObj.Id);
        lc.setAccountId(contMap.get(leadObj.Email).AccountId);
        lc.setContactId(contMap.get(leadObj.Email).Id);
        lc.setDoNotCreateOpportunity(true);

        //get the lead status from the LeadStatus obejct
        LeadStatus convertStatus = [SELECT Id, MasterLabel, IsConverted FROM LeadStatus WHERE IsConverted=true limit 1];
        lc.setConvertedStatus(convertStatus.MasterLabel);

        try{
          //convert the lead. Try Catch is used to display the error message
          Database.LeadConvertResult lcResults = Database.convertLead(lc);
        }Catch(Exception exp){
          contMap.get(leadObj.Email).addError(exp.getMessage());
        }
      }
    }
  }
}