0

I have an existing trigger which converts leads into peron accounts if the company name is blank.

Trigger AutoConvert on Lead (after insert) {
     LeadStatus convertStatus = [
          select MasterLabel
          from LeadStatus
          where IsConverted = true
          limit 1
     ];
     List<Database.LeadConvert> leadConverts = new List<Database.LeadConvert>();

     for (Lead lead: Trigger.new) {
          if (!lead.isConverted && lead.Company == null) {
               Database.LeadConvert lc = new Database.LeadConvert();
               String oppName = lead.Name;

               lc.setLeadId(lead.Id);
               lc.setDoNotCreateOpportunity(true);
               lc.setConvertedStatus(convertStatus.MasterLabel);

               leadConverts.add(lc);
          }
     }

     if (!leadConverts.isEmpty()) {
          List<Database.LeadConvertResult> lcr = Database.convertLead(leadConverts);
     }
}

I need to also write a trigger that stops records from coming into Salesforce if that email already exisits in a contact or an account (we use person accounts).

The issue is how do I get it working with the existing trigger (I need it to run before the trigger that converts it into a person account is run).

Is there a way to combine the two or add the functionality to create the record only if the email address doesn't already exist as a contact in the org?

1
  • Please remember to use the {} tool to format your code. Thanks!
    – David Reed
    Jun 13, 2019 at 12:10

2 Answers 2

4

Yes, we can add more complicated logic in a trigger. Traditionally, we offload the trigger logic in to a "trigger handler" class, as demonstrated in this answer. However, to keep things simple, this is how we'd add the new logic to your trigger:

trigger AutoConvert on Lead (before insert, after insert) {
  switch on Trigger.operationType {
    when BEFORE_INSERT {
      Set<String> emails = new Set<String>();
      for(Lead record: Trigger.new) {
        emails.add(record.Email);
      }
      emails.remove(null);
      for(Contact record: [SELECT Email FROM Contact WHERE Email = :emails]) {
        emails.remove(record.Email);
      }
      for(Lead record: Trigger.new) {
        if(record.Email != null && !emails.contains(record.Email)) {
          record.Email.addErrror('This lead matches an existing email.');
        }
      }
    }
    when AFTER_INSERT {
      // Use existing logic for lead conversion here //
    }
  }
}

As you can see, the name of the trigger now doesn't really represent what's really going on, though. You might want to rename the trigger to something like LeadTrigger; it is strongly advised that you use one trigger per object to keep things simple.

1

I would not do business logic inside a trigger, hand that off to a "Handler" class. That being said you don't have many options here other than to query for it, which happens to be on most organizations largest datasets.

Trigger AutoConvert on Lead (after insert) {
   LeadStatus convertStatus = [
        select MasterLabel
        from LeadStatus
        where IsConverted = true
        limit 1
   ];
   // Get Emails
   List<Database.LeadConvert> leadConverts = new List<Database.LeadConvert>();
   Set<string> leadEmails = new Set<string>();
   for(Lead lead: Trigger.new){
       if(! String.isBlank(lead.Email){
          leadEmails.add(lead.Email);
       }
   }
   List<Contact> contacts = [
       select email from contact where Email IN :leadEmails
   ];
   List<string> emails = new List<string>();
   for(Contact c : contacts){
      emails.add(c.Email);
   }
   //Perform logic
   for (Lead lead: Trigger.new) {
        if (!lead.isConverted && lead.Company == null) {
             Database.LeadConvert lc = new Database.LeadConvert();
             String oppName = lead.Name;

             lc.setLeadId(lead.Id);
             lc.setDoNotCreateOpportunity(true);
             lc.setConvertedStatus(convertStatus.MasterLabel);
             // Check to see if the email exists
             if(!emails.contains(lc.Email){
                leadConverts.add(lc);
             }
        }
   }

   if (!leadConverts.isEmpty()) {
        List<Database.LeadConvertResult> lcr = Database.convertLead(leadConverts);
   }
}
8
  • If you want a formula field to be indexed, you need to file a case with Salesforce Support.
    – David Reed
    Jun 13, 2019 at 13:30
  • 2
    Person Accounts still use contact fields to store the email and other contact information. There's no need for a formula or to even consider if person accounts have been enabled.
    – sfdcfox
    Jun 13, 2019 at 13:31
  • Interesting, @DavidReed I thought salesforce under the hood did indexing for you on commonly run queries but your saying thats only for certain field types? Jun 13, 2019 at 13:36
  • (I'm quite to new to dev) So do I no longer need a handler class to handle the business logic as its in the trigger Jun 13, 2019 at 15:13
  • @ZachHutchins What David said is correct; Salesforce only indexes certain types of fields (see this question's answers for more info). Notably, formula fields are not indexed by default, since they are calculated on-the-fly. Further, if the formula is not deterministic (e.g. it varies based on TODAY() or a parent object's fields), it can't be indexed at all. Salesforce cannot, and does not, index "commonly run queries" as one woudl see in other RDBMS. No indexes means poor performance.
    – sfdcfox
    Jun 13, 2019 at 15:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .