+ Start a Discussion
sales4cesales4ce 

Help needed in bulkifying my trigger

Hi,

 

I have a use case where i have to check if the record has a date overlapping criteria. I have a trigger, but it kinda works only for one record and is not bulkified.

I am hitting a road block to bulkify the trigger. Any ideas?

 

trigger datesCannotOverlap on Tip__c (before Insert, before Update) {
  
  
  Tip__c newTips=New Tip__c();  
  if(trigger.isInsert || trigger.isUpdate){
  
      newTips=Trigger.New[0];
      
      
  }
  

   
   
   List<Tip__c> overlaps=[select Tip_Start_Date__c, Tip_End_Date__c, Business_Unit__c 
 from Tip__c
  where 
  (
      (Tip_Start_Date__c >= :newTips.Tip_Start_Date__c AND Tip_Start_Date__c <= :newTips.Tip_End_Date__c) OR
      (Tip_end_Date__c  >= :newTips.Tip_Start_Date__c AND Tip_End_Date__c  <= :newTips.Tip_End_Date__c) OR
      (Tip_Start_Date__c <= :newTips.Tip_Start_Date__c AND Tip_end_Date__c  >= :newTips.Tip_end_Date__c)
  )
  and Business_Unit__c=:newTips.Business_Unit__c];


System.Debug('overlaps >>>>>'+overlaps);

if(overlaps.Size() > 0){
    newTips.addError('Dates Overlapping with other Tips. please choose New dates');
}
   
   
}

 

 

Thanks,

Sales4ce

Best Answer chosen by Admin (Salesforce Developers) 
Shashikant SharmaShashikant Sharma

Oh I missed it, Thanks For update

Even it will give exceptiion as trigger.newmap will be null so retrieing keySet will give attemp to dereference error. Thats why I always write test methods to find out these issues :)

 

I have updated trigger

 

 

trigger datesCannotOverlap on Tip__c (before Insert, before Update) {
  
  Set<String> setBU =  Set<String>();
  for(Tip__c tip : trigger.new)
     {
         setStartDate.add(tip.Tip_Start_Date__c);
         setEndDate..add(tip.Tip_End_Date__c);
         setBU.add(tip.Business_Unit__c);

     }
  

   
   
   List<Tip__c> overlapstemp;

  if(trigger.isUpdate)
  {
  overlapstemp = [select Tip_Start_Date__c, Tip_End_Date__c, Business_Unit__c 
  from Tip__c
  where Business_Unit__c in: setBU and Id not in : trigger.new];
  }
else
{
overlapstemp = [select Tip_Start_Date__c, Tip_End_Date__c, Business_Unit__c 
  from Tip__c
  where Business_Unit__c in: setBU ];
}

for(Tip__c t : overlapstemp)
    {
    for(Tio__c newTips : trigger.new)
       {
            if((t.Tip_Start_Date__c >= : newTips.Tip_Start_Date__c && t.Tip_Start_Date__c <= :newTips.Tip_End_Date__c) || 
               (t.Tip_end_Date__c  >= :newTips.Tip_Start_Date__c && t.Tip_End_Date__c  <= :newTips.Tip_End_Date__c) ||
               (t.Tip_Start_Date__c <= :newTips.Tip_Start_Date__c && t.Tip_end_Date__c  >= :newTips.Tip_end_Date__c)
            {
              newTips.addError('Dates Overlapping with other Tips. please choose New dates');
            }
      )



   }
}
System.Debug('overlaps >>>>>'+overlaps);


    
}
   
   
}

 

 

All Answers

Shashikant SharmaShashikant Sharma

Please change it like this

 

 

trigger datesCannotOverlap on Tip__c (before Insert, before Update) {
  
  Set<String> setBU =  Set<String>();
  for(Tip__c tip : trigger.new)
     {
         setStartDate.add(tip.Tip_Start_Date__c);
         setEndDate..add(tip.Tip_End_Date__c);
         setBU.add(tip.Business_Unit__c);

     }
  

   
   
   List<Tip__c> overlapstemp =[select Tip_Start_Date__c, Tip_End_Date__c, Business_Unit__c 
 from Tip__c
  where Business_Unit__c in: setBU and Id not in : trigger.newMap];


for(Tip__c t : overlapstemp)
    {
    for(Tio__c newTips : trigger.new)
       {
            if((t.Tip_Start_Date__c >= : newTips.Tip_Start_Date__c && t.Tip_Start_Date__c <= :newTips.Tip_End_Date__c) || 
               (t.Tip_end_Date__c  >= :newTips.Tip_Start_Date__c && t.Tip_End_Date__c  <= :newTips.Tip_End_Date__c) ||
               (t.Tip_Start_Date__c <= :newTips.Tip_Start_Date__c && t.Tip_end_Date__c  >= :newTips.Tip_end_Date__c)
            {
              newTips.addError('Dates Overlapping with other Tips. please choose New dates');
            }
      )



   }
}
System.Debug('overlaps >>>>>'+overlaps);


    
}
   
   
}

 This will work for bulk data as well

 

sales4cesales4ce

Thanks for your reply. But i get an error when i save your version of trigger.

 

ErrorError: Compile Error: IN operator must be used with an iterable expression at line 43 column 74

 

List<Tip__c> overlapstemp =[select Tip_Start_Date__c, Tip_End_Date__c, Business_Unit__c 
 from Tip__c
  where Business_Unit__c in: setBU and Id not in : trigger.newMap];

 

The trigger.newMap is where is bumping.Can you help me figure out what the problem is.

 

Thanks,

Sales4ce

Shashikant SharmaShashikant Sharma

Sorry change it like this

 

 

trigger datesCannotOverlap on Tip__c (before Insert, before Update) {
  
  Set<String> setBU =  Set<String>();
  for(Tip__c tip : trigger.new)
     {
         setStartDate.add(tip.Tip_Start_Date__c);
         setEndDate..add(tip.Tip_End_Date__c);
         setBU.add(tip.Business_Unit__c);

     }
  

   
   
   List<Tip__c> overlapstemp =[select Tip_Start_Date__c, Tip_End_Date__c, Business_Unit__c 
 from Tip__c
  where Business_Unit__c in: setBU and Id not in : trigger.newMap.keySet()];


for(Tip__c t : overlapstemp)
    {
    for(Tio__c newTips : trigger.new)
       {
            if((t.Tip_Start_Date__c >= : newTips.Tip_Start_Date__c && t.Tip_Start_Date__c <= :newTips.Tip_End_Date__c) || 
               (t.Tip_end_Date__c  >= :newTips.Tip_Start_Date__c && t.Tip_End_Date__c  <= :newTips.Tip_End_Date__c) ||
               (t.Tip_Start_Date__c <= :newTips.Tip_Start_Date__c && t.Tip_end_Date__c  >= :newTips.Tip_end_Date__c)
            {
              newTips.addError('Dates Overlapping with other Tips. please choose New dates');
            }
      )



   }
}
System.Debug('overlaps >>>>>'+overlaps);


    
}
   
   
}

 used 

 

trigger.newMap.keySet()

 

Ankit AroraAnkit Arora

Just replace 

 

trigger.newMap

with 

 

trigger.newMap.keySet()

 

 

Thanks
Ankit Arora

 

sales4cesales4ce

Thanks for your help folks.

i can now save my trigger successfully. But i get a run time exception.

System.NullPointerException: Attempt to de-reference a null object: Trigger.datesCannotOverlap: line 43, column 81

List<Tip__c> overlapstemp =[select Tip_Start_Date__c, Tip_End_Date__c, Business_Unit__c 
 from Tip__c
  where Business_Unit__c in: setBU and Id not in : trigger.newMap.keySet()];

My Purpose of the trigger is:

 

I have a custom object , which includes three custom fields (Start date, End Date and Business Unit(Type: Picklist).

The three custom fields should be unique for a record, so the combination of these fields makes my record unique.

 

Example: start date: 06/20/2011, End Date: 06/27/2011, Business Type: Devices

                  Start date: 06/20/2011, End date:06/27/2011, Business Type: Drugs

 

Also, we must make sure that for new record the start and end dates do not fall within the above mentioned dates.

So the next acceptable record is:

 

Start date: 06/28/2011, end date: 06/30/2011,business type:Devices.

 

I need to throw an error for this condition:

 

start date: 06/25/2011, end date: 06/30/2011, Business Type: Devices

 

My trigger works fine for single record. I am unable to bulkify and need assistance here.

Let me know if this was helpful.

 

Thanks,

Sales4ce

Shashikant SharmaShashikant Sharma

Your welcome,

For bulkifying your trigger please see :

 

http://forceschool.blogspot.com/2011/05/writing-apex-trigger-save-limits-in.html

sales4cesales4ce

Thanks for pointing to the best practises. The blog is informative.

Can you help me figure out bulkifying for this trigger. I appreciate your help on this.

 

Thanks,

Sales4ce

Shashikant SharmaShashikant Sharma

I think in bulk case the problem with your code is that it is validating agaist all overlapped records even if they are related to some other. Here is your code

 

 

trigger datesCannotOverlap on Tip__c (before Insert, before Update) {
  
  Set<String> setBU =  Set<String>();
  
  for(Tip__c tip : trigger.new)
     {
         setStartDate.add(tip.Tip_Start_Date__c);
         setEndDate..add(tip.Tip_End_Date__c);
         //condition to stop null overlap values  
         if(tip.Business_Unit__c != null)
            setBU.add(tip.Business_Unit__c);

     }
  

   
   
   List<Tip__c> overlapstemp =[select Tip_Start_Date__c, Tip_End_Date__c, Business_Unit__c 
 from Tip__c
  where Business_Unit__c in: setBU and Id not in : trigger.newMap.keySet()];


for(Tip__c t : overlapstemp)
    {
          for(Tio__c newTips : trigger.new)
             {
               //condition to check overlap values only for same Business Unit  
               if( t.Business_Unit__c  == newTips.Business_Unit__c )
               {
               if((t.Tip_Start_Date__c >= : newTips.Tip_Start_Date__c && t.Tip_Start_Date__c <= :newTips.Tip_End_Date__c) || 
               (t.Tip_end_Date__c  >= :newTips.Tip_Start_Date__c && t.Tip_End_Date__c  <= :newTips.Tip_End_Date__c) ||
               (t.Tip_Start_Date__c <= :newTips.Tip_Start_Date__c && t.Tip_end_Date__c  >= :newTips.Tip_end_Date__c)
               {
                  newTips.addError('Dates Overlapping with other Tips. please choose New dates');
               }
               }
             )



   }
}
System.Debug('overlaps >>>>>'+overlaps);


    
}

 

 

 

In above code some script stmts can be saved using collections.

Rahul S.ax961Rahul S.ax961

Something is wrong in the Query logic:

 

List<Tip__c> overlapstemp =[select Tip_Start_Date__c, Tip_End_Date__c, Business_Unit__c 
from Tip__c
where Business_Unit__c in: setBU and Id not in : trigger.newMap.keySet()];

This query will result output of, Business Unit in Trigger.new and Id not in Trigger.new.

Isn't it contradictory?

Shashikant SharmaShashikant Sharma

Oh I missed it, Thanks For update

Even it will give exceptiion as trigger.newmap will be null so retrieing keySet will give attemp to dereference error. Thats why I always write test methods to find out these issues :)

 

I have updated trigger

 

 

trigger datesCannotOverlap on Tip__c (before Insert, before Update) {
  
  Set<String> setBU =  Set<String>();
  for(Tip__c tip : trigger.new)
     {
         setStartDate.add(tip.Tip_Start_Date__c);
         setEndDate..add(tip.Tip_End_Date__c);
         setBU.add(tip.Business_Unit__c);

     }
  

   
   
   List<Tip__c> overlapstemp;

  if(trigger.isUpdate)
  {
  overlapstemp = [select Tip_Start_Date__c, Tip_End_Date__c, Business_Unit__c 
  from Tip__c
  where Business_Unit__c in: setBU and Id not in : trigger.new];
  }
else
{
overlapstemp = [select Tip_Start_Date__c, Tip_End_Date__c, Business_Unit__c 
  from Tip__c
  where Business_Unit__c in: setBU ];
}

for(Tip__c t : overlapstemp)
    {
    for(Tio__c newTips : trigger.new)
       {
            if((t.Tip_Start_Date__c >= : newTips.Tip_Start_Date__c && t.Tip_Start_Date__c <= :newTips.Tip_End_Date__c) || 
               (t.Tip_end_Date__c  >= :newTips.Tip_Start_Date__c && t.Tip_End_Date__c  <= :newTips.Tip_End_Date__c) ||
               (t.Tip_Start_Date__c <= :newTips.Tip_Start_Date__c && t.Tip_end_Date__c  >= :newTips.Tip_end_Date__c)
            {
              newTips.addError('Dates Overlapping with other Tips. please choose New dates');
            }
      )



   }
}
System.Debug('overlaps >>>>>'+overlaps);


    
}
   
   
}

 

 

This was selected as the best answer
Rahul S.ax961Rahul S.ax961

bro, u missed to check  overlapstemp != empty before for loop.

Shashikant SharmaShashikant Sharma

Good to know you are scaning my post but this time you missed it mate :)

in for loop if list is empty it will not iterate no issues in it, we don't need to check any thing.

sales4cesales4ce

Thanks Sashikanth and Rahul, it worked like charm.

Appreciate your time and help.

 

Thanks,

Sales4ce

Shashikant SharmaShashikant Sharma

Your welcome :)