/**
  * Get all necessary dates for building the TimeSheet in a single call, this is mainly as a performance optimization.
  * @param array $data filter data
  * @return array
  */
 function getTimeSheetDates($base_date)
 {
     $epoch = TTDate::parseDateTime($base_date);
     if ($epoch == '') {
         $epoch = TTDate::getTime();
     }
     $start_date = TTDate::getBeginWeekEpoch($epoch, $this->getCurrentUserPreferenceObject()->getStartWeekDay());
     $end_date = TTDate::getEndWeekEpoch($epoch, $this->getCurrentUserPreferenceObject()->getStartWeekDay());
     $retarr = array('base_date' => $epoch, 'start_date' => $start_date, 'end_date' => $end_date, 'base_display_date' => TTDate::getAPIDate('DATE', $epoch), 'start_display_date' => TTDate::getAPIDate('DATE', $start_date), 'end_display_date' => TTDate::getAPIDate('DATE', $end_date));
     return $retarr;
 }
 function generateData()
 {
     global $current_company, $current_user;
     TTDate::setTimeZone('PST8PDT');
     $current_epoch = time();
     $cf = new CompanyFactory();
     $cf->StartTransaction();
     $company_id = $this->createCompany();
     $clf = new CompanyListFactory();
     $clf->getById($company_id);
     $current_company = $clf->getCurrent();
     if ($company_id !== FALSE) {
         Debug::Text('Company Created Successfully!', __FILE__, __LINE__, __METHOD__, 10);
         $this->createPermissionGroups($company_id);
         //Create currency
         $currency_ids[] = $this->createCurrency($company_id, 10);
         //USD
         $currency_ids[] = $this->createCurrency($company_id, 20);
         //CAD
         //Create branch
         $branch_ids[] = $this->createBranch($company_id, 10);
         //NY
         $branch_ids[] = $this->createBranch($company_id, 20);
         //WA
         //Create departments
         $department_ids[] = $this->createDepartment($company_id, 10);
         $department_ids[] = $this->createDepartment($company_id, 20);
         //Create stations
         $station_id = $this->createStation($company_id);
         //Create pay stub accounts.
         $this->createPayStubAccount($company_id);
         //Link pay stub accounts.
         $this->createPayStubAccountLink($company_id);
         //Company Deductions
         $this->createCompanyDeduction($company_id);
         //Wage Groups
         $wage_group_ids[] = $this->createUserWageGroups($company_id);
         //User Groups
         $user_group_ids[] = $this->createUserGroup($company_id, 10, 0);
         $user_group_ids[] = $this->createUserGroup($company_id, 20, $user_group_ids[0]);
         $user_group_ids[] = $this->createUserGroup($company_id, 30, $user_group_ids[0]);
         $user_group_ids[] = $this->createUserGroup($company_id, 40, 0);
         $user_group_ids[] = $this->createUserGroup($company_id, 50, $user_group_ids[3]);
         //Users
         $user_ids[] = $this->createUser($company_id, 10, 0, $branch_ids[0], $department_ids[0], $currency_ids[0], $user_group_ids[0]);
         $user_ids[] = $this->createUser($company_id, 11, 0, $branch_ids[0], $department_ids[1], $currency_ids[0], $user_group_ids[0]);
         $user_ids[] = $this->createUser($company_id, 12, 0, $branch_ids[0], $department_ids[1], $currency_ids[0], $user_group_ids[0]);
         $user_ids[] = $this->createUser($company_id, 13, 0, $branch_ids[0], $department_ids[1], $currency_ids[0], $user_group_ids[0]);
         $user_ids[] = $this->createUser($company_id, 14, 0, $branch_ids[0], $department_ids[1], $currency_ids[0], $user_group_ids[1]);
         $user_ids[] = $this->createUser($company_id, 15, 0, $branch_ids[0], $department_ids[0], $currency_ids[0], $user_group_ids[1]);
         $user_ids[] = $this->createUser($company_id, 16, 0, $branch_ids[0], $department_ids[1], $currency_ids[0], $user_group_ids[1]);
         $user_ids[] = $this->createUser($company_id, 17, 0, $branch_ids[0], $department_ids[1], $currency_ids[0], $user_group_ids[1]);
         $user_ids[] = $this->createUser($company_id, 18, 0, $branch_ids[0], $department_ids[0], $currency_ids[0], $user_group_ids[2]);
         $user_ids[] = $this->createUser($company_id, 19, 0, $branch_ids[0], $department_ids[1], $currency_ids[0], $user_group_ids[2]);
         $user_ids[] = $this->createUser($company_id, 20, 0, $branch_ids[0], $department_ids[1], $currency_ids[0], $user_group_ids[2]);
         $user_ids[] = $this->createUser($company_id, 21, 0, $branch_ids[1], $department_ids[1], $currency_ids[0], $user_group_ids[3]);
         $user_ids[] = $this->createUser($company_id, 22, 0, $branch_ids[1], $department_ids[1], $currency_ids[0], $user_group_ids[3]);
         $user_ids[] = $this->createUser($company_id, 23, 0, $branch_ids[1], $department_ids[1], $currency_ids[0], $user_group_ids[3]);
         $user_ids[] = $this->createUser($company_id, 24, 0, $branch_ids[1], $department_ids[1], $currency_ids[0], $user_group_ids[3]);
         $user_ids[] = $this->createUser($company_id, 25, 0, $branch_ids[1], $department_ids[1], $currency_ids[0], $user_group_ids[4]);
         $user_ids[] = $this->createUser($company_id, 26, 0, $branch_ids[1], $department_ids[1], $currency_ids[0], $user_group_ids[4]);
         $user_ids[] = $this->createUser($company_id, 27, 0, $branch_ids[1], $department_ids[1], $currency_ids[0], $user_group_ids[4]);
         $user_ids[] = $this->createUser($company_id, 28, 0, $branch_ids[1], $department_ids[1], $currency_ids[0], $user_group_ids[4]);
         $user_ids[] = $this->createUser($company_id, 29, 0, $branch_ids[1], $department_ids[1], $currency_ids[0], $user_group_ids[4]);
         $user_ids[] = $this->createUser($company_id, 30, 0, $branch_ids[1], $department_ids[0], $currency_ids[0], $user_group_ids[4]);
         $user_ids[] = $this->createUser($company_id, 40, 0, $branch_ids[1], $department_ids[0], $currency_ids[0], $user_group_ids[4]);
         $current_user_id = $user_ids[] = $this->createUser($company_id, 100, 0, $branch_ids[0], $department_ids[0], $currency_ids[0], $user_group_ids[1]);
         //Create random users.
         for ($i = 0; $i <= $this->getMaxRandomUsers(); $i++) {
             $tmp_user_id = $this->createUser($company_id, 999, 0, $branch_ids[$i % 2], $department_ids[$i % 2], $currency_ids[0], $user_group_ids[$i % 5]);
             if ($tmp_user_id != FALSE) {
                 $user_ids[] = $tmp_user_id;
             }
         }
         Debug::Arr($user_ids, 'All User IDs:', __FILE__, __LINE__, __METHOD__, 10);
         $ulf = new UserListFactory();
         $ulf->getById($current_user_id);
         $current_user = $ulf->getCurrent();
         unset($current_user_id);
         //Create policies
         $policy_ids['round'][] = $this->createRoundingPolicy($company_id, 10);
         //In
         $policy_ids['round'][] = $this->createRoundingPolicy($company_id, 20);
         //Out
         $policy_ids['accrual'][] = $this->createAccrualPolicy($company_id, 10);
         //Bank Time
         $policy_ids['accrual'][] = $this->createAccrualPolicy($company_id, 20);
         //Vacaction
         $policy_ids['accrual'][] = $this->createAccrualPolicy($company_id, 30);
         //Sick
         $policy_ids['overtime'][] = $this->createOverTimePolicy($company_id, 10);
         $policy_ids['overtime'][] = $this->createOverTimePolicy($company_id, 20, $policy_ids['accrual'][0]);
         $policy_ids['premium'][] = $this->createPremiumPolicy($company_id, 10);
         $policy_ids['absence'][] = $this->createAbsencePolicy($company_id, 10, $policy_ids['accrual'][1]);
         $policy_ids['absence'][] = $this->createAbsencePolicy($company_id, 20, $policy_ids['accrual'][0]);
         $policy_ids['absence'][] = $this->createAbsencePolicy($company_id, 30, $policy_ids['accrual'][2]);
         $policy_ids['meal_1'] = $this->createMealPolicy($company_id);
         $policy_ids['schedule_1'] = $this->createSchedulePolicy($company_id, $policy_ids['meal_1']);
         $policy_ids['exception_1'] = $this->createExceptionPolicy($company_id);
         $hierarchy_user_ids = $user_ids;
         $root_user_id = array_pop($hierarchy_user_ids);
         unset($hierarchy_user_ids[0], $hierarchy_user_ids[1]);
         //Create authorization hierarchy
         $hierarchy_control_id = $this->createAuthorizationHierarchyControl($company_id, $hierarchy_user_ids);
         if ($root_user_id == FALSE) {
             Debug::Text('Administrator wasn\'t created! Duplicate username perhaps? Are we appending a random number?', __FILE__, __LINE__, __METHOD__, 10);
         }
         //Admin user at the top
         $this->createAuthorizationHierarchyLevel($company_id, $hierarchy_control_id, $root_user_id, 1);
         $this->createAuthorizationHierarchyLevel($company_id, $hierarchy_control_id, $user_ids[0], 2);
         $this->createAuthorizationHierarchyLevel($company_id, $hierarchy_control_id, $user_ids[1], 3);
         unset($hierarchy_user_ids, $root_user_id);
         //Pay Period Schedule
         $this->createPayPeriodSchedule($company_id, $user_ids);
         //Create Policy Group
         $this->createPolicyGroup($company_id, $policy_ids['meal_1'], $policy_ids['exception_1'], NULL, $policy_ids['overtime'], $policy_ids['premium'], $policy_ids['round'], $user_ids);
         if (getTTProductEdition() == TT_PRODUCT_PROFESSIONAL) {
             //Task Groups
             $task_group_ids[] = $this->createTaskGroup($company_id, 10, 0);
             $task_group_ids[] = $this->createTaskGroup($company_id, 20, $task_group_ids[0]);
             $task_group_ids[] = $this->createTaskGroup($company_id, 30, $task_group_ids[0]);
             $task_group_ids[] = $this->createTaskGroup($company_id, 40, 0);
             $task_group_ids[] = $this->createTaskGroup($company_id, 50, $task_group_ids[3]);
             $task_group_ids[] = $this->createTaskGroup($company_id, 60, $task_group_ids[3]);
             //Job Tasks
             $default_task_id = $this->createTask($company_id, 10, $task_group_ids[2]);
             $task_ids[] = $this->createTask($company_id, 20, $task_group_ids[1]);
             $task_ids[] = $this->createTask($company_id, 30, $task_group_ids[1]);
             $task_ids[] = $this->createTask($company_id, 40, $task_group_ids[2]);
             $task_ids[] = $this->createTask($company_id, 50, $task_group_ids[4]);
             $task_ids[] = $this->createTask($company_id, 60, $task_group_ids[4]);
             $task_ids[] = $this->createTask($company_id, 70, $task_group_ids[5]);
             //Job Groups
             $job_group_ids[] = $this->createJobGroup($company_id, 10, 0);
             $job_group_ids[] = $this->createJobGroup($company_id, 20, $job_group_ids[0]);
             $job_group_ids[] = $this->createJobGroup($company_id, 30, $job_group_ids[0]);
             $job_group_ids[] = $this->createJobGroup($company_id, 40, 0);
             $job_group_ids[] = $this->createJobGroup($company_id, 50, $job_group_ids[3]);
             $job_group_ids[] = $this->createJobGroup($company_id, 60, $job_group_ids[3]);
             //Jobs
             $job_ids[] = $this->createJob($company_id, 10, $default_task_id, $job_group_ids[1], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 11, $default_task_id, $job_group_ids[1], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 12, $default_task_id, $job_group_ids[1], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 13, $default_task_id, $job_group_ids[1], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 14, $default_task_id, $job_group_ids[1], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 15, $default_task_id, $job_group_ids[2], $branch_ids[1], $department_ids[1]);
             $job_ids[] = $this->createJob($company_id, 16, $default_task_id, $job_group_ids[2], $branch_ids[1], $department_ids[1]);
             $job_ids[] = $this->createJob($company_id, 17, $default_task_id, $job_group_ids[2], $branch_ids[1], $department_ids[1]);
             $job_ids[] = $this->createJob($company_id, 18, $default_task_id, $job_group_ids[2], $branch_ids[1], $department_ids[1]);
             $job_ids[] = $this->createJob($company_id, 19, $default_task_id, $job_group_ids[2], $branch_ids[1], $department_ids[1]);
             $job_ids[] = $this->createJob($company_id, 20, $default_task_id, $job_group_ids[4], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 21, $default_task_id, $job_group_ids[4], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 22, $default_task_id, $job_group_ids[4], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 23, $default_task_id, $job_group_ids[5], $branch_ids[1], $department_ids[1]);
             $job_ids[] = $this->createJob($company_id, 24, $default_task_id, $job_group_ids[5], $branch_ids[1], $department_ids[1]);
             $job_ids[] = $this->createJob($company_id, 25, $default_task_id, $job_group_ids[5], $branch_ids[1], $department_ids[1]);
         } else {
             $task_ids[] = 0;
             $job_ids[] = 0;
         }
         //Create Accrual balances
         foreach ($user_ids as $user_id) {
             foreach ($policy_ids['accrual'] as $accrual_policy_id) {
                 $this->createAccrualBalance($user_id, $accrual_policy_id);
             }
             unset($accrual_policy_id);
         }
         //Create recurring schedule templates
         $recurring_schedule_ids[] = $this->createRecurringScheduleTemplate($company_id, 10, $policy_ids['schedule_1']);
         //Morning shift
         $recurring_schedule_ids[] = $this->createRecurringScheduleTemplate($company_id, 20, $policy_ids['schedule_1']);
         //Afternoon shift
         $recurring_schedule_ids[] = $this->createRecurringScheduleTemplate($company_id, 30, $policy_ids['schedule_1']);
         //Evening shift
         $recurring_schedule_ids[] = $this->createRecurringScheduleTemplate($company_id, 40);
         //Split Shift
         $recurring_schedule_ids[] = $this->createRecurringScheduleTemplate($company_id, 50, $policy_ids['schedule_1']);
         //Full rotation
         $recurring_schedule_start_date = TTDate::getBeginWeekEpoch($current_epoch + 86400 * 7.5);
         $this->createRecurringSchedule($company_id, $recurring_schedule_ids[0], $recurring_schedule_start_date, '', array($user_ids[0], $user_ids[1], $user_ids[2], $user_ids[3], $user_ids[4]));
         $this->createRecurringSchedule($company_id, $recurring_schedule_ids[1], $recurring_schedule_start_date, '', array($user_ids[5], $user_ids[6], $user_ids[7], $user_ids[8], $user_ids[9]));
         $this->createRecurringSchedule($company_id, $recurring_schedule_ids[2], $recurring_schedule_start_date, '', array($user_ids[10], $user_ids[11], $user_ids[12], $user_ids[13], $user_ids[14]));
         //Create schedule for each employee.
         foreach ($user_ids as $user_id) {
             //Create schedule starting 6 weeks ago, up to the end of the week.
             $schedule_options_arr = array('status_id' => 10, 'start_time' => '08:00AM', 'end_time' => '05:00PM', 'schedule_policy_id' => $policy_ids['schedule_1']);
             //$schedule_date = ($current_epoch-(86400*42));
             $schedule_date = $current_epoch - 86400 * 14;
             $schedule_end_date = TTDate::getEndWeekEpoch($current_epoch);
             //$schedule_date = ($current_epoch-(86400*14));
             //$schedule_end_date = ($current_epoch+(86400*28));
             while ($schedule_date <= $schedule_end_date) {
                 //Random departments/branches
                 $schedule_options_arr['branch_id'] = $branch_ids[rand(0, count($branch_ids) - 1)];
                 $schedule_options_arr['department_id'] = $department_ids[rand(0, count($department_ids) - 1)];
                 //Skip weekends.
                 if (date('w', $schedule_date) != 0 and date('w', $schedule_date) != 6) {
                     $this->createSchedule($user_id, $schedule_date, $schedule_options_arr);
                 }
                 $schedule_date += 86400;
             }
             //break;
             unset($schedule_options_arr, $schedule_date, $schedule_end_date, $user_id);
         }
         //Punch users in/out randomly.
         foreach ($user_ids as $user_id) {
             //Pick random jobs/tasks that are used for the entire date range.
             //So one employee isn't punching into 15 jobs.
             $user_random_job_ids = array_rand($job_ids, 2);
             $user_random_task_ids = array_rand($job_ids, 3);
             //Create punches starting 6 weeks ago, up to the end of the week.
             //$start_date = $punch_date = ($current_epoch-(86400*42));
             $start_date = $punch_date = $current_epoch - 86400 * 14;
             $end_date = TTDate::getEndWeekEpoch($current_epoch);
             //$start_date = $punch_date = ($current_epoch-(86400*14));
             //$end_date = ($current_epoch+(86400*28));
             $i = 0;
             while ($punch_date <= $end_date) {
                 $date_stamp = TTDate::getDate('DATE', $punch_date);
                 //$punch_full_time_stamp = strtotime($pc_data['date_stamp'].' '.$pc_data['time_stamp']);
                 $exception_cutoff_date = $current_epoch - 86400 * 14;
                 if (date('w', $punch_date) != 0 and date('w', $punch_date) != 6) {
                     if ($punch_date >= $exception_cutoff_date and $i % 4 == 0) {
                         $first_punch_in = rand(7, 8) . ':' . str_pad(rand(0, 30), 2, '0', STR_PAD_LEFT) . 'AM';
                         $last_punch_out = strtotime($date_stamp . ' ' . rand(4, 5) . ':' . str_pad(rand(0, 30), 2, '0', STR_PAD_LEFT) . 'PM');
                         if ($punch_date >= $exception_cutoff_date and rand(0, 20) == 0) {
                             //Create request
                             $this->createRequest(20, $user_id, $date_stamp);
                         }
                         if ($punch_date >= $exception_cutoff_date and rand(0, 16) == 0) {
                             //Create request
                             $this->createRequest(20, $user_id, $date_stamp);
                         }
                     } else {
                         $first_punch_in = '08:00AM';
                         if ($punch_date >= $exception_cutoff_date and $i % 10 == 0) {
                             //Don't punch out to generate exception.
                             $last_punch_out = NULL;
                             //Forgot to punch out request
                             $this->createRequest(30, $user_id, $date_stamp);
                         } else {
                             $last_punch_out = strtotime($date_stamp . ' 5:00PM');
                         }
                     }
                     //Weekdays
                     $this->createPunchPair($user_id, strtotime($date_stamp . ' ' . $first_punch_in), strtotime($date_stamp . ' 11:00AM'), array('in_type_id' => 10, 'out_type_id' => 10, 'branch_id' => $branch_ids[rand(0, count($branch_ids) - 1)], 'department_id' => $department_ids[rand(0, count($department_ids) - 1)], 'job_id' => $job_ids[array_rand($user_random_job_ids)], 'job_item_id' => $task_ids[array_rand($user_random_task_ids)]), TRUE);
                     $this->createPunchPair($user_id, strtotime($date_stamp . ' 11:00AM'), strtotime($date_stamp . ' 1:00PM'), array('in_type_id' => 10, 'out_type_id' => 20, 'branch_id' => $branch_ids[rand(0, count($branch_ids) - 1)], 'department_id' => $department_ids[rand(0, count($department_ids) - 1)], 'job_id' => $job_ids[array_rand($user_random_job_ids)], 'job_item_id' => $task_ids[array_rand($user_random_task_ids)]), TRUE);
                     //Calc total time on last punch pair only.
                     $this->createPunchPair($user_id, strtotime($date_stamp . ' 2:00PM'), $last_punch_out, array('in_type_id' => 20, 'out_type_id' => 10, 'branch_id' => $branch_ids[rand(0, count($branch_ids) - 1)], 'department_id' => $department_ids[rand(0, count($department_ids) - 1)], 'job_id' => $job_ids[array_rand($user_random_job_ids)], 'job_item_id' => $task_ids[array_rand($user_random_task_ids)]), TRUE);
                 } elseif ($punch_date > $exception_cutoff_date and date('w', $punch_date) == 6 and $i % 10 == 0) {
                     //Sat.
                     $this->createPunchPair($user_id, strtotime($date_stamp . ' 10:00AM'), strtotime($date_stamp . ' 2:30PM'), array('in_type_id' => 10, 'out_type_id' => 10, 'branch_id' => $branch_ids[rand(0, count($branch_ids) - 1)], 'department_id' => $department_ids[rand(0, count($department_ids) - 1)], 'job_id' => $job_ids[array_rand($user_random_job_ids)], 'job_item_id' => $task_ids[array_rand($user_random_task_ids)]), TRUE);
                 }
                 //Recalculate entire day. Performance optimization.
                 //UserDateTotalFactory::reCalculateRange( $user_id, $start_date, $end_date );
                 $punch_date += 86400;
                 $i++;
             }
             unset($punch_options_arr, $punch_date, $user_id);
         }
         //Generate pay stubs for each pay period
         $pplf = new PayPeriodListFactory();
         $pplf->getByCompanyId($company_id);
         if ($pplf->getRecordCount() > 0) {
             foreach ($pplf as $pp_obj) {
                 foreach ($user_ids as $user_id) {
                     $cps = new CalculatePayStub();
                     $cps->setUser($user_id);
                     $cps->setPayPeriod($pp_obj->getId());
                     $cps->calculate();
                 }
             }
         }
         unset($pplf, $pp_obj, $user_id);
     }
     //$cf->FailTransaction();
     $cf->CommitTransaction();
     return FALSE;
 }
 /**
  * Get all necessary dates for building the schedule in a single call, this is mainly as a performance optimization.
  * @param array $data filter data
  * @return array
  */
 function getScheduleDates($base_date, $type, $strict = TRUE)
 {
     $epoch = TTDate::parseDateTime($base_date);
     if ($epoch == '') {
         $epoch = TTDate::getTime();
     }
     if ($type == '') {
         $type = 'week';
     }
     switch (strtolower($type)) {
         case 'day':
             if ($strict == TRUE) {
                 $start_date = TTDate::getBeginDayEpoch($epoch);
                 $end_date = TTDate::getEndDayEpoch($epoch);
             } else {
                 $start_date = TTDate::getBeginDayEpoch($epoch);
                 $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             }
             break;
         case 'week':
             if ($strict == TRUE) {
                 $start_date = TTDate::getBeginWeekEpoch($epoch, $this->getCurrentUserPreferenceObject()->getStartWeekDay());
                 $end_date = TTDate::getEndWeekEpoch($epoch, $this->getCurrentUserPreferenceObject()->getStartWeekDay());
             } else {
                 $start_date = TTDate::getBeginDayEpoch($epoch);
                 $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 7 * 86400);
             }
             break;
         case 'month':
             if ($strict == TRUE) {
                 $start_date = TTDate::getBeginWeekEpoch(TTDate::getBeginMonthEpoch($epoch), $this->getCurrentUserPreferenceObject()->getStartWeekDay());
                 $end_date = TTDate::getEndWeekEpoch(TTDate::getEndMonthEpoch($epoch), $this->getCurrentUserPreferenceObject()->getStartWeekDay());
             } else {
                 $start_date = TTDate::getBeginDayEpoch($epoch);
                 $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 30 * 86400);
             }
             break;
         case 'year':
             if ($strict == TRUE) {
                 $start_date = TTDate::getBeginWeekEpoch(TTDate::getBeginMonthEpoch($epoch), $this->getCurrentUserPreferenceObject()->getStartWeekDay());
                 $end_date = TTDate::getEndWeekEpoch(TTDate::getEndMonthEpoch(TTDate::getEndMonthEpoch($epoch) + 86400 * 2), $this->getCurrentUserPreferenceObject()->getStartWeekDay());
             } else {
                 $start_date = TTDate::getBeginDayEpoch($epoch);
                 $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 62 * 86400);
             }
             break;
     }
     $retarr = array('base_date' => $epoch, 'start_date' => $start_date, 'end_date' => $end_date, 'base_display_date' => TTDate::getAPIDate('DATE', $epoch), 'start_display_date' => TTDate::getAPIDate('DATE', $start_date), 'end_display_date' => TTDate::getAPIDate('DATE', $end_date));
     Debug::Arr($retarr, 'Schedule Dates: Base Date: ' . $base_date . ' Type: ' . $type . ' Strict: ' . (int) $strict, __FILE__, __LINE__, __METHOD__, 10);
     return $retarr;
 }
 function createPayStubAmendments($epoch = NULL)
 {
     //Get all recurring pay stub amendments and generate single pay stub amendments if appropriate.
     if ($epoch == '') {
         $epoch = TTDate::getTime();
     }
     $ulf = TTnew('UserListFactory');
     Debug::text('Recurring PS Amendment ID: ' . $this->getId() . ' Frequency: ' . $this->getFrequency(), __FILE__, __LINE__, __METHOD__, 10);
     $this->StartTransaction();
     $tmp_user_ids = $this->getUser();
     if ($tmp_user_ids[0] == -1) {
         $ulf->getByCompanyIdAndStatus($this->getCompany(), 10);
         foreach ($ulf as $user_obj) {
             $user_ids[] = $user_obj->getId();
         }
         unset($user_obj);
     } else {
         $user_ids = $this->getUser();
     }
     unset($tmp_user_ids);
     Debug::text('Total User IDs: ' . count($user_ids), __FILE__, __LINE__, __METHOD__, 10);
     if (is_array($user_ids) and count($user_ids) > 0) {
         //Make the PS amendment duplicate check start/end date separate
         //Make the PS amendment effective date separate.
         switch ($this->getFrequency()) {
             case 10:
                 //Get all open pay periods
                 $pplf = TTnew('PayPeriodListFactory');
                 //FIXME: Get all non-closed pay periods AFTER the start date.
                 $pplf->getByUserIdListAndNotStatusAndStartDateAndEndDate($user_ids, 20, $this->getStartDate(), $this->getEndDate());
                 //All non-closed pay periods
                 Debug::text('Found Open Pay Periods: ' . $pplf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
                 foreach ($pplf as $pay_period_obj) {
                     Debug::text('Working on Pay Period: ' . $pay_period_obj->getId(), __FILE__, __LINE__, __METHOD__, 10);
                     //If near the end of a pay period, or a pay period is already ended, add PS amendment if
                     //it does not already exist.
                     if ($epoch >= $pay_period_obj->getEndDate() and $this->checkTimeFrame($epoch)) {
                         Debug::text('After end of pay period. Start Date: ' . TTDate::getDate('DATE+TIME', $pay_period_obj->getStartDate()) . ' End Date: ' . TTDate::getDate('DATE+TIME', $pay_period_obj->getEndDate()), __FILE__, __LINE__, __METHOD__, 10);
                         $psalf = TTnew('PayStubAmendmentListFactory');
                         //Loop through each user of this Pay Period Schedule adding PS amendments if they don't already exist.
                         $pay_period_schedule_users = $pay_period_obj->getPayPeriodScheduleObject()->getUser();
                         Debug::text(' Pay Period Schedule Users: ' . count($pay_period_schedule_users), __FILE__, __LINE__, __METHOD__, 10);
                         foreach ($pay_period_schedule_users as $user_id) {
                             //Make sure schedule user is in the PS amendment user list and user is active.
                             Debug::text(' Pay Period Schedule User: '******' Recurring PS Amendment Selected Users: ', __FILE__, __LINE__, __METHOD__,10);
                             if ($ulf->getById($user_id)->getCurrent()->getStatus() == 10 and in_array($user_id, $user_ids)) {
                                 //Check to see if the amendment was added already.
                                 if ($psalf->getByUserIdAndRecurringPayStubAmendmentIdAndStartDateAndEndDate($user_id, $this->getId(), $pay_period_obj->getStartDate(), $pay_period_obj->getEndDate())->getRecordCount() == 0) {
                                     //No amendment, good to insert one
                                     Debug::text('Inserting Recurring PS Amendment for User: '******'PayStubAmendmentFactory');
                                     $psaf->setUser($user_id);
                                     $psaf->setStatus(50);
                                     $psaf->setType($this->getType());
                                     $psaf->setRecurringPayStubAmendmentId($this->getId());
                                     $psaf->setPayStubEntryNameId($this->getPayStubEntryNameId());
                                     if ($this->getType() == 10) {
                                         $psaf->setRate($this->getRate());
                                         $psaf->setUnits($this->getUnits());
                                         $psaf->setAmount($this->getAmount());
                                     } else {
                                         $psaf->setPercentAmount($this->getPercentAmount());
                                         $psaf->setPercentAmountEntryNameID($this->getPercentAmountEntryNameId());
                                     }
                                     $psaf->setDescription($this->getPayStubAmendmentDescription());
                                     $psaf->setEffectiveDate(TTDate::getBeginDayEpoch($pay_period_obj->getEndDate()));
                                     if ($psaf->isValid()) {
                                         $psaf->Save();
                                     }
                                 } else {
                                     //Amendment already inserted!
                                     Debug::text('Recurring PS Amendment already inserted for User: '******'Skipping User because they are INACTIVE or are not on the Recurring PS Amendment User List - ID: ' . $user_id, __FILE__, __LINE__, __METHOD__, 10);
                                 //continue;
                             }
                         }
                     } else {
                         Debug::text('Not in TimeFrame, not inserting amendments: Epoch: ' . $epoch . ' Pay Period End Date: ' . $pay_period_obj->getEndDate(), __FILE__, __LINE__, __METHOD__, 10);
                     }
                 }
                 break;
             case 30:
                 //Weekly
             //Weekly
             case 40:
                 //Monthly
             //Monthly
             case 70:
                 //Annually
                 switch ($this->getFrequency()) {
                     case 30:
                         $trigger_date = TTDate::getDateOfNextDayOfWeek(TTDate::getBeginWeekEpoch($epoch), $this->getStartDate());
                         $start_date = TTDate::getBeginWeekEpoch($epoch);
                         $end_date = TTDate::getEndWeekEpoch($epoch);
                         break;
                     case 40:
                         $trigger_date = TTDate::getDateOfNextDayOfMonth(TTDate::getBeginMonthEpoch($epoch), $this->getStartDate());
                         //$monthly_date = TTDate::getDateOfNextDayOfMonth( TTDate::getBeginMonthEpoch($epoch), $this->getStartDate() );
                         $start_date = TTDate::getBeginMonthEpoch($epoch);
                         $end_date = TTDate::getEndMonthEpoch($epoch);
                         break;
                     case 70:
                         $trigger_date = TTDate::getDateOfNextYear($this->getStartDate(), $epoch);
                         //$start_date = TTDate::getBeginYearEpoch($epoch);
                         //$end_date = TTDate::getEndYearEpoch($epoch);
                         $start_date = TTDate::getBeginDayEpoch($epoch - 86400 * 365);
                         $end_date = TTDate::getEndDayEpoch($epoch);
                         break;
                 }
                 Debug::text('Trigger Date: ' . TTDate::getDate('DATE', $trigger_date), __FILE__, __LINE__, __METHOD__, 10);
                 if ($epoch >= $trigger_date and $this->checkTimeFrame($epoch)) {
                     Debug::text('Within timeframe... Start Date: ' . TTDate::getDate('DATE+TIME', $start_date) . ' End Date: ' . TTDate::getDate('DATE+TIME', $end_date), __FILE__, __LINE__, __METHOD__, 10);
                     foreach ($user_ids as $user_id) {
                         //Make sure schedule user is in the PS amendment user list and user is active.
                         if ($ulf->getById($user_id)->getCurrent()->getStatus() != 10 and !in_array($user_id, $user_ids)) {
                             Debug::text('Skipping User because they are INACTIVE or are not on the Recurring PS Amendment User List - ID: ' . $user_id, __FILE__, __LINE__, __METHOD__, 10);
                             continue;
                         }
                         $psalf = TTnew('PayStubAmendmentListFactory');
                         if ($psalf->getByUserIdAndRecurringPayStubAmendmentIdAndStartDateAndEndDate($user_id, $this->getId(), $start_date, $end_date)->getRecordCount() == 0) {
                             //No amendment, good to insert one
                             Debug::text('Inserting Recurring PS Amendment for User: '******'PayStubAmendmentFactory');
                             $psaf->setUser($user_id);
                             $psaf->setStatus(50);
                             $psaf->setType($this->getType());
                             $psaf->setRecurringPayStubAmendmentId($this->getId());
                             $psaf->setPayStubEntryNameId($this->getPayStubEntryNameId());
                             if ($this->getType() == 10) {
                                 $psaf->setRate($this->getRate());
                                 $psaf->setUnits($this->getUnits());
                                 $psaf->setAmount($this->getAmount());
                             } else {
                                 $psaf->setPercentAmount($this->getPercentAmount());
                                 $psaf->setPercentAmountEntryNameID($this->getPercentAmountEntryNameId());
                             }
                             $psaf->setDescription($this->getDescription());
                             $psaf->setEffectiveDate(TTDate::getBeginDayEpoch($trigger_date));
                             if ($psaf->isValid()) {
                                 $psaf->Save();
                             }
                         } else {
                             //Amendment already inserted!
                             Debug::text('Recurring PS Amendment already inserted for User: ' . $user_id, __FILE__, __LINE__, __METHOD__, 10);
                         }
                     }
                 }
                 break;
         }
     }
     //$this->FailTransaction();
     $this->CommitTransaction();
     return TRUE;
 }
Exemple #5
0
 function generateData()
 {
     global $current_company, $current_user;
     TTDate::setTimeZone('PST8PDT');
     $current_epoch = time();
     $cf = TTnew('CompanyFactory');
     $cf->StartTransaction();
     $company_id = $this->createCompany();
     $clf = TTnew('CompanyListFactory');
     $clf->getById($company_id);
     $current_company = $clf->getCurrent();
     if ($company_id !== FALSE) {
         Debug::Text('Company Created Successfully!', __FILE__, __LINE__, __METHOD__, 10);
         $this->createPermissionGroups($company_id);
         //Create currency
         $currency_ids[] = $this->createCurrency($company_id, 10);
         //USD
         $currency_ids[] = $this->createCurrency($company_id, 20);
         //CAD
         $currency_ids[] = $this->createCurrency($company_id, 30);
         //EUR
         //Create branch
         $branch_ids[] = $this->createBranch($company_id, 10);
         //NY
         $branch_ids[] = $this->createBranch($company_id, 20);
         //WA
         //Create departments
         $department_ids[] = $this->createDepartment($company_id, 10);
         $department_ids[] = $this->createDepartment($company_id, 20);
         $department_ids[] = $this->createDepartment($company_id, 30);
         $department_ids[] = $this->createDepartment($company_id, 40);
         //Create stations
         $station_id = $this->createStation($company_id);
         //Create pay stub accounts.
         $this->createPayStubAccount($company_id);
         //Link pay stub accounts.
         $this->createPayStubAccountLink($company_id);
         //Company Deductions
         $this->createCompanyDeduction($company_id);
         //Wage Groups
         $wage_group_ids[] = $this->createUserWageGroups($company_id);
         //User Groups
         $user_group_ids[] = $this->createUserGroup($company_id, 10, 0);
         $user_group_ids[] = $this->createUserGroup($company_id, 20, $user_group_ids[0]);
         $user_group_ids[] = $this->createUserGroup($company_id, 30, $user_group_ids[0]);
         $user_group_ids[] = $this->createUserGroup($company_id, 40, 0);
         $user_group_ids[] = $this->createUserGroup($company_id, 50, $user_group_ids[3]);
         //User Title
         $user_title_ids[] = $this->createUserTitle($company_id, 10);
         $user_title_ids[] = $this->createUserTitle($company_id, 20);
         $user_title_ids[] = $this->createUserTitle($company_id, 30);
         $user_title_ids[] = $this->createUserTitle($company_id, 40);
         $user_title_ids[] = $this->createUserTitle($company_id, 50);
         $user_title_ids[] = $this->createUserTitle($company_id, 60);
         $user_title_ids[] = $this->createUserTitle($company_id, 70);
         $user_title_ids[] = $this->createUserTitle($company_id, 80);
         $user_title_ids[] = $this->createUserTitle($company_id, 90);
         //Ethnic Group
         $ethnic_group_ids[] = $this->createEthnicGroup($company_id, 10);
         $ethnic_group_ids[] = $this->createEthnicGroup($company_id, 20);
         $ethnic_group_ids[] = $this->createEthnicGroup($company_id, 30);
         $ethnic_group_ids[] = $this->createEthnicGroup($company_id, 40);
         $ethnic_group_ids[] = $this->createEthnicGroup($company_id, 50);
         //Users
         $user_ids[] = $this->createUser($company_id, 10, 0, $branch_ids[0], $department_ids[0], $currency_ids[0], $user_group_ids[0], $user_title_ids[0], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 11, 0, $branch_ids[0], $department_ids[1], $currency_ids[0], $user_group_ids[0], $user_title_ids[0], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 12, 0, $branch_ids[0], $department_ids[1], $currency_ids[0], $user_group_ids[0], $user_title_ids[0], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 13, 0, $branch_ids[0], $department_ids[1], $currency_ids[0], $user_group_ids[0], $user_title_ids[0], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 14, 0, $branch_ids[0], $department_ids[1], $currency_ids[1], $user_group_ids[1], $user_title_ids[1], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 15, 0, $branch_ids[0], $department_ids[0], $currency_ids[1], $user_group_ids[1], $user_title_ids[1], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 16, 0, $branch_ids[0], $department_ids[1], $currency_ids[0], $user_group_ids[1], $user_title_ids[1], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 17, 0, $branch_ids[0], $department_ids[1], $currency_ids[0], $user_group_ids[1], $user_title_ids[1], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 18, 0, $branch_ids[0], $department_ids[0], $currency_ids[0], $user_group_ids[2], $user_title_ids[2], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 19, 0, $branch_ids[0], $department_ids[1], $currency_ids[2], $user_group_ids[2], $user_title_ids[2], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 20, 0, $branch_ids[0], $department_ids[1], $currency_ids[2], $user_group_ids[2], $user_title_ids[2], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 21, 0, $branch_ids[1], $department_ids[1], $currency_ids[0], $user_group_ids[3], $user_title_ids[3], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 22, 0, $branch_ids[1], $department_ids[1], $currency_ids[0], $user_group_ids[3], $user_title_ids[3], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 23, 0, $branch_ids[1], $department_ids[2], $currency_ids[0], $user_group_ids[3], $user_title_ids[3], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 24, 0, $branch_ids[1], $department_ids[2], $currency_ids[0], $user_group_ids[3], $user_title_ids[3], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 25, 0, $branch_ids[1], $department_ids[2], $currency_ids[0], $user_group_ids[4], $user_title_ids[4], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 26, 0, $branch_ids[1], $department_ids[1], $currency_ids[0], $user_group_ids[4], $user_title_ids[4], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 27, 0, $branch_ids[1], $department_ids[3], $currency_ids[0], $user_group_ids[4], $user_title_ids[4], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 28, 0, $branch_ids[1], $department_ids[3], $currency_ids[0], $user_group_ids[4], $user_title_ids[4], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 29, 0, $branch_ids[1], $department_ids[3], $currency_ids[0], $user_group_ids[4], $user_title_ids[4], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 30, 0, $branch_ids[1], $department_ids[0], $currency_ids[0], $user_group_ids[4], $user_title_ids[4], $ethnic_group_ids);
         $user_ids[] = $this->createUser($company_id, 40, 0, $branch_ids[1], $department_ids[0], $currency_ids[0], $user_group_ids[4], $user_title_ids[4], $ethnic_group_ids);
         $current_user_id = $user_ids[] = $this->createUser($company_id, 100, 0, $branch_ids[0], $department_ids[0], $currency_ids[0], $user_group_ids[4], $user_title_ids[0], $ethnic_group_ids);
         //Create random users.
         for ($i = 0; $i <= $this->getMaxRandomUsers(); $i++) {
             $tmp_user_id = $this->createUser($company_id, 999, 0, $branch_ids[$i % 2], $department_ids[$i % 4], $currency_ids[0], $user_group_ids[$i % 5], $user_title_ids[$i % 9], $ethnic_group_ids);
             if ($tmp_user_id != FALSE) {
                 $user_ids[] = $tmp_user_id;
             }
         }
         Debug::Arr($user_ids, 'All User IDs:', __FILE__, __LINE__, __METHOD__, 10);
         $ulf = TTnew('UserListFactory');
         $ulf->getById($current_user_id);
         $current_user = $ulf->getCurrent();
         if ($current_user_id === FALSE) {
             Debug::Text('Administrator user wasn\'t created! Duplicate username perhaps? Are we appending a random number?', __FILE__, __LINE__, __METHOD__, 10);
             return FALSE;
         }
         unset($current_user_id);
         //Create policies
         $policy_ids['round'][] = $this->createRoundingPolicy($company_id, 10);
         //In
         $policy_ids['round'][] = $this->createRoundingPolicy($company_id, 20);
         //Out
         $policy_ids['accrual'][] = $this->createAccrualPolicy($company_id, 10);
         //Bank Time
         $policy_ids['accrual'][] = $this->createAccrualPolicy($company_id, 20);
         //Vacaction
         $policy_ids['accrual'][] = $this->createAccrualPolicy($company_id, 30);
         //Sick
         $policy_ids['overtime'][] = $this->createOverTimePolicy($company_id, 10);
         $policy_ids['overtime'][] = $this->createOverTimePolicy($company_id, 20, $policy_ids['accrual'][0]);
         if (getTTProductEdition() >= TT_PRODUCT_ENTERPRISE) {
             $policy_ids['expense'][] = $this->createExpensePolicy($company_id, 100);
             // Tax(Percent) - HST
             $policy_ids['expense'][] = $this->createExpensePolicy($company_id, 110);
             // Tax(Percent) - VAT
             $policy_ids['expense'][] = $this->createExpensePolicy($company_id, 120);
             // Tax(Flat Amount) - Improvement Fee
             $policy_ids['expense'][] = $this->createExpensePolicy($company_id, 10, array($policy_ids['expense'][1]));
             // Flat Amount
             $policy_ids['expense'][] = $this->createExpensePolicy($company_id, 20, array($policy_ids['expense'][0], $policy_ids['expense'][1]));
             // Percent
             $policy_ids['expense'][] = $this->createExpensePolicy($company_id, 30);
             // Per Unit - No Tax
             $policy_ids['expense'][] = $this->createExpensePolicy($company_id, 40, array($policy_ids['expense'][0], $policy_ids['expense'][2]));
             // Flat Amount
         }
         $policy_ids['premium'][] = $this->createPremiumPolicy($company_id, 10);
         $policy_ids['absence'][] = $this->createAbsencePolicy($company_id, 10, $policy_ids['accrual'][1]);
         $policy_ids['absence'][] = $this->createAbsencePolicy($company_id, 20, $policy_ids['accrual'][0]);
         $policy_ids['absence'][] = $this->createAbsencePolicy($company_id, 30, $policy_ids['accrual'][2]);
         $policy_ids['meal_1'] = $this->createMealPolicy($company_id);
         $policy_ids['schedule_1'] = $this->createSchedulePolicy($company_id, $policy_ids['meal_1']);
         $policy_ids['exception_1'] = $this->createExceptionPolicy($company_id);
         $hierarchy_user_ids = $user_ids;
         $root_user_id = array_pop($hierarchy_user_ids);
         unset($hierarchy_user_ids[0], $hierarchy_user_ids[1]);
         //Create authorization hierarchy
         $hierarchy_control_id = $this->createAuthorizationHierarchyControl($company_id, $hierarchy_user_ids);
         if ($root_user_id == FALSE) {
             Debug::Text('Administrator wasn\'t created! Duplicate username perhaps? Are we appending a random number?', __FILE__, __LINE__, __METHOD__, 10);
             return FALSE;
         }
         //Admin user at the top
         $this->createAuthorizationHierarchyLevel($company_id, $hierarchy_control_id, $root_user_id, 1);
         $this->createAuthorizationHierarchyLevel($company_id, $hierarchy_control_id, $user_ids[0], 2);
         $this->createAuthorizationHierarchyLevel($company_id, $hierarchy_control_id, $user_ids[1], 3);
         unset($hierarchy_user_ids, $root_user_id);
         //Pay Period Schedule
         $this->createPayPeriodSchedule($company_id, $user_ids);
         //Create Policy Group
         $this->createPolicyGroup($company_id, $policy_ids['meal_1'], $policy_ids['exception_1'], NULL, $policy_ids['overtime'], $policy_ids['premium'], $policy_ids['round'], $user_ids, NULL, NULL, $policy_ids['expense'], $policy_ids['absence']);
         if (getTTProductEdition() >= TT_PRODUCT_CORPORATE) {
             //Client Groups
             $client_group_ids[] = $this->createClientGroup($company_id, 10, 0);
             $client_group_ids[] = $this->createClientGroup($company_id, 20, $client_group_ids[0]);
             $client_group_ids[] = $this->createClientGroup($company_id, 30, $client_group_ids[0]);
             $client_group_ids[] = $this->createClientGroup($company_id, 40, 0);
             $client_group_ids[] = $this->createClientGroup($company_id, 50, $client_group_ids[3]);
             $product_group_ids[] = $this->createProductGroup($company_id, 10, 0);
             $product_group_ids[] = $this->createProductGroup($company_id, 20, 0);
             $product_group_ids[] = $this->createProductGroup($company_id, 30, $product_group_ids[1]);
             $product_group_ids[] = $this->createProductGroup($company_id, 40, $product_group_ids[2]);
             $product_group_ids[] = $this->createProductGroup($company_id, 50, $product_group_ids[1]);
             //Create at least 10 Clients
             $client_ids[] = $this->createClient($company_id, 10, $user_ids, $client_group_ids);
             $client_ids[] = $this->createClient($company_id, 20, $user_ids, $client_group_ids);
             $client_ids[] = $this->createClient($company_id, 30, $user_ids, $client_group_ids);
             $client_ids[] = $this->createClient($company_id, 40, $user_ids, $client_group_ids);
             $client_ids[] = $this->createClient($company_id, 50, $user_ids, $client_group_ids);
             $client_ids[] = $this->createClient($company_id, 60, $user_ids, $client_group_ids);
             $client_ids[] = $this->createClient($company_id, 70, $user_ids, $client_group_ids);
             $client_ids[] = $this->createClient($company_id, 80, $user_ids, $client_group_ids);
             //Create Invoice District
             $invoice_district_ids[] = $this->createInvoiceDistrict($company_id, 10);
             //US
             $invoice_district_ids[] = $this->createInvoiceDistrict($company_id, 20);
             //US
             $invoice_district_ids[] = $this->createInvoiceDistrict($company_id, 30);
             //CA
             $invoice_district_ids[] = $this->createInvoiceDistrict($company_id, 40);
             //CA
             //Create Client Contact, Each client should have at least two client contacts.
             foreach ($client_ids as $client_id) {
                 $client_contact_ids[] = $this->createClientContact($client_id, 10, $invoice_district_ids, $currency_ids[0]);
                 $client_contact_ids[] = $this->createClientContact($client_id, 20, $invoice_district_ids, $currency_ids[0]);
             }
             $product_ids[10][] = $this->createProduct($company_id, $product_group_ids, 10, $currency_ids[0]);
             $product_ids[10][] = $this->createProduct($company_id, $product_group_ids, 20, $currency_ids[0]);
             $product_ids[10][] = $this->createProduct($company_id, $product_group_ids, 30, $currency_ids[0]);
             $product_ids[10][] = $this->createProduct($company_id, $product_group_ids, 40, $currency_ids[0]);
             $product_ids[10][] = $this->createProduct($company_id, $product_group_ids, 50, $currency_ids[0]);
             $product_ids[20][] = $this->createProduct($company_id, $product_group_ids, 60, $currency_ids[0]);
             $product_ids[30][] = $this->createProduct($company_id, $product_group_ids, 70, $currency_ids[0]);
             $product_ids[40][] = $this->createProduct($company_id, $product_group_ids, 80, $currency_ids[0]);
             $product_ids[50][] = $this->createProduct($company_id, $product_group_ids, 90, $currency_ids[0]);
             $area_policy_ids[] = $this->createAreaPolicy($company_id, 20, array($invoice_district_ids[0], $invoice_district_ids[1]));
             $area_policy_ids[] = $this->createAreaPolicy($company_id, 10, array($invoice_district_ids[2], $invoice_district_ids[3]));
             $tax_policy_ids[] = $this->createTaxPolicy($company_id, $product_ids[30][0], $area_policy_ids);
             //Create Shipping Policy
             $shipping_policy_ids[] = $this->createShippingPolicy($company_id, $product_ids[40][0], 10, $currency_ids[0], $area_policy_ids);
             $shipping_policy_ids[] = $this->createShippingPolicy($company_id, $product_ids[40][0], 20, $currency_ids[0], $area_policy_ids);
             //Create Invoice
             foreach ($client_ids as $client_id) {
                 $invoice_ids[] = $this->createInvoice($company_id, $client_id, $currency_ids[0], $product_ids[20][0], 100, array(), $user_ids, $shipping_policy_ids);
                 $invoice_ids[] = $this->createInvoice($company_id, $client_id, $currency_ids[0], array($product_ids[10][0], $product_ids[10][1], $product_ids[10][2], $product_ids[10][3], $product_ids[10][4], $product_ids[20][0]), 40, NULL, $user_ids, $shipping_policy_ids);
                 $invoice_ids[] = $this->createInvoice($company_id, $client_id, $currency_ids[0], array($product_ids[10][1], $product_ids[10][2], $product_ids[10][3]), 40, NULL, $user_ids, $shipping_policy_ids);
                 $invoice_ids[] = $this->createInvoice($company_id, $client_id, $currency_ids[0], array($product_ids[10][0], $product_ids[10][4], $product_ids[20][0]), 100, array(), $user_ids, $shipping_policy_ids);
                 $invoice_ids[] = $this->createInvoice($company_id, $client_id, $currency_ids[0], array($product_ids[10][3], $product_ids[10][4]), 100, array(), $user_ids, $shipping_policy_ids);
             }
         } else {
             $client_group_ids[] = 0;
             $product_group_ids[] = 0;
             $client_ids[] = 0;
             $invoice_district_ids[] = 0;
             $client_contact_ids[] = 0;
             $product_ids[10] = 0;
             $product_ids[20] = 0;
             $product_ids[30] = 0;
             $product_ids[40] = 0;
             $product_ids[50] = 0;
             $area_policy_ids[] = 0;
             $tax_policy_ids[] = 0;
             $shipping_policy_ids[] = 0;
             $invoice_ids[] = 0;
         }
         if (getTTProductEdition() >= TT_PRODUCT_CORPORATE) {
             //Task Groups
             $task_group_ids[] = $this->createTaskGroup($company_id, 10, 0);
             $task_group_ids[] = $this->createTaskGroup($company_id, 20, $task_group_ids[0]);
             $task_group_ids[] = $this->createTaskGroup($company_id, 30, $task_group_ids[0]);
             $task_group_ids[] = $this->createTaskGroup($company_id, 40, 0);
             $task_group_ids[] = $this->createTaskGroup($company_id, 50, $task_group_ids[3]);
             $task_group_ids[] = $this->createTaskGroup($company_id, 60, $task_group_ids[3]);
             //Job Tasks
             $default_task_id = $this->createTask($company_id, 10, $task_group_ids[2]);
             $task_ids[] = $this->createTask($company_id, 20, $task_group_ids[1]);
             $task_ids[] = $this->createTask($company_id, 30, $task_group_ids[1]);
             $task_ids[] = $this->createTask($company_id, 40, $task_group_ids[2]);
             $task_ids[] = $this->createTask($company_id, 50, $task_group_ids[4]);
             $task_ids[] = $this->createTask($company_id, 60, $task_group_ids[4]);
             $task_ids[] = $this->createTask($company_id, 70, $task_group_ids[5]);
             //Job Groups
             $job_group_ids[] = $this->createJobGroup($company_id, 10, 0);
             $job_group_ids[] = $this->createJobGroup($company_id, 20, $job_group_ids[0]);
             $job_group_ids[] = $this->createJobGroup($company_id, 30, $job_group_ids[0]);
             $job_group_ids[] = $this->createJobGroup($company_id, 40, 0);
             $job_group_ids[] = $this->createJobGroup($company_id, 50, $job_group_ids[3]);
             $job_group_ids[] = $this->createJobGroup($company_id, 60, $job_group_ids[3]);
             //Jobs
             $job_ids[] = $this->createJob($company_id, 10, $default_task_id, $job_group_ids[1], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 11, $default_task_id, $job_group_ids[1], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 12, $default_task_id, $job_group_ids[1], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 13, $default_task_id, $job_group_ids[1], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 14, $default_task_id, $job_group_ids[1], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 15, $default_task_id, $job_group_ids[2], $branch_ids[1], $department_ids[1]);
             $job_ids[] = $this->createJob($company_id, 16, $default_task_id, $job_group_ids[2], $branch_ids[1], $department_ids[1]);
             $job_ids[] = $this->createJob($company_id, 17, $default_task_id, $job_group_ids[2], $branch_ids[1], $department_ids[1]);
             $job_ids[] = $this->createJob($company_id, 18, $default_task_id, $job_group_ids[2], $branch_ids[1], $department_ids[1]);
             $job_ids[] = $this->createJob($company_id, 19, $default_task_id, $job_group_ids[2], $branch_ids[1], $department_ids[1]);
             $job_ids[] = $this->createJob($company_id, 20, $default_task_id, $job_group_ids[4], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 21, $default_task_id, $job_group_ids[4], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 22, $default_task_id, $job_group_ids[4], $branch_ids[0], $department_ids[0]);
             $job_ids[] = $this->createJob($company_id, 23, $default_task_id, $job_group_ids[5], $branch_ids[1], $department_ids[1]);
             $job_ids[] = $this->createJob($company_id, 24, $default_task_id, $job_group_ids[5], $branch_ids[1], $department_ids[1]);
             $job_ids[] = $this->createJob($company_id, 25, $default_task_id, $job_group_ids[5], $branch_ids[1], $department_ids[1]);
         } else {
             $task_ids[] = 0;
             $job_ids[] = 0;
         }
         if (getTTProductEdition() >= TT_PRODUCT_ENTERPRISE) {
             $user_expense_ids[] = $this->createUserExpense($user_ids[0], $policy_ids['expense'][3], $branch_ids[0], $department_ids[1], $currency_ids[0], $job_ids[1], $task_ids[1]);
             $user_expense_ids[] = $this->createUserExpense($user_ids[3], $policy_ids['expense'][3], $branch_ids[0], $department_ids[2], $currency_ids[1], $job_ids[1], $task_ids[0]);
             $user_expense_ids[] = $this->createUserExpense($user_ids[4], $policy_ids['expense'][3], $branch_ids[0], $department_ids[0], $currency_ids[0], $job_ids[1], $task_ids[2]);
             $user_expense_ids[] = $this->createUserExpense($user_ids[5], $policy_ids['expense'][3], $branch_ids[0], $department_ids[0], $currency_ids[0], $job_ids[2], $task_ids[2]);
             $user_expense_ids[] = $this->createUserExpense($user_ids[6], $policy_ids['expense'][3], $branch_ids[0], $department_ids[0], $currency_ids[0], $job_ids[2], $task_ids[2]);
             $user_expense_ids[] = $this->createUserExpense($user_ids[7], $policy_ids['expense'][3], $branch_ids[0], $department_ids[0], $currency_ids[0], $job_ids[2], $task_ids[2]);
             $user_expense_ids[] = $this->createUserExpense($user_ids[8], $policy_ids['expense'][3], $branch_ids[0], $department_ids[0], $currency_ids[0], $job_ids[3], $task_ids[1]);
             $user_expense_ids[] = $this->createUserExpense($user_ids[9], $policy_ids['expense'][3], $branch_ids[1], $department_ids[0], $currency_ids[0], $job_ids[4], $task_ids[1]);
             $user_expense_ids[] = $this->createUserExpense($user_ids[10], $policy_ids['expense'][3], $branch_ids[1], $department_ids[1], $currency_ids[0], $job_ids[4], $task_ids[1]);
             $user_expense_ids[] = $this->createUserExpense($user_ids[11], $policy_ids['expense'][3], $branch_ids[1], $department_ids[1], $currency_ids[0], $job_ids[5], $task_ids[0]);
             $user_expense_ids[] = $this->createUserExpense($user_ids[12], $policy_ids['expense'][4], $branch_ids[1], $department_ids[1], $currency_ids[0], $job_ids[6], $task_ids[0]);
             $user_expense_ids[] = $this->createUserExpense($user_ids[13], $policy_ids['expense'][4], $branch_ids[1], $department_ids[2], $currency_ids[0], $job_ids[7], $task_ids[0]);
             $user_expense_ids[] = $this->createUserExpense($user_ids[14], $policy_ids['expense'][4], $branch_ids[1], $department_ids[2], $currency_ids[0], $job_ids[7], $task_ids[4]);
             $user_expense_ids[] = $this->createUserExpense($user_ids[15], $policy_ids['expense'][4], $branch_ids[1], $department_ids[2], $currency_ids[0], $job_ids[8], $task_ids[4]);
             $user_expense_ids[] = $this->createUserExpense($user_ids[16], $policy_ids['expense'][4], $branch_ids[1], $department_ids[3], $currency_ids[0], $job_ids[8], $task_ids[4], NULL, 50);
             $user_expense_ids[] = $this->createUserExpense($user_ids[17], $policy_ids['expense'][4], $branch_ids[1], $department_ids[3], $currency_ids[0], $job_ids[9], $task_ids[1], NULL, 50);
             $user_expense_ids[] = $this->createUserExpense($user_ids[18], $policy_ids['expense'][4], $branch_ids[1], $department_ids[3], $currency_ids[0], $job_ids[10], $task_ids[3], NULL, 50);
             $user_expense_ids[] = $this->createUserExpense($user_ids[19], $policy_ids['expense'][4], $branch_ids[1], $department_ids[3], $currency_ids[0], $job_ids[0], $task_ids[3], NULL, 50);
             $user_expense_ids[] = $this->createUserExpense($user_ids[20], $policy_ids['expense'][4], $branch_ids[1], $department_ids[3], $currency_ids[0], $job_ids[0], $task_ids[3], NULL, 50);
         } else {
             $user_expense_ids[] = 0;
         }
         //Create Qualification
         $qualification_group_ids[] = $this->createQualificationGroup($company_id, 10, 0);
         $qualification_group_ids[] = $this->createQualificationGroup($company_id, 20, 0);
         $qualification_group_ids[] = $this->createQualificationGroup($company_id, 30, 0);
         $qualification_group_ids[] = $this->createQualificationGroup($company_id, 40, 0);
         $qualification_group_ids[] = $this->createQualificationGroup($company_id, 50, 0);
         //Create Accrual balances
         foreach ($user_ids as $user_id) {
             foreach ($policy_ids['accrual'] as $accrual_policy_id) {
                 $this->createAccrualBalance($user_id, $accrual_policy_id);
             }
             unset($accrual_policy_id);
         }
         // Create Qualification
         $qualification_ids['skill'][] = $this->createQualification($company_id, 10, $qualification_group_ids[0]);
         $qualification_ids['skill'][] = $this->createQualification($company_id, 20, $qualification_group_ids[1]);
         $qualification_ids['skill'][] = $this->createQualification($company_id, 40, $qualification_group_ids[2]);
         $qualification_ids['skill'][] = $this->createQualification($company_id, 50, $qualification_group_ids[3]);
         $qualification_ids['skill'][] = $this->createQualification($company_id, 60, $qualification_group_ids[0]);
         $qualification_ids['license'][] = $this->createQualification($company_id, 200, $qualification_group_ids[0]);
         $qualification_ids['license'][] = $this->createQualification($company_id, 210, $qualification_group_ids[1]);
         $qualification_ids['license'][] = $this->createQualification($company_id, 220, $qualification_group_ids[1]);
         $qualification_ids['license'][] = $this->createQualification($company_id, 230, $qualification_group_ids[2]);
         $qualification_ids['license'][] = $this->createQualification($company_id, 240, $qualification_group_ids[4]);
         $qualification_ids['education'][] = $this->createQualification($company_id, 310, $qualification_group_ids[4]);
         $qualification_ids['education'][] = $this->createQualification($company_id, 320, $qualification_group_ids[2]);
         $qualification_ids['education'][] = $this->createQualification($company_id, 330, $qualification_group_ids[3]);
         $qualification_ids['education'][] = $this->createQualification($company_id, 340, $qualification_group_ids[2]);
         $qualification_ids['education'][] = $this->createQualification($company_id, 350, $qualification_group_ids[1]);
         $qualification_ids['language'][] = $this->createQualification($company_id, 400, $qualification_group_ids[0]);
         $qualification_ids['language'][] = $this->createQualification($company_id, 410, $qualification_group_ids[1]);
         $qualification_ids['language'][] = $this->createQualification($company_id, 420, $qualification_group_ids[3]);
         $qualification_ids['membership'][] = $this->createQualification($company_id, 500, $qualification_group_ids[0]);
         $qualification_ids['membership'][] = $this->createQualification($company_id, 510, $qualification_group_ids[1]);
         $qualification_ids['membership'][] = $this->createQualification($company_id, 520, $qualification_group_ids[2]);
         $qualification_ids['membership'][] = $this->createQualification($company_id, 530, $qualification_group_ids[3]);
         $kpi_group_ids[] = $this->createKPIGroup($company_id, 10, 0);
         $kpi_group_ids[] = $this->createKPIGroup($company_id, 20, 0);
         $kpi_group_ids[] = $this->createKPIGroup($company_id, 30, 0);
         $kpi_group_ids[] = $this->createKPIGroup($company_id, 40, 0);
         $kpi_group_ids[] = $this->createKPIGroup($company_id, 50, 0);
         $kpi_all_ids[]['10'] = $this->createKPI($company_id, 10, 10, array(-1));
         $kpi_all_ids[]['10'] = $this->createKPI($company_id, 20, 10, array(-1));
         $kpi_all_ids[]['20'] = $this->createKPI($company_id, 30, 20, array(-1));
         $kpi_group1_ids[]['20'] = $this->createKPI($company_id, 40, 20, array($kpi_group_ids[0]));
         $kpi_group1_ids[]['10'] = $this->createKPI($company_id, 50, 10, array($kpi_group_ids[0]));
         $kpi_group2_ids[]['30'] = $this->createKPI($company_id, 60, 30, array($kpi_group_ids[1]));
         $kpi_group2_ids[]['30'] = $this->createKPI($company_id, 70, 30, array($kpi_group_ids[1]));
         foreach ($user_ids as $code => $user_id) {
             $reviewer_user_ids = $user_ids;
             unset($reviewer_user_ids[$code]);
             $reviewer_user_ids = array_values($reviewer_user_ids);
             $reviewer_user_random_ids = array_rand($reviewer_user_ids, 3);
             $user_review_control_id = $this->createUserReviewControl($user_id, $reviewer_user_ids[array_rand($reviewer_user_random_ids)]);
             if ($user_review_control_id != '') {
                 foreach ($kpi_all_ids as $kpi_all_id) {
                     foreach ($kpi_all_id as $code => $kpi_id) {
                         $this->createUserReview($user_review_control_id, $code, $kpi_id);
                     }
                 }
                 $group_id = rand(1, 2);
                 switch ($group_id) {
                     case 1:
                         foreach ($kpi_group1_ids as $kpi_group1_id) {
                             foreach ($kpi_group1_id as $code => $kpi_id) {
                                 $this->createUserReview($user_review_control_id, $code, $kpi_id);
                             }
                         }
                         break;
                     case 2:
                         foreach ($kpi_group2_ids as $kpi_group2_id) {
                             foreach ($kpi_group2_id as $code => $kpi_id) {
                                 $this->createUserReview($user_review_control_id, $code, $kpi_id);
                             }
                         }
                         break;
                 }
             }
         }
         //Create Qualification , Skills , Education ,Language , Lencense , Membership
         $x = 1;
         foreach ($user_ids as $user_id) {
             $type = $x * 10;
             $rand_arr_ids = array(1, 2, 3, 4, 5);
             $rand_ids = array_rand($rand_arr_ids, rand(3, 5));
             foreach ($rand_ids as $rand_id) {
                 switch ($rand_arr_ids[$rand_id]) {
                     case 1:
                         $this->createUserSkill($user_id, $type, $qualification_ids['skill'][rand(0, count($qualification_ids['skill']) - 1)]);
                         break;
                     case 2:
                         $this->createUserEducation($user_id, $qualification_ids['education'][rand(0, count($qualification_ids['education']) - 1)]);
                         break;
                     case 3:
                         $this->createUserLicense($user_id, $qualification_ids['license'][rand(0, count($qualification_ids['license']) - 1)]);
                         break;
                     case 4:
                         $this->createUserLanguage($user_id, $type, $qualification_ids['language'][rand(0, count($qualification_ids['language']) - 1)]);
                         break;
                     case 5:
                         $this->createUserMembership($user_id, $type, $qualification_ids['membership'][rand(0, count($qualification_ids['membership']) - 1)]);
                         break;
                 }
             }
             $x++;
         }
         foreach ($user_ids as $user_id) {
             $x = 1;
             while ($x <= 5) {
                 $this->createUserContact($user_id);
                 $x++;
             }
         }
         if (getTTProductEdition() >= TT_PRODUCT_ENTERPRISE) {
             $x = 1;
             while ($x <= 9) {
                 $interviewer_random_user_ids = array_rand($user_ids, 3);
                 $user_id = $user_ids[array_rand($interviewer_random_user_ids)];
                 $job_vacancy_id = $this->createJobVacancy($company_id, $user_id, $user_title_ids[rand(0, count($user_title_ids) - 1)], $branch_ids[rand(0, count($branch_ids) - 1)], $department_ids[rand(0, count($department_ids) - 1)]);
                 if ($job_vacancy_id != '') {
                     $job_applicant_id = $this->createJobApplicant($company_id);
                     $y = 1;
                     while ($y <= rand(75, 150)) {
                         $this->createJobApplication($job_applicant_id, $job_vacancy_id, $user_id);
                         $y++;
                     }
                     $n = 1;
                     while ($n <= rand(2, 5)) {
                         $this->createJobApplicantLocation($job_applicant_id);
                         $this->createJobApplicantEmployment($job_applicant_id, $n * 10);
                         $this->createJobApplicantReference($job_applicant_id);
                         $this->createJobApplicantSkill($job_applicant_id, $qualification_ids['skill'][rand(0, count($qualification_ids['skill']) - 1)]);
                         $this->createJobApplicantEducation($job_applicant_id, $qualification_ids['education'][rand(0, count($qualification_ids['education']) - 1)]);
                         $this->createJobApplicantLicense($job_applicant_id, $qualification_ids['license'][rand(0, count($qualification_ids['license']) - 1)]);
                         $this->createJobApplicantLanguage($job_applicant_id, $qualification_ids['language'][rand(0, count($qualification_ids['language']) - 1)]);
                         $this->createJobApplicantMembership($job_applicant_id, $qualification_ids['membership'][rand(0, count($qualification_ids['membership']) - 1)], $currency_ids[0]);
                         $n++;
                     }
                 }
                 $x++;
             }
         }
         //Create recurring schedule templates
         $recurring_schedule_ids[] = $this->createRecurringScheduleTemplate($company_id, 10, $policy_ids['schedule_1']);
         //Morning shift
         $recurring_schedule_ids[] = $this->createRecurringScheduleTemplate($company_id, 20, $policy_ids['schedule_1']);
         //Afternoon shift
         $recurring_schedule_ids[] = $this->createRecurringScheduleTemplate($company_id, 30, $policy_ids['schedule_1']);
         //Evening shift
         $recurring_schedule_ids[] = $this->createRecurringScheduleTemplate($company_id, 40);
         //Split Shift
         $recurring_schedule_ids[] = $this->createRecurringScheduleTemplate($company_id, 50, $policy_ids['schedule_1']);
         //Full rotation
         $recurring_schedule_start_date = TTDate::getBeginWeekEpoch($current_epoch + 86400 * 7.5);
         $this->createRecurringSchedule($company_id, $recurring_schedule_ids[0], $recurring_schedule_start_date, '', array($user_ids[0], $user_ids[1], $user_ids[2], $user_ids[3], $user_ids[4]));
         $this->createRecurringSchedule($company_id, $recurring_schedule_ids[1], $recurring_schedule_start_date, '', array($user_ids[5], $user_ids[6], $user_ids[7], $user_ids[8], $user_ids[9]));
         $this->createRecurringSchedule($company_id, $recurring_schedule_ids[2], $recurring_schedule_start_date, '', array($user_ids[10], $user_ids[11], $user_ids[12], $user_ids[13], $user_ids[14]));
         //Create different schedule shifts.
         $schedule_options_arr = array(array('status_id' => 10, 'start_time' => '06:00AM', 'end_time' => '03:00PM', 'schedule_policy_id' => $policy_ids['schedule_1']), array('status_id' => 10, 'start_time' => '10:00AM', 'end_time' => '07:00PM', 'schedule_policy_id' => $policy_ids['schedule_1']), array('status_id' => 10, 'start_time' => '2:00PM', 'end_time' => '11:00PM', 'schedule_policy_id' => $policy_ids['schedule_1']), array('status_id' => 10, 'start_time' => '08:00AM', 'end_time' => '05:00PM', 'schedule_policy_id' => $policy_ids['schedule_1']));
         //Create schedule for each employee.
         $x = 0;
         foreach ($user_ids as $user_id) {
             //Create schedule starting 6 weeks ago, up to the end of the week.
             Debug::Text('Creating schedule for User ID: ' . $user_id, __FILE__, __LINE__, __METHOD__, 10);
             //$schedule_date = ($current_epoch-(86400*42));
             $schedule_date = $current_epoch - 86400 * 14;
             $schedule_end_date = TTDate::getEndWeekEpoch($current_epoch);
             //$schedule_date = ($current_epoch-(86400*14));
             //$schedule_end_date = ($current_epoch+(86400*28));
             while ($schedule_date <= $schedule_end_date) {
                 if ($x % 5 == 0) {
                     $schedule_options_key = 3;
                     //Common shift
                 } else {
                     $schedule_options_key = array_rand($schedule_options_arr);
                 }
                 Debug::Text('  Schedule Date: ' . $schedule_date . ' Schedule Options Key: ' . $schedule_options_key, __FILE__, __LINE__, __METHOD__, 10);
                 //Random departments/branches
                 $schedule_options_arr[$schedule_options_key]['branch_id'] = $branch_ids[rand(0, count($branch_ids) - 1)];
                 $schedule_options_arr[$schedule_options_key]['department_id'] = $department_ids[rand(0, count($department_ids) - 1)];
                 //Schedule just weekdays for users 1-4, then weekends and not mon/tue for user 5.
                 if ($x % 5 != 0 and date('w', $schedule_date) != 0 and date('w', $schedule_date) != 6 or $x % 5 == 0 and date('w', $schedule_date) != 1 and date('w', $schedule_date) != 2) {
                     $this->createSchedule($company_id, $user_id, $schedule_date, $schedule_options_arr[$schedule_options_key]);
                 }
                 $schedule_date += 86400;
             }
             //break;
             unset($schedule_date, $schedule_end_date, $user_id);
             $x++;
         }
         unset($schedule_options_arr, $schedule_options_key);
         //Punch users in/out randomly.
         foreach ($user_ids as $user_id) {
             //Pick random jobs/tasks that are used for the entire date range.
             //So one employee isn't punching into 15 jobs.
             $user_random_job_ids = array_rand($job_ids, 2);
             $user_random_task_ids = array_rand($job_ids, 3);
             //Create punches starting 6 weeks ago, up to the end of the week.
             //$start_date = $punch_date = ($current_epoch-(86400*42));
             $start_date = $punch_date = $current_epoch - 86400 * 14;
             $end_date = TTDate::getEndWeekEpoch($current_epoch);
             //$start_date = $punch_date = ($current_epoch-(86400*14));
             //$end_date = ($current_epoch+(86400*28));
             $i = 0;
             while ($punch_date <= $end_date) {
                 $date_stamp = TTDate::getDate('DATE', $punch_date);
                 //$punch_full_time_stamp = strtotime($pc_data['date_stamp'].' '.$pc_data['time_stamp']);
                 $exception_cutoff_date = $current_epoch - 86400 * 14;
                 if (date('w', $punch_date) != 0 and date('w', $punch_date) != 6) {
                     if ($punch_date >= $exception_cutoff_date and $i % 4 == 0) {
                         $first_punch_in = rand(7, 8) . ':' . str_pad(rand(0, 30), 2, '0', STR_PAD_LEFT) . 'AM';
                         $last_punch_out = strtotime($date_stamp . ' ' . rand(4, 5) . ':' . str_pad(rand(0, 30), 2, '0', STR_PAD_LEFT) . 'PM');
                         if ($punch_date >= $exception_cutoff_date and rand(0, 20) == 0) {
                             //Create request
                             $this->createRequest(20, $user_id, $date_stamp);
                         }
                         if ($punch_date >= $exception_cutoff_date and rand(0, 16) == 0) {
                             //Create request
                             $this->createRequest(20, $user_id, $date_stamp);
                         }
                     } else {
                         $first_punch_in = '08:00AM';
                         if ($punch_date >= $exception_cutoff_date and $i % 10 == 0) {
                             //Don't punch out to generate exception.
                             $last_punch_out = NULL;
                             //Forgot to punch out request
                             $this->createRequest(30, $user_id, $date_stamp);
                         } else {
                             $last_punch_out = strtotime($date_stamp . ' 5:00PM');
                         }
                     }
                     //Weekdays
                     $this->createPunchPair($user_id, strtotime($date_stamp . ' ' . $first_punch_in), strtotime($date_stamp . ' 11:00AM'), array('in_type_id' => 10, 'out_type_id' => 10, 'branch_id' => $branch_ids[rand(0, count($branch_ids) - 1)], 'department_id' => $department_ids[rand(0, count($department_ids) - 1)], 'job_id' => $job_ids[array_rand($user_random_job_ids)], 'job_item_id' => $task_ids[array_rand($user_random_task_ids)]), TRUE);
                     $this->createPunchPair($user_id, strtotime($date_stamp . ' 11:00AM'), strtotime($date_stamp . ' 1:00PM'), array('in_type_id' => 10, 'out_type_id' => 20, 'branch_id' => $branch_ids[rand(0, count($branch_ids) - 1)], 'department_id' => $department_ids[rand(0, count($department_ids) - 1)], 'job_id' => $job_ids[array_rand($user_random_job_ids)], 'job_item_id' => $task_ids[array_rand($user_random_task_ids)]), TRUE);
                     //Calc total time on last punch pair only.
                     $this->createPunchPair($user_id, strtotime($date_stamp . ' 2:00PM'), $last_punch_out, array('in_type_id' => 20, 'out_type_id' => 10, 'branch_id' => $branch_ids[rand(0, count($branch_ids) - 1)], 'department_id' => $department_ids[rand(0, count($department_ids) - 1)], 'job_id' => $job_ids[array_rand($user_random_job_ids)], 'job_item_id' => $task_ids[array_rand($user_random_task_ids)]), TRUE);
                 } elseif ($punch_date > $exception_cutoff_date and date('w', $punch_date) == 6 and $i % 10 == 0) {
                     //Sat.
                     $this->createPunchPair($user_id, strtotime($date_stamp . ' 10:00AM'), strtotime($date_stamp . ' 2:30PM'), array('in_type_id' => 10, 'out_type_id' => 10, 'branch_id' => $branch_ids[rand(0, count($branch_ids) - 1)], 'department_id' => $department_ids[rand(0, count($department_ids) - 1)], 'job_id' => $job_ids[array_rand($user_random_job_ids)], 'job_item_id' => $task_ids[array_rand($user_random_task_ids)]), TRUE);
                 }
                 //Recalculate entire day. Performance optimization.
                 //UserDateTotalFactory::reCalculateRange( $user_id, $start_date, $end_date );
                 $punch_date += 86400;
                 $i++;
             }
             unset($punch_options_arr, $punch_date, $user_id);
         }
         //Generate pay stubs for each pay period
         $pplf = TTnew('PayPeriodListFactory');
         $pplf->getByCompanyId($company_id);
         if ($pplf->getRecordCount() > 0) {
             foreach ($pplf as $pp_obj) {
                 foreach ($user_ids as $user_id) {
                     $cps = new CalculatePayStub();
                     $cps->setUser($user_id);
                     $cps->setPayPeriod($pp_obj->getId());
                     $cps->calculate();
                 }
             }
         }
         unset($pplf, $pp_obj, $user_id);
         $this->createReportCustomColumn($company_id, 'UserSummaryReport', 10);
         $this->createReportCustomColumn($company_id, 'UserSummaryReport', 20);
         $this->createReportCustomColumn($company_id, 'UserSummaryReport', 100);
         $this->createReportCustomColumn($company_id, 'UserSummaryReport', 200);
         $this->createReportCustomColumn($company_id, 'UserSummaryReport', 270);
         $this->createReportCustomColumn($company_id, 'UserSummaryReport', 400);
         $this->createReportCustomColumn($company_id, 'UserSummaryReport', 405);
         $this->createReportCustomColumn($company_id, 'TimesheetSummaryReport', 10);
         $this->createReportCustomColumn($company_id, 'TimesheetSummaryReport', 20);
         $this->createReportCustomColumn($company_id, 'TimesheetSummaryReport', 200);
         $this->createReportCustomColumn($company_id, 'TimesheetDetailReport', 10);
         $this->createReportCustomColumn($company_id, 'TimesheetDetailReport', 20);
         $this->createReportCustomColumn($company_id, 'TimesheetDetailReport', 200);
         if (getTTProductEdition() >= TT_PRODUCT_CORPORATE) {
             // Attach  document to employee
             foreach ($user_ids as $user_id) {
                 $x = 1;
                 while ($x <= rand(2, 4)) {
                     $type = $x * 10;
                     $document_id = $this->createDocument($company_id, 100, $type);
                     $rand_arr = array(1, 2, 3, 4, 5, 6);
                     $rand_ids = array_rand($rand_arr, rand(2, 5));
                     foreach ($rand_ids as $rand_id) {
                         $document_revision_id = $this->createDocumentRevision($document_id, $rand_arr[$rand_id] * 10);
                         $this->createDocumentFilesByObjectType($company_id, 100, $type, $document_revision_id, $document_id);
                     }
                     $this->createDocumentAttachment($document_id, 100, $user_id);
                     $x++;
                 }
             }
             // Attach document to Jobs
             foreach ($job_ids as $job_id) {
                 $x = 1;
                 while ($x <= rand(2, 3)) {
                     $type = $x * 10;
                     $document_id = $this->createDocument($company_id, 60, $type);
                     $rand_arr = array(1, 2, 3, 4, 5, 6);
                     $rand_ids = array_rand($rand_arr, rand(2, 5));
                     foreach ($rand_ids as $rand_id) {
                         $document_revision_id = $this->createDocumentRevision($document_id, $rand_arr[$rand_id] * 10);
                         $this->createDocumentFilesByObjectType($company_id, 60, $type, $document_revision_id, $document_id);
                     }
                     $this->createDocumentAttachment($document_id, 60, $job_id);
                     $x++;
                 }
             }
             // Attach document to clients
             foreach ($client_ids as $client_id) {
                 $x = 1;
                 while ($x <= rand(2, 4)) {
                     $type = $x * 10;
                     $document_id = $this->createDocument($company_id, 80, $type);
                     $rand_arr = array(1, 2, 3, 4, 5, 6);
                     $rand_ids = array_rand($rand_arr, rand(2, 5));
                     foreach ($rand_ids as $rand_id) {
                         $document_revision_id = $this->createDocumentRevision($document_id, $rand_arr[$rand_id] * 10);
                         $this->createDocumentFilesByObjectType($company_id, 80, $type, $document_revision_id, $document_id);
                     }
                     $this->createDocumentAttachment($document_id, 80, $client_id);
                     $x++;
                 }
             }
             // Attach document to client contacts
             foreach ($client_contact_ids as $client_contact_id) {
                 $x = 1;
                 while ($x <= 2) {
                     $type = $x * 10;
                     $document_id = $this->createDocument($company_id, 85, $type);
                     $rand_arr = array(1, 2, 3, 4, 5, 6);
                     $rand_ids = array_rand($rand_arr, rand(2, 5));
                     foreach ($rand_ids as $rand_id) {
                         $document_revision_id = $this->createDocumentRevision($document_id, $rand_arr[$rand_id] * 10);
                         $this->createDocumentFilesByObjectType($company_id, 85, $type, $document_revision_id, $document_id);
                     }
                     $this->createDocumentAttachment($document_id, 85, $client_contact_id);
                     $x++;
                 }
             }
         }
     }
     //$cf->FailTransaction();
     $cf->CommitTransaction();
     return FALSE;
 }
         }
     }
 default:
     if ($permission->Check('schedule', 'view')) {
         Debug::text('Viewing all users schedule', __FILE__, __LINE__, __METHOD__, 10);
         if ($filter_user_id != '') {
             $user_id = $filter_user_id;
         } else {
             $user_id = $current_user->getId();
         }
     } else {
         $user_id = $current_user->getId();
     }
     if ($filter_start_date == '' or $filter_end_date == '') {
         $start_date = $filter_start_date = TTDate::getBeginWeekEpoch(TTDate::getTime() - 86400, $current_user_prefs->getStartWeekDay());
         $end_date = $filter_end_date = TTDate::getEndWeekEpoch(TTDate::getTime() + 86400 * 28, $current_user_prefs->getStartWeekDay());
     }
     //$start_date = $filter_start_date = TTDate::getBeginWeekEpoch( $start_date, 'mon');
     //$end_date = $filter_end_date = TTDate::getEndWeekEpoch( $end_date, 'mon' );
     Debug::text(' Start Date: ' . TTDate::getDate('DATE+TIME', $start_date) . ' End Date: ' . TTDate::getDate('DATE+TIME', $end_date), __FILE__, __LINE__, __METHOD__, 10);
     $sf = TTnew('ScheduleFactory');
     $default_schedule_shifts = $sf->getScheduleArray($user_id, $start_date, $end_date);
     //var_dump($default_schedule_shifts);
     $calendar_array = TTDate::getCalendarArray($start_date, $end_date, $current_user_prefs->getStartWeekDay());
     $smarty->assign_by_ref('calendar_array', $calendar_array);
     //$smarty->assign_by_ref('pay_period_locked_rows', $pay_period_locked_rows);
     $ulf = TTnew('UserListFactory');
     $user_obj = $ulf->getById($user_id)->getCurrent();
     /*
     $holiday = new Holiday();
     $holiday->GetByCountryAndProvince($user_obj->getCountry(), $user_obj->getProvince() );
 function getCalendarArray($start_date, $end_date, $start_day_of_week = 0, $force_weeks = TRUE)
 {
     if ($start_date == '' or $end_date == '') {
         return FALSE;
     }
     //Which day begins the week, Mon or Sun?
     //0 = Sun 1 = Mon
     /*
     if ( strtolower($start_day_of_week) == 'mon' OR $start_day_of_week == 1) {
     	$start_day_of_week = 1;
     } else {
     	$start_day_of_week = 0;
     }
     */
     Debug::text(' Start Day Of Week: ' . $start_day_of_week, __FILE__, __LINE__, __METHOD__, 10);
     Debug::text(' Raw Start Date: ' . TTDate::getDate('DATE+TIME', $start_date) . ' Raw End Date: ' . TTDate::getDate('DATE+TIME', $end_date), __FILE__, __LINE__, __METHOD__, 10);
     if ($force_weeks == TRUE) {
         $cal_start_date = TTDate::getBeginWeekEpoch($start_date, $start_day_of_week);
         //$cal_end_date = TTDate::getEndWeekEpoch($end_date, $start_day_of_week);
         $cal_end_date = TTDate::getEndWeekEpoch($end_date, $start_day_of_week);
     } else {
         $cal_start_date = $start_date;
         $cal_end_date = $end_date;
     }
     Debug::text(' Cal Start Date: ' . TTDate::getDate('DATE+TIME', $cal_start_date) . ' Cal End Date: ' . TTDate::getDate('DATE+TIME', $cal_end_date), __FILE__, __LINE__, __METHOD__, 10);
     $prev_month = NULL;
     //$prev_week=NULL;
     $x = 0;
     //Gotta add more then 86400 because of day light savings time.
     //Causes infinite loop without it.
     //Don't add 7200 to Cal End Date because that could cause more then one
     //week to be displayed.
     //for($i=$cal_start_date; $i <= $cal_end_date; $i+=86400) {
     //for($i=$cal_start_date; $i <= ($cal_end_date+7200); $i+=93600) {
     for ($i = $cal_start_date; $i <= $cal_end_date; $i += 93600) {
         if ($x > 200) {
             break;
         }
         $i = TTDate::getBeginDayEpoch($i);
         $current_month = date('n', $i);
         //$current_week = date('W', $i);
         $current_day_of_week = date('w', $i);
         if ($current_month != $prev_month and $i >= $start_date) {
             $isNewMonth = TRUE;
         } else {
             $isNewMonth = FALSE;
         }
         //if ( $current_week != $prev_week ) {
         if ($current_day_of_week == $start_day_of_week) {
             $isNewWeek = TRUE;
         } else {
             $isNewWeek = FALSE;
         }
         //Display only blank boxes if the date is before the filter start date, or after.
         if ($i >= $start_date and $i <= $end_date) {
             $day_of_week = TTi18n::gettext(date('D', $i));
             // i18n: these short day strings may not be in .po file.
             $day_of_month = date('j', $i);
             $month_name = TTi18n::gettext(date('F', $i));
             // i18n: these short month strings may not be defined in .po file.
         } else {
             //Always have the day of the week at least.
             //$day_of_week = TTi18n::gettext( date('D', $i) ); // i18n: these short day strings may not be in .po file.
             $day_of_week = NULL;
             $day_of_month = NULL;
             $month_name = NULL;
         }
         $retarr[] = array('epoch' => $i, 'date_stamp' => TTDate::getISODateStamp($i), 'start_day_of_week' => $start_day_of_week, 'day_of_week' => $day_of_week, 'day_of_month' => $day_of_month, 'month_name' => $month_name, 'month_short_name' => substr($month_name, 0, 3), 'month' => $current_month, 'isNewMonth' => $isNewMonth, 'isNewWeek' => $isNewWeek);
         $prev_month = $current_month;
         //$prev_week = $current_week;
         //Debug::text('i: '. $i .' Date: '. TTDate::getDate('DATE+TIME', $i), __FILE__, __LINE__, __METHOD__,10);
         $x++;
     }
     return $retarr;
 }
 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_numeric($user_date_ids) and $user_date_ids > 0) {
         $user_date_ids = array($user_date_ids);
     }
     if (!is_array($user_date_ids)) {
         Debug::Text('Returning FALSE... User Date IDs not an array...', __FILE__, __LINE__, __METHOD__, 10);
         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 = TTnew('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 = TTnew('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 = TTnew('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.
                         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();
                 }
             }
             //Use the last date to base the future week calculation on. Make sure we don't unset $week_range['end_date']
             //When BiWeekly overtime policies are calculated, it sets getEnableCalcFutureWeek() to TRUE.
             if (isset($week_range['end_date']) and UserDateTotalFactory::getEnableCalcFutureWeek() == TRUE) {
                 $future_week_date = $week_range['end_date'] + 86400 * 7;
                 Debug::text('Found Biweekly overtime policy, calculate one week into the future: ' . TTDate::getDate('DATE', $future_week_date), __FILE__, __LINE__, __METHOD__, 10);
                 UserDateTotalFactory::reCalculateRange($user_id, TTDate::getBeginWeekEpoch($future_week_date, $start_week_day_id), TTDate::getEndWeekEpoch($future_week_date, $start_week_day_id));
                 UserDateTotalFactory::setEnableCalcFutureWeek(FALSE);
                 //Return to FALSE so future weeks aren't calculate for other users.
                 unset($future_week_date);
             }
             return TRUE;
         }
     }
     Debug::text('Returning FALSE!', __FILE__, __LINE__, __METHOD__, 10);
     return FALSE;
 }
Exemple #9
0
 public static function getTimePeriodDates($time_period, $epoch = NULL, $user_obj = NULL, $params = NULL)
 {
     $time_period = Misc::trimSortPrefix($time_period);
     if ($epoch == NULL or $epoch == '' or !is_numeric($epoch)) {
         $epoch = self::getTime();
     }
     $start_week_day = 0;
     if (is_object($user_obj)) {
         $user_prefs = $user_obj->getUserPreferenceObject();
         if (is_object($user_prefs)) {
             $start_week_day = $user_prefs->getStartWeekDay();
         }
     }
     switch ($time_period) {
         case 'custom_date':
             //Params must pass start_date/end_date
             if (isset($params['start_date'])) {
                 $start_date = TTDate::getBeginDayEpoch($params['start_date']);
             }
             if (isset($params['end_date'])) {
                 $end_date = TTDate::getEndDayEpoch($params['end_date']);
             }
             break;
         case 'custom_time':
             //Params must pass start_date/end_date
             if (isset($params['start_date'])) {
                 $start_date = $params['start_date'];
             }
             if (isset($params['end_date'])) {
                 $end_date = $params['end_date'];
             }
             break;
         case 'custom_pay_period':
             //Params must pass pay_period_ids
             if (isset($params['pay_period_id'])) {
                 $pay_period_ids = (array) $params['pay_period_id'];
             }
             break;
         case 'today':
             $start_date = TTDate::getBeginDayEpoch($epoch);
             $end_date = TTDate::getEndDayEpoch($epoch);
             break;
         case 'yesterday':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             break;
         case 'last_24_hours':
             $start_date = $epoch - 86400;
             $end_date = $epoch;
             break;
         case 'last_48_hours':
             $start_date = $epoch - 86400 * 2;
             $end_date = $epoch;
             break;
         case 'last_72_hours':
             $start_date = $epoch - 86400 * 3;
             $end_date = $epoch;
             break;
         case 'this_week':
             $start_date = TTDate::getBeginWeekEpoch($epoch, $start_week_day);
             $end_date = TTDate::getEndWeekEpoch($epoch, $start_week_day);
             break;
         case 'last_week':
             $start_date = TTDate::getBeginWeekEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 7, $start_week_day);
             $end_date = TTDate::getEndWeekEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 7, $start_week_day);
             break;
         case 'last_2_weeks':
             $start_date = TTDate::getBeginWeekEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 14, $start_week_day);
             $end_date = TTDate::getEndWeekEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 7, $start_week_day);
             break;
         case 'last_7_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 7);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             break;
         case 'last_14_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 14);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             break;
             //Params must be passed if more than one pay period schedule exists.
         //Params must be passed if more than one pay period schedule exists.
         case 'no_pay_period':
         case 'this_pay_period':
         case 'last_pay_period':
             Debug::text('Time Period for Pay Period Schedule selected...', __FILE__, __LINE__, __METHOD__, 10);
             //Make sure user_obj is set.
             if (!is_object($user_obj)) {
                 Debug::text('User Object was not passsed...', __FILE__, __LINE__, __METHOD__, 10);
                 break;
             }
             if (!isset($params['pay_period_schedule_id'])) {
                 $params['pay_period_schedule_id'] = NULL;
             }
             $pay_period_ids = array();
             //Since we allow multiple pay_period schedules to be selected, we have to return pay_period_ids, not start/end dates.
             if ($time_period == 'this_pay_period') {
                 Debug::text('this_pay_period', __FILE__, __LINE__, __METHOD__, 10);
                 $pplf = TTnew('PayPeriodListFactory');
                 $pplf->getThisPayPeriodByCompanyIdAndPayPeriodScheduleIdAndDate($user_obj->getCompany(), $params['pay_period_schedule_id'], time());
                 if ($pplf->getRecordCount() > 0) {
                     foreach ($pplf as $pp_obj) {
                         $pay_period_ids[] = $pp_obj->getId();
                     }
                 }
             } elseif ($time_period == 'last_pay_period') {
                 Debug::text('last_pay_period', __FILE__, __LINE__, __METHOD__, 10);
                 $pplf = TTnew('PayPeriodListFactory');
                 $pplf->getLastPayPeriodByCompanyIdAndPayPeriodScheduleIdAndDate($user_obj->getCompany(), $params['pay_period_schedule_id'], time());
                 if ($pplf->getRecordCount() > 0) {
                     foreach ($pplf as $pp_obj) {
                         $pay_period_ids[] = $pp_obj->getId();
                     }
                 }
             } else {
                 Debug::text('no_pay_period', __FILE__, __LINE__, __METHOD__, 10);
             }
             Debug::Arr($pay_period_ids, 'Pay Period IDs: ', __FILE__, __LINE__, __METHOD__, 10);
             if (count($pay_period_ids) == 0) {
                 unset($pay_period_ids);
             }
             break;
         case 'this_month':
             $start_date = TTDate::getBeginMonthEpoch($epoch);
             $end_date = TTDate::getEndMonthEpoch($epoch);
             break;
         case 'last_month':
             $start_date = TTDate::getBeginMonthEpoch(TTDate::getBeginMonthEpoch($epoch) - 86400);
             $end_date = TTDate::getEndMonthEpoch(TTDate::getBeginMonthEpoch($epoch) - 86400);
             break;
         case 'last_2_months':
             $start_date = TTDate::getBeginMonthEpoch(TTDate::getBeginMonthEpoch($epoch) - 86400 * 32);
             $end_date = TTDate::getEndMonthEpoch(TTDate::getBeginMonthEpoch($epoch) - 86400);
             break;
         case 'last_30_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 30);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             break;
         case 'last_45_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 45);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             break;
         case 'last_60_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 60);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             break;
         case 'this_quarter':
             $quarter = TTDate::getYearQuarter($epoch);
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             //Debug::Arr($quarter_dates, 'Quarter Dates: Quarter: '. $quarter, __FILE__, __LINE__, __METHOD__,10);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'last_quarter':
             $quarter = TTDate::getYearQuarter($epoch) - 1;
             if ($quarter == 0) {
                 $quarter = 4;
                 $epoch = TTDate::getBeginYearEpoch() - 86400;
                 //Need to jump back into the previous year.
             }
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'last_90_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 90);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             break;
         case 'this_year_1st_quarter':
             $quarter = 1;
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'this_year_2nd_quarter':
             $quarter = 2;
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'this_year_3rd_quarter':
             $quarter = 3;
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'this_year_4th_quarter':
             $quarter = 4;
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'last_year_1st_quarter':
             $quarter = 1;
             $quarter_dates = TTDate::getYearQuarters(TTDate::getBeginYearEpoch($epoch) - 86400, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'last_year_2nd_quarter':
             $quarter = 2;
             $quarter_dates = TTDate::getYearQuarters(TTDate::getBeginYearEpoch($epoch) - 86400, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'last_year_3rd_quarter':
             $quarter = 3;
             $quarter_dates = TTDate::getYearQuarters(TTDate::getBeginYearEpoch($epoch) - 86400, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'last_year_4th_quarter':
             $quarter = 4;
             $quarter_dates = TTDate::getYearQuarters(TTDate::getBeginYearEpoch($epoch) - 86400, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'last_3_months':
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date) - 3, TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date));
             break;
         case 'last_6_months':
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date) - 6, TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date));
             break;
         case 'last_9_months':
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date) - 9, TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date));
             break;
         case 'last_12_months':
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date), TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date) - 1);
             break;
         case 'last_18_months':
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date) - 18, TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date));
             break;
         case 'last_24_months':
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date) - 24, TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date));
             break;
         case 'this_year':
             $start_date = TTDate::getBeginYearEpoch($epoch);
             $end_date = TTDate::getEndYearEpoch($epoch);
             break;
         case 'last_year':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch($epoch) - 86400);
             $end_date = TTDate::getEndYearEpoch(TTDate::getBeginYearEpoch($epoch) - 86400);
             break;
         case 'last_2_years':
             $end_date = TTDate::getEndYearEpoch(TTDate::getBeginYearEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date), TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date) - 2);
             break;
         case 'last_3_years':
             $end_date = TTDate::getEndYearEpoch(TTDate::getBeginYearEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date), TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date) - 3);
             break;
         case 'last_5_years':
             $end_date = TTDate::getEndYearEpoch(TTDate::getBeginYearEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date), TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date) - 5);
             break;
         case 'to_yesterday':
             //"Up To" means we need to use the end time of the day we go up to.
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400) - 1;
             break;
         case 'to_today':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch)) - 1;
             break;
         case 'to_this_week':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginWeekEpoch($epoch, $start_week_day) - 1;
             break;
         case 'to_last_week':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginWeekEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 7, $start_week_day) - 1;
             break;
         case 'to_7_days':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 7) - 1;
             break;
         case 'to_14_days':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 14) - 1;
             break;
         case 'to_last_pay_period':
         case 'to_this_pay_period':
             Debug::text('Time Period for Pay Period Schedule selected...', __FILE__, __LINE__, __METHOD__, 10);
             //Make sure user_obj is set.
             if (!is_object($user_obj)) {
                 Debug::text('User Object was not passsed...', __FILE__, __LINE__, __METHOD__, 10);
                 break;
             }
             if (!isset($params['pay_period_schedule_id'])) {
                 $params['pay_period_schedule_id'] = NULL;
             }
             $end_date = FALSE;
             //Since we allow multiple pay_period schedules to be selected, we have to return pay_period_ids, not start/end dates.
             if ($time_period == 'to_this_pay_period') {
                 Debug::text('to_this_pay_period', __FILE__, __LINE__, __METHOD__, 10);
                 $pplf = TTnew('PayPeriodListFactory');
                 $pplf->getThisPayPeriodByCompanyIdAndPayPeriodScheduleIdAndDate($user_obj->getCompany(), $params['pay_period_schedule_id'], time());
                 if ($pplf->getRecordCount() > 0) {
                     foreach ($pplf as $pp_obj) {
                         if ($end_date == FALSE or $pp_obj->getStartDate() < $end_date) {
                             $end_date = $pp_obj->getStartDate();
                         }
                     }
                 }
             } elseif ($time_period == 'to_last_pay_period') {
                 Debug::text('to_last_pay_period', __FILE__, __LINE__, __METHOD__, 10);
                 $pplf = TTnew('PayPeriodListFactory');
                 $pplf->getLastPayPeriodByCompanyIdAndPayPeriodScheduleIdAndDate($user_obj->getCompany(), $params['pay_period_schedule_id'], time());
                 if ($pplf->getRecordCount() > 0) {
                     foreach ($pplf as $pp_obj) {
                         if ($end_date == FALSE or $pp_obj->getStartDate() < $end_date) {
                             $end_date = $pp_obj->getStartDate();
                         }
                     }
                 }
             }
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = $end_date - 1;
             break;
         case 'to_last_month':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginMonthEpoch(TTDate::getBeginMonthEpoch($epoch) - 86400) - 1;
             break;
         case 'to_this_month':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginMonthEpoch($epoch) - 1;
             break;
         case 'to_30_days':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 30) - 1;
             break;
         case 'to_45_days':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 45) - 1;
             break;
         case 'to_60_days':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 60) - 1;
             break;
         case 'to_last_quarter':
             $quarter = TTDate::getYearQuarter($epoch) - 1;
             if ($quarter == 0) {
                 $quarter = 4;
                 $epoch = TTDate::getBeginYearEpoch() - 86400;
                 //Need to jump back into the previous year.
             }
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = $quarter_dates['start'] - 1;
             break;
         case 'to_this_quarter':
             $quarter = TTDate::getYearQuarter($epoch);
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = $quarter_dates['start'] - 1;
             break;
         case 'to_90_days':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 90) - 1;
             break;
         case 'to_this_year':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginYearEpoch($epoch) - 1;
             break;
         case 'to_last_year':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch($epoch) - 86400) - 1;
             break;
         case 'tomorrow':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             break;
         case 'next_24_hours':
             $start_date = $epoch;
             $end_date = $epoch + 86400;
             break;
         case 'next_48_hours':
             $start_date = $epoch;
             $end_date = $epoch + 86400 * 2;
             break;
         case 'next_72_hours':
             $start_date = $epoch;
             $end_date = $epoch + 86400 * 3;
             break;
         case 'next_week':
             $start_date = TTDate::getBeginWeekEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 7, $start_week_day);
             $end_date = TTDate::getEndWeekEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 7, $start_week_day);
             break;
         case 'next_2_weeks':
             $start_date = TTDate::getBeginWeekEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 7, $start_week_day);
             $end_date = TTDate::getEndWeekEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 14, $start_week_day);
             break;
         case 'next_7_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 7);
             break;
         case 'next_14_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 14);
             break;
         case 'next_month':
             $start_date = TTDate::getBeginMonthEpoch(TTDate::getEndMonthEpoch($epoch) + 86400);
             $end_date = TTDate::getEndMonthEpoch(TTDate::getEndMonthEpoch($epoch) + 86400);
             break;
         case 'next_2_months':
             $start_date = TTDate::getBeginMonthEpoch(TTDate::getEndMonthEpoch($epoch) + 86400);
             $end_date = TTDate::getEndMonthEpoch(TTDate::getEndMonthEpoch($epoch) + 86400 * 32);
             break;
         case 'next_30_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 30);
             break;
         case 'next_45_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 45);
             break;
         case 'next_60_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 60);
             break;
         case 'next_quarter':
             $quarter = TTDate::getYearQuarter($epoch) + 1;
             if ($quarter == 5) {
                 $quarter = 1;
                 $epoch = TTDate::getEndYearEpoch() + 86400;
                 //Need to jump back into the previous year.
             }
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'next_90_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 90);
             break;
         case 'next_3_months':
             $start_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date) + 3, TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date));
             break;
         case 'next_6_months':
             $start_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date) + 6, TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date));
             break;
         case 'next_9_months':
             $start_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date) + 9, TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date));
             break;
         case 'next_12_months':
             $start_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date) + 12, TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date));
             break;
         case 'next_18_months':
             $start_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date) + 18, TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date));
             break;
         case 'next_24_months':
             $start_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date) + 24, TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date));
             break;
         case 'next_year':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getEndYearEpoch($epoch) + 86400);
             $end_date = TTDate::getEndYearEpoch(TTDate::getEndYearEpoch($epoch) + 86400);
             break;
         case 'next_2_years':
             $start_date = TTDate::getEndYearEpoch(TTDate::getEndYearEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date), TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date) + 2);
             break;
         case 'next_3_years':
             $start_date = TTDate::getEndYearEpoch(TTDate::getEndYearEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date), TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date) + 3);
             break;
         case 'next_5_years':
             $start_date = TTDate::getEndYearEpoch(TTDate::getEndYearEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date), TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date) + 5);
             break;
         case 'all_years':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getEndYearEpoch(time() + 86400 * (365 * 2));
             break;
         default:
             break;
     }
     if (isset($start_date) and isset($end_date)) {
         //Debug::text('Period: '. $time_period .' Start: '. TTDate::getDate('DATE+TIME', $start_date ) .'('.$start_date.') End: '. TTDate::getDate('DATE+TIME', $end_date ) .'('.$end_date.')', __FILE__, __LINE__, __METHOD__,10);
         return array('start_date' => $start_date, 'end_date' => $end_date);
     } elseif (isset($pay_period_ids)) {
         //Debug::text('Period: '. $time_period .' returning just pay_period_ids...', __FILE__, __LINE__, __METHOD__,10);
         return array('pay_period_id' => $pay_period_ids);
     }
     return FALSE;
 }
 static 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);
     $current_epoch = TTDate::getTime();
     //Get user date info
     $udlf = TTnew('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($current_epoch)) {
             return FALSE;
         }
     } else {
         return FALSE;
     }
     //16hrs... If punches are older then this time, its no longer premature.
     //This should actually be the PayPeriod Schedule maximum shift time.
     if (is_object($user_date_obj->getPayPeriodObject()) and is_object($user_date_obj->getPayPeriodObject()->getPayPeriodScheduleObject())) {
         self::$premature_delay = $user_date_obj->getPayPeriodObject()->getPayPeriodScheduleObject()->getMaximumShiftTime();
         Debug::text(' Setting preMature Exception delay to maximum shift time: ' . self::$premature_delay, __FILE__, __LINE__, __METHOD__, 10);
     } else {
         self::$premature_delay = 57600;
     }
     //Get list of existing exceptions, so we can determine if we need to delete any. We can't delete them all blindly and re-create them
     //as this will send duplicate email notifications for every single punch.
     $existing_exceptions = array();
     $elf = TTnew('ExceptionListFactory');
     $elf->getByUserDateID($user_date_id);
     if ($elf->getRecordCount() > 0) {
         foreach ($elf as $e_obj) {
             $existing_exceptions[] = array('id' => $e_obj->getId(), 'user_date_id' => $e_obj->getUserDateID(), 'exception_policy_id' => $e_obj->getExceptionPolicyID(), 'type_id' => $e_obj->getType(), 'punch_id' => $e_obj->getPunchID(), 'punch_control_id' => $e_obj->getPunchControlID());
         }
     }
     unset($elf, $e_obj);
     //Get all Punches on this date for this user.
     $plf = TTnew('PunchListFactory');
     $plf->getByUserDateId($user_date_id);
     if ($plf->getRecordCount() > 0) {
         Debug::text(' Found Punches: ' . $plf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
     }
     $slf = TTnew('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.
     $current_exceptions = array();
     //Array holding current exception data.
     //Get all active exceptions.
     $eplf = TTnew('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.
                     //Since we now trigger In Late/Out Late exceptions immediately after schedule time, only trigger this exception after
                     //the schedule end time has passed.
                     //**We also need to handle shifts that start at 11:00PM on one day, end at 8:00AM the next day, and they are assigned to the day where
                     //the most time is worked (ie: the next day).
                     //Handle split shifts too...
                     //- This has a side affect that if the schedule policy start/stop time is set to 0, it will trigger both a UnScheduled Absence
                     //  and a Not Scheduled exception for the same schedule/punch.
                     //Loop through all schedules, then find punches to match.
                     if ($slf->getRecordCount() > 0) {
                         foreach ($slf as $s_obj) {
                             if ($s_obj->getStatus() == 10 and $current_epoch >= $s_obj->getEndTime()) {
                                 $add_exception = TRUE;
                                 //Debug::text(' Found Schedule: Start Time: '. TTDate::getDate('DATE+TIME', $s_obj->getStartTime() ), __FILE__, __LINE__, __METHOD__,10);
                                 //Find punches that fall within this schedule time including start/stop window.
                                 if (TTDate::doesRangeSpanMidnight($s_obj->getStartTime(), $s_obj->getEndTime()) and is_object($user_date_obj) and is_object($user_date_obj->getPayPeriodObject()) and is_object($user_date_obj->getPayPeriodObject()->getPayPeriodScheduleObject())) {
                                     //Get punches from both days.
                                     $plf_tmp = TTnew('PunchListFactory');
                                     $plf_tmp->getShiftPunchesByUserIDAndEpoch($user_date_obj->getUser(), $s_obj->getStartTime(), 0, $user_date_obj->getPayPeriodObject()->getPayPeriodScheduleObject()->getMaximumShiftTime());
                                     Debug::text(' Schedule spans midnight... Found rows from expanded search: ' . $plf_tmp->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
                                     if ($plf_tmp->getRecordCount() > 0) {
                                         foreach ($plf_tmp as $p_obj_tmp) {
                                             if ($s_obj->inSchedule($p_obj_tmp->getTimeStamp())) {
                                                 Debug::text(' aFound punch for schedule...', __FILE__, __LINE__, __METHOD__, 10);
                                                 $add_exception = FALSE;
                                                 break;
                                             }
                                         }
                                     }
                                     unset($plf_tmp, $p_obj_tmp);
                                 } else {
                                     //Get punches from just this day.
                                     foreach ($plf as $p_obj) {
                                         if ($s_obj->inSchedule($p_obj->getTimeStamp())) {
                                             //Debug::text(' bFound punch for schedule...', __FILE__, __LINE__, __METHOD__,10);
                                             $add_exception = FALSE;
                                             break;
                                         }
                                     }
                                 }
                                 if ($add_exception == TRUE) {
                                     //Debug::text(' Adding S1 exception...', __FILE__, __LINE__, __METHOD__,10);
                                     $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => FALSE, 'schedule_obj' => $s_obj);
                                 }
                             }
                         }
                     }
                     unset($s_obj, $add_exception);
                     break;
                 case 's2':
                     //Not Scheduled
                     //**We also need to handle shifts that start at 11:00PM on one day, end at 8:00AM the next day, and they are assigned to the day where
                     //the most time is worked (ie: the next day).
                     //Handle split shifts too...
                     if ($plf->getRecordCount() > 1) {
                         //Make sure at least two punche exist.
                         //Loop through each punch, find out if they are scheduled, and if they are in early
                         $prev_punch_time_stamp = FALSE;
                         foreach ($plf as $p_obj) {
                             //Ignore punches that have the exact same timestamp, as they are likely transfer punches.
                             if ($prev_punch_time_stamp != $p_obj->getTimeStamp() and $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());
                                 }
                                 //Check if no schedule exists, or an absent schedule exists. If they work when not scheduled (no schedule) or schedule absent, both should trigger this.
                                 if ($p_obj->setScheduleID($scheduled_id_cache[$p_obj->getID()]) == FALSE or is_object($p_obj->getScheduleObject()) and $p_obj->getScheduleObject()->getStatus() == 20) {
                                     //Debug::text(' Worked when wasnt scheduled', __FILE__, __LINE__, __METHOD__,10);
                                     $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => $p_obj->getID(), 'punch_control_id' => FALSE);
                                 } else {
                                     Debug::text('    Schedule Found', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                             $prev_punch_time_stamp = $p_obj->getTimeStamp();
                         }
                     }
                     unset($scheduled_id_cache, $prev_punch_time_stamp, $p_obj);
                     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
                         $prev_punch_time_stamp = FALSE;
                         foreach ($plf as $p_obj) {
                             //Ignore punches that have the exact same timestamp, as they are likely transfer punches.
                             if ($prev_punch_time_stamp != $p_obj->getTimeStamp() and $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('    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('    NOT Within Grace time, SET EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                             $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => $p_obj->getID(), 'punch_control_id' => FALSE, 'punch_obj' => $p_obj, 'schedule_obj' => $p_obj->getScheduleObject());
                                         }
                                     }
                                 } else {
                                     Debug::text('    NO Schedule Found', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                             $prev_punch_time_stamp = $p_obj->getTimeStamp();
                         }
                     }
                     break;
                 case 's4':
                     //In Late
                     if ($plf->getRecordCount() > 0) {
                         $prev_punch_time_stamp = FALSE;
                         foreach ($plf as $p_obj) {
                             Debug::text('    In Late. Punch: ' . TTDate::getDate('DATE+TIME', $p_obj->getTimeStamp()), __FILE__, __LINE__, __METHOD__, 10);
                             //Ignore punches that have the exact same timestamp and/or punches with the transfer flag, as they are likely transfer punches.
                             if ($prev_punch_time_stamp != $p_obj->getTimeStamp() and $p_obj->getTransfer() == FALSE and $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('    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('    NOT Within Grace time, SET EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                             $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => $p_obj->getID(), 'punch_control_id' => FALSE, 'punch_obj' => $p_obj, 'schedule_obj' => $p_obj->getScheduleObject());
                                         }
                                     }
                                 } else {
                                     Debug::text('    NO Schedule Found', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                             $prev_punch_time_stamp = $p_obj->getTimeStamp();
                         }
                     }
                     unset($scheduled_id_cache);
                     //Late Starting their shift, with no punch yet, trigger exception if:
                     //  - Schedule is found
                     //	- Current time is after schedule start time and before schedule end time.
                     // 	- Current time is after exception grace time
                     //Make sure we take into account split shifts.
                     Debug::text('    Checking Late Starting Shift exception... Current time: ' . TTDate::getDate('DATE+TIME', $current_epoch), __FILE__, __LINE__, __METHOD__, 10);
                     if ($slf->getRecordCount() > 0) {
                         foreach ($slf as $s_obj) {
                             if ($s_obj->getStatus() == 10 and ($current_epoch >= $s_obj->getStartTime() and $current_epoch <= $s_obj->getEndTime())) {
                                 if (TTDate::inWindow($current_epoch, $s_obj->getStartTime(), $ep_obj->getGrace()) == TRUE) {
                                     Debug::text('    Within Grace time, IGNORE EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                 } else {
                                     //See if we can find a punch within the schedule time, if so assume we already created the exception above.
                                     //Make sure we take into account the schedule policy start/stop window.
                                     //However in the case where a single schedule shift and just one punch exists, if an employee comes in really
                                     //early (1AM) before the schedule start/stop window it will trigger an In Late exception.
                                     //This could still be correct though if they only come in for an hour, then come in late for their shift later.
                                     //Schedule start/stop time needs to be correct.
                                     //Also need to take into account shifts that span midnight, ie: 10:30PM to 6:00AM, as its important the schedules/punches match up properly.
                                     $add_exception = TRUE;
                                     Debug::text(' Found Schedule: Start Time: ' . TTDate::getDate('DATE+TIME', $s_obj->getStartTime()), __FILE__, __LINE__, __METHOD__, 10);
                                     //Find punches that fall within this schedule time including start/stop window.
                                     if (TTDate::doesRangeSpanMidnight($s_obj->getStartTime(), $s_obj->getEndTime()) and is_object($user_date_obj) and is_object($user_date_obj->getPayPeriodObject()) and is_object($user_date_obj->getPayPeriodObject()->getPayPeriodScheduleObject())) {
                                         //Get punches from both days.
                                         $plf_tmp = TTnew('PunchListFactory');
                                         $plf_tmp->getShiftPunchesByUserIDAndEpoch($user_date_obj->getUser(), $s_obj->getStartTime(), 0, $user_date_obj->getPayPeriodObject()->getPayPeriodScheduleObject()->getMaximumShiftTime());
                                         Debug::text(' Schedule spans midnight... Found rows from expanded search: ' . $plf_tmp->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
                                         if ($plf_tmp->getRecordCount() > 0) {
                                             foreach ($plf_tmp as $p_obj_tmp) {
                                                 if ($s_obj->inSchedule($p_obj_tmp->getTimeStamp())) {
                                                     Debug::text('    Found punch for this schedule, skipping schedule...', __FILE__, __LINE__, __METHOD__, 10);
                                                     $add_exception = FALSE;
                                                     continue 2;
                                                     //Skip to next schedule without creating exception.
                                                 }
                                             }
                                         }
                                         unset($plf_tmp, $p_obj_tmp);
                                     } else {
                                         //Get punches from just this day.
                                         foreach ($plf as $p_obj) {
                                             if ($s_obj->inSchedule($p_obj->getTimeStamp())) {
                                                 Debug::text(' bFound punch for schedule...', __FILE__, __LINE__, __METHOD__, 10);
                                                 $add_exception = FALSE;
                                                 break;
                                             }
                                         }
                                     }
                                     if ($add_exception == TRUE) {
                                         Debug::text('    NOT Within Grace time, SET EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                         $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => FALSE, 'schedule_obj' => $s_obj);
                                     }
                                 }
                             }
                         }
                     } else {
                         Debug::text('    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
                         $prev_punch_time_stamp = FALSE;
                         $total_punches = $plf->getRecordCount();
                         $x = 1;
                         foreach ($plf as $p_obj) {
                             //Ignore punches that have the exact same timestamp and/or punches with the transfer flag, as they are likely transfer punches.
                             //For Out Early, we have to wait until we are at the last punch, or there is a subsequent punch
                             // to see if it matches the exact same time (transfer)
                             //Therefore we need a two step confirmation before this exception can be triggered. Current punch, then next punch if it exists.
                             if ($p_obj->getTransfer() == FALSE and $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('    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('    NOT Within Grace time, SET EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                             $tmp_exception = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => $p_obj->getID(), 'punch_control_id' => FALSE, 'punch_obj' => $p_obj, 'schedule_obj' => $p_obj->getScheduleObject());
                                             if ($x == $total_punches) {
                                                 //Trigger exception if we're the last punch.
                                                 $current_exceptions[] = $tmp_exception;
                                             } else {
                                                 //Save exception to be triggered if the next punch doesn't match the same time.
                                             }
                                         }
                                     }
                                 } else {
                                     Debug::text('    NO Schedule Found', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             } elseif ($p_obj->getType() == 10 and $p_obj->getStatus() == 10) {
                                 //Normal In
                                 //This comes after an OUT punch, so we need to check if there are two punches
                                 //in a row with the same timestamp, if so ignore the exception.
                                 if (isset($tmp_exception) and $p_obj->getTimeStamp() == $prev_punch_time_stamp) {
                                     unset($tmp_exception);
                                 } elseif (isset($tmp_exception)) {
                                     $current_exceptions[] = $tmp_exception;
                                     //Set exception.
                                 }
                             }
                             $prev_punch_time_stamp = $p_obj->getTimeStamp();
                             $x++;
                         }
                     }
                     unset($tmp_exception, $x, $prev_punch_time_stamp);
                     break;
                 case 's6':
                     //Out Late
                     if ($plf->getRecordCount() > 0) {
                         $prev_punch_time_stamp = FALSE;
                         foreach ($plf as $p_obj) {
                             $punch_pairs[$p_obj->getPunchControlID()][] = array('status_id' => $p_obj->getStatus(), 'punch_control_id' => $p_obj->getPunchControlID(), 'time_stamp' => $p_obj->getTimeStamp());
                             if ($prev_punch_time_stamp != $p_obj->getTimeStamp() and $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('    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('    NOT Within Grace time, SET EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                             $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => $p_obj->getID(), 'punch_control_id' => FALSE, 'punch_obj' => $p_obj, 'schedule_obj' => $p_obj->getScheduleObject());
                                         }
                                     }
                                 } else {
                                     Debug::text('    NO Schedule Found', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                             $prev_punch_time_stamp = $p_obj->getTimeStamp();
                         }
                         //Trigger exception if no out punch and we have passed schedule out time.
                         //  - Schedule is found
                         //	- Make sure the user is missing an OUT punch.
                         //	- Current time is after schedule end time
                         // 	- Current time is after exception grace time
                         //  - Current time is before schedule end time + maximum shift time.
                         if (isset($punch_pairs) and $slf->getRecordCount() > 0) {
                             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);
                                         foreach ($slf as $s_obj) {
                                             Debug::text('Punch: ' . TTDate::getDate('DATE+TIME', $punch_pair[0]['time_stamp']) . ' Schedule Start Time: ' . TTDate::getDate('DATE+TIME', $s_obj->getStartTime()) . ' End Time: ' . TTDate::getDate('DATE+TIME', $s_obj->getEndTime()), __FILE__, __LINE__, __METHOD__, 10);
                                             //Because this is just an IN punch, make sure the IN punch is before the schedule end time
                                             //So we can eliminate split shift schedules.
                                             if ($punch_pair[0]['time_stamp'] <= $s_obj->getEndTime() and $current_epoch >= $s_obj->getEndTime() and $current_epoch <= $s_obj->getEndTime() + self::$premature_delay) {
                                                 if (TTDate::inWindow($current_epoch, $s_obj->getEndTime(), $ep_obj->getGrace()) == TRUE) {
                                                     Debug::text('    Within Grace time, IGNORE EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                                 } else {
                                                     Debug::text('    NOT Within Grace time, SET EXCEPTION: ', __FILE__, __LINE__, __METHOD__, 10);
                                                     $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => $punch_pair[0]['punch_control_id'], 'schedule_obj' => $s_obj);
                                                 }
                                             }
                                         }
                                     }
                                 } else {
                                     Debug::text('No Missing Punches...', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                         }
                         unset($punch_pairs, $punch_pair);
                     }
                     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() < $current_epoch - 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('a1Found Missing Punch: ', __FILE__, __LINE__, __METHOD__, 10);
                                     if ($punch_pair[0]['status_id'] == 20) {
                                         //Missing In Punch
                                         Debug::text('b1Found Missing In Punch: ', __FILE__, __LINE__, __METHOD__, 10);
                                         $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => $punch_pair[0]['punch_control_id']);
                                     }
                                 } 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);
                             //This causes the exception to trigger if the first punch pair is more than the Maximum Shift time away from the current punch,
                             //ie: In: 1:00AM, Out: 2:00AM, In 3:00PM (Maximum Shift Time less than 12hrs). The missing punch exception will be triggered immediately upon the 3:00PM punch.
                             //if ( $type_id == 5 AND $p_obj->getTimeStamp() < ($current_epoch-self::$premature_delay) ) {
                             //	$type_id = 50;
                             //}
                             $punch_pairs[$p_obj->getPunchControlID()][] = array('status_id' => $p_obj->getStatus(), 'punch_control_id' => $p_obj->getPunchControlID(), 'time_stamp' => $p_obj->getTimeStamp());
                         }
                         if (isset($punch_pairs)) {
                             foreach ($punch_pairs as $punch_control_id => $punch_pair) {
                                 if (count($punch_pair) != 2) {
                                     Debug::text('a2Found Missing Punch: ', __FILE__, __LINE__, __METHOD__, 10);
                                     if ($punch_pair[0]['status_id'] == 10) {
                                         //Missing Out Punch
                                         Debug::text('b2Found Missing Out Punch: ', __FILE__, __LINE__, __METHOD__, 10);
                                         //Make sure we are at least MaximumShift Time from the matching In punch before trigging this exception.
                                         //Even when an supervisor is entering punches for today, make missing out punch pre-mature if the maximum shift time isn't exceeded.
                                         //This will prevent timesheet recalculations from having missing punches for everyone today.
                                         //if ( $type_id == 5 AND $punch_pair[0]['time_stamp'] < ($current_epoch-self::$premature_delay) ) {
                                         if ($punch_pair[0]['time_stamp'] < $current_epoch - self::$premature_delay) {
                                             $type_id = 50;
                                         } else {
                                             $type_id = 5;
                                         }
                                         $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => $punch_pair[0]['punch_control_id']);
                                     }
                                 } 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() < $current_epoch - 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);
                                     $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => $invalid_punch_arr['punch_id'], 'punch_control_id' => FALSE);
                                 }
                                 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() < $current_epoch - 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);
                                     $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => $invalid_punch_arr['punch_id'], 'punch_control_id' => FALSE);
                                 }
                                 unset($invalid_punch_arr);
                             } else {
                                 Debug::text('Lunch Punches match up.', __FILE__, __LINE__, __METHOD__, 10);
                             }
                             unset($invalid_punches);
                         }
                     }
                     break;
                 case 'c1':
                     //Missed Check-in
                     //Use grace period and make sure the employee punches within that period of time (usually a transfer punch, but break/lunch should work too)
                     if ($plf->getRecordCount() > 0 and $ep_obj->getGrace() > 0) {
                         $prev_punch_time_stamp = FALSE;
                         $prev_punch_obj = FALSE;
                         $x = 1;
                         foreach ($plf as $p_obj) {
                             Debug::text('   Missed Check-In Punch: ' . TTDate::getDate('DATE+TIME', $p_obj->getTimeStamp()) . ' Delay: ' . self::$premature_delay . ' Current Epoch: ' . $current_epoch, __FILE__, __LINE__, __METHOD__, 10);
                             //Handle punch pairs below. Only trigger on OUT punches.
                             if (is_object($prev_punch_obj) and $prev_punch_obj->getStatus() == 10 and $p_obj->getStatus() == 20 and $p_obj->getTimeStamp() - $prev_punch_time_stamp > $ep_obj->getGrace()) {
                                 //Only check OUT punches when paired.
                                 Debug::text('   Triggering excepetion as employee missed check-in within: ' . ($p_obj->getTimeStamp() - $prev_punch_time_stamp), __FILE__, __LINE__, __METHOD__, 10);
                                 $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => $p_obj->getID(), 'punch_control_id' => FALSE, 'punch_obj' => $p_obj, 'schedule_obj' => $p_obj->getScheduleObject());
                             } elseif ($prev_punch_time_stamp !== FALSE) {
                                 Debug::text('   Employee Checked-In within: ' . ($p_obj->getTimeStamp() - $prev_punch_time_stamp), __FILE__, __LINE__, __METHOD__, 10);
                             }
                             //Handle cases where there is a IN punch but no OUT punch yet.
                             //However ignore cases where there is a OUT punch but no IN punch.
                             if ($x == $plf->getRecordCount() and $p_obj->getStatus() == 10 and $current_epoch - $p_obj->getTimeStamp() > $ep_obj->getGrace() and $p_obj->getTimeStamp() > $current_epoch - self::$premature_delay) {
                                 Debug::text('   Triggering excepetion as employee hasnt checked in yet, within: ' . ($current_epoch - $prev_punch_time_stamp), __FILE__, __LINE__, __METHOD__, 10);
                                 $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => $p_obj->getPunchControlID(), 'punch_obj' => $p_obj, 'schedule_obj' => $p_obj->getScheduleObject());
                             }
                             $prev_punch_time_stamp = $p_obj->getTimeStamp();
                             $prev_punch_obj = $p_obj;
                             $x++;
                         }
                     }
                     unset($prev_punch_obj, $prev_punch_time_stamp, $x);
                     break;
                 case 'd1':
                     //No Branch or Department
                     $add_exception = FALSE;
                     foreach ($plf as $p_obj) {
                         //In punches only
                         if ($p_obj->getStatus() == 10 and is_object($p_obj->getPunchControlObject())) {
                             //If no Tasks are setup, ignore checking them.
                             if ($p_obj->getPunchControlObject()->getBranch() == '' or $p_obj->getPunchControlObject()->getBranch() == 0 or $p_obj->getPunchControlObject()->getBranch() == FALSE) {
                                 $add_exception = TRUE;
                             }
                             if ($p_obj->getPunchControlObject()->getDepartment() == '' or $p_obj->getPunchControlObject()->getDepartment() == 0 or $p_obj->getPunchControlObject()->getDepartment() == FALSE) {
                                 //Make sure at least one task exists before triggering exception.
                                 $dlf = TTNew('DepartmentListFactory');
                                 $dlf->getByCompanyID($user_date_obj->getUserObject()->getCompany(), 1);
                                 //Limit to just 1 record.
                                 if ($dlf->getRecordCount() > 0) {
                                     $add_exception = TRUE;
                                 }
                             }
                             if ($add_exception === TRUE) {
                                 $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => $p_obj->getId(), 'punch_control_id' => $p_obj->getPunchControlId());
                             }
                         }
                     }
                     break;
                 case 's7':
                     //Over Scheduled Hours
                     if ($plf->getRecordCount() > 0) {
                         //FIXME: Assign this exception to the last punch of the day, so it can be related back to a punch branch/department?
                         //This ONLY takes in to account WORKED hours, not paid absence hours.
                         //FIXME: Do we want to trigger this before their last out punch?
                         $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 = TTnew('UserDateTotalListFactory');
                                 //Take into account auto-deduct/add meal policies, but not paid absences.
                                 //$udtlf->getByUserDateIdAndStatusAndType( $user_date_id, 10, 10 );
                                 $udtlf->getByUserDateId($user_date_id);
                                 if ($udtlf->getRecordCount() > 0) {
                                     foreach ($udtlf as $udt_obj) {
                                         if ($udt_obj->getTimeCategory() == 'worked_time') {
                                             $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);
                                     $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => FALSE);
                                 } 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) {
                         //FIXME: Assign this exception to the last punch of the day, so it can be related back to a punch branch/department?
                         //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 = TTnew('UserDateTotalListFactory');
                                 //Take into account auto-deduct/add meal policies
                                 //$udtlf->getByUserDateIdAndStatusAndType( $user_date_id, 10, 10 );
                                 $udtlf->getByUserDateId($user_date_id);
                                 if ($udtlf->getRecordCount() > 0) {
                                     foreach ($udtlf as $udt_obj) {
                                         if ($udt_obj->getTimeCategory() == 'worked_time') {
                                             $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($current_epoch - self::$premature_delay)) {
                                         $type_id = 50;
                                     }
                                     $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => FALSE);
                                 } 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) {
                         //FIXME: Assign this exception to the last punch of the day, so it can be related back to a punch branch/department?
                         //This ONLY takes in to account WORKED hours, not paid absence hours.
                         //FIXME: Do we want to trigger this before their last out punch?
                         $daily_total_time = 0;
                         //Get daily total time.
                         $udtlf = TTnew('UserDateTotalListFactory');
                         //Take into account auto-deduct/add meal policies
                         //$udtlf->getByUserDateIdAndStatusAndType( $user_date_id, 10, 10 );
                         $udtlf->getByUserDateId($user_date_id);
                         if ($udtlf->getRecordCount() > 0) {
                             foreach ($udtlf as $udt_obj) {
                                 if ($udt_obj->getTimeCategory() == 'worked_time') {
                                     $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);
                             $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => FALSE);
                         } 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) {
                         //FIXME: Assign this exception to the last punch of the day, so it can be related back to a punch branch/department?
                         //Get Pay Period Schedule info
                         //FIXME: Do we want to trigger this before their last out punch?
                         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;
                         //Currently we only consider committed scheduled shifts. We may need to change this to take into account
                         //recurring scheduled shifts that haven't been committed yet as well.
                         //In either case though we should take into account the entires week worth of scheduled time even if we are only partially through
                         //the week, that way we won't be triggering s9 exceptions on a Wed and a Fri or something, it will only occur on the last days of the week.
                         if (strtolower($ep_obj->getType()) == 's9') {
                             $tmp_slf = TTnew('ScheduleListFactory');
                             $tmp_slf->getByUserIdAndStartDateAndEndDate($user_date_obj->getUser(), TTDate::getBeginWeekEpoch($user_date_obj->getDateStamp(), $start_week_day_id), TTDate::getEndWeekEpoch($user_date_obj->getDateStamp(), $start_week_day_id));
                             if ($tmp_slf->getRecordCount() > 0) {
                                 foreach ($tmp_slf as $s_obj) {
                                     if ($s_obj->getStatus() == 10) {
                                         //Only working shifts.
                                         $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 = TTnew('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);
                         //Don't trigger either of these exceptions unless both the worked and scheduled time is greater than 0. If they aren't scheduled at all
                         //it should trigger a Unscheduled Absence exception instead of a over weekly scheduled time exception.
                         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_scheduled_total_time > 0 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);
                             $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => FALSE);
                         } 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 = TTnew('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);
                                             if (isset($time_stamp_arr['punch_id'])) {
                                                 $punch_id = $time_stamp_arr['punch_id'];
                                             } else {
                                                 $punch_id = FALSE;
                                             }
                                             $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => $punch_id, 'punch_control_id' => FALSE);
                                             unset($punch_id);
                                         } 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 short shift though.
                         //Also ignore this exception if the lunch is auto-deduct.
                         //**Try to assign this exception to a specific punch control id, so we can do searches based on punch branch.
                         //Find meal policy
                         //Use scheduled meal policy first.
                         $meal_policy_obj = NULL;
                         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);
                                     $meal_policy_obj = $s_obj->getSchedulePolicyObject()->getMealPolicyObject();
                                 } 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 = TTnew('MealPolicyListFactory');
                             $mplf->getByPolicyGroupUserId($user_date_obj->getUser());
                             if ($mplf->getRecordCount() > 0) {
                                 foreach ($mplf as $mp_obj) {
                                     if ($mp_obj->getType() != 10) {
                                         Debug::text('Found UnScheduled meal Policy... Trigger Time: ' . $mp_obj->getTriggerTime(), __FILE__, __LINE__, __METHOD__, 10);
                                         $meal_policy_obj = $mp_obj;
                                     }
                                 }
                                 unset($mplf, $mp_obj);
                             } else {
                                 //There is no  meal policy or schedule policy with a meal policy assigned to it
                                 //With out this we could still apply No meal exceptions, but they will happen even on
                                 //a 2minute shift.
                                 Debug::text('No Lunch policy, applying No meal exception.', __FILE__, __LINE__, __METHOD__, 10);
                                 $meal_policy_obj = TRUE;
                             }
                         }
                         if (is_object($meal_policy_obj) or $meal_policy_obj === TRUE) {
                             $punch_control_id = FALSE;
                             $daily_total_time = 0;
                             $udtlf = TTnew('UserDateTotalListFactory');
                             $udtlf->getByUserDateIdAndStatus($user_date_id, 20);
                             if ($udtlf->getRecordCount() > 0) {
                                 foreach ($udtlf as $udt_obj) {
                                     $daily_total_time += $udt_obj->getTotalTime();
                                     $punch_control_total_time[$udt_obj->getPunchControlID()] = $udt_obj->getTotalTime();
                                 }
                             }
                             Debug::text('Day Total Time: ' . $daily_total_time, __FILE__, __LINE__, __METHOD__, 10);
                             //Debug::Arr($punch_control_total_time, 'Punch Control Total Time: ', __FILE__, __LINE__, __METHOD__,10);
                             if ($daily_total_time > 0 and ($meal_policy_obj === TRUE or $daily_total_time > $meal_policy_obj->getTriggerTime())) {
                                 //Check for meal punch.
                                 $meal_punch = FALSE;
                                 $tmp_punch_total_time = 0;
                                 $tmp_punch_control_ids = array();
                                 foreach ($plf as $p_obj) {
                                     if ($p_obj->getType() == 20) {
                                         //20 = Lunch
                                         Debug::text('Found meal Punch: ' . $p_obj->getTimeStamp(), __FILE__, __LINE__, __METHOD__, 10);
                                         $meal_punch = TRUE;
                                         break;
                                     }
                                     if (isset($punch_control_total_time[$p_obj->getPunchControlID()]) and !isset($tmp_punch_control_ids[$p_obj->getPunchControlID()])) {
                                         $tmp_punch_total_time += $punch_control_total_time[$p_obj->getPunchControlID()];
                                         if ($punch_control_id === FALSE and ($meal_policy_obj === TRUE or $tmp_punch_total_time > $meal_policy_obj->getTriggerTime())) {
                                             Debug::text('Found punch control for exception: ' . $p_obj->getPunchControlID() . ' Total Time: ' . $tmp_punch_total_time, __FILE__, __LINE__, __METHOD__, 10);
                                             $punch_control_id = $p_obj->getPunchControlID();
                                             //Don't meal the loop here, as we have to continue on and check for other meals.
                                         }
                                     }
                                     $tmp_punch_control_ids[$p_obj->getPunchControlID()] = TRUE;
                                 }
                                 unset($tmp_punch_total_time, $tmp_punch_control_ids);
                                 if ($meal_punch == FALSE) {
                                     Debug::text('Triggering No Lunch exception!', __FILE__, __LINE__, __METHOD__, 10);
                                     $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => $punch_control_id);
                                 }
                             }
                         }
                     }
                     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 = TTnew('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()->getBreakPolicy();
                                         $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);
                                                 if (isset($time_stamp_arr['punch_id'])) {
                                                     $punch_id = $time_stamp_arr['punch_id'];
                                                 } else {
                                                     $punch_id = FALSE;
                                                 }
                                                 $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => $punch_id, 'punch_control_id' => FALSE);
                                                 unset($punch_id);
                                             } 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);
                         //Get daily total time.
                         $daily_total_time = 0;
                         $udtlf = TTnew('UserDateTotalListFactory');
                         //$udtlf->getByUserDateIdAndStatusAndType( $user_date_id, 10, 10 );
                         $udtlf->getByUserDateId($user_date_id);
                         if ($udtlf->getRecordCount() > 0) {
                             foreach ($udtlf as $udt_obj) {
                                 if ($udt_obj->getTimeCategory() == 'worked_time') {
                                     $daily_total_time += $udt_obj->getTotalTime();
                                 }
                             }
                         }
                         Debug::text(' Daily Total Time: ' . $daily_total_time . ' User Date ID: ' . $user_date_id, __FILE__, __LINE__, __METHOD__, 10);
                         //Make sure we take into account how long they have currently worked, so we don't
                         //say too few breaks for 3hr shift that they employee took one break on.
                         //Trigger this exception if the employee doesn't take a break at all?
                         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 = TTnew('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()->getBreakPolicy();
                                         $bplf->getByIdAndCompanyId($break_policy_ids, $user_date_obj->getUserObject()->getCompany());
                                     } else {
                                         //$bplf->getByPolicyGroupUserId( $user_date_obj->getUser() );
                                         $bplf->getByPolicyGroupUserIdAndDayTotalTime($user_date_obj->getUser(), $daily_total_time);
                                     }
                                     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);
                                         if (isset($time_stamp_arr['punch_id']) and strtolower($ep_obj->getType()) == 'b3') {
                                             $punch_id = $time_stamp_arr['punch_id'];
                                         } else {
                                             $punch_id = FALSE;
                                         }
                                         $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => $punch_id, 'punch_control_id' => FALSE);
                                         unset($punch_id);
                                     } else {
                                         Debug::text('Not Adding Exception!', __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                 }
                             }
                         }
                     }
                     break;
                 case 'b5':
                     //No Break
                     if ($plf->getRecordCount() > 0) {
                         //If they are scheduled or not, we can check for a break policy and base our
                         //decision off that. We don't want a No Break exception on a 3hr short shift though.
                         //Also ignore this exception if the break is auto-deduct.
                         //**Try to assign this exception to a specific punch control id, so we can do searches based on punch branch.
                         //Find break policy
                         //Use scheduled break policy first.
                         $break_policy_obj = NULL;
                         if ($slf->getRecordCount() > 0) {
                             Debug::text('Schedule Found...', __FILE__, __LINE__, __METHOD__, 10);
                             foreach ($slf as $s_obj) {
                                 if ($s_obj->getSchedulePolicyObject() !== FALSE) {
                                     $break_policy_ids = $s_obj->getSchedulePolicyObject()->getBreakPolicy();
                                     if (is_array($break_policy_ids)) {
                                         $bplf = TTNew('BreakPolicyListFactory');
                                         $bplf->getByIdAndCompanyId($break_policy_ids, $user_date_obj->getUserObject()->getCompany());
                                         if ($bplf->getRecordCount() > 0) {
                                             foreach ($bplf as $bp_obj) {
                                                 if ($bp_obj->getType() != 10) {
                                                     $break_policy_obj = $bp_obj;
                                                     break;
                                                 }
                                             }
                                         }
                                     }
                                 }
                                 unset($s_obj, $break_policy_ids, $bplf, $bp_obj);
                             }
                         } else {
                             Debug::text('No Schedule Found...', __FILE__, __LINE__, __METHOD__, 10);
                             //Check if they have a break policy, with no schedule.
                             $bplf = TTnew('BreakPolicyListFactory');
                             $bplf->getByPolicyGroupUserId($user_date_obj->getUser());
                             if ($bplf->getRecordCount() > 0) {
                                 Debug::text('Found UnScheduled Break Policy...', __FILE__, __LINE__, __METHOD__, 10);
                                 foreach ($bplf as $bp_obj) {
                                     if ($bp_obj->getType() != 10) {
                                         $break_policy_obj = $bp_obj;
                                         break;
                                     }
                                 }
                                 unset($bplf, $bp_obj);
                             } else {
                                 //There is no  break policy or schedule policy with a break policy assigned to it
                                 //With out this we could still apply No Break exceptions, but they will happen even on
                                 //a 2minute shift.
                                 Debug::text('No break policy, applying No break exception.', __FILE__, __LINE__, __METHOD__, 10);
                                 $break_policy_obj = TRUE;
                             }
                         }
                         if (is_object($break_policy_obj) or $break_policy_obj === TRUE) {
                             $punch_control_id = FALSE;
                             $daily_total_time = 0;
                             $udtlf = TTnew('UserDateTotalListFactory');
                             $udtlf->getByUserDateIdAndStatus($user_date_id, 20);
                             if ($udtlf->getRecordCount() > 0) {
                                 foreach ($udtlf as $udt_obj) {
                                     $daily_total_time += $udt_obj->getTotalTime();
                                     $punch_control_total_time[$udt_obj->getPunchControlID()] = $udt_obj->getTotalTime();
                                 }
                             }
                             Debug::text('Day Total Time: ' . $daily_total_time, __FILE__, __LINE__, __METHOD__, 10);
                             //Debug::Arr($punch_control_total_time, 'Punch Control Total Time: ', __FILE__, __LINE__, __METHOD__,10);
                             if ($daily_total_time > 0 and ($break_policy_obj === TRUE or $daily_total_time > $break_policy_obj->getTriggerTime())) {
                                 //Check for break punch.
                                 $break_punch = FALSE;
                                 $tmp_punch_total_time = 0;
                                 $tmp_punch_control_ids = array();
                                 foreach ($plf as $p_obj) {
                                     if ($p_obj->getType() == 30) {
                                         //30 = Break
                                         Debug::text('Found break Punch: ' . $p_obj->getTimeStamp(), __FILE__, __LINE__, __METHOD__, 10);
                                         $break_punch = TRUE;
                                         break;
                                     }
                                     if (isset($punch_control_total_time[$p_obj->getPunchControlID()]) and !isset($tmp_punch_control_ids[$p_obj->getPunchControlID()])) {
                                         $tmp_punch_total_time += $punch_control_total_time[$p_obj->getPunchControlID()];
                                         if ($punch_control_id === FALSE and ($break_policy_obj === TRUE or $tmp_punch_total_time > $break_policy_obj->getTriggerTime())) {
                                             Debug::text('Found punch control for exception: ' . $p_obj->getPunchControlID(), __FILE__, __LINE__, __METHOD__, 10);
                                             $punch_control_id = $p_obj->getPunchControlID();
                                             //Don't break the loop here, as we have to continue on and check for other breaks.
                                         }
                                     }
                                     $tmp_punch_control_ids[$p_obj->getPunchControlID()] = TRUE;
                                 }
                                 unset($tmp_punch_total_time, $tmp_punch_control_ids);
                                 if ($break_punch == FALSE) {
                                     Debug::text('Triggering No Break exception!', __FILE__, __LINE__, __METHOD__, 10);
                                     $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => $punch_control_id);
                                 }
                             }
                         }
                     }
                     break;
                 case 'v1':
                     //TimeSheet Not Verified
                     //Get pay period schedule data, determine if timesheet verification is even enabled.
                     if (is_object($user_date_obj->getPayPeriodObject()) and is_object($user_date_obj->getPayPeriodObject()->getPayPeriodScheduleObject()) and $user_date_obj->getPayPeriodObject()->getPayPeriodScheduleObject()->getTimeSheetVerifyType() > 10) {
                         Debug::text('Verification enabled... Window Start: ' . TTDate::getDate('DATE+TIME', $user_date_obj->getPayPeriodObject()->getTimeSheetVerifyWindowStartDate()) . ' Grace Time: ' . $ep_obj->getGrace(), __FILE__, __LINE__, __METHOD__, 10);
                         //*Only* trigger this exception on the last day of the pay period, because when the pay period is verified it has to force the last day to be recalculated.
                         //Ignore timesheets without any time, (worked and absence). Or we could use the Watch Window to specify the minimum time required on
                         //a timesheet to trigger this instead?
                         //Make sure we are after the timesheet window start date + the grace period.
                         if ($user_date_obj->getPayPeriodObject()->getStatus() != 50 and $current_epoch >= $user_date_obj->getPayPeriodObject()->getTimeSheetVerifyWindowStartDate() + $ep_obj->getGrace() and TTDate::getBeginDayEpoch($user_date_obj->getDateStamp()) == TTDate::getBeginDayEpoch($user_date_obj->getPayPeriodObject()->getEndDate())) {
                             //Get pay period total time, include worked and paid absence time.
                             $udtlf = TTnew('UserDateTotalListFactory');
                             $total_time = $udtlf->getTimeSumByUserIDAndPayPeriodId($user_date_obj->getUser(), $user_date_obj->getPayPeriodObject()->getID());
                             if ($total_time > 0) {
                                 //Check to see if pay period has been verified or not yet.
                                 $pptsvlf = TTnew('PayPeriodTimeSheetVerifyListFactory');
                                 $pptsvlf->getByPayPeriodIdAndUserId($user_date_obj->getPayPeriodObject()->getId(), $user_date_obj->getUser());
                                 $pay_period_verified = FALSE;
                                 if ($pptsvlf->getRecordCount() > 0) {
                                     $pay_period_verified = $pptsvlf->getCurrent()->getAuthorized();
                                 }
                                 if ($pay_period_verified == FALSE) {
                                     //Always allow for emailing this exception because it can be triggered after a punch is modified and
                                     //any supervisor would need to be notified to verify the timesheet again.
                                     $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => FALSE, 'enable_email_notification' => TRUE);
                                 } else {
                                     Debug::text('TimeSheet has already been authorized!', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             } else {
                                 Debug::text('Timesheet does not have any worked or paid absence time...', __FILE__, __LINE__, __METHOD__, 10);
                             }
                             unset($udtlf, $total_time);
                         } else {
                             Debug::text('Not within timesheet verification window, or not after grace time.', __FILE__, __LINE__, __METHOD__, 10);
                         }
                     } else {
                         Debug::text('No Pay Period Schedule or TimeSheet Verificiation disabled...', __FILE__, __LINE__, __METHOD__, 10);
                     }
                     break;
                 case 'j1':
                     //Not Allowed on Job
                     if (getTTProductEdition() >= TT_PRODUCT_CORPORATE and $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 = TTnew('JobListFactory');
                                     $jlf->getById($p_obj->getPunchControlObject()->getJob());
                                     if ($jlf->getRecordCount() > 0) {
                                         $j_obj = $jlf->getCurrent();
                                         if ($j_obj->isAllowedUser($user_date_obj->getUser()) == FALSE) {
                                             $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => $p_obj->getPunchControlId());
                                         } else {
                                             Debug::text('    User allowed on Job!', __FILE__, __LINE__, __METHOD__, 10);
                                         }
                                     } else {
                                         Debug::text('    Job not found!', __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                 } else {
                                     //Debug::text('    Not a Job Punch...', __FILE__, __LINE__, __METHOD__,10);
                                 }
                             }
                         }
                         unset($j_obj);
                     }
                     break;
                 case 'j2':
                     //Not Allowed on Task
                     if (getTTProductEdition() >= TT_PRODUCT_CORPORATE and $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 = TTnew('JobListFactory');
                                     $jlf->getById($p_obj->getPunchControlObject()->getJob());
                                     if ($jlf->getRecordCount() > 0) {
                                         $j_obj = $jlf->getCurrent();
                                         if ($j_obj->isAllowedItem($p_obj->getPunchControlObject()->getJobItem()) == FALSE) {
                                             $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => $p_obj->getPunchControlId());
                                         } else {
                                             Debug::text('    Job item allowed on job!', __FILE__, __LINE__, __METHOD__, 10);
                                         }
                                     } else {
                                         Debug::text('    Job not found!', __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                 } else {
                                     //Debug::text('    Not a Job Punch...', __FILE__, __LINE__, __METHOD__,10);
                                 }
                             }
                         }
                         unset($j_obj);
                     }
                     break;
                 case 'j3':
                     //Job already completed
                     if (getTTProductEdition() >= TT_PRODUCT_CORPORATE and $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 = TTnew('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()) {
                                             $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => FALSE, 'punch_control_id' => $p_obj->getPunchControlId());
                                         } else {
                                             Debug::text('    Job Not Completed!', __FILE__, __LINE__, __METHOD__, 10);
                                         }
                                     } else {
                                         Debug::text('    Job not found!', __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                 } else {
                                     Debug::text('    Not a Job Punch...', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             }
                         }
                         unset($j_obj);
                     }
                     break;
                 case 'j4':
                     //No Job or Task
                     if (getTTProductEdition() >= TT_PRODUCT_CORPORATE and $plf->getRecordCount() > 0) {
                         foreach ($plf as $p_obj) {
                             $add_exception = FALSE;
                             //In punches only
                             if ($p_obj->getStatus() == 10 and is_object($p_obj->getPunchControlObject())) {
                                 //If no Tasks are setup, ignore checking them.
                                 if ($p_obj->getPunchControlObject()->getJob() == '' or $p_obj->getPunchControlObject()->getJob() == 0 or $p_obj->getPunchControlObject()->getJob() == FALSE) {
                                     $add_exception = TRUE;
                                 }
                                 if ($p_obj->getPunchControlObject()->getJobItem() == '' or $p_obj->getPunchControlObject()->getJobItem() == 0 or $p_obj->getPunchControlObject()->getJobItem() == FALSE) {
                                     //Make sure at least one task exists before triggering exception.
                                     $jilf = TTNew('JobItemListFactory');
                                     $jilf->getByCompanyID($user_date_obj->getUserObject()->getCompany(), 1);
                                     //Limit to just 1 record.
                                     if ($jilf->getRecordCount() > 0) {
                                         $add_exception = TRUE;
                                     }
                                 }
                                 if ($add_exception === TRUE) {
                                     $current_exceptions[] = array('user_date_id' => $user_date_id, 'exception_policy_id' => $ep_obj->getId(), 'type_id' => $type_id, 'punch_id' => $p_obj->getId(), 'punch_control_id' => $p_obj->getPunchControlId());
                                 }
                             }
                         }
                     }
                     break;
                 default:
                     Debug::text('BAD, should never get here: ', __FILE__, __LINE__, __METHOD__, 10);
                     break;
             }
         }
     }
     unset($ep_obj);
     $exceptions = self::diffExistingAndCurrentExceptions($existing_exceptions, $current_exceptions);
     if (is_array($exceptions)) {
         if (isset($exceptions['create_exceptions']) and is_array($exceptions['create_exceptions']) and count($exceptions['create_exceptions']) > 0) {
             Debug::text('Creating new exceptions... Total: ' . count($exceptions['create_exceptions']), __FILE__, __LINE__, __METHOD__, 10);
             foreach ($exceptions['create_exceptions'] as $tmp_exception) {
                 $ef = TTnew('ExceptionFactory');
                 $ef->setUserDateID($tmp_exception['user_date_id']);
                 $ef->setExceptionPolicyID($tmp_exception['exception_policy_id']);
                 $ef->setType($tmp_exception['type_id']);
                 if (isset($tmp_exception['punch_control_id']) and $tmp_exception['punch_control_id'] != '') {
                     $ef->setPunchControlId($tmp_exception['punch_control_id']);
                 }
                 if (isset($tmp_exception['punch_id']) and $tmp_exception['punch_id'] != '') {
                     $ef->setPunchId($tmp_exception['punch_id']);
                 }
                 $ef->setEnableDemerits(TRUE);
                 if ($ef->isValid()) {
                     $ef->Save(FALSE);
                     //Save exception prior to emailing it, otherwise we can't save audit logs.
                     if ($enable_premature_exceptions == TRUE or isset($tmp_exception['enable_email_notification']) and $tmp_exception['enable_email_notification'] == TRUE) {
                         $eplf = TTnew('ExceptionPolicyListFactory');
                         $eplf->getById($tmp_exception['exception_policy_id']);
                         if ($eplf->getRecordCount() == 1) {
                             $ep_obj = $eplf->getCurrent();
                             $ef->emailException($user_date_obj->getUserObject(), $user_date_obj, isset($tmp_exception['punch_obj']) ? $tmp_exception['punch_obj'] : NULL, isset($tmp_exception['schedule_obj']) ? $tmp_exception['schedule_obj'] : NULL, $ep_obj);
                         }
                     } else {
                         Debug::text('Not emailing new exception: User Date ID: ' . $tmp_exception['user_date_id'] . ' Type ID: ' . $tmp_exception['type_id'] . ' Enable PreMature: ' . (int) $enable_premature_exceptions, __FILE__, __LINE__, __METHOD__, 10);
                     }
                 }
                 unset($ef);
             }
         }
         if (isset($exceptions['delete_exceptions']) and is_array($exceptions['delete_exceptions']) and count($exceptions['delete_exceptions']) > 0) {
             Debug::Text('Deleting no longer valid exceptions... Total: ' . count($exceptions['delete_exceptions']), __FILE__, __LINE__, __METHOD__, 10);
             $ef = TTnew('ExceptionFactory');
             $ef->bulkDelete($exceptions['delete_exceptions']);
         }
     }
     $profiler->stopTimer("ExceptionPolicy::calcExceptions()");
     return TRUE;
 }
     break;
 case 'recalculate_company':
     Debug::Text('Recalculating company timesheet!', __FILE__, __LINE__, __METHOD__, 10);
     //Redirect::Page( URLBuilder::getURL( array('action' => 'recalculate_company', 'pay_period_ids' => $pay_period_id, 'next_page' => urlencode( URLBuilder::getURL( array('filter_date' => $filter_date ), '../timesheet/ViewUserTimeSheet.php') ) ), '../progress_bar/ProgressBarControl.php') );
     Redirect::Page(URLBuilder::getURL(array('action' => 'recalculate_company', 'pay_period_ids' => $pay_period_id, 'next_page' => urlencode(URLBuilder::getURL(NULL, '../timesheet/ViewUserTimeSheet.php'))), '../progress_bar/ProgressBarControl.php'), FALSE);
     break;
 case 'recalculate_employee':
     Debug::Text('Recalculating employee timesheet!', __FILE__, __LINE__, __METHOD__, 10);
     Redirect::Page(URLBuilder::getURL(array('action' => 'recalculate_employee', 'pay_period_ids' => $pay_period_id, 'filter_user_id' => $filter_data['user_id'], 'next_page' => urlencode(URLBuilder::getURL(NULL, '../timesheet/ViewUserTimeSheet.php'))), '../progress_bar/ProgressBarControl.php'), FALSE);
     break;
 case 'submit':
 default:
     BreadCrumb::setCrumb($title);
     Debug::Text('Default Action: ' . $action, __FILE__, __LINE__, __METHOD__, 10);
     $start_date = TTDate::getBeginWeekEpoch($filter_data['date'], $current_user_prefs->getStartWeekDay());
     $end_date = TTDate::getEndWeekEpoch($filter_data['date'], $current_user_prefs->getStartWeekDay());
     Debug::Text('Start Date: ' . TTDate::getDate('DATE+TIME', $start_date) . ' End Date: ' . TTDate::getDate('DATE+TIME', $end_date), __FILE__, __LINE__, __METHOD__, 10);
     $calendar_array = TTDate::getCalendarArray($start_date, $end_date, $current_user_prefs->getStartWeekDay());
     //var_dump($calendar_array);
     //Get all punches, put in array by date epoch.
     $plf = TTnew('PunchListFactory');
     $plf->getByCompanyIDAndUserIdAndStartDateAndEndDate($current_company->getId(), $user_id, $start_date, $end_date);
     if ($plf->getRecordCount() > 0) {
         foreach ($plf as $punch_obj) {
             $user_date_stamp = TTDate::strtotime($punch_obj->getColumn('user_date_stamp'));
             if ($punch_obj->getColumn('note') != '') {
                 $has_note = TRUE;
             } else {
                 $has_note = FALSE;
             }
             $punches[$user_date_stamp][] = array('date_stamp' => $punch_obj->getColumn('user_date_stamp'), 'id' => $punch_obj->getId(), 'punch_control_id' => $punch_obj->getPunchControlId(), 'time_stamp' => $punch_obj->getTimeStamp(), 'status_id' => $punch_obj->getStatus(), 'type_id' => $punch_obj->getType(), 'type_code' => $punch_obj->getTypeCode(), 'has_note' => $has_note);
Exemple #12
0
 /**
  * Get punch data for one or more punches.
  * @param array $data filter data
  * @return array
  */
 function getPunch($data = NULL, $disable_paging = FALSE)
 {
     if (!$this->getPermissionObject()->Check('punch', 'enabled') or !($this->getPermissionObject()->Check('punch', 'view') or $this->getPermissionObject()->Check('punch', 'view_own') or $this->getPermissionObject()->Check('punch', 'view_child'))) {
         return $this->getPermissionObject()->PermissionDenied();
     }
     $data = $this->initializeFilterAndPager($data, $disable_paging);
     $data['filter_data']['permission_children_ids'] = $this->getPermissionObject()->getPermissionChildren('punch', 'view');
     //As a performance optimization to prevent the API from having to do additional date lookups, accept a single "date" field, that converts
     //into start/end dates.
     if (isset($data['filter_data']['date']) and $data['filter_data']['date'] != '') {
         $data['filter_data']['start_date'] = TTDate::getBeginWeekEpoch($data['filter_data']['date'], $this->getCurrentUserPreferenceObject()->getStartWeekDay());
         $data['filter_data']['end_date'] = TTDate::getEndWeekEpoch($data['filter_data']['date'], $this->getCurrentUserPreferenceObject()->getStartWeekDay());
     }
     //No filter data, restrict to last pay period as a performance optimization when hundreds of thousands of punches exist.
     //The issue with this though is that the API doesn't know what the filter criteria is, so it can't display this to the user.
     if (count($data['filter_data']) == 1 and !isset($data['filter_data']['pay_period_ids'])) {
         Debug::Text('Adding default filter data...', __FILE__, __LINE__, __METHOD__, 10);
         $pplf = TTnew('PayPeriodListFactory');
         $pplf->getByCompanyId($this->getCurrentCompanyObject()->getId());
         $pay_period_ids = array_keys((array) $pplf->getArrayByListFactory($pplf, FALSE, FALSE));
         if (isset($pay_period_ids[0]) and isset($pay_period_ids[1])) {
             $data['filter_data']['pay_period_ids'] = array($pay_period_ids[0], $pay_period_ids[1]);
         }
         unset($pplf, $pay_period_ids);
     }
     $blf = TTnew('PunchListFactory');
     $blf->getAPISearchByCompanyIdAndArrayCriteria($this->getCurrentCompanyObject()->getId(), $data['filter_data'], $data['filter_items_per_page'], $data['filter_page'], NULL, $data['filter_sort']);
     Debug::Text('Record Count: ' . $blf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
     if ($blf->getRecordCount() > 0) {
         $this->getProgressBarObject()->start($this->getAMFMessageID(), $blf->getRecordCount());
         $this->setPagerObject($blf);
         foreach ($blf as $b_obj) {
             $retarr[] = $b_obj->getObjectAsArray($data['filter_columns'], $data['filter_data']['permission_children_ids']);
             $this->getProgressBarObject()->set($this->getAMFMessageID(), $blf->getCurrentRow());
         }
         $this->getProgressBarObject()->stop($this->getAMFMessageID());
         return $this->returnHandler($retarr);
     }
     return $this->returnHandler(TRUE);
     //No records returned.
 }