Exemple #1
0
 unset($ppslf, $pps_obj, $tmp_start_date);
 //Get earliest pre_mature exception in a NON-closed pay period.
 $elf = new ExceptionListFactory();
 $elf->getByCompanyIDAndTypeAndPayPeriodStatus($c_obj->getId(), 5, array(10, 12, 15, 30), 1, NULL, NULL, array('b.date_stamp' => 'asc'));
 //Limit 1
 if ($elf->getRecordCount() > 0) {
     foreach ($elf as $e_obj) {
         $tmp_start_date = $e_obj->getUserDateObject()->getDateStamp();
         if ($tmp_start_date < $start_date) {
             $start_date = $tmp_start_date;
             Debug::text('  Pre-Mature exceptions occur before start date, reducing to: ' . TTDate::getDate('DATE+TIME', $start_date) . '(' . $e_obj->getId() . ')', __FILE__, __LINE__, __METHOD__, 5);
         }
     }
 }
 unset($elf, $e_obj, $tmp_start_date);
 $udlf = new UserDateListFactory();
 $udlf->getByCompanyIdAndStartDateAndEndDateAndPayPeriodStatus($c_obj->getId(), $start_date, $end_date, array(10, 12, 15, 30));
 Debug::text(' Start Date: ' . TTDate::getDate('DATE+TIME', $start_date) . ' End Date: ' . TTDate::getDate('DATE+TIME', $end_date) . ' User Date Rows: ' . $udlf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 5);
 if ($udlf->getRecordCount() > 0) {
     $i = 0;
     foreach ($udlf as $ud_obj) {
         $user_obj_prefs = $ud_obj->getUserObject()->getUserPreferenceObject();
         if (is_object($user_obj_prefs)) {
             $user_obj_prefs->setTimeZonePreferences();
         } else {
             //Use system timezone.
             TTDate::setTimeZone();
         }
         //Recalculate system time, and exceptions for the day.
         //Because if its a Monday, it will also recalculate the rest of the days in the week.
         //Shouldn't be a big deal though.
 function preSave()
 {
     if ($this->getDeleted() == TRUE) {
         //Delete (for real) any already deleted rows in hopes to prevent a
         //unique index conflict across user_id,date_stamp,deleted
         $udlf = new UserDateListFactory();
         $udlf->deleteByUserIdAndDateAndDeleted($this->getUser(), $this->getDateStamp(), TRUE);
     }
     return TRUE;
 }
 function setUserDateID($id)
 {
     $id = trim($id);
     $udlf = new UserDateListFactory();
     if ($this->Validator->isResultSetWithRows('user_date', $udlf->getByID($id), TTi18n::gettext('Invalid User Date ID'))) {
         if ($this->getUserDateID() !== $id and $this->getOldUserDateID() != $this->getUserDateID()) {
             Debug::Text(' Setting Old User Date ID... Current Old ID: ' . (int) $this->getOldUserDateID() . ' Current ID: ' . (int) $this->getUserDateID(), __FILE__, __LINE__, __METHOD__, 10);
             $this->setOldUserDateID($this->getUserDateID());
         }
         $this->data['user_date_id'] = $id;
         return TRUE;
     }
     return FALSE;
 }
 function setUserDateID($id = NULL)
 {
     $id = trim($id);
     $udlf = new UserDateListFactory();
     if ($this->Validator->isResultSetWithRows('user_date', $udlf->getByID($id), TTi18n::gettext('Invalid User Date ID'))) {
         $this->data['user_date_id'] = $id;
         return TRUE;
     }
     return FALSE;
 }
 function setUserDateID($id, $skip_check = FALSE)
 {
     $id = (int) trim($id);
     $udlf = new UserDateListFactory();
     if ($skip_check == TRUE or $id > 0 and $this->Validator->isResultSetWithRows('user_date', $udlf->getByID($id), TTi18n::gettext('Invalid User/Date. Pay Period may be locked'))) {
         $this->data['user_date_id'] = $id;
         return TRUE;
     }
     return FALSE;
 }
Debug::text('Next Page: ' . $next_page, __FILE__, __LINE__, __METHOD__, 10);
$ppf = new PayPeriodFactory();
$action = strtolower($action);
switch ($action) {
    case 'recalculate_company':
    case 'recalculate_employee':
        Debug::text('Recalculating Employee Timesheet: User ID: ' . $filter_user_id . ' Pay Period ID: ' . $pay_period_ids, __FILE__, __LINE__, __METHOD__, 10);
        //Debug::setVerbosity(11);
        //Make sure pay period is not CLOSED.
        //We can re-calc on locked though.
        $pplf = new PayPeriodListFactory();
        $pplf->getById($pay_period_ids);
        if ($pplf->getRecordCount() > 0) {
            $pp_obj = $pplf->getCurrent();
            if ($pp_obj->getStatus() != 20) {
                $udlf = new UserDateListFactory();
                if ($action == 'recalculate_company') {
                    TTLog::addEntry($current_company->getId(), TTi18n::gettext('Notice'), TTi18n::gettext(' Recalculating Company TimeSheet'), $current_user->getId(), 'user_date_total');
                    $udlf->getByCompanyIdAndPayPeriodID($current_company->getId(), $pay_period_ids);
                } else {
                    TTLog::addEntry($filter_user_id, TTi18n::gettext('Notice'), TTi18n::gettext(' Recalculating Employee TimeSheet'), $current_user->getId(), 'user_date_total');
                    $udlf->getByUserIdAndPayPeriodID($filter_user_id, $pay_period_ids);
                }
                if ($udlf->getRecordCount() > 0) {
                    InitProgressBar();
                    $progress_bar->setValue(0);
                    $progress_bar->display();
                    Debug::text('Found days to re-calculate: ' . $udlf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
                    $udlf->StartTransaction();
                    $x = 1;
                    foreach ($udlf as $ud_obj) {
 case 'submit':
     $pplf = new PayPeriodListFactory();
     $pplf->getByIdAndCompanyId($pay_period_id, $current_company->getId());
     foreach ($pplf as $pay_period_obj) {
         $pay_period_obj->setStatus($status_id);
         $pay_period_obj->save();
     }
     Redirect::Page(URLBuilder::getURL(array('pay_period_id' => $pay_period_id), 'ViewPayPeriod.php'));
     break;
 case 'generate_paystubs':
     Debug::Text('Generate Pay Stubs!', __FILE__, __LINE__, __METHOD__, 10);
     Redirect::Page(URLBuilder::getURL(array('action' => 'generate_paystubs', 'pay_period_ids' => $pay_period_id, 'next_page' => URLBuilder::getURL(array('filter_pay_period_id' => $pay_period_id), '../pay_stub/PayStubList.php')), '../progress_bar/ProgressBarControl.php'));
     break;
 case 'import':
     //Imports already created shifts in to this pay period, from another pay period.
     $udlf = new UserDateListFactory();
     //Get all users assigned to this pay period schedule.
     $pplf = new PayPeriodListFactory();
     $pay_period_obj = $pplf->getByIdAndCompanyId($pay_period_id, $current_company->getId())->getCurrent();
     $pay_period_obj->getPayPeriodScheduleObject()->setPayPeriodTimeZone();
     $pay_period_users = $pay_period_obj->getPayPeriodScheduleObject()->getUser();
     $udlf->StartTransaction();
     $udlf->getByUserIdAndStartDateAndEndDate($pay_period_users, $pay_period_obj->getStartDate(), $pay_period_obj->getEndDate());
     foreach ($udlf as $ud_obj) {
         $new_pay_period_id = $ud_obj->findPayPeriod();
         Debug::Text('Current Pay Period: ' . $ud_obj->getPayPeriod() . ' (' . $pay_period_id . ') New PayPeriod ID: ' . $new_pay_period_id, __FILE__, __LINE__, __METHOD__, 10);
         //Make sure original pay period isn't already closed
         if ($pay_period_id == $new_pay_period_id and $ud_obj->getPayPeriodObject()->getStatus() != 20) {
             $ud_obj->setPayPeriod($new_pay_period_id);
             $ud_obj->Save();
         } else {
         break;
     }
 default:
     if ($id != '') {
         Debug::Text(' ID was passed: ' . $id, __FILE__, __LINE__, __METHOD__, 10);
         $udtlf = new UserDateTotalListFactory();
         $udtlf->getById($id);
         foreach ($udtlf as $udt_obj) {
             //Debug::Arr($station,'Department', __FILE__, __LINE__, __METHOD__,10);
             $udt_data = array('id' => $udt_obj->getId(), 'user_date_id' => $udt_obj->getUserDateId(), 'date_stamp' => $udt_obj->getUserDateObject()->getDateStamp(), 'user_id' => $udt_obj->getUserDateObject()->getUser(), 'user_full_name' => $udt_obj->getUserDateObject()->getUserObject()->getFullName(), 'status_id' => $udt_obj->getStatus(), 'type_id' => $udt_obj->getType(), 'total_time' => $udt_obj->getTotalTime(), 'branch_id' => $udt_obj->getBranch(), 'department_id' => $udt_obj->getDepartment(), 'job_id' => $udt_obj->getJob(), 'job_item_id' => $udt_obj->getJobItem(), 'quantity' => $udt_obj->getQuantity(), 'bad_quantity' => $udt_obj->getBadQuantity(), 'punch_control_id' => $udt_obj->getPunchControlID(), 'absence_policy_id' => $udt_obj->getAbsencePolicyID(), 'over_time_policy_id' => $udt_obj->getOverTimePolicyID(), 'premium_policy_id' => $udt_obj->getPremiumPolicyID(), 'meal_policy_id' => $udt_obj->getMealPolicyID(), 'override' => $udt_obj->getOverride(), 'created_date' => $udt_obj->getCreatedDate(), 'created_by' => $udt_obj->getCreatedBy(), 'updated_date' => $udt_obj->getUpdatedDate(), 'updated_by' => $udt_obj->getUpdatedBy(), 'deleted_date' => $udt_obj->getDeletedDate(), 'deleted_by' => $udt_obj->getDeletedBy(), 'override' => $udt_obj->getOverride());
         }
     } elseif ($action != 'submit') {
         Debug::Text(' ID was NOT passed: ' . $id, __FILE__, __LINE__, __METHOD__, 10);
         //UserID has to be set at minimum
         if ($user_date_id != '') {
             $udlf = new UserDateListFactory();
             $udlf->getById($user_date_id);
             if ($udlf->getRecordCount() > 0) {
                 $udt_obj = $udlf->getCurrent();
                 $udt_data = array('user_date_id' => $user_date_id, 'date_stamp' => $udt_obj->getDateStamp(), 'user_id' => $udt_obj->getUser(), 'user_full_name' => $udt_obj->getUserObject()->getFullName(), 'branch_id' => $udt_obj->getUserObject()->getDefaultBranch(), 'department_id' => $udt_obj->getUserObject()->getDefaultDepartment(), 'total_time' => 0, 'status_id' => 20, 'quantity' => 0, 'bad_quantity' => 0, 'punch_control_id' => 0, 'override' => FALSE);
             }
         }
     }
     $blf = new BranchListFactory();
     $branch_options = $blf->getByCompanyIdArray($current_company->getId());
     $dlf = new DepartmentListFactory();
     $department_options = $dlf->getByCompanyIdArray($current_company->getId());
     //Absence policies
     $otplf = new AbsencePolicyListFactory();
     $absence_policy_options = $otplf->getByCompanyIDArray($current_company->getId(), TRUE);
     //Overtime policies
 function postSave()
 {
     //If status is pending auth (55=declined) delete all authorization history, because they could be re-verifying.
     if ($this->getCurrentUser() != FALSE and $this->getStatus() == 55) {
         $alf = TTnew('AuthorizationListFactory');
         $alf->getByObjectTypeAndObjectId(90, $this->getId());
         if ($alf->getRecordCount() > 0) {
             foreach ($alf as $a_obj) {
                 //Delete the record outright for now, as marking it as deleted causes transaction issues
                 //and it never gets committed.
                 $a_obj->Delete();
             }
         }
     }
     $time_sheet_verification_type_id = $this->getVerificationType();
     if ($time_sheet_verification_type_id > 10) {
         //10 = Disabled
         $authorize_timesheet = FALSE;
         if ($time_sheet_verification_type_id == 20) {
             //Employee Only
             $authorize_timesheet = TRUE;
         } elseif ($time_sheet_verification_type_id == 30) {
             //Superior Only
             if ($this->getStatus() == 30 and $this->getCurrentUser() != FALSE) {
                 //Check on CurrentUser so we don't loop indefinitely through AuthorizationFactory.
                 Debug::Text(' aAuthorizing TimeSheet as superior...', __FILE__, __LINE__, __METHOD__, 10);
                 $authorize_timesheet = TRUE;
             }
         } elseif ($time_sheet_verification_type_id == 40) {
             //Superior & Employee
             if ($this->getStatus() == 30 and $this->getCurrentUser() != FALSE and $this->getCurrentUser() != $this->getUser()) {
                 //Check on CurrentUser so we don't loop indefinitely through AuthorizationFactory.
                 Debug::Text(' bAuthorizing TimeSheet as superior...', __FILE__, __LINE__, __METHOD__, 10);
                 $authorize_timesheet = TRUE;
             }
         }
         if ($authorize_timesheet == TRUE) {
             $af = TTnew('AuthorizationFactory');
             $af->setCurrentUser($this->getCurrentUser());
             $af->setObjectType('timesheet');
             $af->setObject($this->getId());
             $af->setAuthorized(TRUE);
             if ($af->isValid()) {
                 $af->Save();
             }
         } else {
             Debug::Text('Not authorizing timesheet...', __FILE__, __LINE__, __METHOD__, 10);
         }
         if ($authorize_timesheet == TRUE or $this->getAuthorized() == TRUE) {
             //Recalculate exceptions on the last day of pay period to remove any TimeSheet Not Verified exceptions.
             //Get user_date_id.
             if (is_object($this->getPayPeriodObject())) {
                 $udlf = new UserDateListFactory();
                 $udlf->getByUserIdAndDate($this->getUser(), $this->getPayPeriodObject()->getEndDate());
                 if ($udlf->getRecordCount() > 0) {
                     Debug::Text('Recalculating exceptions on last day of pay period... Date: ' . $this->getPayPeriodObject()->getEndDate(), __FILE__, __LINE__, __METHOD__, 10);
                     ExceptionPolicyFactory::calcExceptions($udlf->getCurrent()->getID(), FALSE, FALSE);
                 }
             } else {
                 Debug::Text('No Pay Period found...', __FILE__, __LINE__, __METHOD__, 10);
             }
         } else {
             Debug::Text('Not recalculating last day of pay period...', __FILE__, __LINE__, __METHOD__, 10);
         }
     } else {
         Debug::Text('TimeSheet Verification is disabled...', __FILE__, __LINE__, __METHOD__, 10);
     }
     return TRUE;
 }
$ugdf->setCompany($current_company->getId());
$ugdf->setUser($current_user->getId());
$ugdf->setScript($_SERVER['SCRIPT_NAME']);
$ugdf->setName('Default');
//This has to go after company,user and script are already set.
$ugdf->setData($filter_data);
$ugdf->setDefault(TRUE);
if ($ugdf->isValid()) {
    $ugf_id = $ugdf->Save();
    if ($ugf_id !== TRUE) {
        $generic_data['id'] = $ugf_id;
    }
    unset($generic_data['name']);
}
//Get pay period info from filter date.
$udlf = new UserDateListFactory();
$udlf->getByUserIdAndDate($user_id, $filter_data['date']);
if ($udlf->getRecordCount() > 0) {
    $pay_period_id = $udlf->getCurrent()->getPayPeriod();
} else {
    Debug::text('bPay Period Lookup: ', __FILE__, __LINE__, __METHOD__, 10);
    //Slower method, find another user date in
    //FIXME: If they change pay period schedules for an employee, and the employee
    //doesn't have user_date rows for weekends, it won't know which pay period they belong to.
    //This will guess they belong to the new pay period schedule.
    //Only real fix I see for this is to make sure we have a user_date row for EVERY day, for EVERY
    //user, regardless if they work or not.
    $pplf = new PayPeriodListFactory();
    $pplf->getByUserIdAndEndDate($user_id, $filter_data['date']);
    if ($pplf->getRecordCount() > 0) {
        $pay_period_obj = $pplf->getCurrent();
 function getScheduleObjectByUserIdAndEpoch($user_id, $epoch)
 {
     if ($user_id == '') {
         return FALSE;
     }
     if ($epoch == '') {
         return FALSE;
     }
     $udlf = new UserDateListFactory();
     $udlf->getByUserIdAndDate($user_id, $epoch);
     if ($udlf->getRecordCount() > 0) {
         Debug::Text(' Found User Date ID! ', __FILE__, __LINE__, __METHOD__, 10);
         $slf = new ScheduleListFactory();
         $slf->getByUserDateId($udlf->getCurrent()->getId());
         if ($slf->getRecordCount() > 0) {
             Debug::Text(' Found Schedule!: ', __FILE__, __LINE__, __METHOD__, 10);
             foreach ($slf as $s_obj) {
                 if ($s_obj->inSchedule($epoch)) {
                     Debug::Text(' in Found Schedule! Branch: ' . $s_obj->getBranch(), __FILE__, __LINE__, __METHOD__, 10);
                     return $s_obj;
                 } else {
                     Debug::Text(' NOT in Found Schedule!: ', __FILE__, __LINE__, __METHOD__, 10);
                 }
             }
         }
     }
     return FALSE;
 }
Exemple #12
0
         }
     }
 }
 /*
 	Get Attendance History
 */
 if (isset($columns['attendance'])) {
     //Get policy names.
     $oplf = new OverTimePolicyListFactory();
     $over_time_policy_arr = $oplf->getByCompanyIdArray($current_company->getId(), FALSE);
     $aplf = new AbsencePolicyListFactory();
     $absence_policy_arr = $aplf->getByCompanyIdArray($current_company->getId(), FALSE);
     $pplf = new PremiumPolicyListFactory();
     $premium_policy_arr = $pplf->getByCompanyIdArray($current_company->getId(), FALSE);
     //Get stats on number of days worked per month/week
     $udlf = new UserDateListFactory();
     $udlf->getDaysWorkedByTimePeriodAndUserIdAndCompanyIdAndStartDateAndEndDate('month', $filter_data['user_ids'], $current_company->getId(), $filter_data['start_date'], $filter_data['end_date']);
     if ($udlf->getRecordCount() > 0) {
         foreach ($udlf as $ud_obj) {
             //$user_days_worked[$ud_obj->getUser()]['month']
             $user_attendance_rows[$ud_obj->getUser()]['days_worked']['month'] = array('avg' => round($ud_obj->getColumn('avg'), 2), 'min' => $ud_obj->getColumn('min'), 'max' => $ud_obj->getColumn('max'));
         }
     }
     $udlf->getDaysWorkedByTimePeriodAndUserIdAndCompanyIdAndStartDateAndEndDate('week', $filter_data['user_ids'], $current_company->getId(), $filter_data['start_date'], $filter_data['end_date']);
     if ($udlf->getRecordCount() > 0) {
         foreach ($udlf as $ud_obj) {
             $user_attendance_rows[$ud_obj->getUser()]['days_worked']['week'] = array('avg' => round($ud_obj->getColumn('avg'), 2), 'min' => $ud_obj->getColumn('min'), 'max' => $ud_obj->getColumn('max'));
         }
     }
     //var_dump($user_days_worked);
     $udtlf = new UserDateTotalListFactory();
 static function smartReCalculate($user_id, $user_date_ids, $enable_exception = TRUE, $enable_premature_exceptions = FALSE, $enable_future_exceptions = TRUE)
 {
     if ($user_id == '') {
         return FALSE;
     }
     //Debug::Arr($user_date_ids, 'aUser Date IDs: ', __FILE__, __LINE__, __METHOD__, 10);
     if (!is_array($user_date_ids) and is_int($user_date_ids)) {
         $user_date_ids = array($user_date_ids);
     }
     if (!is_array($user_date_ids)) {
         return FALSE;
     }
     $user_date_ids = array_unique($user_date_ids);
     //Debug::Arr($user_date_ids, 'bUser Date IDs: ', __FILE__, __LINE__, __METHOD__, 10);
     $start_week_day_id = 0;
     $ppslf = new PayPeriodScheduleListFactory();
     $ppslf->getByUserId($user_id);
     if ($ppslf->getRecordCount() == 1) {
         $pps_obj = $ppslf->getCurrent();
         $start_week_day_id = $pps_obj->getStartWeekDay();
     }
     Debug::text('Start Week Day ID: ' . $start_week_day_id, __FILE__, __LINE__, __METHOD__, 10);
     //Get date stamps for all user_date_ids.
     $udlf = new UserDateListFactory();
     $udlf->getByIds($user_date_ids, NULL, array('date_stamp' => 'asc'));
     //Order by date asc
     if ($udlf->getRecordCount() > 0) {
         //Order them, and get the one or more sets of date ranges that need to be recalculated.
         //Need to consider re-calculating multiple weeks at once.
         $i = 0;
         foreach ($udlf as $ud_obj) {
             $start_week_epoch = TTDate::getBeginWeekEpoch($ud_obj->getDateStamp(), $start_week_day_id);
             $end_week_epoch = TTDate::getEndWeekEpoch($ud_obj->getDateStamp(), $start_week_day_id);
             Debug::text('Current Date: ' . TTDate::getDate('DATE', $ud_obj->getDateStamp()) . ' Start Week: ' . TTDate::getDate('DATE', $start_week_epoch) . ' End Week: ' . TTDate::getDate('DATE', $end_week_epoch), __FILE__, __LINE__, __METHOD__, 10);
             if ($i == 0) {
                 $range_arr[$start_week_epoch] = array('start_date' => $ud_obj->getDateStamp(), 'end_date' => $end_week_epoch);
             } else {
                 //Loop through each range extending it if needed.
                 foreach ($range_arr as $tmp_start_week_epoch => $tmp_range) {
                     if ($ud_obj->getDateStamp() >= $tmp_range['start_date'] and $ud_obj->getDateStamp() <= $tmp_range['end_date']) {
                         //Date falls within already existing range
                         continue;
                     } elseif ($ud_obj->getDateStamp() < $tmp_range['start_date'] and $ud_obj->getDateStamp() >= $tmp_start_week_epoch) {
                         //Date falls within the same week, but before the current start date.
                         $range_arr[$tmp_start_week_epoch]['start_date'] = $ud_obj->getDateStamp();
                         Debug::text('Pushing Start Date back...', __FILE__, __LINE__, __METHOD__, 10);
                     } else {
                         //Outside current range. Check to make sure it isn't within another range.
                         if (isset($range_arr[$start_week_epoch])) {
                             //Within another existing week, check to see if we need to extend it.
                             if ($ud_obj->getDateStamp() < $range_arr[$start_week_epoch]['start_date']) {
                                 Debug::text('bPushing Start Date back...', __FILE__, __LINE__, __METHOD__, 10);
                                 $range_arr[$start_week_epoch]['start_date'] = $ud_obj->getDateStamp();
                             }
                         } else {
                             //Not within another existing week
                             Debug::text('Adding new range...', __FILE__, __LINE__, __METHOD__, 10);
                             $range_arr[$start_week_epoch] = array('start_date' => $ud_obj->getDateStamp(), 'end_date' => $end_week_epoch);
                         }
                     }
                 }
                 unset($tmp_range, $tmp_start_week_epoch);
             }
             $i++;
         }
         unset($start_week_epoch, $end_week_epoch, $udlf, $ud_obj);
         if (is_array($range_arr)) {
             ksort($range_arr);
             //Sort range by start week, so recalculating goes in date order.
             //Debug::Arr($range_arr, 'Range Array: ', __FILE__, __LINE__, __METHOD__, 10);
             foreach ($range_arr as $week_range) {
                 $udlf = new UserDateListFactory();
                 $udlf->getByUserIdAndStartDateAndEndDate($user_id, $week_range['start_date'], $week_range['end_date']);
                 if ($udlf->getRecordCount() > 0) {
                     Debug::text('Found days to re-calculate: ' . $udlf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
                     $udlf->StartTransaction();
                     $z = 1;
                     $z_max = $udlf->getRecordCount();
                     foreach ($udlf as $ud_obj) {
                         //We only need to re-calculate exceptions on the exact days specified by user_date_ids.
                         //This was the case before we Over Weekly Time/Over Scheduled Weekly Time exceptions,
                         //Now we have to enable calculating exceptions for the entire week.
                         /*
                         if ( in_array( $ud_obj->getId(), $user_date_ids ) ) {
                         	//Calculate exceptions
                         	Debug::text('Re-calculating day with exceptions: '. $ud_obj->getId() , __FILE__, __LINE__, __METHOD__, 10);
                         	UserDateTotalFactory::reCalculateDay( $ud_obj->getId(), $enable_exception, $enable_premature_exceptions, $enable_future_exceptions );
                         } else {
                         	//Don't calculate exceptions.
                         	UserDateTotalFactory::reCalculateDay( $ud_obj->getId() );
                         }
                         */
                         Debug::text('Re-calculating day with exceptions: ' . $ud_obj->getId(), __FILE__, __LINE__, __METHOD__, 10);
                         if ($z == $z_max) {
                             //Enable recalculating holidays at the end of each week.
                             UserDateTotalFactory::reCalculateDay($ud_obj->getId(), $enable_exception, $enable_premature_exceptions, $enable_future_exceptions, TRUE);
                         } else {
                             UserDateTotalFactory::reCalculateDay($ud_obj->getId(), $enable_exception, $enable_premature_exceptions, $enable_future_exceptions);
                         }
                         $z++;
                     }
                     $udlf->CommitTransaction();
                 }
             }
             return TRUE;
         }
     }
     Debug::text('Returning FALSE!', __FILE__, __LINE__, __METHOD__, 10);
     return FALSE;
 }
 function calcExceptions($user_date_id, $enable_premature_exceptions = FALSE, $enable_future_exceptions = TRUE)
 {
     global $profiler;
     $profiler->startTimer("ExceptionPolicy::calcExceptions()");
     if ($user_date_id == '') {
         return FALSE;
     }
     Debug::text(' User Date ID: ' . $user_date_id . ' PreMature: ' . (int) $enable_premature_exceptions, __FILE__, __LINE__, __METHOD__, 10);
     //Get user date info
     $udlf = new UserDateListFactory();
     $udlf->getById($user_date_id);
     if ($udlf->getRecordCount() > 0) {
         $user_date_obj = $udlf->getCurrent();
         if ($enable_future_exceptions == FALSE and $user_date_obj->getDateStamp() > TTDate::getEndDayEpoch()) {
             return FALSE;
         }
     } else {
         return FALSE;
     }
     //Since we are not usng demerits yet, just always delete exceptions and re-calculate them
     $elf = new ExceptionListFactory();
     $elf->getByUserDateID($user_date_id);
     if ($elf->getRecordCount() > 0) {
         foreach ($elf as $e_obj) {
             Debug::text(' Deleting Exception: ' . $e_obj->getID(), __FILE__, __LINE__, __METHOD__, 10);
             $e_obj->Delete();
         }
     }
     //Get all Punches on this date for this user.
     $plf = new PunchListFactory();
     $plf->getByUserDateId($user_date_id);
     if ($plf->getRecordCount() > 0) {
         Debug::text(' Found Punches: ' . $plf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
     }
     $slf = new ScheduleListFactory();
     $slf->getByUserDateIdAndStatusId($user_date_id, 10);
     if ($slf->getRecordCount() > 0) {
         Debug::text(' Found Schedule: ' . $slf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
     }
     $schedule_id_cache = NULL;
     //Cache schedule IDs so we don't need to do a lookup for every exception.
     //Get all active exceptions.
     $eplf = new ExceptionPolicyListFactory();
     $eplf->getByPolicyGroupUserIdAndActive($user_date_obj->getUser(), TRUE);
     if ($eplf->getRecordCount() > 0) {
         Debug::text(' Found Active Exceptions: ' . $eplf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
         foreach ($eplf as $ep_obj) {
             //Debug::text(' Found Exception Type: '. $ep_obj->getType() .' ID: '. $ep_obj->getID() .' Control ID: '. $ep_obj->getExceptionPolicyControl(), __FILE__, __LINE__, __METHOD__,10);
             if ($enable_premature_exceptions == TRUE and self::isPreMature($ep_obj->getType()) == TRUE) {
                 //Debug::text(' Premature Exception: '. $ep_obj->getType() , __FILE__, __LINE__, __METHOD__,10);
                 $type_id = 5;
                 //Pre-Mature
             } else {
                 //Debug::text(' NOT Premature Exception: '. $ep_obj->getType() , __FILE__, __LINE__, __METHOD__,10);
                 $type_id = 50;
                 //Active
             }
             switch (strtolower($ep_obj->getType())) {
                 case 's1':
                     //Unscheduled Absence... Anytime they are scheduled and have not punched in.
                     //Ignore these exceptions if the schedule is after today (not including today),
                     //so if a supervisors schedules an employee two days in advance they don't get a unscheduled
                     //absence appearing right away.
                     if ($plf->getRecordCount() == 0) {
                         if ($slf->getRecordCount() > 0) {
                             foreach ($slf as $s_obj) {
                                 if ($s_obj->getStatus() == 10 and TTDate::getBeginDayEpoch($s_obj->getStartTime()) - TTDate::getBeginDayEpoch(TTDate::getTime()) <= 0) {
                                     $ef = new ExceptionFactory();
                                     $ef->setUserDateID($user_date_id);
                                     $ef->setExceptionPolicyID($ep_obj->getId());
                                     $ef->setType($type_id);
                                     $ef->setEnableDemerits(TRUE);
                                     if ($ef->isValid()) {
                                         if ($enable_premature_exceptions == TRUE) {
                                             $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                         }
                                         $ef->Save();
                                     }
                                 }
                             }
                         } else {
                             Debug::text(' NOT Scheduled', __FILE__, __LINE__, __METHOD__, 10);
                         }
                     }
                     break;
                 case 's2':
                     //Not Scheduled
                     $schedule_total_time = 0;
                     if ($slf->getRecordCount() == 0) {
                         if ($plf->getRecordCount() > 0) {
                             Debug::text(' Worked when wasnt scheduled', __FILE__, __LINE__, __METHOD__, 10);
                             $ef = new ExceptionFactory();
                             $ef->setUserDateID($user_date_id);
                             $ef->setExceptionPolicyID($ep_obj->getId());
                             $ef->setType($type_id);
                             $ef->setEnableDemerits(TRUE);
                             if ($ef->isValid()) {
                                 if ($enable_premature_exceptions == TRUE) {
                                     $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                 }
                                 $ef->Save();
                             }
                         }
                     } else {
                         Debug::text(' IS Scheduled', __FILE__, __LINE__, __METHOD__, 10);
                     }
                     break;
                 case 's3':
                     //In Early
                     if ($plf->getRecordCount() > 0) {
                         //Loop through each punch, find out if they are scheduled, and if they are in early
                         foreach ($plf as $p_obj) {
                             if ($p_obj->getType() == 10 and $p_obj->getStatus() == 10) {
                                 //Normal In
                                 if (!isset($scheduled_id_cache[$p_obj->getID()])) {
                                     $scheduled_id_cache[$p_obj->getID()] = $p_obj->findScheduleID(NULL, $user_date_obj->getUser());
                                 }
                                 if ($p_obj->setScheduleID($scheduled_id_cache[$p_obj->getID()]) == TRUE) {
                                     if ($p_obj->getTimeStamp() < $p_obj->getScheduleObject()->getStartTime()) {
                                         if (TTDate::inWindow($p_obj->getTimeStamp(), $p_obj->getScheduleObject()->getStartTime(), $ep_obj->getGrace()) == TRUE) {
                                             Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;Within Grace time, IGNORE EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                         } elseif (TTDate::inWindow($p_obj->getTimeStamp(), $p_obj->getScheduleObject()->getStartTime(), $ep_obj->getWatchWindow()) == TRUE) {
                                             Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;NOT Within Grace time, SET EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                             $ef = new ExceptionFactory();
                                             $ef->setUserDateID($user_date_id);
                                             $ef->setExceptionPolicyID($ep_obj->getId());
                                             $ef->setPunchID($p_obj->getID());
                                             $ef->setType($type_id);
                                             $ef->setEnableDemerits(TRUE);
                                             if ($ef->isValid()) {
                                                 if ($enable_premature_exceptions == TRUE) {
                                                     $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                                 }
                                                 $ef->Save();
                                             }
                                         }
                                     }
                                 } else {
                                     Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;NO Schedule Found', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                         }
                     }
                     break;
                 case 's4':
                     //In Late
                     if ($plf->getRecordCount() > 0) {
                         foreach ($plf as $p_obj) {
                             if ($p_obj->getType() == 10 and $p_obj->getStatus() == 10) {
                                 //Normal In
                                 if (!isset($scheduled_id_cache[$p_obj->getID()])) {
                                     $scheduled_id_cache[$p_obj->getID()] = $p_obj->findScheduleID(NULL, $user_date_obj->getUser());
                                 }
                                 if ($p_obj->setScheduleID($scheduled_id_cache[$p_obj->getID()]) == TRUE) {
                                     if ($p_obj->getTimeStamp() > $p_obj->getScheduleObject()->getStartTime()) {
                                         if (TTDate::inWindow($p_obj->getTimeStamp(), $p_obj->getScheduleObject()->getStartTime(), $ep_obj->getGrace()) == TRUE) {
                                             Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;Within Grace time, IGNORE EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                         } elseif (TTDate::inWindow($p_obj->getTimeStamp(), $p_obj->getScheduleObject()->getStartTime(), $ep_obj->getWatchWindow()) == TRUE) {
                                             Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;NOT Within Grace time, SET EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                             $ef = new ExceptionFactory();
                                             $ef->setUserDateID($user_date_id);
                                             $ef->setExceptionPolicyID($ep_obj->getId());
                                             $ef->setPunchID($p_obj->getID());
                                             $ef->setType($type_id);
                                             $ef->setEnableDemerits(TRUE);
                                             if ($ef->isValid()) {
                                                 if ($enable_premature_exceptions == TRUE) {
                                                     $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                                 }
                                                 $ef->Save();
                                             }
                                         }
                                     }
                                 } else {
                                     Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;NO Schedule Found', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                         }
                     }
                     break;
                 case 's5':
                     //Out Early
                     if ($plf->getRecordCount() > 0) {
                         //Loop through each punch, find out if they are scheduled, and if they are in early
                         foreach ($plf as $p_obj) {
                             if ($p_obj->getType() == 10 and $p_obj->getStatus() == 20) {
                                 //Normal Out
                                 if (!isset($scheduled_id_cache[$p_obj->getID()])) {
                                     $scheduled_id_cache[$p_obj->getID()] = $p_obj->findScheduleID(NULL, $user_date_obj->getUser());
                                 }
                                 if ($p_obj->setScheduleID($scheduled_id_cache[$p_obj->getID()]) == TRUE) {
                                     if ($p_obj->getTimeStamp() < $p_obj->getScheduleObject()->getEndTime()) {
                                         if (TTDate::inWindow($p_obj->getTimeStamp(), $p_obj->getScheduleObject()->getEndTime(), $ep_obj->getGrace()) == TRUE) {
                                             Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;Within Grace time, IGNORE EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                         } elseif (TTDate::inWindow($p_obj->getTimeStamp(), $p_obj->getScheduleObject()->getEndTime(), $ep_obj->getWatchWindow()) == TRUE) {
                                             Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;NOT Within Grace time, SET EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                             $ef = new ExceptionFactory();
                                             $ef->setUserDateID($user_date_id);
                                             $ef->setExceptionPolicyID($ep_obj->getId());
                                             $ef->setPunchID($p_obj->getID());
                                             $ef->setType($type_id);
                                             $ef->setEnableDemerits(TRUE);
                                             if ($ef->isValid()) {
                                                 if ($enable_premature_exceptions == TRUE) {
                                                     $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                                 }
                                                 $ef->Save();
                                             }
                                         }
                                     }
                                 } else {
                                     Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;NO Schedule Found', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                         }
                     }
                     break;
                 case 's6':
                     //Out Late
                     if ($plf->getRecordCount() > 0) {
                         foreach ($plf as $p_obj) {
                             if ($p_obj->getType() == 10 and $p_obj->getStatus() == 20) {
                                 //Normal Out
                                 if (!isset($scheduled_id_cache[$p_obj->getID()])) {
                                     $scheduled_id_cache[$p_obj->getID()] = $p_obj->findScheduleID(NULL, $user_date_obj->getUser());
                                 }
                                 if ($p_obj->setScheduleID($scheduled_id_cache[$p_obj->getID()]) == TRUE) {
                                     if ($p_obj->getTimeStamp() > $p_obj->getScheduleObject()->getEndTime()) {
                                         if (TTDate::inWindow($p_obj->getTimeStamp(), $p_obj->getScheduleObject()->getEndTime(), $ep_obj->getGrace()) == TRUE) {
                                             Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;Within Grace time, IGNORE EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                         } elseif (TTDate::inWindow($p_obj->getTimeStamp(), $p_obj->getScheduleObject()->getEndTime(), $ep_obj->getWatchWindow()) == TRUE) {
                                             Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;NOT Within Grace time, SET EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                             $ef = new ExceptionFactory();
                                             $ef->setUserDateID($user_date_id);
                                             $ef->setExceptionPolicyID($ep_obj->getId());
                                             $ef->setPunchID($p_obj->getID());
                                             $ef->setType($type_id);
                                             $ef->setEnableDemerits(TRUE);
                                             if ($ef->isValid()) {
                                                 if ($enable_premature_exceptions == TRUE) {
                                                     $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                                 }
                                                 $ef->Save();
                                             }
                                         }
                                     }
                                 } else {
                                     Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;NO Schedule Found', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                         }
                     }
                     break;
                 case 'm1':
                     //Missing In Punch
                     if ($plf->getRecordCount() > 0) {
                         foreach ($plf as $p_obj) {
                             //Debug::text(' Punch: Status: '. $p_obj->getStatus() .' Punch Control ID: '. $p_obj->getPunchControlID() .' Punch ID: '. $p_obj->getId() .' TimeStamp: '. $p_obj->getTimeStamp(), __FILE__, __LINE__, __METHOD__,10);
                             if ($type_id == 5 and $p_obj->getTimeStamp() < time() - self::$premature_delay) {
                                 $type_id = 50;
                             }
                             $punch_pairs[$p_obj->getPunchControlID()][] = array('status_id' => $p_obj->getStatus(), 'punch_control_id' => $p_obj->getPunchControlID(), 'punch_id' => $p_obj->getId());
                         }
                         if (isset($punch_pairs)) {
                             foreach ($punch_pairs as $punch_control_id => $punch_pair) {
                                 //Debug::Arr($punch_pair, 'Punch Pair for Control ID:'. $punch_control_id, __FILE__, __LINE__, __METHOD__,10);
                                 if (count($punch_pair) != 2) {
                                     Debug::text('aFound Missing Punch: ', __FILE__, __LINE__, __METHOD__, 10);
                                     if ($punch_pair[0]['status_id'] == 20) {
                                         //Missing In Punch
                                         Debug::text('bFound Missing In Punch: ', __FILE__, __LINE__, __METHOD__, 10);
                                         $ef = new ExceptionFactory();
                                         $ef->setUserDateID($user_date_id);
                                         $ef->setExceptionPolicyID($ep_obj->getId());
                                         $ef->setPunchControlID($punch_pair[0]['punch_control_id']);
                                         $ef->setType($type_id);
                                         $ef->setEnableDemerits(TRUE);
                                         if ($ef->isValid()) {
                                             if ($enable_premature_exceptions == TRUE) {
                                                 $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                             }
                                             $ef->Save();
                                         }
                                     }
                                 } else {
                                     Debug::text('No Missing Punches...', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                         }
                         unset($punch_pairs, $punch_pair);
                     }
                     break;
                 case 'm2':
                     //Missing Out Punch
                     if ($plf->getRecordCount() > 0) {
                         foreach ($plf as $p_obj) {
                             Debug::text(' Punch: Status: ' . $p_obj->getStatus() . ' Punch Control ID: ' . $p_obj->getPunchControlID() . ' Punch ID: ' . $p_obj->getId() . ' TimeStamp: ' . $p_obj->getTimeStamp(), __FILE__, __LINE__, __METHOD__, 10);
                             if ($type_id == 5 and $p_obj->getTimeStamp() < time() - self::$premature_delay) {
                                 $type_id = 50;
                             }
                             $punch_pairs[$p_obj->getPunchControlID()][] = array('status_id' => $p_obj->getStatus(), 'punch_control_id' => $p_obj->getPunchControlID());
                         }
                         if (isset($punch_pairs)) {
                             foreach ($punch_pairs as $punch_control_id => $punch_pair) {
                                 if (count($punch_pair) != 2) {
                                     Debug::text('aFound Missing Punch: ', __FILE__, __LINE__, __METHOD__, 10);
                                     if ($punch_pair[0]['status_id'] == 10) {
                                         //Missing Out Punch
                                         Debug::text('bFound Missing Out Punch: ', __FILE__, __LINE__, __METHOD__, 10);
                                         $ef = new ExceptionFactory();
                                         $ef->setUserDateID($user_date_id);
                                         $ef->setExceptionPolicyID($ep_obj->getId());
                                         $ef->setPunchControlID($punch_pair[0]['punch_control_id']);
                                         $ef->setType($type_id);
                                         $ef->setEnableDemerits(TRUE);
                                         if ($ef->isValid()) {
                                             if ($enable_premature_exceptions == TRUE) {
                                                 $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                             }
                                             $ef->Save();
                                         }
                                     }
                                 } else {
                                     Debug::text('No Missing Punches...', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                         }
                         unset($punch_pairs, $punch_pair);
                     }
                     break;
                 case 'm3':
                     //Missing Lunch In/Out punch
                     if ($plf->getRecordCount() > 0) {
                         //We need to account for cases where they may punch IN from lunch first, then Out.
                         //As well as just a Lunch In punch and nothing else.
                         foreach ($plf as $p_obj) {
                             if ($type_id == 5 and $p_obj->getTimeStamp() < time() - self::$premature_delay) {
                                 $type_id = 50;
                             }
                             $punches[] = $p_obj;
                         }
                         if (isset($punches) and is_array($punches)) {
                             foreach ($punches as $key => $p_obj) {
                                 if ($p_obj->getType() == 20) {
                                     //Lunch
                                     Debug::text(' Punch: Status: ' . $p_obj->getStatus() . ' Punch Control ID: ' . $p_obj->getPunchControlID() . ' TimeStamp: ' . $p_obj->getTimeStamp(), __FILE__, __LINE__, __METHOD__, 10);
                                     if ($p_obj->getStatus() == 10) {
                                         //Make sure previous punch is Lunch/Out
                                         if (!isset($punches[$key - 1]) or isset($punches[$key - 1]) and is_object($punches[$key - 1]) and ($punches[$key - 1]->getType() != 20 or $punches[$key - 1]->getStatus() != 20)) {
                                             //Invalid punch
                                             $invalid_punches[] = array('punch_id' => $p_obj->getId());
                                         }
                                     } else {
                                         //Make sure next punch is Lunch/In
                                         if (!isset($punches[$key + 1]) or isset($punches[$key + 1]) and is_object($punches[$key + 1]) and ($punches[$key + 1]->getType() != 20 or $punches[$key + 1]->getStatus() != 10)) {
                                             //Invalid punch
                                             $invalid_punches[] = array('punch_id' => $p_obj->getId());
                                         }
                                     }
                                 }
                             }
                             unset($punches, $key, $p_obj);
                             if (isset($invalid_punches) and count($invalid_punches) > 0) {
                                 foreach ($invalid_punches as $invalid_punch_arr) {
                                     Debug::text('Found Missing Lunch In/Out Punch: ', __FILE__, __LINE__, __METHOD__, 10);
                                     $ef = new ExceptionFactory();
                                     $ef->setUserDateID($user_date_id);
                                     $ef->setExceptionPolicyID($ep_obj->getId());
                                     //$ef->setPunchControlID( $invalid_punch_arr['punch_id'] );
                                     $ef->setPunchID($invalid_punch_arr['punch_id']);
                                     $ef->setType($type_id);
                                     $ef->setEnableDemerits(TRUE);
                                     if ($ef->isValid()) {
                                         if ($enable_premature_exceptions == TRUE) {
                                             $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                         }
                                         $ef->Save();
                                     }
                                 }
                                 unset($invalid_punch_arr);
                             } else {
                                 Debug::text('Lunch Punches match up.', __FILE__, __LINE__, __METHOD__, 10);
                             }
                             unset($invalid_punches);
                         }
                     }
                     break;
                 case 'm4':
                     //Missing Break In/Out punch
                     if ($plf->getRecordCount() > 0) {
                         //We need to account for cases where they may punch IN from break first, then Out.
                         //As well as just a break In punch and nothing else.
                         foreach ($plf as $p_obj) {
                             if ($type_id == 5 and $p_obj->getTimeStamp() < time() - self::$premature_delay) {
                                 $type_id = 50;
                             }
                             $punches[] = $p_obj;
                         }
                         if (isset($punches) and is_array($punches)) {
                             foreach ($punches as $key => $p_obj) {
                                 if ($p_obj->getType() == 30) {
                                     //Break
                                     Debug::text(' Punch: Status: ' . $p_obj->getStatus() . ' Type: ' . $p_obj->getType() . ' Punch Control ID: ' . $p_obj->getPunchControlID() . ' TimeStamp: ' . $p_obj->getTimeStamp(), __FILE__, __LINE__, __METHOD__, 10);
                                     if ($p_obj->getStatus() == 10) {
                                         //Make sure previous punch is Break/Out
                                         if (!isset($punches[$key - 1]) or isset($punches[$key - 1]) and is_object($punches[$key - 1]) and ($punches[$key - 1]->getType() != 30 or $punches[$key - 1]->getStatus() != 20)) {
                                             //Invalid punch
                                             $invalid_punches[] = array('punch_id' => $p_obj->getId());
                                         }
                                     } else {
                                         //Make sure next punch is Break/In
                                         if (!isset($punches[$key + 1]) or isset($punches[$key + 1]) and is_object($punches[$key + 1]) and ($punches[$key + 1]->getType() != 30 or $punches[$key + 1]->getStatus() != 10)) {
                                             //Invalid punch
                                             $invalid_punches[] = array('punch_id' => $p_obj->getId());
                                         }
                                     }
                                 }
                             }
                             unset($punches, $key, $p_obj);
                             if (isset($invalid_punches) and count($invalid_punches) > 0) {
                                 foreach ($invalid_punches as $invalid_punch_arr) {
                                     Debug::text('Found Missing Break In/Out Punch: ', __FILE__, __LINE__, __METHOD__, 10);
                                     $ef = new ExceptionFactory();
                                     $ef->setUserDateID($user_date_id);
                                     $ef->setExceptionPolicyID($ep_obj->getId());
                                     //$ef->setPunchControlID( $invalid_punch_arr['punch_id'] );
                                     $ef->setPunchID($invalid_punch_arr['punch_id']);
                                     $ef->setType($type_id);
                                     $ef->setEnableDemerits(TRUE);
                                     if ($ef->isValid()) {
                                         if ($enable_premature_exceptions == TRUE) {
                                             $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                         }
                                         $ef->Save();
                                     }
                                 }
                                 unset($invalid_punch_arr);
                             } else {
                                 Debug::text('Lunch Punches match up.', __FILE__, __LINE__, __METHOD__, 10);
                             }
                             unset($invalid_punches);
                         }
                     }
                     break;
                 case 's7':
                     //Over Scheduled Hours
                     if ($plf->getRecordCount() > 0) {
                         //This ONLY takes in to account WORKED hours, not paid absence hours.
                         $schedule_total_time = 0;
                         if ($slf->getRecordCount() > 0) {
                             //Check for schedule policy
                             foreach ($slf as $s_obj) {
                                 Debug::text(' Schedule Total Time: ' . $s_obj->getTotalTime(), __FILE__, __LINE__, __METHOD__, 10);
                                 $schedule_total_time += $s_obj->getTotalTime();
                             }
                             $daily_total_time = 0;
                             if ($schedule_total_time > 0) {
                                 //Get daily total time.
                                 $udtlf = new UserDateTotalListFactory();
                                 //Take into account auto-deduct/add meal policies
                                 //$udtlf->getByUserDateIdAndStatus( $user_date_id, 20 );
                                 $udtlf->getByUserDateIdAndStatusAndType($user_date_id, 10, 10);
                                 if ($udtlf->getRecordCount() > 0) {
                                     foreach ($udtlf as $udt_obj) {
                                         $daily_total_time += $udt_obj->getTotalTime();
                                     }
                                 }
                                 Debug::text(' Daily Total Time: ' . $daily_total_time . ' Schedule Total Time: ' . $schedule_total_time, __FILE__, __LINE__, __METHOD__, 10);
                                 if ($daily_total_time > 0 and $daily_total_time > $schedule_total_time + $ep_obj->getGrace()) {
                                     Debug::text(' Worked Over Scheduled Hours', __FILE__, __LINE__, __METHOD__, 10);
                                     $ef = new ExceptionFactory();
                                     $ef->setUserDateID($user_date_id);
                                     $ef->setExceptionPolicyID($ep_obj->getId());
                                     $ef->setType($type_id);
                                     $ef->setEnableDemerits(TRUE);
                                     if ($ef->isValid()) {
                                         if ($enable_premature_exceptions == TRUE) {
                                             $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                         }
                                         $ef->Save();
                                     }
                                 } else {
                                     Debug::text(' DID NOT Work Over Scheduled Hours', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                         } else {
                             Debug::text(' Not Scheduled', __FILE__, __LINE__, __METHOD__, 10);
                         }
                     }
                     break;
                 case 's8':
                     //Under Scheduled Hours
                     if ($plf->getRecordCount() > 0) {
                         //This ONLY takes in to account WORKED hours, not paid absence hours.
                         $schedule_total_time = 0;
                         if ($slf->getRecordCount() > 0) {
                             //Check for schedule policy
                             foreach ($slf as $s_obj) {
                                 Debug::text(' Schedule Total Time: ' . $s_obj->getTotalTime(), __FILE__, __LINE__, __METHOD__, 10);
                                 $schedule_total_time += $s_obj->getTotalTime();
                             }
                             $daily_total_time = 0;
                             if ($schedule_total_time > 0) {
                                 //Get daily total time.
                                 $udtlf = new UserDateTotalListFactory();
                                 //Take into account auto-deduct/add meal policies
                                 //$udtlf->getByUserDateIdAndStatus( $user_date_id, 20 );
                                 $udtlf->getByUserDateIdAndStatusAndType($user_date_id, 10, 10);
                                 if ($udtlf->getRecordCount() > 0) {
                                     foreach ($udtlf as $udt_obj) {
                                         $daily_total_time += $udt_obj->getTotalTime();
                                     }
                                 }
                                 Debug::text(' Daily Total Time: ' . $daily_total_time . ' Schedule Total Time: ' . $schedule_total_time, __FILE__, __LINE__, __METHOD__, 10);
                                 if ($daily_total_time < $schedule_total_time - $ep_obj->getGrace()) {
                                     Debug::text(' Worked Under Scheduled Hours', __FILE__, __LINE__, __METHOD__, 10);
                                     if ($type_id == 5 and $user_date_obj->getDateStamp() < TTDate::getBeginDayEpoch(time() - self::$premature_delay)) {
                                         $type_id = 50;
                                     }
                                     $ef = new ExceptionFactory();
                                     $ef->setUserDateID($user_date_id);
                                     $ef->setExceptionPolicyID($ep_obj->getId());
                                     $ef->setType($type_id);
                                     $ef->setEnableDemerits(TRUE);
                                     if ($ef->isValid()) {
                                         if ($enable_premature_exceptions == TRUE) {
                                             $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                         }
                                         $ef->Save();
                                     }
                                 } else {
                                     Debug::text(' DID NOT Work Under Scheduled Hours', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                         } else {
                             Debug::text(' Not Scheduled', __FILE__, __LINE__, __METHOD__, 10);
                         }
                     }
                     break;
                 case 'o1':
                     //Over Daily Time.
                     if ($plf->getRecordCount() > 0) {
                         //This ONLY takes in to account WORKED hours, not paid absence hours.
                         $daily_total_time = 0;
                         //Get daily total time.
                         $udtlf = new UserDateTotalListFactory();
                         //Take into account auto-deduct/add meal policies
                         $udtlf->getByUserDateIdAndStatusAndType($user_date_id, 10, 10);
                         if ($udtlf->getRecordCount() > 0) {
                             foreach ($udtlf as $udt_obj) {
                                 $daily_total_time += $udt_obj->getTotalTime();
                             }
                         }
                         Debug::text(' Daily Total Time: ' . $daily_total_time . ' Watch Window: ' . $ep_obj->getWatchWindow() . ' User Date ID: ' . $user_date_id, __FILE__, __LINE__, __METHOD__, 10);
                         if ($daily_total_time > 0 and $daily_total_time > $ep_obj->getWatchWindow()) {
                             Debug::text(' Worked Over Daily Hours', __FILE__, __LINE__, __METHOD__, 10);
                             $ef = new ExceptionFactory();
                             $ef->setUserDateID($user_date_id);
                             $ef->setExceptionPolicyID($ep_obj->getId());
                             $ef->setType($type_id);
                             $ef->setEnableDemerits(TRUE);
                             if ($ef->isValid()) {
                                 if ($enable_premature_exceptions == TRUE) {
                                     $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                 }
                                 $ef->Save();
                             }
                         } else {
                             Debug::text(' DID NOT Work Over Scheduled Hours', __FILE__, __LINE__, __METHOD__, 10);
                         }
                     }
                     break;
                 case 'o2':
                     //Over Weekly Time.
                 //Over Weekly Time.
                 case 's9':
                     //Over Weekly Scheduled Time.
                     if ($plf->getRecordCount() > 0) {
                         //Get Pay Period Schedule info
                         if (is_object($user_date_obj->getPayPeriodObject()) and is_object($user_date_obj->getPayPeriodObject()->getPayPeriodScheduleObject())) {
                             $start_week_day_id = $user_date_obj->getPayPeriodObject()->getPayPeriodScheduleObject()->getStartWeekDay();
                         } else {
                             $start_week_day_id = 0;
                         }
                         Debug::text('Start Week Day ID: ' . $start_week_day_id, __FILE__, __LINE__, __METHOD__, 10);
                         $weekly_scheduled_total_time = 0;
                         if (strtolower($ep_obj->getType()) == 's9') {
                             $tmp_slf = new ScheduleListFactory();
                             $tmp_slf->getByUserIdAndStartDateAndEndDate($user_date_obj->getUser(), TTDate::getBeginWeekEpoch($user_date_obj->getDateStamp(), $start_week_day_id), $user_date_obj->getDateStamp());
                             if ($tmp_slf->getRecordCount() > 0) {
                                 foreach ($tmp_slf as $s_obj) {
                                     $weekly_scheduled_total_time += $s_obj->getTotalTime();
                                 }
                             }
                             unset($tmp_slf, $s_obj);
                         }
                         //This ONLY takes in to account WORKED hours, not paid absence hours.
                         $weekly_total_time = 0;
                         //Get daily total time.
                         $udtlf = new UserDateTotalListFactory();
                         $weekly_total_time = $udtlf->getWorkedTimeSumByUserIDAndStartDateAndEndDate($user_date_obj->getUser(), TTDate::getBeginWeekEpoch($user_date_obj->getDateStamp(), $start_week_day_id), $user_date_obj->getDateStamp());
                         Debug::text(' Weekly Total Time: ' . $weekly_total_time . ' Weekly Scheduled Total Time: ' . $weekly_scheduled_total_time . ' Watch Window: ' . $ep_obj->getWatchWindow() . ' Grace: ' . $ep_obj->getGrace() . ' User Date ID: ' . $user_date_id, __FILE__, __LINE__, __METHOD__, 10);
                         if (strtolower($ep_obj->getType()) == 'o2' and $weekly_total_time > 0 and $weekly_total_time > $ep_obj->getWatchWindow() or strtolower($ep_obj->getType()) == 's9' and $weekly_total_time > 0 and $weekly_total_time > $weekly_scheduled_total_time + $ep_obj->getGrace()) {
                             Debug::text(' Worked Over Weekly Hours', __FILE__, __LINE__, __METHOD__, 10);
                             $ef = new ExceptionFactory();
                             $ef->setUserDateID($user_date_id);
                             $ef->setExceptionPolicyID($ep_obj->getId());
                             $ef->setType($type_id);
                             $ef->setEnableDemerits(TRUE);
                             if ($ef->isValid()) {
                                 if ($enable_premature_exceptions == TRUE) {
                                     $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                 }
                                 $ef->Save();
                             }
                         } else {
                             Debug::text(' DID NOT Work Over Scheduled Hours', __FILE__, __LINE__, __METHOD__, 10);
                         }
                     }
                     break;
                 case 'l1':
                     //Long Lunch
                 //Long Lunch
                 case 'l2':
                     //Short Lunch
                     if ($plf->getRecordCount() > 0) {
                         //Get all lunch punches.
                         $pair = 0;
                         $x = 0;
                         $out_for_lunch = FALSE;
                         foreach ($plf as $p_obj) {
                             if ($p_obj->getStatus() == 20 and $p_obj->getType() == 20) {
                                 $lunch_out_timestamp = $p_obj->getTimeStamp();
                                 $lunch_punch_arr[$pair]['punch_id'] = $p_obj->getId();
                                 $out_for_lunch = TRUE;
                             } elseif ($out_for_lunch == TRUE and $p_obj->getStatus() == 10 and $p_obj->getType() == 20) {
                                 $lunch_punch_arr[$pair][20] = $lunch_out_timestamp;
                                 $lunch_punch_arr[$pair][10] = $p_obj->getTimeStamp();
                                 $out_for_lunch = FALSE;
                                 $pair++;
                                 unset($lunch_out_timestamp);
                             } else {
                                 $out_for_lunch = FALSE;
                             }
                         }
                         if (isset($lunch_punch_arr)) {
                             Debug::Arr($lunch_punch_arr, 'Lunch Punch Array: ', __FILE__, __LINE__, __METHOD__, 10);
                             foreach ($lunch_punch_arr as $pair => $time_stamp_arr) {
                                 if (isset($time_stamp_arr[10]) and isset($time_stamp_arr[20])) {
                                     $lunch_total_time = bcsub($time_stamp_arr[10], $time_stamp_arr[20]);
                                     Debug::text(' Lunch Total Time: ' . $lunch_total_time, __FILE__, __LINE__, __METHOD__, 10);
                                     if (!isset($scheduled_id_cache[$p_obj->getID()])) {
                                         $scheduled_id_cache[$p_obj->getID()] = $p_obj->findScheduleID(NULL, $user_date_obj->getUser());
                                     }
                                     //Check to see if they have a schedule policy
                                     if ($p_obj->setScheduleID($scheduled_id_cache[$p_obj->getID()]) == TRUE and is_object($p_obj->getScheduleObject()) == TRUE and is_object($p_obj->getScheduleObject()->getSchedulePolicyObject()) == TRUE) {
                                         $mp_obj = $p_obj->getScheduleObject()->getSchedulePolicyObject()->getMealPolicyObject();
                                     } else {
                                         $mplf = new MealPolicyListFactory();
                                         $mplf->getByPolicyGroupUserId($user_date_obj->getUserObject()->getId());
                                         if ($mplf->getRecordCount() > 0) {
                                             Debug::text('Found Meal Policy to apply.', __FILE__, __LINE__, __METHOD__, 10);
                                             $mp_obj = $mplf->getCurrent();
                                         }
                                     }
                                     if (isset($mp_obj) and is_object($mp_obj)) {
                                         $meal_policy_lunch_time = $mp_obj->getAmount();
                                         Debug::text('Meal Policy Time: ' . $meal_policy_lunch_time, __FILE__, __LINE__, __METHOD__, 10);
                                         $add_exception = FALSE;
                                         if (strtolower($ep_obj->getType()) == 'l1' and $meal_policy_lunch_time > 0 and $lunch_total_time > 0 and $lunch_total_time > $meal_policy_lunch_time + $ep_obj->getGrace()) {
                                             $add_exception = TRUE;
                                         } elseif (strtolower($ep_obj->getType()) == 'l2' and $meal_policy_lunch_time > 0 and $lunch_total_time > 0 and $lunch_total_time < $meal_policy_lunch_time - $ep_obj->getGrace()) {
                                             $add_exception = TRUE;
                                         }
                                         if ($add_exception == TRUE) {
                                             Debug::text('Adding Exception!', __FILE__, __LINE__, __METHOD__, 10);
                                             $ef = new ExceptionFactory();
                                             $ef->setUserDateID($user_date_id);
                                             $ef->setExceptionPolicyID($ep_obj->getId());
                                             if (isset($time_stamp_arr['punch_id'])) {
                                                 $ef->setPunchID($time_stamp_arr['punch_id']);
                                             }
                                             $ef->setType($type_id);
                                             $ef->setEnableDemerits(TRUE);
                                             if ($ef->isValid()) {
                                                 if ($enable_premature_exceptions == TRUE) {
                                                     $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                                 }
                                                 $ef->Save();
                                             }
                                         } else {
                                             Debug::text('Not Adding Exception!', __FILE__, __LINE__, __METHOD__, 10);
                                         }
                                     }
                                 } else {
                                     Debug::text(' Lunch Punches not paired... Skipping!', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                         } else {
                             Debug::text(' No Lunch Punches found, or none are paired.', __FILE__, __LINE__, __METHOD__, 10);
                         }
                     }
                     break;
                 case 'l3':
                     //No Lunch
                     if ($plf->getRecordCount() > 0) {
                         //If they are scheduled or not, we can check for a meal policy and base our
                         //decision off that. We don't want a No Lunch exception on a 3hr shift though.
                         //Also ignore this exception if the lunch is auto-deduct.
                         $daily_total_time = 0;
                         $udtlf = new UserDateTotalListFactory();
                         $udtlf->getByUserDateIdAndStatus($user_date_id, 20);
                         if ($udtlf->getRecordCount() > 0) {
                             foreach ($udtlf as $udt_obj) {
                                 $daily_total_time += $udt_obj->getTotalTime();
                             }
                         }
                         Debug::text('Day Total Time: ' . $daily_total_time, __FILE__, __LINE__, __METHOD__, 10);
                         if ($daily_total_time > 0) {
                             //Check for lunch punch.
                             $lunch_punch = FALSE;
                             foreach ($plf as $p_obj) {
                                 if ($p_obj->getType() == 20) {
                                     Debug::text('Found Lunch Punch: ' . $p_obj->getTimeStamp(), __FILE__, __LINE__, __METHOD__, 10);
                                     $lunch_punch = TRUE;
                                     break;
                                 }
                             }
                             if ($lunch_punch == FALSE) {
                                 Debug::text('DID NOT Find Lunch Punch... Checking meal policies. ', __FILE__, __LINE__, __METHOD__, 10);
                                 //Use scheduled meal policy first.
                                 if ($slf->getRecordCount() > 0) {
                                     Debug::text('Schedule Found...', __FILE__, __LINE__, __METHOD__, 10);
                                     foreach ($slf as $s_obj) {
                                         if ($s_obj->getSchedulePolicyObject() !== FALSE and $s_obj->getSchedulePolicyObject()->getMealPolicyObject() !== FALSE and $s_obj->getSchedulePolicyObject()->getMealPolicyObject()->getType() != 10) {
                                             Debug::text('Found Schedule Meal Policy... Trigger Time: ' . $s_obj->getSchedulePolicyObject()->getMealPolicyObject()->getTriggerTime(), __FILE__, __LINE__, __METHOD__, 10);
                                             if ($daily_total_time > $s_obj->getSchedulePolicyObject()->getMealPolicyObject()->getTriggerTime()) {
                                                 Debug::text('Daily Total Time is After Schedule Meal Policy Trigger Time: ', __FILE__, __LINE__, __METHOD__, 10);
                                                 $ef = new ExceptionFactory();
                                                 $ef->setUserDateID($user_date_id);
                                                 $ef->setExceptionPolicyID($ep_obj->getId());
                                                 $ef->setType($type_id);
                                                 $ef->setEnableDemerits(TRUE);
                                                 if ($ef->isValid()) {
                                                     if ($enable_premature_exceptions == TRUE) {
                                                         $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                                     }
                                                     $ef->Save();
                                                 }
                                             }
                                         } else {
                                             Debug::text('Schedule Meal Policy does not exist, or is auto-deduct?', __FILE__, __LINE__, __METHOD__, 10);
                                         }
                                     }
                                 } else {
                                     Debug::text('No Schedule Found...', __FILE__, __LINE__, __METHOD__, 10);
                                     //Check if they have a meal policy, with no schedule.
                                     $mplf = new MealPolicyListFactory();
                                     $mplf->getByPolicyGroupUserId($user_date_obj->getUser());
                                     if ($mplf->getRecordCount() > 0) {
                                         Debug::text('Found UnScheduled Meal Policy...', __FILE__, __LINE__, __METHOD__, 10);
                                         $m_obj = $mplf->getCurrent();
                                         if ($daily_total_time > $m_obj->getTriggerTime() and $m_obj->getType() == 20) {
                                             Debug::text('Daily Total Time is After Schedule Meal Policy Trigger Time: ' . $m_obj->getTriggerTime(), __FILE__, __LINE__, __METHOD__, 10);
                                             $ef = new ExceptionFactory();
                                             $ef->setUserDateID($user_date_id);
                                             $ef->setExceptionPolicyID($ep_obj->getId());
                                             $ef->setType($type_id);
                                             $ef->setEnableDemerits(TRUE);
                                             if ($ef->isValid()) {
                                                 if ($enable_premature_exceptions == TRUE) {
                                                     $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                                 }
                                                 $ef->Save();
                                             }
                                         } else {
                                             Debug::text('Auto-deduct meal policy, ignorning this exception.', __FILE__, __LINE__, __METHOD__, 10);
                                         }
                                     } else {
                                         //There is no  meal policy or schedule policy with a meal policy assigned to it
                                         //With out this we could still apply No Lunch exceptions, but they will happen even on
                                         //a 2minute shift.
                                         Debug::text('No meal policy, applying No Lunch exception.', __FILE__, __LINE__, __METHOD__, 10);
                                         $ef = new ExceptionFactory();
                                         $ef->setUserDateID($user_date_id);
                                         $ef->setExceptionPolicyID($ep_obj->getId());
                                         $ef->setType($type_id);
                                         $ef->setEnableDemerits(TRUE);
                                         if ($ef->isValid()) {
                                             if ($enable_premature_exceptions == TRUE) {
                                                 $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                             }
                                             $ef->Save();
                                         }
                                     }
                                 }
                             } else {
                                 Debug::text('Found Lunch Punch... Ignoring this exception. ', __FILE__, __LINE__, __METHOD__, 10);
                             }
                         }
                     }
                     break;
                 case 'b1':
                     //Long Break
                 //Long Break
                 case 'b2':
                     //Short Break
                     if ($plf->getRecordCount() > 0) {
                         //Get all break punches.
                         $pair = 0;
                         $x = 0;
                         $out_for_break = FALSE;
                         foreach ($plf as $p_obj) {
                             if ($p_obj->getStatus() == 20 and $p_obj->getType() == 30) {
                                 $break_out_timestamp = $p_obj->getTimeStamp();
                                 $break_punch_arr[$pair]['punch_id'] = $p_obj->getId();
                                 $out_for_break = TRUE;
                             } elseif ($out_for_break == TRUE and $p_obj->getStatus() == 10 and $p_obj->getType() == 30) {
                                 $break_punch_arr[$pair][20] = $break_out_timestamp;
                                 $break_punch_arr[$pair][10] = $p_obj->getTimeStamp();
                                 $out_for_break = FALSE;
                                 $pair++;
                                 unset($break_out_timestamp);
                             } else {
                                 $out_for_break = FALSE;
                             }
                         }
                         unset($pair);
                         if (isset($break_punch_arr)) {
                             Debug::Arr($break_punch_arr, 'Break Punch Array: ', __FILE__, __LINE__, __METHOD__, 10);
                             foreach ($break_punch_arr as $pair => $time_stamp_arr) {
                                 if (isset($time_stamp_arr[10]) and isset($time_stamp_arr[20])) {
                                     $break_total_time = bcsub($time_stamp_arr[10], $time_stamp_arr[20]);
                                     Debug::text(' Break Total Time: ' . $break_total_time, __FILE__, __LINE__, __METHOD__, 10);
                                     if (!isset($scheduled_id_cache[$p_obj->getID()])) {
                                         $scheduled_id_cache[$p_obj->getID()] = $p_obj->findScheduleID(NULL, $user_date_obj->getUser());
                                     }
                                     //Check to see if they have a schedule policy
                                     $bplf = new BreakPolicyListFactory();
                                     if ($p_obj->setScheduleID($scheduled_id_cache[$p_obj->getID()]) == TRUE and is_object($p_obj->getScheduleObject()) == TRUE and is_object($p_obj->getScheduleObject()->getSchedulePolicyObject()) == TRUE) {
                                         $break_policy_ids = $p_obj->getScheduleObject()->getSchedulePolicyObject()->getBreakPolicyObject();
                                         $bplf->getByIdAndCompanyId($break_policy_ids, $user_date_obj->getUserObject()->getCompany());
                                     } else {
                                         $bplf->getByPolicyGroupUserId($user_date_obj->getUser());
                                     }
                                     unset($break_policy_ids);
                                     if ($bplf->getRecordCount() > 0) {
                                         Debug::text('Found Break Policy(ies) to apply: ' . $bplf->getRecordCount() . ' Pair: ' . $pair, __FILE__, __LINE__, __METHOD__, 10);
                                         foreach ($bplf as $bp_obj) {
                                             $bp_objs[] = $bp_obj;
                                         }
                                         unset($bplf, $bp_obj);
                                         if (isset($bp_objs[$pair]) and is_object($bp_objs[$pair])) {
                                             $bp_obj = $bp_objs[$pair];
                                             $break_policy_break_time = $bp_obj->getAmount();
                                             Debug::text('Break Policy Time: ' . $break_policy_break_time . ' ID: ' . $bp_obj->getID(), __FILE__, __LINE__, __METHOD__, 10);
                                             $add_exception = FALSE;
                                             if (strtolower($ep_obj->getType()) == 'b1' and $break_policy_break_time > 0 and $break_total_time > 0 and $break_total_time > $break_policy_break_time + $ep_obj->getGrace()) {
                                                 $add_exception = TRUE;
                                             } elseif (strtolower($ep_obj->getType()) == 'b2' and $break_policy_break_time > 0 and $break_total_time > 0 and $break_total_time < $break_policy_break_time - $ep_obj->getGrace()) {
                                                 $add_exception = TRUE;
                                             }
                                             if ($add_exception == TRUE) {
                                                 Debug::text('Adding Exception! ' . $ep_obj->getType(), __FILE__, __LINE__, __METHOD__, 10);
                                                 $ef = new ExceptionFactory();
                                                 $ef->setUserDateID($user_date_id);
                                                 $ef->setExceptionPolicyID($ep_obj->getId());
                                                 if (isset($time_stamp_arr['punch_id'])) {
                                                     $ef->setPunchID($time_stamp_arr['punch_id']);
                                                 }
                                                 $ef->setType($type_id);
                                                 $ef->setEnableDemerits(TRUE);
                                                 if ($ef->isValid()) {
                                                     if ($enable_premature_exceptions == TRUE) {
                                                         $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                                     }
                                                     $ef->Save();
                                                 }
                                             } else {
                                                 Debug::text('Not Adding Exception!', __FILE__, __LINE__, __METHOD__, 10);
                                             }
                                             unset($bp_obj);
                                         }
                                         unset($bp_objs);
                                     }
                                 } else {
                                     Debug::text(' Break Punches not paired... Skipping!', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                         } else {
                             Debug::text(' No Break Punches found, or none are paired.', __FILE__, __LINE__, __METHOD__, 10);
                         }
                     }
                     break;
                 case 'b3':
                     //Too Many Breaks
                 //Too Many Breaks
                 case 'b4':
                     //Too Few Breaks
                     if ($plf->getRecordCount() > 0) {
                         //Get all break punches.
                         $pair = 0;
                         $x = 0;
                         $out_for_break = FALSE;
                         foreach ($plf as $p_obj) {
                             if ($p_obj->getStatus() == 20 and $p_obj->getType() == 30) {
                                 $break_out_timestamp = $p_obj->getTimeStamp();
                                 $break_punch_arr[$pair]['punch_id'] = $p_obj->getId();
                                 $out_for_break = TRUE;
                             } elseif ($out_for_break == TRUE and $p_obj->getStatus() == 10 and $p_obj->getType() == 30) {
                                 $break_punch_arr[$pair][20] = $break_out_timestamp;
                                 $break_punch_arr[$pair][10] = $p_obj->getTimeStamp();
                                 $out_for_break = FALSE;
                                 $pair++;
                                 unset($break_out_timestamp);
                             } else {
                                 $out_for_break = FALSE;
                             }
                         }
                         unset($pair);
                         if (isset($break_punch_arr)) {
                             $total_breaks = count($break_punch_arr);
                             Debug::Arr($break_punch_arr, 'Break Punch Array: ', __FILE__, __LINE__, __METHOD__, 10);
                             foreach ($break_punch_arr as $pair => $time_stamp_arr) {
                                 if (isset($time_stamp_arr[10]) and isset($time_stamp_arr[20])) {
                                     $break_total_time = bcsub($time_stamp_arr[10], $time_stamp_arr[20]);
                                     Debug::text(' Break Total Time: ' . $break_total_time, __FILE__, __LINE__, __METHOD__, 10);
                                     if (!isset($scheduled_id_cache[$p_obj->getID()])) {
                                         $scheduled_id_cache[$p_obj->getID()] = $p_obj->findScheduleID(NULL, $user_date_obj->getUser());
                                     }
                                     //Check to see if they have a schedule policy
                                     $bplf = new BreakPolicyListFactory();
                                     if ($p_obj->setScheduleID($scheduled_id_cache[$p_obj->getID()]) == TRUE and is_object($p_obj->getScheduleObject()) == TRUE and is_object($p_obj->getScheduleObject()->getSchedulePolicyObject()) == TRUE) {
                                         $break_policy_ids = $p_obj->getScheduleObject()->getSchedulePolicyObject()->getBreakPolicyObject();
                                         $bplf->getByIdAndCompanyId($break_policy_ids, $user_date_obj->getUserObject()->getCompany());
                                     } else {
                                         $bplf->getByPolicyGroupUserId($user_date_obj->getUser());
                                     }
                                     unset($break_policy_ids);
                                     $allowed_breaks = $bplf->getRecordCount();
                                     $add_exception = FALSE;
                                     if (strtolower($ep_obj->getType()) == 'b3' and $total_breaks > $allowed_breaks) {
                                         Debug::text(' Too many breaks taken...', __FILE__, __LINE__, __METHOD__, 10);
                                         $add_exception = TRUE;
                                     } elseif (strtolower($ep_obj->getType()) == 'b4' and $total_breaks < $allowed_breaks) {
                                         Debug::text(' Too few breaks taken...', __FILE__, __LINE__, __METHOD__, 10);
                                         $add_exception = TRUE;
                                     } else {
                                         Debug::text(' Proper number of breaks taken...', __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                     if ($add_exception == TRUE and (strtolower($ep_obj->getType()) == 'b4' or strtolower($ep_obj->getType()) == 'b3' and $pair > $allowed_breaks - 1)) {
                                         Debug::text('Adding Exception! ' . $ep_obj->getType(), __FILE__, __LINE__, __METHOD__, 10);
                                         $ef = new ExceptionFactory();
                                         $ef->setUserDateID($user_date_id);
                                         $ef->setExceptionPolicyID($ep_obj->getId());
                                         if (isset($time_stamp_arr['punch_id']) and strtolower($ep_obj->getType()) == 'b3') {
                                             $ef->setPunchID($time_stamp_arr['punch_id']);
                                         }
                                         $ef->setType($type_id);
                                         $ef->setEnableDemerits(TRUE);
                                         if ($ef->isValid()) {
                                             if ($enable_premature_exceptions == TRUE) {
                                                 $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                             }
                                             $ef->Save();
                                         }
                                     } else {
                                         Debug::text('Not Adding Exception!', __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                 }
                             }
                         }
                     }
                     break;
                 case 'j1':
                     //Not Allowed on Job
                     if ($plf->getRecordCount() > 0) {
                         foreach ($plf as $p_obj) {
                             if ($p_obj->getStatus() == 10) {
                                 //In punches
                                 if (is_object($p_obj->getPunchControlObject()) and $p_obj->getPunchControlObject()->getJob() > 0) {
                                     //Found job punch, check job settings.
                                     $jlf = new JobListFactory();
                                     $jlf->getById($p_obj->getPunchControlObject()->getJob());
                                     if ($jlf->getRecordCount() > 0) {
                                         $j_obj = $jlf->getCurrent();
                                         if ($j_obj->isAllowedUser($user_date_obj->getUser()) == FALSE) {
                                             $ef = new ExceptionFactory();
                                             $ef->setUserDateID($user_date_id);
                                             $ef->setExceptionPolicyID($ep_obj->getId());
                                             $ef->setType($type_id);
                                             $ef->setPunchControlId($p_obj->getPunchControlId());
                                             $ef->setEnableDemerits(TRUE);
                                             if ($ef->isValid()) {
                                                 if ($enable_premature_exceptions == TRUE) {
                                                     $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                                 }
                                                 $ef->Save();
                                             }
                                         } else {
                                             Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;User allowed on Job!', __FILE__, __LINE__, __METHOD__, 10);
                                         }
                                     } else {
                                         Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;Job not found!', __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                 } else {
                                     Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;Not a Job Punch...', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                         }
                         unset($j_obj);
                     }
                     break;
                 case 'j2':
                     //Not Allowed on Task
                     if ($plf->getRecordCount() > 0) {
                         foreach ($plf as $p_obj) {
                             if ($p_obj->getStatus() == 10) {
                                 //In punches
                                 if (is_object($p_obj->getPunchControlObject()) and $p_obj->getPunchControlObject()->getJob() > 0 and $p_obj->getPunchControlObject()->getJobItem() > 0) {
                                     //Found job punch, check job settings.
                                     $jlf = new JobListFactory();
                                     $jlf->getById($p_obj->getPunchControlObject()->getJob());
                                     if ($jlf->getRecordCount() > 0) {
                                         $j_obj = $jlf->getCurrent();
                                         if ($j_obj->isAllowedItem($p_obj->getPunchControlObject()->getJobItem()) == FALSE) {
                                             $ef = new ExceptionFactory();
                                             $ef->setUserDateID($user_date_id);
                                             $ef->setExceptionPolicyID($ep_obj->getId());
                                             $ef->setType($type_id);
                                             $ef->setPunchControlId($p_obj->getPunchControlId());
                                             $ef->setEnableDemerits(TRUE);
                                             if ($ef->isValid()) {
                                                 if ($enable_premature_exceptions == TRUE) {
                                                     $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                                 }
                                                 $ef->Save();
                                             }
                                         } else {
                                             Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;Job item allowed on job!', __FILE__, __LINE__, __METHOD__, 10);
                                         }
                                     } else {
                                         Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;Job not found!', __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                 } else {
                                     Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;Not a Job Punch...', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                         }
                         unset($j_obj);
                     }
                     break;
                 case 'j3':
                     //Job already completed
                     if ($plf->getRecordCount() > 0) {
                         foreach ($plf as $p_obj) {
                             if ($p_obj->getStatus() == 10) {
                                 //In punches
                                 if (is_object($p_obj->getPunchControlObject()) and $p_obj->getPunchControlObject()->getJob() > 0) {
                                     //Found job punch, check job settings.
                                     $jlf = new JobListFactory();
                                     $jlf->getById($p_obj->getPunchControlObject()->getJob());
                                     if ($jlf->getRecordCount() > 0) {
                                         $j_obj = $jlf->getCurrent();
                                         //Status is completed and the User Date Stamp is greater then the job end date.
                                         //If no end date is set, ignore this.
                                         if ($j_obj->getStatus() == 30 and $j_obj->getEndDate() != FALSE and $user_date_obj->getDateStamp() > $j_obj->getEndDate()) {
                                             $ef = new ExceptionFactory();
                                             $ef->setUserDateID($user_date_id);
                                             $ef->setExceptionPolicyID($ep_obj->getId());
                                             $ef->setType($type_id);
                                             $ef->setPunchControlId($p_obj->getPunchControlId());
                                             $ef->setEnableDemerits(TRUE);
                                             if ($ef->isValid()) {
                                                 if ($enable_premature_exceptions == TRUE) {
                                                     $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                                 }
                                                 $ef->Save();
                                             }
                                         } else {
                                             Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;Job Not Completed!', __FILE__, __LINE__, __METHOD__, 10);
                                         }
                                     } else {
                                         Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;Job not found!', __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                 } else {
                                     Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;Not a Job Punch...', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                         }
                         unset($j_obj);
                     }
                     break;
                 case 'j4':
                     //No Job or Task
                     if ($plf->getRecordCount() > 0) {
                         foreach ($plf as $p_obj) {
                             //In punches only
                             if ($p_obj->getStatus() == 10 and is_object($p_obj->getPunchControlObject()) and ($p_obj->getPunchControlObject()->getJob() == '' or $p_obj->getPunchControlObject()->getJob() == 0 or $p_obj->getPunchControlObject()->getJob() == FALSE or $p_obj->getPunchControlObject()->getJobItem() == '' or $p_obj->getPunchControlObject()->getJobItem() == 0 or $p_obj->getPunchControlObject()->getJobItem() == FALSE)) {
                                 $ef = new ExceptionFactory();
                                 $ef->setUserDateID($user_date_id);
                                 $ef->setExceptionPolicyID($ep_obj->getId());
                                 $ef->setType($type_id);
                                 $ef->setPunchControlId($p_obj->getPunchControlId());
                                 $ef->setPunchId($p_obj->getId());
                                 $ef->setEnableDemerits(TRUE);
                                 if ($ef->isValid()) {
                                     if ($enable_premature_exceptions == TRUE) {
                                         $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, $ep_obj);
                                     }
                                     $ef->Save();
                                 }
                             }
                         }
                     }
                     break;
                 default:
                     Debug::text('BAD, should never get here: ', __FILE__, __LINE__, __METHOD__, 10);
                     break;
             }
         }
     }
     $profiler->stopTimer("ExceptionPolicy::calcExceptions()");
     return TRUE;
 }
/*
 * Calculate Exceptions for the previous day. This helps especially for
 * the "Unscheuled Absence" exception.
 *
 * Run this once a day. AFTER AddUserDate
 */
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'global.inc.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'CLI.inc.php';
//Debug::setVerbosity(5);
$execution_time = time();
//Calculate exceptions just for today and yesterday, because some shifts may start late in the day and need to be handled first thing in the morning.
//Make sure we also go one day in the future too, since the servers can be PST and if its 11:00PM, it will stop at midnight for that day, so
//shifts that would have already started in a different timezone (say EST) will not receive exceptions until we have moved into the next day for PST (3hrs late)
$start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($execution_time) - 86400);
$end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($execution_time) + 86400);
$udlf = new UserDateListFactory();
//Use optimized query to speed this process up significantly.
$udlf->getMidDayExceptionsByStartDateAndEndDateAndPayPeriodStatus($start_date, $end_date, array(10, 12, 15, 30));
Debug::text(' calcQuickExceptions: Start Date: ' . TTDate::getDate('DATE+TIME', $start_date) . ' End Date: ' . TTDate::getDate('DATE+TIME', $end_date) . ' User Date Rows: ' . $udlf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 5);
if ($udlf->getRecordCount() > 0) {
    $i = 0;
    foreach ($udlf as $ud_obj) {
        $user_obj_prefs = $ud_obj->getUserObject()->getUserPreferenceObject();
        if (is_object($user_obj_prefs)) {
            $user_obj_prefs->setTimeZonePreferences();
        } else {
            //Use system timezone.
            TTDate::setTimeZone();
        }
        Debug::text('(' . $i . '). User: '******' Date: ' . TTDate::getDate('DATE+TIME', $ud_obj->getDateStamp()) . ' User Date ID: ' . $ud_obj->getId(), __FILE__, __LINE__, __METHOD__, 5);
        //Calculate pre-mature exceptions, so pre-mature Missing Out Punch exceptions arn't made active until they are ready.
 function importData()
 {
     $pps_obj = $this->getPayPeriodScheduleObject();
     if (is_object($pps_obj)) {
         //Get all users assigned to this pp schedule
         $udlf = new UserDateListFactory();
         $udlf->getByUserIdAndStartDateAndEndDateAndEmptyPayPeriod($pps_obj->getUser(), $this->getStartDate(), $this->getEndDate());
         Debug::text(' Pay Period ID: ' . $this->getId() . ' Pay Period orphaned User Date Rows: ' . $udlf->getRecordCount() . ' Start Date: ' . TTDate::getDate('DATE+TIME', $this->getStartDate()) . ' End Date: ' . TTDate::getDate('DATE+TIME', $this->getEndDate()), __FILE__, __LINE__, __METHOD__, 10);
         if ($udlf->getRecordCount() > 0) {
             $udlf->StartTransaction();
             foreach ($udlf as $ud_obj) {
                 $ud_obj->setPayPeriod($this->getId());
                 if ($ud_obj->isValid()) {
                     $ud_obj->Save();
                 }
             }
             $ud_obj->CommitTransaction();
         }
         return TRUE;
     }
     return FALSE;
 }