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?

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

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);
   }
}
  • If you want a formula field to be indexed, you need to file a case with Salesforce Support. – David Reed Jun 13 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 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? – Zach Hutchins Jun 13 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 – Natasha Ali Jun 13 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 at 15:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.