Tuesday 18 September 2018

Salesforce.com Event Overlap handling through trigger

Workflow or Process Builder is not capable of handling the overlapping of OOB event timing, therefore, it requires a trigger. The scenario was to show an error message to the user on creating an event that this start time and end date overlaps with another event of the same owner and the user should get the link of that previously saved event. The trigger should be written on Before Insert and Before Update to prevent it from saving the event record. I also asked to only check the overlap event on some particular record types. Therefore first filled a SET of those record types and match that event has the same record types or not.

The Trigger code is given below



Trigger EventValidation on Event(before insert, before update)
{
    
   EventUtility Utility = new EventUtility();
   set<id> RtIds = new set<id>();
  
    for(RecordType rt : [SELECT Id FROM RecordType WHERE DeveloperName in ('Test_RecordType1',' Test_RecordType2')])
        RtIds.add(rt.id);
   
    system.debug('RtIds :'+RtIds);
    List<Event> selectedRtEvent = new list<Event>();
    for(Event t : trigger.new)
    {
        system.debug('t.recordtype.name' + t.recordtypeid);
       
        if(RtIds.contains(t.recordtypeid))
            selectedRtEvent.add(t);
    }
    system.debug('selectedRtEvent ::' + selectedRtEvent );
    if(selectedRtEvent.size() > 0)
    {
        system.debug('selectedRtEvent : ' + selectedRtEvent);
        Utility.ValidateRecord(selectedRtEvent);
    }
 }


The bottom yellow highlighted lines call the utility class which validates the overlapping of event timings.

Code of Utility Class given below

public with sharing class EventUtility
{   
   
    public void EventUtility()
    {}
   
    public void ValidateRecord(List<Event> LstEvent)
    {
        map<Id,List<Event>> mEvent = new map<Id,List<Event>>();
        set<Id> sOwner = new set<Id>();
        for(Event t : LstEvent)
        {
            sOwner.add(t.ownerid);
        }
       
        for(Event t: [SELECT OwnerId, WhoId, WhatId, StartDateTime, EndDateTime FROM Event where OwnerId in :sOwner])
        {
            if(mEvent.containsKey(t.OwnerId))
            {
                list<Event> lst = mEvent.get(t.OwnerId);
                lst.add(t);
                mEvent.put(t.OwnerId,lst);
            }
            else
            {
                list<Event> lst = new list<Event>();
                lst.add(t);
                mEvent.put(t.OwnerId,lst);
            }
        }
       
       
        String errorMsg = 'Record Already Exists : ';
        String baseUrl = URL.getSalesforceBaseUrl().toExternalForm();
        boolean IsOverlap = false;
        for(Event newRecords : LstEvent)
        {
           
           
            if(mEvent.containsKey(newRecords.ownerid))
            {
                for(Event userrecords : mEvent.get(newRecords.ownerid))
                {
                   
                    IsOverlap = false;
                    IsOverlap = TimePeriodOverlap(newRecords.StartDateTime,newRecords.EndDateTime,userrecords.StartDateTime,userrecords.EndDateTime);
                    system.debug('IsOverlap: ' + IsOverlap);
                   
                    if (IsOverlap == true && (userrecords.ownerid == newRecords.ownerid))
                    {
                        newRecords.addError(errorMsg + '<a target="_blank" href =' +baseUrl+'/'+userrecords.id+'> (Duplicate Record)</a>',false);
                    }
                   
                }
            }
        }
       
       
    }      
        public boolean TimePeriodOverlap(DateTime BS, DateTime BE, DateTime TS, DateTime TE)
        {
            // More simple?
            // return !((TS < BS && TE < BS) || (TS > BE && TE > BE));

            // The version below, without comments
            /*
            return (
                (TS >= BS && TS < BE) || (TE <= BE && TE > BS) || (TS <= BS && TE >= BE)
            );
            */

            return (
                // 1. Case:
                //
                //       TS-------TE
                //    BS------BE
                //
                // TS is after BS but before BE
                (TS >= BS && TS < BE)
                || // or

                // 2. Case
                //
                //    TS-------TE
                //        BS---------BE
                //
                // TE is before BE but after BS
                (TE <= BE && TE > BS)
                || // or

                // 3. Case
                //
                //  TS----------TE
                //     BS----BE
                //
                // TS is before BS and TE is after BE
                (TS <= BS && TE >= BE)
            );
        }
       
   
}


No comments:

Post a Comment