1

My trigger fires on my CustomObject ProductionOrganizer__c and searches leads with the same E-Mail or same LastName && Company (The object therefore has a field for email, lastname and company).

Now my problem is the bulkification to avoid hitting the governor limits. At the moment, the best I got is this code inside my trigger. I already filtered the posToInvestigate to be only the objects that are actually relevant (because of field values, etc):

for (ProductionOrganizer__c po: posToInvestigate.values()) {
    ProductionOrganizerRules porules = new ProductionOrganizerRules(po);

    // leads
    Lead l = TriggerArchitectureLead.findLeadForOrganizer(po);
    If (l != NULL) {
        po.RelatedLeadId__c = l.Id;
        posToUpdate.put(po.Id, po);
    }
}

the code in findLeadForOrganizer does the following:

public static Lead findLeadForOrganizer(ProductionOrganizer__c po) {

    List<Lead> ls = new List<Lead>();

    // query for identical email
    ls.addAll([SELECT Id, LastName, Company, EMail FROM Lead WHERE EMail =:po.Name]);
    If (ls.size() > 0) return ls[0];

    // query for lastname & company
    ls.addAll([SELECT Id, LastName, Company, EMail FROM Lead WHERE (LastName =:po.last_name__c AND Company =:po.organization__c)]);
    If (ls.size() > 0) return ls[0];

    return NULL;

}

Is there any chance I can avoid this SOQL-in-a-for-loop and maybe write a function that receives a map of organizers and adds a lookup to every matched lead in the field RelatedLeadId__c in my object?

Everything is appreciated, even if you tell me that my approach is completly flawed. Thanks in advance!

2 Answers 2

1

Your task here is not entirely straightforward, but the following approach should work for you. You need to build a collection for each field (Email, LastName, and Company), and then map by those values. There are a couple different ways to map by a dual-key, but concatenation is the simplest scheme. You just need to make sure you check carefully for null values.

Mapping

static String elide(String value) { return String.isBlank(value) ? '' : value; }
static String concat(String lastName, String company)
{
    return elide(lastName) + '||' + elide(company);
}
static Map<String, List<Lead>> getLeadsByEmail(Set<String> emails)
{
    Map<String, List<Lead>> leads = new Map<String, List<Lead>>();
    for (Lead lead : [SELECT Email FROM Lead WHERE Email IN :emails])
    {
        if (!leads.containsKey(lead.Email))
            leads.put(lead.Email, new List<Lead>());
        leads.get(lead.Email).add(lead);
    }
    return leads;
}
static Map<String, List<Lead>> getLeadsByLastNameAndCompany
    (Set<String> lastNames, Set<String> companies)
{
    Map<String, List<Lead>> leads = new Map<String, List<Lead>>();
    for (Lead lead : [
        SELECT LastName, Company FROM Lead
        WHERE LastName IN :lastNames
        AND Company IN :companies
    ]){
        String key = concat(lead.LastName, lead.Company);
        if (!leads.containsKey(key))
            leads.put(key, new List<Lead>());
        leads.get(key).add(lead);
    }
    return leads;
}

Collections

With the above, you have everything you need to bulkify your method.

Set<String> emails = new Set<String>();
Set<String> lastNames = new Set<String>();
Set<String> companies = new Set<String>();
for (ProductOrganizer__c po : values)
{
    emails.add(po.Name);
    lastNames.add(po.Last_Name__c);
    companies.add(po.Organization__c);
}
Map<String, List<Lead>> byEmail = getLeadsByEmail(emails);
Map<String, List<Lead>> byLastNameAndCompany =
    getLeadsByLastNameAndCompany(lastNames, companies);

for (ProductOrganizer__c po : values)
{
    if (byEmail.containsKey(po.Name))
    {
        po.RelatedLeadId__c = byEmail.get(po.Name)[0].Id;
        posToUpdate.put(po.Id, po);
    }
    else
    {
        String key = concat(po.Last_Name__c, po.Organization__c);
        if (byLastNameAndCompany.containsKey(key))
        {
            po.RelatedLeadId__c = byLastNameAndCompany.get(key)[0].Id;
            posToUpdate.put(po.Id, po);
        }
    }
}
1
  • Why did you use Maps with Lists of Leads? Is there any use besides the possibility, that two leads may have the same mail adress? (The duplicate-rules in my organization prevent that anyway) May 29, 2016 at 16:44
0

Well it depends what you want to achieve if you want to check if the records lastname / email already exists in the db then this is a sample code for the lastname checker:

Note: in the code below leads.newValues() stores the Trigger.new values

public void DuplicateCheck(){

          Map< string,id> leadMapName = new Map< string,id>();

          for (Lead l : newLead.values()) {
            leadapName.put(a.lastname,a.id);
           }

       List<Lead> leads = new List<Lead>([Select id,last_name  from Lead where last_name in: leadMapName.keySet() and id not in: newLead.values() ]);

       Set<id> duplicateIDs = new Set<id>();
       if(leads.size()>0 ){         
          for(Lead l : leads){

              id  duplicateid = leadMapName.get(l.lastname);
              duplicateIDs.add(duplicateid);
              // do whatever you want with those records
          }  
       }
}

You must log in to answer this question.

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