3

The below code searches on the lead record if the Account already exists in Salesforce using the website/email domain field. The code works just fine but I keep getting this error in my inbox: System.LimitException: Apex CPU time limit exceeded

Trigger Accname on Lead (before insert, before update) { 

    Account[] accts = [SELECT Name, id,Website,Domain__c FROM Account WHERE (Website != NULL OR Domain__c != NULL)];
    for(Lead l : Trigger.new)
    {        
        for(Integer i = 0; i < accts.size(); i++)
        {
            if(l.Domain__c == accts[i].Domain__c ||  l.Domain__c == accts[i].Website)
            {
                l.Account_Leads__c = accts[i].id;
                l.Account_Found__c = True;

            } else(System.debug('Not triggered.'));
        }
    }
}
2

2 Answers 2

11

Try at least restricting to Account records which might match, and mapping by those values.

public with sharing class LeadService
{
    public static void findAccountsByDomain(List<Lead> newRecords)
    {
        Set<String> domains = new Set<String>();
        for (Lead record : newRecords) domains.add(record.Domain__c);
        Map<String, Account> domainToAccount = new Map<String, Account>();
        for (Account record : [
            SELECT Website, Domain__c FROM Account
            WHERE Website IN :domains OR Domain__c IN :domains
        ]){
            domainToAccount.put(safeLowerCase(record.Website), record);
            domainToAccount.put(safeLowerCase(record.Domain__c), record);
        }
        domainToAccount.remove(null);

        for (Lead record : newRecords)
        {
            Account parent = domainToAccount.get(safeLowerCase(record.Domain__c));
            if (parent != null)
            {
                record.Account_Leads__c = parent.Id;
                record.Account_Found__c = true;
            }
        }
    }
    static String safeLowerCase(String input)
    {
        return input == null ? input : input.toLowerCase();
    }
}

Then in your trigger you would call LeadService.findAccountsByDomain(trigger.new);.

Note that you may have multiple records that match the same key, but you are arbitrarily choosing one. This means your code is not deterministic. You should also look up trigger handlers and find a pattern that works for you to implement logic-less triggers.

4
  • In the line record.Account_Leads__c = record.Id, it is mapping the lead id to the lead record. How to map the account id to that field?
    – Mike
    Feb 27, 2017 at 0:58
  • 2
    Just change to record.Account_Leads__c = domainToAccount.get(record.Domain__c).Id; Feb 26, 2018 at 21:00
  • @Mike N.B. map keys will be case sensitive so application should ensure that Account.Website, Account.Domain__c, Lead.Domain__c are all the same case (presumably lower) - otherwise Account parent = domainToAccount.get(record.Domain__c); will not always work
    – cropredy
    Mar 5, 2018 at 19:24
  • The domain could also be null though, so you have to account for that too. I'll update though.
    – Adrian Larson
    Mar 5, 2018 at 19:26
1

I'm putting my edit as a separate answer:

Besides the minor edit that I have made, the suggested solution from Adrian seems to solve your problem, where is used map collection (their primary use to solve these use cases)

Set<String> domains = new Set<String>();
for (Lead record : trigger.new) 
    domains.add(record.Domain__c);
Map<String, Account> domainToAccount = new Map<String, Account>();
for (Account record : [
    SELECT Website, Domain__c FROM Account
    WHERE Website IN :domains OR Domain__c IN :domains
]){
    domainToAccount.put(record.Website, record);
    domainToAccount.put(record.Domain__c, record);
}

for (Lead record : trigger.new)
{
    if (domainToAccount.containsKey(record.Domain__c))
    {
        record.Account_Leads__c = domainToAccount.get(record.Domain__c).Id; // edit, based on the logic of question
        record.Account_Found__c = true;
    }
}
2

You must log in to answer this question.

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