Link to home
Start Free TrialLog in
Avatar of -Dman100-
-Dman100-Flag for United States of America

asked on

logic help - check if event already exists

I have code that fires when an opportunity is moved to a closed won status.  When this condition is met, it will create a series of events on a related oject (Project_Requst__c).  This all works fine, but I am trying to make the existing code a little more intelligent and check if an event already exists on the date before adding a new event.  I'm just trying to prevent double booking of events.

So, I'm trying to determine how I can check if an existing event is already on the calendar that has the same record type id and same owner id.  I've created a list of Events with the same ownerId and recordTypeId. Next, I've created a set of the existing event startDateTimes that I can check to see if that start date exists already within the for loop.  However, if it finds that the startDateTime already exists, I can add a day to the current startDateTime, but how do I check if the next day on the calendar already has an event that exists?

So, for example, my iterator is 7 and I'm looping 7 times to create 7 events. I check the startDateTime in the first iteration and determine that an event already exists so I add one day.  However, I won't know if an event exists on the calendar date that was added to by one day.

How can I prevent the double booking of events?

See my method and helper method in the code below.

Please note, the code I'm using is APEX (Salesforce coding language). Its closest relative is Java, which is why I'm requesting help in this zone.  The logic should apply across any programming language.

Thanks in advance for any help.
Regards.
private static void doResourceEventsInsert(List<Opportunity> inNew, Map<Id, Opportunity> inOld) {
	
		//Gather all Data
 		List<Opportunity> lstOpps = new List<Opportunity>([Select Id, StageName, Name, Project_Number__c, (Select Id From Project_Request_and_Follow_up__r) From Opportunity o Where (Opportunity_Record_Type_Name_Static__c = 'WithintheContractProject' OR Opportunity_Record_Type_Name_Static__c = 'BillableProject') and isWon = true and id in :inNew]);

		if (lstOpps.size() > 0) {
        	Map<Id,Pricing__c> mapPricing = new Map<Id,Pricing__c>([Select Id,  (Select Id From Product_Management__r)  From Pricing__c Where isPrimaryPricing__c = true and Opportunity__c in :lstOpps]);  
 			Map<Id,ProductManagement__c> mapCS = new Map<Id,ProductManagement__c>([Select Id, (Select Id, Hours__c, DateOfWorkAllocation__c, Month_Index__c, Resource__r.Id, Resource__r.User_Id__c From Scheduling1__r) from ProductManagement__c Where Pricing__c in :mapPricing.values()]);

			RecordType rt = [Select Id From RecordType Where Name = 'Service Delivery Event' and sObjectType = 'Event'];
			List<Event> lstEvent = new List<Event>();
            
			//Loop through Data 	
			for(Opportunity opp : lstOpps) {
				if (inOld.get(opp.Id).isWon == false && opp.Project_Request_and_Follow_up__r.size() > 0) { 
					for(Pricing__c p : mapPricing.values()){
						for (ProductManagement__c cs : mapPricing.get(p.Id).Product_Management__r) {
							for (Scheduling__c s : mapCS.get(cs.Id).Scheduling1__r) {
								if (s.Hours__c != null && s.Resource__r.User_Id__c != null) {
									lstEvent = doResourceEventsStage(lstEvent,s.Resource__r.User_Id__c, opp.Project_Request_and_Follow_up__r.get(0).Id, rt.Id, s.DateOfWorkAllocation__c.year(), s.DateOfWorkAllocation__c.month(), s.Hours__c, opp.Name, opp.Project_Number__c);
					            }
							}
						}
					}
				}
				if (lstEvent.size() > 0) { 
					insert lstEvent;
				}
			}
		}
	}
 

	public static List<Event> doResourceEventsStage(List<Event> lstEvent, Id idEventOwner, Id idProjectRequest, Id idRecordType, Integer intYear, Integer intMonth, Decimal decHours, String oppName, String projectCode) {
		
        Integer recurrenceInterval = ((math.ceil(decHours / 8)) - 1).intValue();
        Integer currentMonth = system.today().month();
        Datetime startDate = Datetime.newInstance(intYear, intMonth, system.today().day(), 8, 0, 0);
        Date firstDayOfMonth = LibCommonFunctions.doConvertDateTimeToDate(startDate);
        
        if (currentMonth > intMonth) {
            firstDayOfMonth = firstDayOfMonth.toStartOfMonth();
        }
        
        Datetime firstWorkDayOfMonth = LibCommonFunctions.doConvertDateToDateTime(firstDayOfMonth, 8, 0, 0);
        Integer intStart = LibCommonFunctions.skipToNextBusinessDay(firstWorkDayOfMonth);
        
        if (intStart == 1) {
            firstWorkDayOfMonth = firstWorkDayOfMonth.addDays(1);
        }
        else if (intStart == 2) {
            firstWorkDayOfMonth = firstWorkDayOfMonth.addDays(2);
        }
        
        Datetime dt = LibCommonFunctions.doCalculateEndDate(firstWorkDayOfMonth, recurrenceInterval);
        Date endDate = LibCommonFunctions.doConvertDateTimeToDate(dt);
        
        List<Event> existingEvents = [Select Id, StartDateTime From Event Where ownerId =: idEventOwner AND RecordTypeId =: idRecordType];
        
        Set<DateTime> EventStartTimes = new Set<DateTime>();
		for(Event ev : existingEvents){
   			EventStartTimes.add(ev.StartDateTime);
		}
	
		for (Integer i = 0; i <= recurrenceInterval; i++){
			if (EventStartTimes.contains(firstWorkDayOfMonth)){
				firstWorkDayOfMonth = firstWorkDayOfMonth.addDays(1);
				firstWorkDayOfMonth = firstWorkDayOfMonth.addDays(LibCommonFunctions.skipToNextBusinessDay(firstWorkDayOfMonth));
			}	
			Event e = new Event();
			e.OwnerId = idEventOwner;
			e.RecordTypeId = idRecordType;
			e.Subject = oppName + ' - ' + projectCode;
			e.WhatId = idProjectRequest;
			e.StartDateTime = firstWorkDayOfMonth;
			e.EndDateTime = firstWorkDayOfMonth.addHours(8);
			firstWorkDayOfMonth = firstWorkDayOfMonth.addDays(1);
			firstWorkDayOfMonth = firstWorkDayOfMonth.addDays(LibCommonFunctions.skipToNextBusinessDay(firstWorkDayOfMonth));
			lstEvent.add(e);
		}
		
		return lstEvent;
		
	}

Open in new window

Avatar of techhealth
techhealth
Flag of United States of America image

Well, since you already have EventStartTimes on hand, why not just have a do-while loop to keep skipping date, until you find a date that's not contained in the set?

BTW I assume the whole thing is invoked in a trigger?  Can't see why you need a helper class.
Avatar of -Dman100-

ASKER

Hi techhealth,

Thank you for replying to my post.  I appreciate the help.  Yes, you are correct, I am invoking this code thru a trigger.  I abstracted into a seperate helper class for easier maintainabilty and the additional helper method was needed for unit test coverage and hitting governor limits when running all unit tests.

I haven't used do while loops very much, so I'm not too good with those loops.  Here is what I'm trying.  Is this correct?  I'm not sure if I'm implementing this correctly.

Note: In Apex do-while loop does not check the Boolean condition statement until after the first loop is executed. Consequently, the code block always runs at least once.  This is slightly different in Java as I understand it.  Does this make a difference?

Thanks again for your help.
public static List<Event> doResourceEventsStage(List<Event> lstEvent, Id idEventOwner, Id idProjectRequest, Id idRecordType, Integer intYear, Integer intMonth, Decimal decHours, String oppName, String projectCode) {
		
        Integer recurrenceInterval = ((math.ceil(decHours / 8)) - 1).intValue();
        Integer currentMonth = system.today().month();
        Datetime startDate = Datetime.newInstance(intYear, intMonth, system.today().day(), 8, 0, 0);
        Date firstDayOfMonth = LibCommonFunctions.doConvertDateTimeToDate(startDate);
        
        if (currentMonth > intMonth) {
            firstDayOfMonth = firstDayOfMonth.toStartOfMonth();
        }
        
        Datetime firstWorkDayOfMonth = LibCommonFunctions.doConvertDateToDateTime(firstDayOfMonth, 8, 0, 0);
        Integer intStart = LibCommonFunctions.skipToNextBusinessDay(firstWorkDayOfMonth);
        
        if (intStart == 1) {
            firstWorkDayOfMonth = firstWorkDayOfMonth.addDays(1);
        }
        else if (intStart == 2) {
            firstWorkDayOfMonth = firstWorkDayOfMonth.addDays(2);
        }
        
        Datetime dt = LibCommonFunctions.doCalculateEndDate(firstWorkDayOfMonth, recurrenceInterval);
        Date endDate = LibCommonFunctions.doConvertDateTimeToDate(dt);
        
        List<Event> existingEvents = [Select Id, StartDateTime From Event Where ownerId =: idEventOwner AND RecordTypeId =: idRecordType];
        
        Set<DateTime> EventStartTimes = new Set<DateTime>();
		for(Event ev : existingEvents){
   			EventStartTimes.add(ev.StartDateTime);
		}	
		for (Integer i = 0; i <= recurrenceInterval; i++){
			do {	
			Event e = new Event();
			e.OwnerId = idEventOwner;
			e.RecordTypeId = idRecordType;
			e.Subject = oppName + ' - ' + projectCode;
			e.WhatId = idProjectRequest;
			e.StartDateTime = firstWorkDayOfMonth;
			e.EndDateTime = firstWorkDayOfMonth.addHours(8);
			firstWorkDayOfMonth = firstWorkDayOfMonth.addDays(1);
			firstWorkDayOfMonth = firstWorkDayOfMonth.addDays(LibCommonFunctions.skipToNextBusinessDay(firstWorkDayOfMonth));
			lstEvent.add(e);
			} while(EventStartTimes.contains(firstWorkDayOfMonth));
		}
		
		return lstEvent;
		
	}

Open in new window

>>
However, I won't know if an event exists on the calendar date that was added to by one day.

How can I prevent the double booking of events?
>>

Since the most important attribute of an Event is its start time, why not make the time the UID of the Event? You would then use a Set<Event>. This would make it impossible to double-book - a double-booking would simply replace the previous Event (which you could warn about, or not, as you please)
Unfortunately, I do not have the option to make time the UID.  This is a cloud cumputing system and the data schema is already defined and is not alterable by the customer.  I have to work within the confines of the Salesforce system.

OK. You could always use a wrapper class with the required functionality
ASKER CERTIFIED SOLUTION
Avatar of techhealth
techhealth
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you for your help!  It worked perfectly.  This was exactly what I needed.  I sincerely appreciate your help!!

Regards,
-D
Glad I could help.  Have fun with force.com!