function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
VisionaryVisionary 

anyway to bulkify this ?

I have a task to assign a lead to a specific user depending on 2 factors (Zip Code, and Product Family)
Some leads will have Product Family and Zip filled out - we only need to look at ones that have both filled in.

Each Zip Code can be owned by multiple individuals but that is segregated by Division
Custom Object: Zip_Code__c example
OwnerID                    ZipCode    Division__c
00511000000AAaa    50000       1
00511000000AAab    50000       2
00511000000AAac    50000       3
00511000000AAad    50000       4

Division is based on Product Family in Product2 Object
Name                       Family                Division__c
iPad Air                    Tablet                 1
iPad mini                  Tablet                 1
iPhone 7                   Phone                2
Samsung S7             Phone                3

So what i have to do is this
Get Lead.ProductFamily, and Lead.PostalCode
and figure out how to get Zip_Code__c.OwnerID for each Lead
 

This is my current code, but it seems to sometimes not work (no errors) just not pulling as expected.. I REALLY need someone's help.

 

trigger LeadTrigger on Lead (before insert) {

List<Lead> leadsToUpdate = new List<Lead>();
                  
                    
    for (Lead lead : Trigger.new)
    {     
      if (lead.ProductFamily__c == null || lead.ProductFamily__c == '' || lead.PostalCode.length() < 5)
      {
          // do nothing
      }
      else
      {
         
              List<Product2> prodList = [SELECT id,Division__c FROM Product2 WHERE Family = :lead.ProductFamily__c limit 1];
              if (prodList.size()<1)
              {
                  break;
              }
              List<Zip_Code__c> zipList = [SELECT OwnerId, Division__c, Zip_Code__c FROM Zip_Code__c WHERE Zip_Code__c = :lead.PostalCode.subString(0,5) and Division__c INCLUDES(:prodList[0].Division__c) ];
              if (zipList.size()<1){
                 break;
              }
              
              String[] divisions = zipList.size() > 0 ? zipList[0].Division__c.split(';') : null;
              if(divisions != null && prodList.size() > 0) {
                for(String div : divisions) {
                    if(prodList[0].Division__c == div) {
                        lead.OwnerId = zipList[0].OwnerId;
                        
                        leadsToUpdate.add(lead);
                    }
                }
             }
      } 
    }
}
Alain CabonAlain Cabon
Hi,

Replace the breaks with some continues

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_loops.htm

All loops allow for loop control structures:
break; exits the entire loop
continue; skips to the next iteration of the loop

Regards
Alain
VisionaryVisionary

Hi Alain,

made the changes you provided (thanks!) and now i get too many soql queries error, i know getting more errors actually brings me closer, to the answer, but i'm still not sure how to bulkify the trigger.
I'll keep digging and will post results/questions back here

Alain CabonAlain Cabon
Hi,

Move any database operations outside of for loops using sets of keys. 

Set <Id> ProductFamilies = new Set<Id>();
for (Lead lead : Trigger.new) {
   if (lead.PostalCode.length() < 5) 
        ProductFamilies.add(lead.ProductFamily__c);
}
List<Product2> prodLists = [SELECT id,Division__c FROM Product2 WHERE Family IN :ProductFamilies];

There is only one main query instead of hundreds by this way if the query was still inside the loop.
That is the principle but it is more complex to write the final code because you have to iterate across the lists all the time.

for (Product2 prod:prodLists) {
    ...
}

The folowing lists must be outside the main loop:
  1. List<Product2> prodList = [SELECT id,Division__c FROM Product2 WHERE Family = :lead.ProductFamily__c limit 1];
  2. List<Zip_Code__c> zipList = [SELECT OwnerId, Division__c, Zip_Code__c FROM Zip_Code__c WHERE Zip_Code__c = :lead.PostalCode.subString(0,5) and Division__c INCLUDES(:prodList[0].Division__c) ];
That is your main problem for "bulkifying" your code. 

https://developer.salesforce.com/page/Apex_Code_Best_Practices

Here is the optimal way to 'bulkify' the code to efficiently query the contacts in a single query and only perform a single update DML operation.
trigger accountTestTrggr on Account (before insert, before update) {
  //This queries all Contacts related to the incoming Account records in a single SOQL query.
  //This is also an example of how to use child relationships in SOQL
  List<Account> accountsWithContacts = [select id, name, (select id, salutation, description, 
                                                                firstname, lastname, email from Contacts) 
                                                                from Account where Id IN :Trigger.newMap.keySet()];
	  
  List<Contact> contactsToUpdate = new List<Contact>{};
  // For loop to iterate through all the queried Account records 
  for(Account a: accountsWithContacts){
     // Use the child relationships dot syntax to access the related Contacts
     for(Contact c: a.Contacts){
   	  System.debug('Contact Id[' + c.Id + '], FirstName[' + c.firstname + '], LastName[' + c.lastname +']');
   	  c.Description=c.salutation + ' ' + c.firstName + ' ' + c.lastname; 
   	  contactsToUpdate.add(c);
     }    	  
   }
      
   //Now outside the FOR Loop, perform a single Update DML statement. 
   update contactsToUpdate;
}

Regards

Alain