function checkTimeFrame($epoch = NULL)
 {
     if ($epoch == NULL) {
         $epoch = TTDate::getTime();
     }
     //Due to Cron running late, we want to still be able to insert
     //Recurring PS amendments up to two days after the end date.
     if ($this->getEndDate() == '' and $epoch >= $this->getStartDate() or $this->getEndDate() != '' and ($epoch >= $this->getStartDate() and $epoch <= $this->getEndDate() + 86400 * 2)) {
         Debug::text('IN TimeFrame: ' . TTDate::getDATE('DATE+TIME', $epoch), __FILE__, __LINE__, __METHOD__, 10);
         return TRUE;
     }
     Debug::text('Not in TimeFrame: ' . TTDate::getDATE('DATE+TIME', $epoch), __FILE__, __LINE__, __METHOD__, 10);
     return FALSE;
 }
 static function dragNdropPunch($company_id, $src_punch_id, $dst_punch_id, $dst_status_id = NULL, $position = 0, $action = 0, $dst_date = NULL)
 {
     /*
     	FIXME: This needs to handle batches to be able to handle all the differnet corner cases.
     	Operations to handle:
     		- Moving punch from Out to In, or In to Out in same punch pair, this is ALWAYS a move, and not a copy.
     		- Move punch from one pair to another in the same day, this can be a copy or move.
     			- Check moving AND copying Out punch from one punch pair to In in another on the same day. ie: In 8:00AM, Out 1:00PM, Out 5:00PM. Move the 1PM punch to pair with 5PM.
     		- Move punch from one day to another, inserting inbetween other punches if necessary.
     		- Move punch from one day to another without any other punches.
     
     
     		- Inserting BEFORE on a dst_punch_id that is an In punch doesn't do any splitting.
     		- Inserting AFTER on a dst_punch_id that is on a Out punch doesn't do any splitting.
     		- Overwriting should just take the punch time and overwrite the existing punch time.
     		- The first thing this function does it check if there are two punches assigned to the punch control of the destination punch, if there is, it splits the punches
     			across two punch_controls, it then attaches the src_punch_id to the same punch_control_id as the dst_punch_id.
     		- If no dst_punch_id is specified, assume copying to a blank cell, just copy the punch to that date along with the punch_control?
     		- Copying punches that span midnight work, however moving punches does not always
     			since we don't move punches in batches, we do it one at a time, and when the first punch punch
     			gets moved, it can cause other punches to follow it automatically.
     */
     $dst_date = TTDate::getMiddleDayEpoch($dst_date);
     Debug::text('Src Punch ID: ' . $src_punch_id . ' Dst Punch ID: ' . $dst_punch_id . ' Dst Status ID: ' . $dst_status_id . ' Position: ' . $position . ' Action: ' . $action . ' Dst Date: ' . $dst_date, __FILE__, __LINE__, __METHOD__, 10);
     $retval = FALSE;
     //Get source and destination punch objects.
     $plf = TTnew('PunchListFactory');
     $plf->StartTransaction();
     $plf->getByCompanyIDAndId($company_id, $src_punch_id);
     if ($plf->getRecordCount() == 1) {
         $src_punch_obj = $plf->getCurrent();
         $src_punch_date = TTDate::getMiddleDayEpoch($src_punch_obj->getPunchControlObject()->getUserDateObject()->getDateStamp());
         Debug::text('Found SRC punch ID: ' . $src_punch_id . ' Source Punch Date: ' . $src_punch_date, __FILE__, __LINE__, __METHOD__, 10);
         //Get the PunchControlObject as early as possible, before the punch is deleted, as it will be cleared even if Save(FALSE) is called below.
         $src_punch_control_obj = clone $src_punch_obj->getPunchControlObject();
         if (TTDate::getMiddleDayEpoch($src_punch_date) != TTDate::getMiddleDayEpoch($src_punch_obj->getTimeStamp())) {
             Debug::text('Punch spans midnight... Source Punch Date: ' . TTDate::getDATE('DATE+TIME', $src_punch_date) . ' Source Punch TimeStamp: ' . TTDate::getDATE('DATE+TIME', $src_punch_obj->getTimeStamp()), __FILE__, __LINE__, __METHOD__, 10);
             $dst_date_modifier = 86400;
             //Bump day by 24hrs.
         } else {
             $dst_date_modifier = 0;
         }
         //If we are moving the punch, we need to delete the source punch first so it doesn't conflict with the new punch.
         //Especially if we are just moving a punch to fill a gap in the same day.
         //If the punch being moved is in the same day, or within the same punch pair, we don't want to delete the source punch, instead we just modify
         //the necessary bits later on. So we need to short circuit the move functionality when copying/moving punches within the same day.
         if ($action == 1 and $src_punch_id != $dst_punch_id and $src_punch_date != $dst_date or $action == 1 and $src_punch_id != $dst_punch_id and $src_punch_date == $dst_date) {
             //Move
             Debug::text('Deleting original punch...: ' . $src_punch_id, __FILE__, __LINE__, __METHOD__, 10);
             $src_punch_obj->setUser($src_punch_control_obj->getUserDateObject()->getUser());
             $src_punch_obj->setDeleted(TRUE);
             //These aren't doing anything because they aren't acting on the PunchControl object?
             $src_punch_obj->setEnableCalcTotalTime(TRUE);
             $src_punch_obj->setEnableCalcSystemTotalTime(TRUE);
             $src_punch_obj->setEnableCalcWeeklySystemTotalTime(TRUE);
             $src_punch_obj->setEnableCalcUserDateTotal(TRUE);
             $src_punch_obj->setEnableCalcException(TRUE);
             $src_punch_obj->Save(FALSE);
             //Keep object around for later.
         } else {
             Debug::text('NOT Deleting original punch, either in copy mode or condition is not met...', __FILE__, __LINE__, __METHOD__, 10);
         }
         if ($src_punch_id == $dst_punch_id or $dst_punch_id == '') {
             //Assume we are just moving a punch within the same punch pair, unless a new date is specfied.
             //However if we're simply splitting an existing punch pair, like dragging the Out punch from an In/Out pair into its own separate pair.
             if ($src_punch_date != $dst_date or $src_punch_date == $dst_date and $dst_punch_id == '') {
                 Debug::text('aCopying punch to new day...', __FILE__, __LINE__, __METHOD__, 10);
                 //Moving punch to a new date.
                 //Copy source punch to proper location by destination punch.
                 $src_punch_obj->setId(FALSE);
                 $src_punch_obj->setPunchControlId((int) $src_punch_control_obj->getNextInsertId());
                 $src_punch_obj->setDeleted(FALSE);
                 //Just in case it was marked deleted by the MOVE action.
                 $new_time_stamp = TTDate::getTimeLockedDate($src_punch_obj->getTimeStamp(), $dst_date + $dst_date_modifier);
                 Debug::text('SRC TimeStamp: ' . TTDate::getDate('DATE+TIME', $src_punch_obj->getTimeStamp()) . ' DST TimeStamp: ' . TTDate::getDate('DATE+TIME', $new_time_stamp), __FILE__, __LINE__, __METHOD__, 10);
                 $src_punch_obj->setTimeStamp($new_time_stamp, FALSE);
                 $src_punch_obj->setActualTimeStamp($new_time_stamp);
                 $src_punch_obj->setOriginalTimeStamp($new_time_stamp);
                 if ($dst_status_id != '') {
                     $src_punch_obj->setStatus($dst_status_id);
                     //Change the status to fit in the proper place.
                 }
                 $src_punch_obj->setStation(NULL);
                 //When drag&drop copying punches, clear the station.
                 if ($src_punch_obj->isValid() == TRUE) {
                     $insert_id = $src_punch_obj->Save(FALSE);
                     $src_punch_control_obj->shift_data = NULL;
                     //Need to clear the shift data so its obtained from the DB again, otherwise shifts will appear on strange days.
                     $src_punch_control_obj->user_date_obj = NULL;
                     //Need to clear user_date_obj from cache so a new one is obtained.
                     $src_punch_control_obj->setId($src_punch_obj->getPunchControlID());
                     $src_punch_control_obj->setPunchObject($src_punch_obj);
                     if ($src_punch_control_obj->isValid() == TRUE) {
                         Debug::Text(' Punch Control is valid, saving...: ', __FILE__, __LINE__, __METHOD__, 10);
                         //We need to calculate new total time for the day and exceptions because we are never guaranteed that the gaps will be filled immediately after
                         //in the case of a drag & drop or something.
                         $src_punch_control_obj->setEnableStrictJobValidation(TRUE);
                         $src_punch_control_obj->setEnableCalcUserDateID(TRUE);
                         $src_punch_control_obj->setEnableCalcTotalTime(TRUE);
                         $src_punch_control_obj->setEnableCalcSystemTotalTime(TRUE);
                         $src_punch_control_obj->setEnableCalcWeeklySystemTotalTime(TRUE);
                         $src_punch_control_obj->setEnableCalcUserDateTotal(TRUE);
                         $src_punch_control_obj->setEnableCalcException(TRUE);
                         if ($src_punch_control_obj->isValid() == TRUE) {
                             if ($src_punch_control_obj->Save(TRUE, TRUE) == TRUE) {
                                 //Return newly inserted punch_id, so Flex can base other actions on it.
                                 $retval = $insert_id;
                             }
                         }
                     }
                 }
             } else {
                 Debug::text('Copying punch within same pair/day...', __FILE__, __LINE__, __METHOD__, 10);
                 //Moving punch within the same punch pair.
                 $src_punch_obj->setStatus($src_punch_obj->getNextStatus());
                 //Change just the punch status.
                 //$src_punch_obj->setDeleted(FALSE); //Just in case it was marked deleted by the MOVE action.
                 if ($src_punch_obj->isValid() == TRUE) {
                     //Return punch_id, so Flex can base other actions on it.
                     $retval = $src_punch_obj->Save(FALSE);
                 }
             }
         } else {
             Debug::text('bCopying punch to new day...', __FILE__, __LINE__, __METHOD__, 10);
             $plf->getByCompanyIDAndId($company_id, $dst_punch_id);
             if ($plf->getRecordCount() == 1) {
                 Debug::text('Found DST punch ID: ' . $dst_punch_id, __FILE__, __LINE__, __METHOD__, 10);
                 $dst_punch_obj = $plf->getCurrent();
                 $dst_punch_control_obj = $dst_punch_obj->getPunchControlObject();
                 Debug::text('aSRC TimeStamp: ' . TTDate::getDate('DATE+TIME', $src_punch_obj->getTimeStamp()) . ' DST TimeStamp: ' . TTDate::getDate('DATE+TIME', $dst_punch_obj->getTimeStamp()), __FILE__, __LINE__, __METHOD__, 10);
                 $is_punch_control_split = FALSE;
                 if ($position == 0) {
                     //Overwrite
                     Debug::text('Overwriting...', __FILE__, __LINE__, __METHOD__, 10);
                     //All we need to do is update the time of the destination punch.
                     $punch_obj = $dst_punch_obj;
                 } else {
                     //Before or After
                     //Determine if the destination punch needs to split from another punch
                     if ($position == -1 and $dst_punch_obj->getStatus() == 20 or $position == 1 and $dst_punch_obj->getStatus() == 10) {
                         //Before on Out punch, After on In Punch,
                         Debug::text('Need to split destination punch out to its own Punch Control row...', __FILE__, __LINE__, __METHOD__, 10);
                         $is_punch_control_split = PunchControlFactory::splitPunchControl($dst_punch_obj->getPunchControlID());
                         //Once a split occurs, we need to re-get the destination punch as the punch_control_id may have changed.
                         //We could probably optimize this to only occur when the destination punch is an In punch, as the
                         //Out punch is always the one to be moved to a new punch_control_id
                         if ($src_punch_obj->getStatus() != $dst_punch_obj->getStatus()) {
                             $plf->getByCompanyIDAndId($company_id, $dst_punch_id);
                             if ($plf->getRecordCount() == 1) {
                                 $dst_punch_obj = $plf->getCurrent();
                                 Debug::text('Found DST punch ID: ' . $dst_punch_id . ' Punch Control ID: ' . $dst_punch_obj->getPunchControlID(), __FILE__, __LINE__, __METHOD__, 10);
                             }
                         }
                         $punch_control_id = $dst_punch_obj->getPunchControlID();
                     } else {
                         Debug::text('No Need to split destination punch, simply add a new punch/punch_control all on its own.', __FILE__, __LINE__, __METHOD__, 10);
                         //Check to see if the src and dst punches are the same status though.
                         $punch_control_id = (int) $dst_punch_control_obj->getNextInsertId();
                     }
                     //Take the source punch and base our new punch on that.
                     $punch_obj = $src_punch_obj;
                     //Copy source punch to proper location by destination punch.
                     $punch_obj->setId(FALSE);
                     $punch_obj->setDeleted(FALSE);
                     //Just in case it was marked deleted by the MOVE action.
                     $punch_obj->setPunchControlId($punch_control_id);
                 }
                 //$new_time_stamp = TTDate::getTimeLockedDate($src_punch_obj->getTimeStamp(), $dst_punch_obj->getTimeStamp()+$dst_date_modifier );
                 $new_time_stamp = TTDate::getTimeLockedDate($src_punch_obj->getTimeStamp(), $dst_punch_obj->getPunchControlObject()->getUserDateObject()->getDateStamp() + $dst_date_modifier);
                 Debug::text('SRC TimeStamp: ' . TTDate::getDate('DATE+TIME', $src_punch_obj->getTimeStamp()) . ' DST TimeStamp: ' . TTDate::getDate('DATE+TIME', $dst_punch_obj->getTimeStamp()) . ' New TimeStamp: ' . TTDate::getDate('DATE+TIME', $new_time_stamp), __FILE__, __LINE__, __METHOD__, 10);
                 $punch_obj->setTimeStamp($new_time_stamp, FALSE);
                 $punch_obj->setActualTimeStamp($new_time_stamp);
                 $punch_obj->setOriginalTimeStamp($new_time_stamp);
                 $src_punch_obj->setStation(NULL);
                 //When drag&drop copying punches, clear the station.
                 //Need to take into account copying a Out punch and inserting it BEFORE another Out punch in a punch pair.
                 //In this case a split needs to occur, and the status needs to stay the same.
                 //Status also needs to stay the same when overwriting an existing punch.
                 Debug::text('Punch Status: ' . $punch_obj->getStatus() . ' DST Punch Status: ' . $dst_punch_obj->getStatus() . ' Split Punch Control: ' . (int) $is_punch_control_split, __FILE__, __LINE__, __METHOD__, 10);
                 if ($position != 0 and $is_punch_control_split == FALSE and $punch_obj->getStatus() == $dst_punch_obj->getStatus() and $punch_obj->getPunchControlID() == $dst_punch_obj->getPunchControlID()) {
                     Debug::text('Changing punch status to opposite: ' . $dst_punch_obj->getNextStatus(), __FILE__, __LINE__, __METHOD__, 10);
                     $punch_obj->setStatus($dst_punch_obj->getNextStatus());
                     //Change the status to fit in the proper place.
                 }
                 if ($punch_obj->isValid() == TRUE) {
                     $insert_id = $punch_obj->Save(FALSE);
                     $dst_punch_control_obj->shift_data = NULL;
                     //Need to clear the shift data so its obtained from the DB again, otherwise shifts will appear on strange days, or cause strange conflicts.
                     $dst_punch_control_obj->setID($punch_obj->getPunchControlID());
                     $dst_punch_control_obj->setPunchObject($punch_obj);
                     if ($dst_punch_control_obj->isValid() == TRUE) {
                         Debug::Text(' Punch Control is valid, saving...: ', __FILE__, __LINE__, __METHOD__, 10);
                         //We need to calculate new total time for the day and exceptions because we are never guaranteed that the gaps will be filled immediately after
                         //in the case of a drag & drop or something.
                         $dst_punch_control_obj->setEnableStrictJobValidation(TRUE);
                         $dst_punch_control_obj->setEnableCalcUserDateID(TRUE);
                         $dst_punch_control_obj->setEnableCalcTotalTime(TRUE);
                         $dst_punch_control_obj->setEnableCalcSystemTotalTime(TRUE);
                         $dst_punch_control_obj->setEnableCalcWeeklySystemTotalTime(TRUE);
                         $dst_punch_control_obj->setEnableCalcUserDateTotal(TRUE);
                         $dst_punch_control_obj->setEnableCalcException(TRUE);
                         if ($dst_punch_control_obj->isValid() == TRUE) {
                             if ($dst_punch_control_obj->Save(TRUE, TRUE) == TRUE) {
                                 //Force isNew() lookup.
                                 //Return newly inserted punch_id, so Flex can base other actions on it.
                                 $retval = $insert_id;
                                 //$retval = TRUE;
                             }
                         }
                     }
                 }
             }
         }
     }
     if ($retval == FALSE) {
         $plf->FailTransaction();
     }
     //$plf->FailTransaction();
     $plf->CommitTransaction();
     Debug::text('Returning: ' . (int) $retval, __FILE__, __LINE__, __METHOD__, 10);
     return $retval;
 }
 function calcAccrualPolicyTime($u_obj, $epoch, $offset, $pps_obj, $pay_period_arr, $accrual_balance, $update_records = TRUE)
 {
     $retval = 0;
     Debug::Text('User: '******' Status: ' . $u_obj->getStatus() . ' Epoch: ' . TTDate::getDate('DATE+TIME', $epoch), __FILE__, __LINE__, __METHOD__, 10);
     //Make sure only active employees accrue time *after* their hire date.
     //Will this negative affect Employees who may be on leave?
     if ($u_obj->getStatus() == 10 and $epoch >= $u_obj->getHireDate() and ($this->getMinimumEmployedDays() == 0 or TTDate::getDays($epoch - $u_obj->getHireDate()) >= $this->getMinimumEmployedDays())) {
         Debug::Text('&nbsp;&nbsp;User is active and has been employed long enough.', __FILE__, __LINE__, __METHOD__, 10);
         $annual_pay_periods = $pps_obj->getAnnualPayPeriods();
         $in_apply_frequency_window = FALSE;
         $in_apply_rollover_window = FALSE;
         $pay_period_start_date = NULL;
         $accrual_amount = 0;
         if ($this->getType() == 30) {
             Debug::Text('&nbsp;&nbsp;Accrual policy is hour based, real-time window.', __FILE__, __LINE__, __METHOD__, 10);
             //Hour based, apply frequency is real-time.
             $in_apply_frequency_window = TRUE;
         } else {
             if ($this->getApplyFrequency() == 10) {
                 $pay_period_dates = $this->getPayPeriodDatesFromArray($pay_period_arr, $epoch - $offset);
                 if (is_array($pay_period_dates)) {
                     Debug::Text('&nbsp;&nbsp; Pay Period Start Date: ' . TTDate::getDate('DATE+TIME', $pay_period_dates['start_date']) . ' End Date: ' . TTDate::getDate('DATE+TIME', $pay_period_dates['end_date']), __FILE__, __LINE__, __METHOD__, 10);
                     if ($this->inApplyFrequencyWindow($epoch, $offset, $pay_period_dates['end_date']) == TRUE) {
                         $in_apply_frequency_window = TRUE;
                         $pay_period_start_date = $pay_period_dates['start_date'];
                         //Used for inRolloverFrequencyWindow
                     } else {
                         Debug::Text('&nbsp;&nbsp;User not in Apply Frequency Window: ', __FILE__, __LINE__, __METHOD__, 10);
                     }
                 } else {
                     Debug::Arr($pay_period_dates, '&nbsp;&nbsp; No Pay Period Dates Found.', __FILE__, __LINE__, __METHOD__, 10);
                 }
             } elseif ($this->inApplyFrequencyWindow($epoch, $offset, NULL, $u_obj->getHireDate()) == TRUE) {
                 Debug::Text('&nbsp;&nbsp;User IS in NON-PayPeriod Apply Frequency Window.', __FILE__, __LINE__, __METHOD__, 10);
                 $in_apply_frequency_window = TRUE;
             } else {
                 Debug::Text('&nbsp;&nbsp;User is not in Apply Frequency Window.', __FILE__, __LINE__, __METHOD__, 10);
                 $in_apply_frequency_window = FALSE;
             }
         }
         if ($this->inRolloverFrequencyWindow($epoch, $offset, $u_obj->getHireDate(), $pay_period_start_date)) {
             Debug::Text('&nbsp;&nbsp; In rollover window...', __FILE__, __LINE__, __METHOD__, 10);
             $in_apply_rollover_window = TRUE;
         }
         if ($in_apply_frequency_window == TRUE or $in_apply_rollover_window == TRUE) {
             $milestone_obj = $this->getActiveMilestoneObject($u_obj, $epoch);
         }
         if ($in_apply_rollover_window == TRUE and (isset($milestone_obj) and is_object($milestone_obj))) {
             //Have accrual balance passed in for optimization
             //$accrual_balance = $this->getCurrentAccrualBalance( $u_obj->getID(), $this->getId() );
             //Handle maximum rollover adjustments before continuing.
             if ($accrual_balance > $milestone_obj->getRolloverTime()) {
                 $rollover_accrual_adjustment = bcsub($milestone_obj->getRolloverTime(), $accrual_balance, 0);
                 Debug::Text('&nbsp;&nbsp; Adding rollover adjustment of: ' . $rollover_accrual_adjustment, __FILE__, __LINE__, __METHOD__, 10);
                 //Check to make sure there isn't an identical entry already made.
                 //Ignore rollover adjustment is another adjustment of any amount has been made on the same day.
                 $alf = TTnew('AccrualListFactory');
                 if ($update_records == TRUE) {
                     $alf->getByCompanyIdAndUserIdAndAccrualPolicyIDAndTypeIDAndTimeStamp($u_obj->getCompany(), $u_obj->getID(), $this->getId(), 60, TTDate::getMiddleDayEpoch($epoch));
                 }
                 if ($alf->getRecordCount() == 0) {
                     //Get effective date, try to use the current milestone rollover date to make things more clear.
                     $current_milestone_rollover_date = $this->getCurrentMilestoneRolloverDate($epoch, $u_obj->getHireDate());
                     //If milestone rollover date comes after the current epoch, back date it by one year.
                     if ($current_milestone_rollover_date > $epoch) {
                         $current_milestone_rollover_date = mktime(0, 0, 0, TTDate::getMonth($current_milestone_rollover_date), TTDate::getDayOfMonth($current_milestone_rollover_date), TTDate::getYear($epoch) - 1);
                     }
                     if ($update_records == TRUE) {
                         //Don't round to the nearest minute, as that can cause too much error on weekly frequencies.
                         $af = TTnew('AccrualFactory');
                         $af->setUser($u_obj->getID());
                         $af->setType(60);
                         //Rollover Adjustment
                         $af->setAccrualPolicyID($this->getId());
                         $af->setAmount($rollover_accrual_adjustment);
                         $af->setTimeStamp(TTDate::getMiddleDayEpoch($current_milestone_rollover_date));
                         $af->setEnableCalcBalance(TRUE);
                         if ($af->isValid()) {
                             $af->Save();
                         }
                     } else {
                         Debug::Text('&nbsp;&nbsp; NOT UPDATING RECORDS...', __FILE__, __LINE__, __METHOD__, 10);
                         $retval = $rollover_accrual_adjustment;
                     }
                     //Make sure we get updated balance after rollover adjustment was made.
                     $accrual_balance += $rollover_accrual_adjustment;
                     unset($current_milestone_rollover_date);
                 } else {
                     Debug::Text('&nbsp;&nbsp; Found duplicate rollover accrual entry, skipping...', __FILE__, __LINE__, __METHOD__, 10);
                 }
             } else {
                 Debug::Text('&nbsp;&nbsp; Balance hasnt exceeded rollover adjustment...', __FILE__, __LINE__, __METHOD__, 10);
             }
             unset($rollover_accrual_adjustment, $alf, $af);
         }
         if ($in_apply_frequency_window === TRUE) {
             if (isset($milestone_obj) and is_object($milestone_obj)) {
                 Debug::Text('&nbsp;&nbsp;Found Matching Milestone, Accrual Rate: (ID: ' . $milestone_obj->getId() . ') ' . $milestone_obj->getAccrualRate() . '/year', __FILE__, __LINE__, __METHOD__, 10);
                 //Make sure we get updated balance after rollover adjustment was made.
                 //Have accrual balance passed in for optimization
                 //$accrual_balance = $this->getCurrentAccrualBalance( $u_obj->getID(), $this->getId() );
                 if ($accrual_balance < $milestone_obj->getMaximumTime()) {
                     $accrual_amount = $this->calcAccrualAmount($milestone_obj, 0, $annual_pay_periods);
                     if ($accrual_amount > 0) {
                         $new_accrual_balance = bcadd($accrual_balance, $accrual_amount);
                         //If Maximum time is set to 0, make that unlimited.
                         if ($milestone_obj->getMaximumTime() > 0 and $new_accrual_balance > $milestone_obj->getMaximumTime()) {
                             $accrual_amount = bcsub($milestone_obj->getMaximumTime(), $accrual_balance, 0);
                         }
                         Debug::Text('&nbsp;&nbsp; Min/Max Adjusted Accrual Amount: ' . $accrual_amount . ' Limits: Min: ' . $milestone_obj->getMinimumTime() . ' Max: ' . $milestone_obj->getMaximumTime(), __FILE__, __LINE__, __METHOD__, 10);
                         //Check to make sure there isn't an identical entry already made.
                         $alf = TTnew('AccrualListFactory');
                         if ($update_records == TRUE) {
                             $alf->getByCompanyIdAndUserIdAndAccrualPolicyIDAndTimeStampAndAmount($u_obj->getCompany(), $u_obj->getID(), $this->getId(), TTDate::getMiddleDayEpoch($epoch), $accrual_amount);
                         }
                         if ($alf->getRecordCount() == 0) {
                             if ($update_records == TRUE) {
                                 Debug::Text('&nbsp;&nbsp; UPDATING RECORDS...', __FILE__, __LINE__, __METHOD__, 10);
                                 //Round to nearest 1min
                                 $af = TTnew('AccrualFactory');
                                 $af->setUser($u_obj->getID());
                                 $af->setType(75);
                                 //Accrual Policy
                                 $af->setAccrualPolicyID($this->getId());
                                 $af->setAmount($accrual_amount);
                                 $af->setTimeStamp(TTDate::getMiddleDayEpoch($epoch));
                                 $af->setEnableCalcBalance(TRUE);
                                 if ($af->isValid()) {
                                     $af->Save();
                                 }
                             } else {
                                 Debug::Text('&nbsp;&nbsp; NOT UPDATING RECORDS...', __FILE__, __LINE__, __METHOD__, 10);
                                 $retval += $accrual_amount;
                             }
                         } else {
                             Debug::Text('&nbsp;&nbsp; Found duplicate accrual entry, skipping...', __FILE__, __LINE__, __METHOD__, 10);
                         }
                         unset($accrual_amount, $accrual_balance, $new_accrual_balance);
                     } else {
                         Debug::Text('&nbsp;&nbsp; Accrual Amount is 0...', __FILE__, __LINE__, __METHOD__, 10);
                     }
                 } else {
                     Debug::Text('&nbsp;&nbsp; Accrual Balance is outside Milestone Range. Skipping...', __FILE__, __LINE__, __METHOD__, 10);
                 }
             } else {
                 Debug::Text('&nbsp;&nbsp;DID NOT Find Matching Milestone.', __FILE__, __LINE__, __METHOD__, 10);
             }
             unset($milestone_obj);
         }
     } else {
         Debug::Text('&nbsp;&nbsp;User is not active (Status: ' . $u_obj->getStatus() . ') or has only been employed: ' . TTDate::getDays($epoch - $u_obj->getHireDate()) . ' Days, not enough. Hire Date: ' . TTDate::getDATE('DATE+TIME', $u_obj->getHireDate()), __FILE__, __LINE__, __METHOD__, 10);
     }
     if ($update_records == TRUE) {
         return TRUE;
     } else {
         Debug::Text('Retval: ' . $retval, __FILE__, __LINE__, __METHOD__, 10);
         return $retval;
     }
 }
 function getScheduleObjectByUserIdAndEpoch($user_id, $epoch)
 {
     if ($user_id == '') {
         return FALSE;
     }
     if ($epoch == '') {
         return FALSE;
     }
     //Need to handle schedules on next/previous dates from when the punch is.
     //ie: if the schedule started on 11:30PM on Jul 5th and the punch is 01:00AM on Jul 6th.
     $slf = new ScheduleListFactory();
     $slf->getByUserIdAndStartDateAndEndDate($user_id, TTDate::getMiddleDayEpoch($epoch) - 86400, TTDate::getMiddleDayEpoch($epoch) + 86400);
     if ($slf->getRecordCount() > 0) {
         Debug::Text(' Found User Date ID! User: '******' Epoch: ' . TTDate::getDATE('DATE+TIME', $epoch) . '(' . $epoch . ')', __FILE__, __LINE__, __METHOD__, 10);
         $retval = FALSE;
         $best_diff = FALSE;
         //Check for schedule policy
         foreach ($slf as $s_obj) {
             Debug::Text(' Found Schedule!: ID: ' . $s_obj->getID(), __FILE__, __LINE__, __METHOD__, 10);
             //If the Start/Stop window is large (ie: 6-8hrs) we need to find the closest schedule.
             $schedule_diff = $s_obj->inScheduleDifference($epoch);
             if ($schedule_diff === 0) {
                 Debug::text(' Within schedule times. ', __FILE__, __LINE__, __METHOD__, 10);
                 return $s_obj;
             } else {
                 if ($schedule_diff > 0 and ($best_diff === FALSE or $schedule_diff < $best_diff)) {
                     Debug::text(' Within schedule start/stop time by: ' . $schedule_diff . ' Prev Best Diff: ' . $best_diff, __FILE__, __LINE__, __METHOD__, 10);
                     $best_diff = $schedule_diff;
                     $retval = $s_obj;
                 }
             }
         }
         if (isset($retval) and is_object($retval)) {
             return $retval;
         }
     }
     /*
     $udlf = new UserDateListFactory();
     //$udlf->getByUserIdAndDate( $user_id, $epoch );
     $udlf->getByUserIdAndStartDateAndEndDate($user_id, TTDate::getMiddleDayEpoch($epoch)-(86400), TTDate::getMiddleDayEpoch($epoch)+86400 );
     if ( $udlf->getRecordCount() > 0 ) {
     	Debug::Text(' Found User Date ID! User: '******' Epoch: '. TTDate::getDATE('DATE+TIME', $epoch ) .'('.$epoch.')' , __FILE__, __LINE__, __METHOD__,10);
     
     	//Loop through all user_Date
     	$user_date_ids = array();
     	foreach( $udlf as $ud_obj ) {
     		$user_date_ids[] = $ud_obj->getID();
     	}
     	
     	$slf = new ScheduleListFactory();
     	$slf->getByUserDateId( $user_date_ids );
     	if ( $slf->getRecordCount() > 0 ) {
     		$retval = FALSE;
     		$best_diff = FALSE;
     		//Check for schedule policy
     		foreach( $slf as $s_obj ) {
     			Debug::Text(' Found Schedule!: ID: '. $s_obj->getID(), __FILE__, __LINE__, __METHOD__,10);
     			//If the Start/Stop window is large (ie: 6-8hrs) we need to find the closest schedule.
     			$schedule_diff = $s_obj->inScheduleDifference( $epoch );
     			if ( $schedule_diff === 0 ) {
     				Debug::text(' Within schedule times. ', __FILE__, __LINE__, __METHOD__,10);
     				return $s_obj;
     			} else {
     				if ( $schedule_diff > 0 AND ( $best_diff === FALSE OR $schedule_diff < $best_diff ) ) {
     					Debug::text(' Within schedule start/stop time by: '. $schedule_diff .' Prev Best Diff: '. $best_diff, __FILE__, __LINE__, __METHOD__,10);
     					$best_diff = $schedule_diff;
     					$retval = $s_obj;
     				}
     			}
     		}
     
     		if ( isset($retval) AND is_object($retval) ) {
     			return $retval;
     		}
     	}
     }
     */
     return FALSE;
 }