Monday, 16 March 2015

Checking for Working Days and Company Holidays

Checking for Working Days and Company Holidays

In this post I talk through a Trigger I wrote to check whether a Custom Activity record was created on a weekday, or during a public holiday.

The Problem

My customer was storing their work activity in a Custom Object called Project Time Log.

At the end of the month they would run a report showing how much activity had taken place.

The problem was that doesn't seem to have any way out of the box of excluding Weekends and Public Holidays out of report criteria so the customer's reports were alwaysinaccurate.
Therefore I had to develop a Trigger to check each submitted activity log and decide whether the activity was on a working day/or on a scheduled public holiday.


trigger CheckWorkingDay on Project_Time_Log__c (before insert, before update) {
    //This trigger will mark whether activity record was saving during working day or not
    Map<ID, Date> allHolidays = new Map<ID, Date>(); 
    //Create a place to store holiday
    Map<ID, Date> logDates = new Map<ID, Date>();
    //The map we'll store all of the values in
    for (Project_Time_Log__c so : {  
        //Step 1: First loop for populating maps and sets
        //Loop through collection gathering timestamp    
        logDates.put(so.Id, so.Date_of_Action__c);  
        System.debug('ID and Date added ' + so.Id + so.Date_of_Action__c);    
        //Populate map
        allholidays.put(so.Id, so.Date_of_Action__c);
    } //end for loop
    system.debug('We have ' + logDates.size() + ' item in the logDates list');
    // Step 2: Query all the records in Step 1 - see if this is a specified Holiday
    Map<Date, Holiday> holidayMatch = new Map<Date,Holiday>();
    for (Holiday a: [Select ID, ActivityDate From Holiday]){
        holidayMatch.put(a.ActivityDate, a);  
    System.debug('We found ' + holidayMatch.size() + ' holiday dates');
    //Step 3: Repeat the loop again checking against the actual lists
    for (Project_Time_Log__c so2 : {  
        if (holidayMatch.containsKey(so2.Date_of_Action__c)) {
            System.debug('We found a holiday');
            so2.IsHoliday__c = True;
            so2.Billable__c = False; 
      so2.IsWorkingDay__c = False;                
        } //end of if
        else if (!holidayMatch.containsKey(so2.Date_of_Action__c)) {
        so2.IsHoliday__c = False;   
        //Render Date_of_Action__c into a single day of the week
        Datetime myDateTime = so2.Date_of_Action__c;
        String dayOfWeek = myDateTime.format('EEEE');
        //Tick the checkbox if day of action was on normal working day
        if (dayOfWeek == 'Monday' || dayOfWeek == 'Tuesday' || dayOfWeek == 'Wednesday' || dayOfWeek == 'Thursday' || dayOfWeek == 'Friday' ) {
            so2.IsWorkingDay__c = True;        
        Date selectedDate =  so2.Date_of_Action__c; //Give your date
        Date firstDate = selectedDate.toStartOfMonth();
        Date lastDate = firstDate.addDays(date.daysInMonth(selectedDate.year() , selectedDate.month())  - 1);
        system.debug(firstDate  + ' **** ' +lastDate );
        //Set the first working day - based on Action Date
        so2.X1stWorkingDate__c = firstDate;
        so2.LastWorkingDate__c = lastDate;
        //Set the last working day - based on Action Date
        //Finally decide whether this was Billable or not
        String activity = so2.Project_Activity_Log__c;
        if (activity != null && activity.startsWith('PS-') ) {
            so2.Billable__c = True; 

        //Final step update the field on the Activity Log
    } //end second for loop