Пример #1
0
function parse_hire_date($input, $default_value = NULL, $parse_hint = NULL)
{
    if (isset($parse_hint) and $parse_hint != '') {
        TTDate::setDateFormat($parse_hint);
        return TTDate::getMiddleDayEpoch(TTDate::parseDateTime($input));
    } else {
        return TTDate::getMiddleDayEpoch(TTDate::strtotime($input));
    }
}
Пример #2
0
 */
/*
 * Calculate Exceptions for the previous day. This helps especially for
 * the "Unscheuled Absence" exception.
 *
 * Run this once a day. AFTER AddUserDate
 */
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'global.inc.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'CLI.inc.php';
//Debug::setVerbosity(5);
$execution_time = time();
//Calculate exceptions just for today and yesterday, because some shifts may start late in the day and need to be handled first thing in the morning.
//Make sure we also go one day in the future too, since the servers can be PST and if its 11:00PM, it will stop at midnight for that day, so
//shifts that would have already started in a different timezone (say EST) will not receive exceptions until we have moved into the next day for PST (3hrs late)
$start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($execution_time) - 86400);
$end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($execution_time) + 86400);
$udlf = new UserDateListFactory();
//Use optimized query to speed this process up significantly.
$udlf->getMidDayExceptionsByStartDateAndEndDateAndPayPeriodStatus($start_date, $end_date, array(10, 12, 15, 30));
Debug::text(' calcQuickExceptions: Start Date: ' . TTDate::getDate('DATE+TIME', $start_date) . ' End Date: ' . TTDate::getDate('DATE+TIME', $end_date) . ' User Date Rows: ' . $udlf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 5);
if ($udlf->getRecordCount() > 0) {
    $i = 0;
    foreach ($udlf as $ud_obj) {
        $user_obj_prefs = $ud_obj->getUserObject()->getUserPreferenceObject();
        if (is_object($user_obj_prefs)) {
            $user_obj_prefs->setTimeZonePreferences();
        } else {
            //Use system timezone.
            TTDate::setTimeZone();
        }
        Debug::text('(' . $i . '). User: '******' Date: ' . TTDate::getDate('DATE+TIME', $ud_obj->getDateStamp()) . ' User Date ID: ' . $ud_obj->getId(), __FILE__, __LINE__, __METHOD__, 5);
Пример #3
0
                $i = 0;
                foreach ($udlf as $ud_obj) {
                    //Recalculate system time, and exceptions for the day.
                    //Because if its a Monday, it will also recalculate the rest of the days in the week.
                    //Shouldn't be a big deal though.
                    //This isn't needed, since we now do it in AddRecurringScheduleShift, so dock time is
                    //applied at the beginning of the day.
                    //The problem is that AddRecurringScheduleShift does it, then for the entire day someone with
                    //a dock policy shows up as dock time. Some users have complained about this a few times.
                    //Reason for doing two days ago is that if someone starts a shift at 11pm, but doesn't end it in
                    //time, it still needs to be re-calculated a day later.
                    //Could maybe get around this by getting all punches of yesterday, and getting their date_ids
                    //and just recalculating those.
                    //Enable pre-mature exceptions if we're recalculating just one day ago.
                    $enable_premature_exceptions = FALSE;
                    if ($end_date == TTDate::getMiddleDayEpoch($ud_obj->getDateStamp())) {
                        $enable_premature_exceptions = TRUE;
                    }
                    Debug::text($x . '(' . $i . '). User: '******' Date: ' . TTDate::getDate('DATE+TIME', $ud_obj->getDateStamp()) . ' User Date ID: ' . $ud_obj->getId() . ' Enable PreMature Exceptions: ' . (int) $enable_premature_exceptions, __FILE__, __LINE__, __METHOD__, 5);
                    UserDateTotalFactory::reCalculateDay($ud_obj->getId(), TRUE, $enable_premature_exceptions);
                    $i++;
                    $x++;
                }
            }
            Debug::text('Company: ' . $c_obj->getName() . '(' . $c_obj->getId() . ') Finished In: ' . (microtime(TRUE) - $company_start_time) . 's', __FILE__, __LINE__, __METHOD__, 5);
        }
    }
}
/*
//Two days ago.
$date = TTDate::getMiddleDayEpoch( time() ) - (86400*2);
 function getNextPayPeriod($end_date = NULL)
 {
     if (!$this->Validator->isValid()) {
         return FALSE;
     }
     //Manual Pay Period Schedule, skip repeating...
     if ($this->getType() == 5) {
         return FALSE;
     }
     $pplf = new PayPeriodListFactory();
     //Debug::text('PP Schedule ID: '. $this->getId(), __FILE__, __LINE__, __METHOD__, 10);
     //Debug::text('PP Schedule Name: '. $this->getName(), __FILE__, __LINE__, __METHOD__, 10);
     Debug::text('PP Schedule Type (' . $this->getType() . '): ' . Option::getByKey($this->getType(), $this->getOptions('type')), __FILE__, __LINE__, __METHOD__, 10);
     //Debug::text('Anchor Date: '. $this->getAnchorDate() ." - ". TTDate::getDate('DATE+TIME', $this->getAnchorDate() ), __FILE__, __LINE__, __METHOD__, 10);
     //Debug::text('Primary Date: '. $this->getPrimaryDate() ." - ". TTDate::getDate('DATE+TIME', $this->getPrimaryDate() ), __FILE__, __LINE__, __METHOD__, 10);
     //Debug::text('Secondary Date: '. $this->getSecondaryDate() ." - ". TTDate::getDate('DATE+TIME', $this->getPrimaryDate() ), __FILE__, __LINE__, __METHOD__, 10);
     $last_pay_period_is_new = FALSE;
     if ($end_date != '' and $end_date != 0) {
         Debug::text('End Date is set: ' . TTDate::getDate('DATE+TIME', $end_date), __FILE__, __LINE__, __METHOD__, 10);
         $last_pay_period_end_date = $end_date;
     } else {
         Debug::text('Checking for Previous pay periods...', __FILE__, __LINE__, __METHOD__, 10);
         //Get the last pay period schedule in the database.
         $pplf->getByPayPeriodScheduleId($this->getId(), NULL, NULL, NULL, array('start_date' => 'desc'));
         $last_pay_period = $pplf->getCurrent();
         if ($last_pay_period->isNew()) {
             $last_pay_period_is_new = TRUE;
             Debug::text('No Previous pay periods...', __FILE__, __LINE__, __METHOD__, 10);
             //Do this so a rollover doesn't happen while we're calculating.
             //$last_pay_period_end_date = TTDate::getTime();
             //This causes the pay period schedule to jump ahead one month. So set this to be beginning of the month.
             $last_pay_period_end_date = TTDate::getBeginMonthEpoch();
         } else {
             Debug::text('Previous pay periods found... ID: ' . $last_pay_period->getId(), __FILE__, __LINE__, __METHOD__, 10);
             $last_pay_period_end_date = $last_pay_period->getEndDate();
         }
         unset($last_pay_period, $pplf);
     }
     Debug::text('aLast Pay Period End Date: ' . TTDate::getDate('DATE+TIME', $last_pay_period_end_date) . ' (' . $last_pay_period_end_date . ')', __FILE__, __LINE__, __METHOD__, 10);
     //FIXME: This breaks having pay periods with different daily start times.
     //However, without it, I think DST breaks pay periods.
     //$last_pay_period_end_date = TTDate::getEndDayEpoch( $last_pay_period_end_date + 1 ) - 86400;
     $last_pay_period_end_date = TTDate::getEndDayEpoch($last_pay_period_end_date - 86400 / 2);
     Debug::text('bLast Pay Period End Date: ' . TTDate::getDate('DATE+TIME', $last_pay_period_end_date) . ' (' . $last_pay_period_end_date . ')', __FILE__, __LINE__, __METHOD__, 10);
     if ($this->getDayStartTime() != 0) {
         Debug::text('Daily Start Time is set, adjusting Last Pay Period End Date by: ' . TTDate::getHours($this->getDayStartTime()), __FILE__, __LINE__, __METHOD__, 10);
         //Next adjust last_pay_period_end_date (which becomes the start date) to DayStartTime because then there could be a gap if they
         //change this mid-schedule. The End Date will take care of it after the first pay period.
         $last_pay_period_end_date = TTDate::getTimeLockedDate(TTDate::getBeginDayEpoch($last_pay_period_end_date) + $this->getDayStartTime(), $last_pay_period_end_date);
         Debug::text('cLast Pay Period End Date: ' . TTDate::getDate('DATE+TIME', $last_pay_period_end_date) . ' (' . $last_pay_period_end_date . ')', __FILE__, __LINE__, __METHOD__, 10);
     }
     $insert_pay_period = 1;
     //deprecate primary pay periods.
     switch ($this->getType()) {
         case 10:
             //Weekly
         //Weekly
         case 20:
             //Bi-Weekly
             $last_pay_period_end_day_of_week = TTDate::getDayOfWeek($last_pay_period_end_date);
             Debug::text('Last Pay Period End Day Of Week: ' . $last_pay_period_end_day_of_week . ' Start Day Of Week: ' . $this->getStartDayOfWeek(), __LINE__, __METHOD__, 10);
             if ($last_pay_period_end_day_of_week != $this->getStartDayOfWeek()) {
                 Debug::text('zTmp Pay Period End Date: ' . 'next ' . TTDate::getDayOfWeekByInt($this->getStartDayOfWeek()), __FILE__, __LINE__, __METHOD__, 10);
                 //$tmp_pay_period_end_date = strtotime('next '. TTDate::getDayOfWeekByInt( $this->getStartDayOfWeek() ), $last_pay_period_end_date )-1;
                 $tmp_pay_period_end_date = strtotime('next ' . TTDate::getDayOfWeekByInt($this->getStartDayOfWeek(), FALSE), $last_pay_period_end_date);
                 //strtotime doesn't keep time when using "next", it resets it to midnight on the day, so we need to adjust for that.
                 $tmp_pay_period_end_date = TTDate::getTimeLockedDate(TTDate::getBeginDayEpoch($tmp_pay_period_end_date) + $this->getDayStartTime(), $tmp_pay_period_end_date) - 1;
             } else {
                 $tmp_pay_period_end_date = $last_pay_period_end_date;
                 //This should fix a bug where if they are creating a new pay period schedule
                 //starting on Monday with the anchor date of 01-Jul-08, it would start on 01-Jul-08 (Tue)
                 //rather moving back to the Monday.
                 if (TTDate::getDayOfMonth($tmp_pay_period_end_date) != TTDate::getDayOfMonth($tmp_pay_period_end_date + 1)) {
                     Debug::text('Right on day boundary, minus an additional second to account for difference...', __FILE__, __LINE__, __METHOD__, 10);
                     $tmp_pay_period_end_date--;
                 }
             }
             Debug::text('aTmp Pay Period End Date: ' . TTDate::getDate('DATE+TIME', $tmp_pay_period_end_date) . ' (' . $tmp_pay_period_end_date . ')', __FILE__, __LINE__, __METHOD__, 10);
             $start_date = $tmp_pay_period_end_date + 1;
             if ($this->getType() == 10) {
                 //Weekly
                 $tmp_pay_period_end_date = TTDate::getMiddleDayEpoch($start_date) + 86400 * 7;
                 //Add one week
             } elseif ($this->getType() == 20) {
                 //Bi-Weekly
                 $tmp_pay_period_end_date = TTDate::getMiddleDayEpoch($start_date) + 86400 * 14;
                 //Add two weeks
             }
             //Use Begin Day Epoch to nullify DST issues.
             $end_date = TTDate::getBeginDayEpoch($tmp_pay_period_end_date) - 1;
             $transaction_date = TTDate::getMiddleDayEpoch(TTDate::getMiddleDayEpoch($end_date) + $this->getTransactionDate() * 86400);
             break;
         case 30:
             //Semi-monthly
             $tmp_last_pay_period_end_day_of_month = TTDate::getDayOfMonth($last_pay_period_end_date + 1);
             Debug::text('bLast Pay Period End Day Of Month: ' . $tmp_last_pay_period_end_day_of_month, __FILE__, __LINE__, __METHOD__, 10);
             if ($tmp_last_pay_period_end_day_of_month == $this->convertLastDayOfMonth($this->getPrimaryDayOfMonth())) {
                 $insert_pay_period = 1;
                 $primary = TRUE;
             } elseif ($tmp_last_pay_period_end_day_of_month == $this->convertLastDayOfMonth($this->getSecondaryDayOfMonth())) {
                 $insert_pay_period = 2;
                 $primary = FALSE;
             } else {
                 Debug::text('Finding if Primary or Secondary is closest...', __FILE__, __LINE__, __METHOD__, 10);
                 $primary_date_offset = TTDate::getDateOfNextDayOfMonth($last_pay_period_end_date, NULL, $this->convertLastDayOfMonth($this->getPrimaryDayOfMonth())) - $last_pay_period_end_date;
                 $secondary_date_offset = TTDate::getDateOfNextDayOfMonth($last_pay_period_end_date, NULL, $this->convertLastDayOfMonth($this->getSecondaryDayOfMonth())) - $last_pay_period_end_date;
                 Debug::text('Primary Date Offset: ' . TTDate::getDays($primary_date_offset) . ' Secondary Date Offset: ' . TTDate::getDays($secondary_date_offset), __FILE__, __LINE__, __METHOD__, 10);
                 if ($primary_date_offset <= $secondary_date_offset) {
                     $insert_pay_period = 1;
                     $primary = TRUE;
                     $last_pay_period_end_date = TTDate::getDateOfNextDayOfMonth($last_pay_period_end_date, NULL, $this->convertLastDayOfMonth($this->getPrimaryDayOfMonth()));
                 } else {
                     $insert_pay_period = 2;
                     $primary = FALSE;
                     $last_pay_period_end_date = TTDate::getDateOfNextDayOfMonth($last_pay_period_end_date, NULL, $this->convertLastDayOfMonth($this->getSecondaryDayOfMonth()));
                 }
                 $last_pay_period_end_date = TTDate::getBeginDayEpoch($last_pay_period_end_date);
             }
             unset($tmp_last_pay_period_end_day_of_month);
             Debug::text('cLast Pay Period End Date: ' . TTDate::getDate('DATE+TIME', $last_pay_period_end_date) . ' (' . $last_pay_period_end_date . ') Primary: ' . (int) $primary, __FILE__, __LINE__, __METHOD__, 10);
             $start_date = $last_pay_period_end_date + 1;
             if ($primary == TRUE) {
                 $end_date = TTDate::getBeginDayEpoch(TTDate::getDateOfNextDayOfMonth($start_date, NULL, $this->convertLastDayOfMonth($this->getSecondaryDayOfMonth()))) - 1;
                 $transaction_date = TTDate::getMiddleDayEpoch(TTDate::getDateOfNextDayOfMonth(TTDate::getMiddleDayEpoch($end_date), NULL, $this->convertLastDayOfMonth($this->getPrimaryTransactionDayOfMonth())));
             } else {
                 $end_date = TTDate::getBeginDayEpoch(TTDate::getDateOfNextDayOfMonth($start_date, NULL, $this->convertLastDayOfMonth($this->getPrimaryDayOfMonth()))) - 1;
                 $transaction_date = TTDate::getMiddleDayEpoch(TTDate::getDateOfNextDayOfMonth(TTDate::getMiddleDayEpoch($end_date), NULL, $this->convertLastDayOfMonth($this->getSecondaryTransactionDayOfMonth())));
             }
             break;
         case 50:
             //Monthly
             $start_date = $last_pay_period_end_date + 1;
             $end_date = TTDate::getDateOfNextDayOfMonth($start_date + 86400, NULL, $this->convertLastDayOfMonth($this->getPrimaryDayOfMonth()));
             //Use Begin Day Epoch to nullify DST issues.
             $end_date = TTDate::getBeginDayEpoch(TTDate::getBeginMinuteEpoch($end_date)) - 1;
             $transaction_date = TTDate::getMiddleDayEpoch(TTDate::getDateOfNextDayOfMonth($end_date, NULL, $this->convertLastDayOfMonth($this->getPrimaryTransactionDayOfMonth())));
             break;
     }
     if ($this->getDayStartTime() != 0) {
         Debug::text('Daily Start Time is set, adjusting End Date by: ' . TTDate::getHours($this->getDayStartTime()) . ' Start Date: ' . TTDate::getDate('DATE+TIME', $start_date), __FILE__, __LINE__, __METHOD__, 10);
         //We already account for DayStartTime in weekly/bi-weekly start_date cases above, so skip applying it again here.
         if ($this->getType() != 10 and $this->getType() != 20) {
             $start_date = $start_date + $this->getDayStartTime();
         }
         $end_date = $end_date + $this->getDayStartTime();
         //Need to do this, otherwise transaction date could be earlier then end date.
         $transaction_date = $transaction_date + $this->getDayStartTime();
     }
     Debug::text('aStart Date(' . $start_date . '): ' . TTDate::getDate('DATE+TIME', $start_date), __FILE__, __LINE__, __METHOD__, 10);
     Debug::text('aEnd Date(' . $end_date . '): ' . TTDate::getDate('DATE+TIME', $end_date), __FILE__, __LINE__, __METHOD__, 10);
     Debug::text('aPay Date(' . $transaction_date . '): ' . TTDate::getDate('DATE+TIME', $transaction_date), __FILE__, __LINE__, __METHOD__, 10);
     //Handle last day of the month flag for primary and secondary dates here
     if ($this->getType() == 30 and ($insert_pay_period == 1 and ($this->getPrimaryDayOfMonth() == 31 or $this->getPrimaryDayOfMonth() == -1) or $insert_pay_period == 2 and ($this->getSecondaryDayOfMonth() == 31 or $this->getSecondaryDayOfMonth() == -1)) or $this->getType() == 50 and ($this->getPrimaryDayOfMonth() == 31 or $this->getPrimaryDayOfMonth() == -1)) {
         Debug::text('Last day of the month set for start date: ', __FILE__, __LINE__, __METHOD__, 10);
         if ($this->getDayStartTime() > 0) {
             //Minus one day, THEN add daily start time, otherwise it will go past the month boundary
             $end_date = TTDate::getEndMonthEpoch($end_date) - 86400 + $this->getDayStartTime();
             //End month epoch is 23:59:59, so don't minus one.
         } else {
             $end_date = TTDate::getEndMonthEpoch($end_date) + $this->getDayStartTime();
             //End month epoch is 23:59:59, so don't minus one.
         }
     }
     //Handle "last day of the month" for transaction dates.
     if ($this->getPrimaryDayOfMonth() == 31 or $this->getPrimaryDayOfMonth() == -1) {
         //Debug::text('LDOM set for Primary: ', __FILE__, __LINE__, __METHOD__, 10);
         $transaction_date = TTDate::getEndMonthEpoch($transaction_date);
     }
     //Handle "always business day" flag for transaction dates here.
     if ($this->getTransactionDateBusinessDay() == TRUE) {
         $transaction_date = $this->getTransactionBusinessDay($transaction_date);
     }
     if ($transaction_date < $end_date) {
         $transaction_date = $end_date;
     }
     Debug::text('Start Date: ' . TTDate::getDate('DATE+TIME', $start_date), __FILE__, __LINE__, __METHOD__, 10);
     Debug::text('End Date: ' . TTDate::getDate('DATE+TIME', $end_date), __FILE__, __LINE__, __METHOD__, 10);
     Debug::text('Pay Date: ' . TTDate::getDate('DATE+TIME', $transaction_date), __FILE__, __LINE__, __METHOD__, 10);
     Debug::text("<br><br>\n\n", __FILE__, __LINE__, __METHOD__, 10);
     $this->next_start_date = $start_date;
     $this->next_end_date = $end_date;
     $this->next_transaction_date = $transaction_date;
     //Its a primary pay period
     if ($insert_pay_period == 1) {
         $this->next_primary = TRUE;
     } else {
         $this->next_primary = FALSE;
     }
     return TRUE;
 }
Пример #5
0
                    //Because if its a Monday, it will also recalculate the rest of the days in the week.
                    //Shouldn't be a big deal though.
                    //This isn't needed, since we now do it in AddRecurringScheduleShift, so dock time is
                    //applied at the beginning of the day.
                    //The problem is that AddRecurringScheduleShift does it, then for the entire day someone with
                    //a dock policy shows up as dock time. Some users have complained about this a few times.
                    //Reason for doing two days ago is that if someone starts a shift at 11pm, but doesn't end it in
                    //time, it still needs to be re-calculated a day later.
                    //Could maybe get around this by getting all punches of yesterday, and getting their date_ids
                    //and just recalculating those.
                    //Enable pre-mature exceptions if we're recalculating just one day ago.
                    //Problem is a late shift on say Monday: 2:00PM to 11:00PM won't trigger the exception at 1AM the next day,
                    //but by 1AM the following day (2days later) its too late and emails are disabled if enable_premature_exceptions are disabled.
                    $enable_premature_exceptions = FALSE;
                    //if ( $end_date == TTDate::getMiddleDayEpoch( $ud_obj->getDateStamp() ) ) {
                    if (TTDate::getMiddleDayEpoch($ud_obj->getDateStamp()) >= TTDate::getMiddleDayEpoch($execution_time) - 86400 * 2) {
                        $enable_premature_exceptions = TRUE;
                    }
                    Debug::text($x . '(' . $i . '). User: '******' Date: ' . TTDate::getDate('DATE+TIME', $ud_obj->getDateStamp()) . ' User Date ID: ' . $ud_obj->getId() . ' Enable PreMature Exceptions: ' . (int) $enable_premature_exceptions, __FILE__, __LINE__, __METHOD__, 5);
                    UserDateTotalFactory::reCalculateDay($ud_obj->getId(), TRUE, $enable_premature_exceptions);
                    TTDate::setTimeZone();
                    $i++;
                    $x++;
                }
            }
            Debug::text('Company: ' . $c_obj->getName() . '(' . $c_obj->getId() . ') Finished In: ' . (microtime(TRUE) - $company_start_time) . 's', __FILE__, __LINE__, __METHOD__, 5);
        }
    }
}
Debug::writeToLog();
Debug::Display();
 static function findOrInsertUserDate($user_id, $date, $timezone = NULL)
 {
     $date = TTDate::getMiddleDayEpoch($date);
     //Use mid day epoch so the timezone conversion across DST doesn't affect the date.
     if ($timezone == NULL) {
         //Find the employees preferred timezone, base the user date off that instead of the pay period timezone,
         //as it can be really confusing to the user if they punch in at 10AM on Sept 27th, but it records as Sept 26th because
         //the PP Schedule timezone is 12hrs different or something.
         $uplf = new UserPreferenceListFactory();
         $uplf->getByUserID($user_id);
         if ($uplf->getRecordCount() > 0) {
             $timezone = $uplf->getCurrent()->getTimeZone();
         }
     }
     $date = TTDate::convertTimeZone($date, $timezone);
     Debug::text(' Using TimeZone: ' . $timezone . ' Date: ' . TTDate::getDate('DATE+TIME', $date) . '(' . $date . ')', __FILE__, __LINE__, __METHOD__, 10);
     $udlf = new UserDateListFactory();
     $udlf->getByUserIdAndDate($user_id, $date);
     if ($udlf->getRecordCount() == 1) {
         $id = $udlf->getCurrent()->getId();
         Debug::text(' Found Already Existing User Date ID: ' . $id, __FILE__, __LINE__, __METHOD__, 10);
         return $id;
     } elseif ($udlf->getRecordCount() == 0) {
         Debug::text(' Inserting new UserDate row.', __FILE__, __LINE__, __METHOD__, 10);
         //Insert new row
         $udf = new UserDateFactory();
         $udf->setUser($user_id);
         $udf->setDateStamp($date);
         $udf->setPayPeriod();
         if ($udf->isValid()) {
             return $udf->Save();
         } else {
             Debug::text(' INVALID user date row. Pay Period Locked?', __FILE__, __LINE__, __METHOD__, 10);
         }
     } elseif ($udlf->getRecordCount() > 1) {
         Debug::text(' More then 1 user date row was detected!!: ' . $udlf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
     }
     Debug::text(' Cant find or insert User Date ID. User ID: ' . $user_id . ' Date: ' . $date, __FILE__, __LINE__, __METHOD__, 10);
     return FALSE;
 }
Пример #7
0
 function generatePayStubs($pay_period_ids, $user_ids = NULL, $enable_correction = FALSE)
 {
     global $profiler;
     Debug::Text('Generate Pay Stubs!', __FILE__, __LINE__, __METHOD__, 10);
     if (!$this->getPermissionObject()->Check('pay_period_schedule', 'enabled') or !($this->getPermissionObject()->Check('pay_period_schedule', 'edit') or $this->getPermissionObject()->Check('pay_period_schedule', 'edit_own'))) {
         return $this->getPermissionObject()->PermissionDenied();
     }
     if (!is_array($pay_period_ids)) {
         $pay_period_ids = array($pay_period_ids);
     }
     if ($user_ids !== NULL and !is_array($user_ids) and $user_ids > 0) {
         $user_ids = array($user_ids);
     } elseif (is_array($user_ids) and isset($user_ids[0]) and $user_ids[0] == 0) {
         $user_ids = NULL;
     }
     foreach ($pay_period_ids as $pay_period_id) {
         Debug::text('Pay Period ID: ' . $pay_period_id, __FILE__, __LINE__, __METHOD__, 10);
         $pplf = TTnew('PayPeriodListFactory');
         $pplf->getByIdAndCompanyId($pay_period_id, $this->getCurrentCompanyObject()->getId());
         $epoch = TTDate::getTime();
         foreach ($pplf as $pay_period_obj) {
             Debug::text('Pay Period Schedule ID: ' . $pay_period_obj->getPayPeriodSchedule(), __FILE__, __LINE__, __METHOD__, 10);
             if ($pay_period_obj->isPreviousPayPeriodClosed() == TRUE) {
                 //Grab all users for pay period
                 $ppsulf = TTnew('PayPeriodScheduleUserListFactory');
                 if (is_array($user_ids) and count($user_ids) > 0) {
                     Debug::text('Generating pay stubs for specific users...', __FILE__, __LINE__, __METHOD__, 10);
                     TTLog::addEntry($this->getCurrentCompanyObject()->getId(), 500, TTi18n::gettext('Calculating Company Pay Stubs for Pay Period') . ': ' . $pay_period_id, $this->getCurrentUserObject()->getId(), 'pay_stub');
                     //Notice
                     $ppsulf->getByCompanyIDAndPayPeriodScheduleIdAndUserID($this->getCurrentCompanyObject()->getId(), $pay_period_obj->getPayPeriodSchedule(), $user_ids);
                 } else {
                     TTLog::addEntry($this->getCurrentCompanyObject()->getId(), 500, TTi18n::gettext('Calculating Employee Pay Stub for Pay Period') . ': ' . $pay_period_id, $this->getCurrentUserObject()->getId(), 'pay_stub');
                     $ppsulf->getByCompanyIDAndPayPeriodScheduleId($this->getCurrentCompanyObject()->getId(), $pay_period_obj->getPayPeriodSchedule());
                 }
                 $total_pay_stubs = $ppsulf->getRecordCount();
                 $this->getProgressBarObject()->start($this->getAMFMessageID(), $total_pay_stubs, NULL, TTi18n::getText('Generating Paystubs...'));
                 //Delete existing pay stub. Make sure we only
                 //delete pay stubs that are the same as what we're creating.
                 $pslf = TTnew('PayStubListFactory');
                 $pslf->getByPayPeriodId($pay_period_obj->getId());
                 foreach ($pslf as $pay_stub_obj) {
                     if (is_array($user_ids) and count($user_ids) > 0 and in_array($pay_stub_obj->getUser(), $user_ids) == FALSE) {
                         continue;
                         //Only generating pay stubs for individual employees, skip ones not in the list.
                     }
                     Debug::text('Existing Pay Stub: ' . $pay_stub_obj->getId(), __FILE__, __LINE__, __METHOD__, 10);
                     //Check PS End Date to match with PP End Date
                     //So if an ROE was generated, it won't get deleted when they generate all other Pay Stubs
                     //later on.
                     if ($pay_stub_obj->getStatus() <= 25 and $pay_stub_obj->getTainted() === FALSE and TTDate::getMiddleDayEpoch($pay_stub_obj->getEndDate()) == TTDate::getMiddleDayEpoch($pay_period_obj->getEndDate())) {
                         Debug::text('Deleting pay stub: ' . $pay_stub_obj->getId(), __FILE__, __LINE__, __METHOD__, 10);
                         $pay_stub_obj->setDeleted(TRUE);
                         $pay_stub_obj->Save();
                     } else {
                         Debug::text('Pay stub does not need regenerating, or it is LOCKED! ID: ' . $pay_stub_obj->getID() . ' Status: ' . $pay_stub_obj->getStatus() . ' Tainted: ' . (int) $pay_stub_obj->getTainted() . ' Pay Stub End Date: ' . $pay_stub_obj->getEndDate() . ' Pay Period End Date: ' . $pay_period_obj->getEndDate(), __FILE__, __LINE__, __METHOD__, 10);
                     }
                 }
                 $i = 1;
                 foreach ($ppsulf as $pay_period_schdule_user_obj) {
                     Debug::text('Pay Period User ID: ' . $pay_period_schdule_user_obj->getUser(), __FILE__, __LINE__, __METHOD__, 10);
                     Debug::text('Total Pay Stubs: ' . $total_pay_stubs . ' - ' . ceil(1 / (100 / $total_pay_stubs)), __FILE__, __LINE__, __METHOD__, 10);
                     $profiler->startTimer('Calculating Pay Stub');
                     //Calc paystubs.
                     $cps = new CalculatePayStub();
                     $cps->setEnableCorrection((bool) $enable_correction);
                     $cps->setUser($pay_period_schdule_user_obj->getUser());
                     $cps->setPayPeriod($pay_period_obj->getId());
                     $cps->calculate();
                     unset($cps);
                     $profiler->stopTimer('Calculating Pay Stub');
                     $this->getProgressBarObject()->set($this->getAMFMessageID(), $i);
                     //sleep(1); /////////////////////////////// FOR TESTING ONLY //////////////////
                     $i++;
                 }
                 unset($ppsulf);
                 $this->getProgressBarObject()->stop($this->getAMFMessageID());
             } else {
                 UserGenericStatusFactory::queueGenericStatus(TTi18n::gettext('ERROR'), 10, TTi18n::gettext('Pay period prior to %1 is not closed, please close all previous pay periods and try again...', array(TTDate::getDate('DATE', $pay_period_obj->getStartDate()) . ' -> ' . TTDate::getDate('DATE', $pay_period_obj->getEndDate()))), NULL);
             }
         }
     }
     if (UserGenericStatusFactory::isStaticQueue() == TRUE) {
         $ugsf = TTnew('UserGenericStatusFactory');
         $ugsf->setUser($this->getCurrentUserObject()->getId());
         $ugsf->setBatchID($ugsf->getNextBatchId());
         $ugsf->setQueue(UserGenericStatusFactory::getStaticQueue());
         $ugsf->saveQueue();
         $user_generic_status_batch_id = $ugsf->getBatchID();
     } else {
         $user_generic_status_batch_id = FALSE;
     }
     unset($ugsf);
     return $this->returnHandler(TRUE, TRUE, FALSE, FALSE, FALSE, $user_generic_status_batch_id);
 }
 function addAccrualPolicyTime($epoch = NULL, $offset = 79200, $daily_total_time = NULL)
 {
     //22hr offset
     if ($epoch == '') {
         $epoch = TTDate::getTime();
     }
     Debug::Text('Accrual Policy ID: ' . $this->getId() . ' Current EPOCH: ' . TTDate::getDate('DATE+TIME', $epoch), __FILE__, __LINE__, __METHOD__, 10);
     $pglf = new PolicyGroupListFactory();
     $pglf->StartTransaction();
     $pglf->getSearchByCompanyIdAndArrayCriteria($this->getCompany(), array('accrual_policy_id' => array($this->getId())));
     if ($pglf->getRecordCount() > 0) {
         Debug::Text('Found Policy Group...', __FILE__, __LINE__, __METHOD__, 10);
         foreach ($pglf as $pg_obj) {
             //Get all users assigned to this policy group.
             $policy_group_users = $pg_obj->getUser();
             if (is_array($policy_group_users) and count($policy_group_users) > 0) {
                 Debug::Text('Found Policy Group Users: ' . count($policy_group_users), __FILE__, __LINE__, __METHOD__, 10);
                 foreach ($policy_group_users as $user_id) {
                     Debug::Text('Policy Group User ID: ' . $user_id, __FILE__, __LINE__, __METHOD__, 10);
                     //Get User Object
                     $ulf = new UserListFactory();
                     $ulf->getByIDAndCompanyID($user_id, $this->getCompany());
                     if ($ulf->getRecordCount() == 1) {
                         $u_obj = $ulf->getCurrent();
                         Debug::Text('User: '******' Status: ' . $u_obj->getStatus(), __FILE__, __LINE__, __METHOD__, 10);
                         //Make sure only active employees accrue time. Will this negative affect
                         //Employees who may be on leave?
                         if ($u_obj->getStatus() == 10 and ($this->getMinimumEmployedDays() == 0 or TTDate::getDays($epoch - $u_obj->getHireDate()) >= $this->getMinimumEmployedDays())) {
                             Debug::Text('&nbsp;&nbsp;User is active and has been employed long enough.', __FILE__, __LINE__, __METHOD__, 10);
                             $annual_pay_periods = 0;
                             $in_apply_frequency_window = FALSE;
                             $accrual_balance = 0;
                             $accrual_amount = 0;
                             if ($this->getType() == 30) {
                                 Debug::Text('&nbsp;&nbsp;Accrual policy is hour based, real-time window.', __FILE__, __LINE__, __METHOD__, 10);
                                 //Hour based, apply frequency is real-time.
                                 $in_apply_frequency_window = TRUE;
                             } else {
                                 if ($this->getApplyFrequency() == 10) {
                                     //Because of pay period frequencies, and users being assigned to different
                                     //pay period schedules we need to get the last pay period of each user individually.
                                     //This will return the pay period that just ended in the offset time.
                                     $pplf = new PayPeriodListFactory();
                                     $pplf->getByUserIdAndEndDate($user_id, $epoch - $offset);
                                     if ($pplf->getRecordCount() > 0) {
                                         foreach ($pplf as $pp_obj) {
                                             Debug::Text('&nbsp;&nbsp;Pay Period End Date: ' . TTDate::getDate('DATE+TIME', $pp_obj->getEndDate()), __FILE__, __LINE__, __METHOD__, 10);
                                             if ($this->inApplyFrequencyWindow($epoch, $offset, $pp_obj->getEndDate()) == TRUE) {
                                                 $in_apply_frequency_window = TRUE;
                                                 $annual_pay_periods = $pp_obj->getPayPeriodScheduleObject()->getAnnualPayPeriods();
                                                 break;
                                             } else {
                                                 Debug::Text('&nbsp;&nbsp;User not in Apply Frequency Window: ', __FILE__, __LINE__, __METHOD__, 10);
                                             }
                                         }
                                     } else {
                                         Debug::Text('&nbsp;&nbsp; No Pay Period Found.', __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                 } elseif ($this->inApplyFrequencyWindow($epoch, $offset) == TRUE) {
                                     Debug::Text('&nbsp;&nbsp;User IS in NON-PayPeriod Apply Frequency Window.', __FILE__, __LINE__, __METHOD__, 10);
                                     $in_apply_frequency_window = TRUE;
                                 } else {
                                     Debug::Text('&nbsp;&nbsp;User is not in Apply Frequency Window.', __FILE__, __LINE__, __METHOD__, 10);
                                     $in_apply_frequency_window = FALSE;
                                 }
                             }
                             if ($in_apply_frequency_window == TRUE) {
                                 $milestone_obj = $this->getActiveMilestoneObject($u_obj, $epoch);
                                 if (isset($milestone_obj) and is_object($milestone_obj)) {
                                     Debug::Text('&nbsp;&nbsp;Found Matching Milestone, Accrual Rate: (ID: ' . $milestone_obj->getId() . ') ' . $milestone_obj->getAccrualRate() . '/year', __FILE__, __LINE__, __METHOD__, 10);
                                     $accrual_balance = $this->getCurrentAccrualBalance($user_id, $this->getId());
                                     if ($accrual_balance < $milestone_obj->getMaximumTime()) {
                                         $accrual_amount = $this->calcAccrualAmount($milestone_obj, 0, $annual_pay_periods);
                                         if ($accrual_amount > 0) {
                                             $new_accrual_balance = bcadd($accrual_balance, $accrual_amount);
                                             //If Maximum time is set to 0, make that unlimited.
                                             if ($milestone_obj->getMaximumTime() > 0 and $new_accrual_balance > $milestone_obj->getMaximumTime()) {
                                                 $accrual_amount = bcsub($milestone_obj->getMaximumTime(), $accrual_balance, 0);
                                             }
                                             Debug::Text('&nbsp;&nbsp; Min/Max Adjusted Accrual Amount: ' . $accrual_amount . ' Limits: Min: ' . $milestone_obj->getMinimumTime() . ' Max: ' . $milestone_obj->getMaximumTime(), __FILE__, __LINE__, __METHOD__, 10);
                                             //Check to make sure there isn't an identical entry already made.
                                             $alf = new AccrualListFactory();
                                             $alf->getByCompanyIdAndUserIdAndAccrualPolicyIDAndTimeStampAndAmount($u_obj->getCompany(), $user_id, $this->getId(), TTDate::getMiddleDayEpoch($epoch), $accrual_amount);
                                             if ($alf->getRecordCount() == 0) {
                                                 //Round to nearest 1min
                                                 $af = new AccrualFactory();
                                                 $af->setUser($user_id);
                                                 $af->setType(75);
                                                 //Accrual Policy
                                                 $af->setAccrualPolicyID($this->getId());
                                                 $af->setAmount($accrual_amount);
                                                 $af->setTimeStamp(TTDate::getMiddleDayEpoch($epoch));
                                                 $af->setEnableCalcBalance(TRUE);
                                                 if ($af->isValid()) {
                                                     $af->Save();
                                                 }
                                             } else {
                                                 Debug::Text('&nbsp;&nbsp; Found duplicate accrual entry, skipping...', __FILE__, __LINE__, __METHOD__, 10);
                                             }
                                             unset($accrual_amount, $accrual_balance, $new_accrual_balance);
                                         } else {
                                             Debug::Text('&nbsp;&nbsp; Accrual Amount is 0...', __FILE__, __LINE__, __METHOD__, 10);
                                         }
                                     } else {
                                         Debug::Text('&nbsp;&nbsp; Accrual Balance is outside Milestone Range. Skipping...', __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                 } else {
                                     Debug::Text('&nbsp;&nbsp;DID NOT Find Matching Milestone.', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                                 unset($milestone_obj);
                             }
                         } else {
                             Debug::Text('&nbsp;&nbsp;User is not active (Status: ' . $u_obj->getStatus() . ') or has only been employed: ' . TTDate::getDays($epoch - $u_obj->getHireDate()) . ' Days, not enough.', __FILE__, __LINE__, __METHOD__, 10);
                         }
                     } else {
                         Debug::Text('No User Found. Company ID: ' . $this->getCompany(), __FILE__, __LINE__, __METHOD__, 10);
                     }
                 }
             }
         }
     }
     $pglf->CommitTransaction();
     return TRUE;
 }
 function displayVerifyButton($current_user_id = NULL, $user_id = NULL)
 {
     if ($current_user_id == '') {
         $current_user_id = $this->getCurrentUser();
     }
     if ($current_user_id == '') {
         return FALSE;
     }
     if ($user_id == '') {
         $user_id = $this->getUser();
     }
     $pay_period_verify_type_id = $this->getVerificationType();
     $is_timesheet_superior = $this->isHierarchySuperior($current_user_id, $user_id);
     Debug::text('Current User ID: ' . $current_user_id . ' User ID: ' . $user_id . ' Verification Type ID: ' . $pay_period_verify_type_id . ' TimeSheet Superior: ' . (int) $is_timesheet_superior, __FILE__, __LINE__, __METHOD__, 10);
     //Debug::text('Hire Date: '. TTDate::getDATE('DATE+TIME', $this->getUserObject()->getHireDate() ) .' Termination Date: '. TTDate::getDATE('DATE+TIME', $this->getUserObject()->getTerminationDate() ), __FILE__, __LINE__, __METHOD__,10);
     if (($pay_period_verify_type_id == 20 and $current_user_id == $user_id or $pay_period_verify_type_id == 30 and $this->getStatus() != 50 and ($is_timesheet_superior == TRUE and $current_user_id != $user_id and !in_array($current_user_id, (array) $this->getAuthorizedUsers())) or $pay_period_verify_type_id == 40 and ($this->getStatus() == 55 or $current_user_id == $user_id and $this->getUserVerified() == 0 or $is_timesheet_superior == TRUE and !in_array($current_user_id, (array) $this->getAuthorizedUsers()))) and (is_object($this->getUserObject()) and TTDate::getMiddleDayEpoch($this->getUserObject()->getHireDate()) <= TTDate::getMiddleDayEpoch($this->getPayPeriodObject()->getEndDate()) and ($this->getUserObject()->getTerminationDate() == '' or $this->getUserObject()->getTerminationDate() != '' and TTDate::getMiddleDayEpoch($this->getUserObject()->getTerminationDate()) >= TTDate::getMiddleDayEpoch($this->getPayPeriodObject()->getStartDate())) and TTDate::getTime() >= $this->getPayPeriodObject()->getTimeSheetVerifyWindowStartDate() and TTDate::getTime() <= $this->getPayPeriodObject()->getTimeSheetVerifyWindowEndDate() and $this->getStatus() != 50)) {
         return TRUE;
     }
     return FALSE;
 }
Пример #10
0
 function setBirthDate($epoch)
 {
     if ($epoch !== FALSE and $epoch == '' or $this->Validator->isDate('birth_date', $epoch, TTi18n::gettext('Birth date is invalid, try specifying the year with four digits.'))) {
         //Allow for negative epochs, for birthdates less than 1960's
         $this->data['birth_date'] = ($epoch != 0 and $epoch != '') ? TTDate::getMiddleDayEpoch($epoch) : '';
         //Allow blank birthdate.
         return TRUE;
     }
     return FALSE;
 }
Пример #11
0
 function _getData($format = NULL)
 {
     $this->tmp_data = array('pay_stub_entry' => array());
     $columns = $this->getColumnDataConfig();
     $filter_data = $this->getFilterConfig();
     $form_data = $this->formatFormConfig();
     require_once Environment::getBasePath() . '/classes/payroll_deduction/PayrollDeduction.class.php';
     $pd_obj = new PayrollDeduction('US', 'WA');
     //State doesn't matter.
     $pd_obj->setDate($filter_data['end_date']);
     $social_security_wage_limit = $pd_obj->getSocialSecurityMaximumEarnings();
     $medicare_additional_threshold_limit = $pd_obj->getMedicareAdditionalEmployerThreshold();
     Debug::Text('Social Security Wage Limit: ' . $social_security_wage_limit . ' Medicare Threshold: ' . $medicare_additional_threshold_limit . ' Date: ' . TTDate::getDate('DATE', $filter_data['end_date']), __FILE__, __LINE__, __METHOD__, 10);
     //Need to get totals up to the beginning of this quarter so we can determine if any employees have exceeded the social security limit.
     $pself = TTnew('PayStubEntryListFactory');
     $ytd_filter_data = $filter_data;
     $ytd_filter_data['end_date'] = $ytd_filter_data['start_date'] - 1;
     $ytd_filter_data['start_date'] = TTDate::getBeginYearEpoch($ytd_filter_data['start_date']);
     $pself->getAPIReportByCompanyIdAndArrayCriteria($this->getUserObject()->getCompany(), $ytd_filter_data);
     //Debug::Arr($ytd_filter_data, 'YTD Filter Data: Row Count: '.  $pself->getRecordCount(), __FILE__, __LINE__, __METHOD__,10);
     if ($pself->getRecordCount() > 0) {
         foreach ($pself as $pse_obj) {
             $user_id = $pse_obj->getColumn('user_id');
             //Make sure we don't add this to the unique user_id list.
             //Always use middle day epoch, otherwise multiple entries could exist for the same day.
             $date_stamp = TTDate::getMiddleDayEpoch(TTDate::strtotime($pse_obj->getColumn('pay_stub_transaction_date')));
             $branch = $pse_obj->getColumn('default_branch');
             $department = $pse_obj->getColumn('default_department');
             $pay_stub_entry_name_id = $pse_obj->getPayStubEntryNameId();
             if (!isset($this->tmp_data['pay_stub_entry'][$user_id][$date_stamp])) {
                 $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp] = array('pay_period_start_date' => strtotime($pse_obj->getColumn('pay_stub_start_date')), 'pay_period_end_date' => strtotime($pse_obj->getColumn('pay_stub_end_date')), 'pay_period_transaction_date' => strtotime($pse_obj->getColumn('pay_stub_transaction_date')), 'pay_period' => strtotime($pse_obj->getColumn('pay_stub_transaction_date')));
             }
             if (isset($this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['psen_ids'][$pay_stub_entry_name_id])) {
                 $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['psen_ids'][$pay_stub_entry_name_id] = bcadd($this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['psen_ids'][$pay_stub_entry_name_id], $pse_obj->getColumn('amount'));
             } else {
                 $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['psen_ids'][$pay_stub_entry_name_id] = $pse_obj->getColumn('amount');
             }
         }
         if (isset($this->tmp_data['pay_stub_entry']) and is_array($this->tmp_data['pay_stub_entry'])) {
             foreach ($this->tmp_data['pay_stub_entry'] as $user_id => $data_a) {
                 foreach ($data_a as $date_stamp => $data_b) {
                     if (!isset($this->tmp_data['ytd_pay_stub_entry'][$user_id]['social_security_wages'])) {
                         $this->tmp_data['ytd_pay_stub_entry'][$user_id]['social_security_wages'] = 0;
                     }
                     $this->tmp_data['ytd_pay_stub_entry'][$user_id]['social_security_wages'] += Misc::calculateMultipleColumns($data_b['psen_ids'], $form_data['social_security_wages']['include_pay_stub_entry_account'], $form_data['social_security_wages']['exclude_pay_stub_entry_account']);
                     //Include tips in this amount as well.
                     $this->tmp_data['ytd_pay_stub_entry'][$user_id]['social_security_wages'] += Misc::calculateMultipleColumns($data_b['psen_ids'], $form_data['social_security_tips']['include_pay_stub_entry_account'], $form_data['social_security_tips']['exclude_pay_stub_entry_account']);
                     //Handle additional medicare wages in excess of 200,000
                     if (!isset($this->tmp_data['ytd_pay_stub_entry'][$user_id]['medicare_wages'])) {
                         $this->tmp_data['ytd_pay_stub_entry'][$user_id]['medicare_wages'] = 0;
                     }
                     $this->tmp_data['ytd_pay_stub_entry'][$user_id]['medicare_wages'] += Misc::calculateMultipleColumns($data_b['psen_ids'], $form_data['medicare_wages']['include_pay_stub_entry_account'], $form_data['medicare_wages']['exclude_pay_stub_entry_account']);
                 }
             }
         }
         //Debug::Arr($this->tmp_data['ytd_pay_stub_entry'], 'YTD Tmp Raw Data: ', __FILE__, __LINE__, __METHOD__,10);
     }
     unset($pse_obj, $user_id, $date_stamp, $branch, $department, $pay_stub_entry_name_id, $this->tmp_data['pay_stub_entry']);
     //Get just the data for the quarter now.
     $pself->getAPIReportByCompanyIdAndArrayCriteria($this->getUserObject()->getCompany(), $filter_data);
     if ($pself->getRecordCount() > 0) {
         foreach ($pself as $pse_obj) {
             $user_id = $this->user_ids[] = $pse_obj->getColumn('user_id');
             //Always use middle day epoch, otherwise multiple entries could exist for the same day.
             $date_stamp = TTDate::getMiddleDayEpoch(TTDate::strtotime($pse_obj->getColumn('pay_stub_transaction_date')));
             $branch = $pse_obj->getColumn('default_branch');
             $department = $pse_obj->getColumn('default_department');
             $pay_stub_entry_name_id = $pse_obj->getPayStubEntryNameId();
             if (!isset($this->tmp_data['pay_stub_entry'][$user_id][$date_stamp])) {
                 $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp] = array('pay_period_start_date' => strtotime($pse_obj->getColumn('pay_stub_start_date')), 'pay_period_end_date' => strtotime($pse_obj->getColumn('pay_stub_end_date')), 'pay_period_transaction_date' => strtotime($pse_obj->getColumn('pay_stub_transaction_date')), 'pay_period' => strtotime($pse_obj->getColumn('pay_stub_transaction_date')));
             }
             if (isset($this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['psen_ids'][$pay_stub_entry_name_id])) {
                 $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['psen_ids'][$pay_stub_entry_name_id] = bcadd($this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['psen_ids'][$pay_stub_entry_name_id], $pse_obj->getColumn('amount'));
             } else {
                 $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['psen_ids'][$pay_stub_entry_name_id] = $pse_obj->getColumn('amount');
             }
         }
         if (isset($this->tmp_data['pay_stub_entry']) and is_array($this->tmp_data['pay_stub_entry'])) {
             foreach ($this->tmp_data['pay_stub_entry'] as $user_id => $data_a) {
                 foreach ($data_a as $date_stamp => $data_b) {
                     $quarter_month = TTDate::getYearQuarterMonthNumber($date_stamp);
                     //Debug::Text('Quarter Month: '. $quarter_month .' Epoch: '. TTDate::getDate('DATE', $date_stamp), __FILE__, __LINE__, __METHOD__,10);
                     $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['wages'] = Misc::calculateMultipleColumns($data_b['psen_ids'], $form_data['wages']['include_pay_stub_entry_account'], $form_data['wages']['exclude_pay_stub_entry_account']);
                     $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['income_tax'] = Misc::calculateMultipleColumns($data_b['psen_ids'], $form_data['income_tax']['include_pay_stub_entry_account'], $form_data['income_tax']['exclude_pay_stub_entry_account']);
                     //FIXME: If employees are excluded from Social Security, it will still include total wages
                     //resulting in the 941 form being incorrect in its calculation.
                     //Add Form Setup tab field to select the Social Security tax/deductions?
                     //However there can often be two of them, is just the employee one enough? We could use the employees and include/exclude accounts from that at least then.
                     $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_wages'] = Misc::calculateMultipleColumns($data_b['psen_ids'], $form_data['social_security_wages']['include_pay_stub_entry_account'], $form_data['social_security_wages']['exclude_pay_stub_entry_account']);
                     //Handle social security wage limit.
                     if (!isset($this->tmp_data['ytd_pay_stub_entry'][$user_id]['social_security_wages'])) {
                         $this->tmp_data['ytd_pay_stub_entry'][$user_id]['social_security_wages'] = 0;
                     }
                     if ($this->tmp_data['ytd_pay_stub_entry'][$user_id]['social_security_wages'] < $social_security_wage_limit) {
                         $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_wages'] = Misc::calculateMultipleColumns($data_b['psen_ids'], $form_data['social_security_wages']['include_pay_stub_entry_account'], $form_data['social_security_wages']['exclude_pay_stub_entry_account']);
                         $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_tips'] = Misc::calculateMultipleColumns($data_b['psen_ids'], $form_data['social_security_tips']['include_pay_stub_entry_account'], $form_data['social_security_tips']['exclude_pay_stub_entry_account']);
                         if ($this->tmp_data['ytd_pay_stub_entry'][$user_id]['social_security_wages'] + $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_wages'] + $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_tips'] > $social_security_wage_limit) {
                             $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_wages'] = $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_wages'] - ($this->tmp_data['ytd_pay_stub_entry'][$user_id]['social_security_wages'] + $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_wages'] + $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_tips'] - $social_security_wage_limit);
                             $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_tips'] = 0;
                             $this->tmp_data['ytd_pay_stub_entry'][$user_id]['social_security_wages'] = $social_security_wage_limit;
                         } else {
                             $this->tmp_data['ytd_pay_stub_entry'][$user_id]['social_security_wages'] += $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_wages'];
                             $this->tmp_data['ytd_pay_stub_entry'][$user_id]['social_security_wages'] += $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_tips'];
                         }
                     } else {
                         $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_wages'] = 0;
                         $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_tips'] = 0;
                     }
                     $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['medicare_wages'] = Misc::calculateMultipleColumns($data_b['psen_ids'], $form_data['medicare_wages']['include_pay_stub_entry_account'], $form_data['medicare_wages']['exclude_pay_stub_entry_account']);
                     $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['medicare_additional_wages'] = 0;
                     //Handle medicare additional wage limit, only consider wages earned above the threshold to be "medicare_additional_wages"
                     if (!isset($this->tmp_data['ytd_pay_stub_entry'][$user_id]['medicare_wages'])) {
                         $this->tmp_data['ytd_pay_stub_entry'][$user_id]['medicare_wages'] = 0;
                     }
                     if ($this->tmp_data['ytd_pay_stub_entry'][$user_id]['medicare_wages'] > $medicare_additional_threshold_limit) {
                         $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['medicare_additional_wages'] = $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['medicare_wages'];
                     } else {
                         if ($this->tmp_data['ytd_pay_stub_entry'][$user_id]['medicare_wages'] + $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['medicare_wages'] > $medicare_additional_threshold_limit) {
                             $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['medicare_additional_wages'] = $this->tmp_data['ytd_pay_stub_entry'][$user_id]['medicare_wages'] + $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['medicare_wages'] - $medicare_additional_threshold_limit;
                         } else {
                             $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['medicare_additional_wages'] = 0;
                         }
                     }
                     //Debug::Text('User ID: '. $user_id .' DateStamp: '. $date_stamp .' YTD Medicare Additional Wages: '. $this->tmp_data['ytd_pay_stub_entry'][$user_id]['medicare_wages'] .' This Pay Stub: '. $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['medicare_additional_wages'], __FILE__, __LINE__, __METHOD__,10);
                     $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['sick_wages'] = Misc::calculateMultipleColumns($data_b['psen_ids'], $form_data['sick_wages']['include_pay_stub_entry_account'], $form_data['sick_wages']['exclude_pay_stub_entry_account']);
                     $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['eic'] = Misc::calculateMultipleColumns($data_b['psen_ids'], $form_data['eic']['include_pay_stub_entry_account'], $form_data['eic']['exclude_pay_stub_entry_account']);
                     //Separate data used for reporting, grouping, sorting, from data specific used for the Form.
                     if (!isset($this->form_data['pay_period'][$quarter_month][$date_stamp])) {
                         $this->form_data['pay_period'][$quarter_month][$date_stamp] = Misc::preSetArrayValues(array(), array('l2', 'l3', 'l5a', 'l5b', 'l5c', 'l5d', 'l7', 'l9', 'l5a2', 'l5b2', 'l5c2', 'l5d', 'l8', 'l10'), 0);
                     }
                     $this->form_data['pay_period'][$quarter_month][$date_stamp]['l2'] += $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['wages'];
                     $this->form_data['pay_period'][$quarter_month][$date_stamp]['l3'] += $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['income_tax'];
                     $this->form_data['pay_period'][$quarter_month][$date_stamp]['l5a'] += $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_wages'];
                     $this->form_data['pay_period'][$quarter_month][$date_stamp]['l5b'] += $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['social_security_tips'];
                     $this->form_data['pay_period'][$quarter_month][$date_stamp]['l5c'] += $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['medicare_wages'];
                     $this->form_data['pay_period'][$quarter_month][$date_stamp]['l5d'] += $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['medicare_additional_wages'];
                     //$this->form_data['pay_period'][$quarter_month][$date_stamp]['l9'] += $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['eic'];
                     $this->form_data['pay_period'][$quarter_month][$date_stamp]['l5f'] = 0;
                     //Not implemented currently.
                     //Calculated fields, make sure we don't use += on these.
                     $this->form_data['pay_period'][$quarter_month][$date_stamp]['l5a2'] = bcmul($this->form_data['pay_period'][$quarter_month][$date_stamp]['l5a'], $this->getF941Object()->social_security_rate);
                     $this->form_data['pay_period'][$quarter_month][$date_stamp]['l5b2'] = bcmul($this->form_data['pay_period'][$quarter_month][$date_stamp]['l5b'], $this->getF941Object()->social_security_rate);
                     $this->form_data['pay_period'][$quarter_month][$date_stamp]['l5c2'] = bcmul($this->form_data['pay_period'][$quarter_month][$date_stamp]['l5c'], $this->getF941Object()->medicare_rate);
                     $this->form_data['pay_period'][$quarter_month][$date_stamp]['l5d2'] = bcmul($this->form_data['pay_period'][$quarter_month][$date_stamp]['l5d'], $this->getF941Object()->medicare_additional_rate);
                     $this->form_data['pay_period'][$quarter_month][$date_stamp]['l5e'] = bcadd($this->form_data['pay_period'][$quarter_month][$date_stamp]['l5a2'], bcadd($this->form_data['pay_period'][$quarter_month][$date_stamp]['l5b2'], bcadd($this->form_data['pay_period'][$quarter_month][$date_stamp]['l5c2'], $this->form_data['pay_period'][$quarter_month][$date_stamp]['l5d2'])));
                     $this->form_data['pay_period'][$quarter_month][$date_stamp]['l6'] = bcadd($this->form_data['pay_period'][$quarter_month][$date_stamp]['l3'], bcadd($this->form_data['pay_period'][$quarter_month][$date_stamp]['l5e'], $this->form_data['pay_period'][$quarter_month][$date_stamp]['l5f']));
                     //Calculate amounts for Schedule B.
                     $this->form_data['pay_period'][$quarter_month][$date_stamp]['l10'] = $this->form_data['pay_period'][$quarter_month][$date_stamp]['l6'];
                     //Add L6 -> L9 if they are implemented later.
                 }
             }
             //Total all pay periods by month_id
             if (isset($this->form_data['pay_period'])) {
                 foreach ($this->form_data['pay_period'] as $month_id => $pp_data) {
                     $this->form_data['quarter'][$month_id] = Misc::ArrayAssocSum($pp_data, NULL, 8);
                 }
                 //Total all quarters.
                 if (isset($this->form_data['quarter'])) {
                     $this->form_data['total'] = Misc::ArrayAssocSum($this->form_data['quarter'], NULL, 6);
                 }
             }
         }
     }
     $this->user_ids = array_unique($this->user_ids);
     //Used to get the total number of employees.
     //Debug::Arr($this->user_ids, 'User IDs: ', __FILE__, __LINE__, __METHOD__,10);
     Debug::Arr($this->form_data, 'Form Raw Data: ', __FILE__, __LINE__, __METHOD__, 10);
     //Debug::Arr($this->tmp_data, 'Tmp Raw Data: ', __FILE__, __LINE__, __METHOD__,10);
     //Get user data for joining.
     $ulf = TTnew('UserListFactory');
     $ulf->getAPISearchByCompanyIdAndArrayCriteria($this->getUserObject()->getCompany(), $filter_data);
     Debug::Text(' User Total Rows: ' . $ulf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
     $this->getProgressBarObject()->start($this->getAMFMessageID(), $ulf->getRecordCount(), NULL, TTi18n::getText('Retrieving Data...'));
     foreach ($ulf as $key => $u_obj) {
         $this->tmp_data['user'][$u_obj->getId()] = (array) $u_obj->getObjectAsArray($this->getColumnDataConfig());
         $this->getProgressBarObject()->set($this->getAMFMessageID(), $key);
     }
     //Debug::Arr($this->tmp_data['user'], 'User Raw Data: ', __FILE__, __LINE__, __METHOD__,10);
     return TRUE;
 }
 static function dragNdropPunch($company_id, $src_punch_id, $dst_punch_id, $dst_status_id = NULL, $position = 0, $action = 0, $dst_date = NULL)
 {
     /*
     	FIXME: This needs to handle batches to be able to handle all the differnet corner cases.
     	Operations to handle:
     		- Moving punch from Out to In, or In to Out in same punch pair, this is ALWAYS a move, and not a copy.
     		- Move punch from one pair to another in the same day, this can be a copy or move.
     			- Check moving AND copying Out punch from one punch pair to In in another on the same day. ie: In 8:00AM, Out 1:00PM, Out 5:00PM. Move the 1PM punch to pair with 5PM.
     		- Move punch from one day to another, inserting inbetween other punches if necessary.
     		- Move punch from one day to another without any other punches.
     
     
     		- Inserting BEFORE on a dst_punch_id that is an In punch doesn't do any splitting.
     		- Inserting AFTER on a dst_punch_id that is on a Out punch doesn't do any splitting.
     		- Overwriting should just take the punch time and overwrite the existing punch time.
     		- The first thing this function does it check if there are two punches assigned to the punch control of the destination punch, if there is, it splits the punches
     			across two punch_controls, it then attaches the src_punch_id to the same punch_control_id as the dst_punch_id.
     		- If no dst_punch_id is specified, assume copying to a blank cell, just copy the punch to that date along with the punch_control?
     		- Copying punches that span midnight work, however moving punches does not always
     			since we don't move punches in batches, we do it one at a time, and when the first punch punch
     			gets moved, it can cause other punches to follow it automatically.
     */
     $dst_date = TTDate::getMiddleDayEpoch($dst_date);
     Debug::text('Src Punch ID: ' . $src_punch_id . ' Dst Punch ID: ' . $dst_punch_id . ' Dst Status ID: ' . $dst_status_id . ' Position: ' . $position . ' Action: ' . $action . ' Dst Date: ' . $dst_date, __FILE__, __LINE__, __METHOD__, 10);
     $retval = FALSE;
     //Get source and destination punch objects.
     $plf = TTnew('PunchListFactory');
     $plf->StartTransaction();
     $plf->getByCompanyIDAndId($company_id, $src_punch_id);
     if ($plf->getRecordCount() == 1) {
         $src_punch_obj = $plf->getCurrent();
         $src_punch_date = TTDate::getMiddleDayEpoch($src_punch_obj->getPunchControlObject()->getUserDateObject()->getDateStamp());
         Debug::text('Found SRC punch ID: ' . $src_punch_id . ' Source Punch Date: ' . $src_punch_date, __FILE__, __LINE__, __METHOD__, 10);
         //Get the PunchControlObject as early as possible, before the punch is deleted, as it will be cleared even if Save(FALSE) is called below.
         $src_punch_control_obj = clone $src_punch_obj->getPunchControlObject();
         if (TTDate::getMiddleDayEpoch($src_punch_date) != TTDate::getMiddleDayEpoch($src_punch_obj->getTimeStamp())) {
             Debug::text('Punch spans midnight... Source Punch Date: ' . TTDate::getDATE('DATE+TIME', $src_punch_date) . ' Source Punch TimeStamp: ' . TTDate::getDATE('DATE+TIME', $src_punch_obj->getTimeStamp()), __FILE__, __LINE__, __METHOD__, 10);
             $dst_date_modifier = 86400;
             //Bump day by 24hrs.
         } else {
             $dst_date_modifier = 0;
         }
         //If we are moving the punch, we need to delete the source punch first so it doesn't conflict with the new punch.
         //Especially if we are just moving a punch to fill a gap in the same day.
         //If the punch being moved is in the same day, or within the same punch pair, we don't want to delete the source punch, instead we just modify
         //the necessary bits later on. So we need to short circuit the move functionality when copying/moving punches within the same day.
         if ($action == 1 and $src_punch_id != $dst_punch_id and $src_punch_date != $dst_date or $action == 1 and $src_punch_id != $dst_punch_id and $src_punch_date == $dst_date) {
             //Move
             Debug::text('Deleting original punch...: ' . $src_punch_id, __FILE__, __LINE__, __METHOD__, 10);
             $src_punch_obj->setUser($src_punch_control_obj->getUserDateObject()->getUser());
             $src_punch_obj->setDeleted(TRUE);
             //These aren't doing anything because they aren't acting on the PunchControl object?
             $src_punch_obj->setEnableCalcTotalTime(TRUE);
             $src_punch_obj->setEnableCalcSystemTotalTime(TRUE);
             $src_punch_obj->setEnableCalcWeeklySystemTotalTime(TRUE);
             $src_punch_obj->setEnableCalcUserDateTotal(TRUE);
             $src_punch_obj->setEnableCalcException(TRUE);
             $src_punch_obj->Save(FALSE);
             //Keep object around for later.
         } else {
             Debug::text('NOT Deleting original punch, either in copy mode or condition is not met...', __FILE__, __LINE__, __METHOD__, 10);
         }
         if ($src_punch_id == $dst_punch_id or $dst_punch_id == '') {
             //Assume we are just moving a punch within the same punch pair, unless a new date is specfied.
             //However if we're simply splitting an existing punch pair, like dragging the Out punch from an In/Out pair into its own separate pair.
             if ($src_punch_date != $dst_date or $src_punch_date == $dst_date and $dst_punch_id == '') {
                 Debug::text('aCopying punch to new day...', __FILE__, __LINE__, __METHOD__, 10);
                 //Moving punch to a new date.
                 //Copy source punch to proper location by destination punch.
                 $src_punch_obj->setId(FALSE);
                 $src_punch_obj->setPunchControlId((int) $src_punch_control_obj->getNextInsertId());
                 $src_punch_obj->setDeleted(FALSE);
                 //Just in case it was marked deleted by the MOVE action.
                 $new_time_stamp = TTDate::getTimeLockedDate($src_punch_obj->getTimeStamp(), $dst_date + $dst_date_modifier);
                 Debug::text('SRC TimeStamp: ' . TTDate::getDate('DATE+TIME', $src_punch_obj->getTimeStamp()) . ' DST TimeStamp: ' . TTDate::getDate('DATE+TIME', $new_time_stamp), __FILE__, __LINE__, __METHOD__, 10);
                 $src_punch_obj->setTimeStamp($new_time_stamp, FALSE);
                 $src_punch_obj->setActualTimeStamp($new_time_stamp);
                 $src_punch_obj->setOriginalTimeStamp($new_time_stamp);
                 if ($dst_status_id != '') {
                     $src_punch_obj->setStatus($dst_status_id);
                     //Change the status to fit in the proper place.
                 }
                 $src_punch_obj->setStation(NULL);
                 //When drag&drop copying punches, clear the station.
                 if ($src_punch_obj->isValid() == TRUE) {
                     $insert_id = $src_punch_obj->Save(FALSE);
                     $src_punch_control_obj->shift_data = NULL;
                     //Need to clear the shift data so its obtained from the DB again, otherwise shifts will appear on strange days.
                     $src_punch_control_obj->user_date_obj = NULL;
                     //Need to clear user_date_obj from cache so a new one is obtained.
                     $src_punch_control_obj->setId($src_punch_obj->getPunchControlID());
                     $src_punch_control_obj->setPunchObject($src_punch_obj);
                     if ($src_punch_control_obj->isValid() == TRUE) {
                         Debug::Text(' Punch Control is valid, saving...: ', __FILE__, __LINE__, __METHOD__, 10);
                         //We need to calculate new total time for the day and exceptions because we are never guaranteed that the gaps will be filled immediately after
                         //in the case of a drag & drop or something.
                         $src_punch_control_obj->setEnableStrictJobValidation(TRUE);
                         $src_punch_control_obj->setEnableCalcUserDateID(TRUE);
                         $src_punch_control_obj->setEnableCalcTotalTime(TRUE);
                         $src_punch_control_obj->setEnableCalcSystemTotalTime(TRUE);
                         $src_punch_control_obj->setEnableCalcWeeklySystemTotalTime(TRUE);
                         $src_punch_control_obj->setEnableCalcUserDateTotal(TRUE);
                         $src_punch_control_obj->setEnableCalcException(TRUE);
                         if ($src_punch_control_obj->isValid() == TRUE) {
                             if ($src_punch_control_obj->Save(TRUE, TRUE) == TRUE) {
                                 //Return newly inserted punch_id, so Flex can base other actions on it.
                                 $retval = $insert_id;
                             }
                         }
                     }
                 }
             } else {
                 Debug::text('Copying punch within same pair/day...', __FILE__, __LINE__, __METHOD__, 10);
                 //Moving punch within the same punch pair.
                 $src_punch_obj->setStatus($src_punch_obj->getNextStatus());
                 //Change just the punch status.
                 //$src_punch_obj->setDeleted(FALSE); //Just in case it was marked deleted by the MOVE action.
                 if ($src_punch_obj->isValid() == TRUE) {
                     //Return punch_id, so Flex can base other actions on it.
                     $retval = $src_punch_obj->Save(FALSE);
                 }
             }
         } else {
             Debug::text('bCopying punch to new day...', __FILE__, __LINE__, __METHOD__, 10);
             $plf->getByCompanyIDAndId($company_id, $dst_punch_id);
             if ($plf->getRecordCount() == 1) {
                 Debug::text('Found DST punch ID: ' . $dst_punch_id, __FILE__, __LINE__, __METHOD__, 10);
                 $dst_punch_obj = $plf->getCurrent();
                 $dst_punch_control_obj = $dst_punch_obj->getPunchControlObject();
                 Debug::text('aSRC TimeStamp: ' . TTDate::getDate('DATE+TIME', $src_punch_obj->getTimeStamp()) . ' DST TimeStamp: ' . TTDate::getDate('DATE+TIME', $dst_punch_obj->getTimeStamp()), __FILE__, __LINE__, __METHOD__, 10);
                 $is_punch_control_split = FALSE;
                 if ($position == 0) {
                     //Overwrite
                     Debug::text('Overwriting...', __FILE__, __LINE__, __METHOD__, 10);
                     //All we need to do is update the time of the destination punch.
                     $punch_obj = $dst_punch_obj;
                 } else {
                     //Before or After
                     //Determine if the destination punch needs to split from another punch
                     if ($position == -1 and $dst_punch_obj->getStatus() == 20 or $position == 1 and $dst_punch_obj->getStatus() == 10) {
                         //Before on Out punch, After on In Punch,
                         Debug::text('Need to split destination punch out to its own Punch Control row...', __FILE__, __LINE__, __METHOD__, 10);
                         $is_punch_control_split = PunchControlFactory::splitPunchControl($dst_punch_obj->getPunchControlID());
                         //Once a split occurs, we need to re-get the destination punch as the punch_control_id may have changed.
                         //We could probably optimize this to only occur when the destination punch is an In punch, as the
                         //Out punch is always the one to be moved to a new punch_control_id
                         if ($src_punch_obj->getStatus() != $dst_punch_obj->getStatus()) {
                             $plf->getByCompanyIDAndId($company_id, $dst_punch_id);
                             if ($plf->getRecordCount() == 1) {
                                 $dst_punch_obj = $plf->getCurrent();
                                 Debug::text('Found DST punch ID: ' . $dst_punch_id . ' Punch Control ID: ' . $dst_punch_obj->getPunchControlID(), __FILE__, __LINE__, __METHOD__, 10);
                             }
                         }
                         $punch_control_id = $dst_punch_obj->getPunchControlID();
                     } else {
                         Debug::text('No Need to split destination punch, simply add a new punch/punch_control all on its own.', __FILE__, __LINE__, __METHOD__, 10);
                         //Check to see if the src and dst punches are the same status though.
                         $punch_control_id = (int) $dst_punch_control_obj->getNextInsertId();
                     }
                     //Take the source punch and base our new punch on that.
                     $punch_obj = $src_punch_obj;
                     //Copy source punch to proper location by destination punch.
                     $punch_obj->setId(FALSE);
                     $punch_obj->setDeleted(FALSE);
                     //Just in case it was marked deleted by the MOVE action.
                     $punch_obj->setPunchControlId($punch_control_id);
                 }
                 //$new_time_stamp = TTDate::getTimeLockedDate($src_punch_obj->getTimeStamp(), $dst_punch_obj->getTimeStamp()+$dst_date_modifier );
                 $new_time_stamp = TTDate::getTimeLockedDate($src_punch_obj->getTimeStamp(), $dst_punch_obj->getPunchControlObject()->getUserDateObject()->getDateStamp() + $dst_date_modifier);
                 Debug::text('SRC TimeStamp: ' . TTDate::getDate('DATE+TIME', $src_punch_obj->getTimeStamp()) . ' DST TimeStamp: ' . TTDate::getDate('DATE+TIME', $dst_punch_obj->getTimeStamp()) . ' New TimeStamp: ' . TTDate::getDate('DATE+TIME', $new_time_stamp), __FILE__, __LINE__, __METHOD__, 10);
                 $punch_obj->setTimeStamp($new_time_stamp, FALSE);
                 $punch_obj->setActualTimeStamp($new_time_stamp);
                 $punch_obj->setOriginalTimeStamp($new_time_stamp);
                 $src_punch_obj->setStation(NULL);
                 //When drag&drop copying punches, clear the station.
                 //Need to take into account copying a Out punch and inserting it BEFORE another Out punch in a punch pair.
                 //In this case a split needs to occur, and the status needs to stay the same.
                 //Status also needs to stay the same when overwriting an existing punch.
                 Debug::text('Punch Status: ' . $punch_obj->getStatus() . ' DST Punch Status: ' . $dst_punch_obj->getStatus() . ' Split Punch Control: ' . (int) $is_punch_control_split, __FILE__, __LINE__, __METHOD__, 10);
                 if ($position != 0 and $is_punch_control_split == FALSE and $punch_obj->getStatus() == $dst_punch_obj->getStatus() and $punch_obj->getPunchControlID() == $dst_punch_obj->getPunchControlID()) {
                     Debug::text('Changing punch status to opposite: ' . $dst_punch_obj->getNextStatus(), __FILE__, __LINE__, __METHOD__, 10);
                     $punch_obj->setStatus($dst_punch_obj->getNextStatus());
                     //Change the status to fit in the proper place.
                 }
                 if ($punch_obj->isValid() == TRUE) {
                     $insert_id = $punch_obj->Save(FALSE);
                     $dst_punch_control_obj->shift_data = NULL;
                     //Need to clear the shift data so its obtained from the DB again, otherwise shifts will appear on strange days, or cause strange conflicts.
                     $dst_punch_control_obj->setID($punch_obj->getPunchControlID());
                     $dst_punch_control_obj->setPunchObject($punch_obj);
                     if ($dst_punch_control_obj->isValid() == TRUE) {
                         Debug::Text(' Punch Control is valid, saving...: ', __FILE__, __LINE__, __METHOD__, 10);
                         //We need to calculate new total time for the day and exceptions because we are never guaranteed that the gaps will be filled immediately after
                         //in the case of a drag & drop or something.
                         $dst_punch_control_obj->setEnableStrictJobValidation(TRUE);
                         $dst_punch_control_obj->setEnableCalcUserDateID(TRUE);
                         $dst_punch_control_obj->setEnableCalcTotalTime(TRUE);
                         $dst_punch_control_obj->setEnableCalcSystemTotalTime(TRUE);
                         $dst_punch_control_obj->setEnableCalcWeeklySystemTotalTime(TRUE);
                         $dst_punch_control_obj->setEnableCalcUserDateTotal(TRUE);
                         $dst_punch_control_obj->setEnableCalcException(TRUE);
                         if ($dst_punch_control_obj->isValid() == TRUE) {
                             if ($dst_punch_control_obj->Save(TRUE, TRUE) == TRUE) {
                                 //Force isNew() lookup.
                                 //Return newly inserted punch_id, so Flex can base other actions on it.
                                 $retval = $insert_id;
                                 //$retval = TRUE;
                             }
                         }
                     }
                 }
             }
         }
     }
     if ($retval == FALSE) {
         $plf->FailTransaction();
     }
     //$plf->FailTransaction();
     $plf->CommitTransaction();
     Debug::text('Returning: ' . (int) $retval, __FILE__, __LINE__, __METHOD__, 10);
     return $retval;
 }
 function _outputPDFTimesheet($format)
 {
     Debug::Text(' Format: ' . $format, __FILE__, __LINE__, __METHOD__, 10);
     $border = 0;
     $current_company = $this->getUserObject()->getCompanyObject();
     if (!is_object($current_company)) {
         Debug::Text('Invalid company object...', __FILE__, __LINE__, __METHOD__, 10);
         return FALSE;
     }
     $pdf_created_date = time();
     $adjust_x = 10;
     $adjust_y = 10;
     //Debug::Arr($this->form_data, 'Form Data: ', __FILE__, __LINE__, __METHOD__,10);
     if (isset($this->form_data) and count($this->form_data) > 0) {
         //Make sure we sort the form data for printable timesheets.
         $this->form_data['user_date_total'] = Sort::arrayMultiSort($this->form_data['user_date_total'], $this->getSortConfig());
         //Get pay period schedule data for each pay period.
         $this->pdf = new TTPDF($this->config['other']['page_orientation'], 'mm', $this->config['other']['page_format'], $this->getUserObject()->getCompanyObject()->getEncoding());
         $this->pdf->SetAuthor(APPLICATION_NAME);
         $this->pdf->SetTitle($this->title);
         $this->pdf->SetSubject(APPLICATION_NAME . ' ' . TTi18n::getText('Report'));
         $this->pdf->setMargins($this->config['other']['left_margin'], $this->config['other']['top_margin'], $this->config['other']['right_margin']);
         //Debug::Arr($this->config['other'], 'Margins: ', __FILE__, __LINE__, __METHOD__,10);
         $this->pdf->SetAutoPageBreak(FALSE);
         $this->pdf->SetFont($this->config['other']['default_font'], '', $this->_pdf_fontSize(10));
         //Debug::Arr($this->form_data, 'zabUser Raw Data: ', __FILE__, __LINE__, __METHOD__,10);
         $filter_data = $this->getFilterConfig();
         $columns = Misc::trimSortPrefix($this->getOptions('columns'));
         $this->getProgressBarObject()->start($this->getAMFMessageID(), 2, NULL, TTi18n::getText('Querying Database...'));
         //Iterations need to be 2, otherwise progress bar is not created.
         $this->getProgressBarObject()->set($this->getAMFMessageID(), 2);
         if ($format == 'pdf_timesheet_detail') {
             $plf = TTnew('PunchListFactory');
             $plf->getSearchByCompanyIdAndArrayCriteria($this->getUserObject()->getCompany(), $filter_data);
             Debug::Text('Got punch data... Total Rows: ' . $plf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
             $this->getProgressBarObject()->start($this->getAMFMessageID(), $plf->getRecordCount(), NULL, TTi18n::getText('Retrieving Punch Data...'));
             if ($plf->getRecordCount() > 0) {
                 foreach ($plf as $key => $p_obj) {
                     $this->form_data['user_date_total'][$p_obj->getColumn('user_id')]['punch_rows'][$p_obj->getColumn('pay_period_id')][TTDate::strtotime($p_obj->getColumn('date_stamp'))][$p_obj->getPunchControlID()][$p_obj->getStatus()] = array('status_id' => $p_obj->getStatus(), 'type_id' => $p_obj->getType(), 'type_code' => $p_obj->getTypeCode(), 'time_stamp' => $p_obj->getTimeStamp());
                     $this->getProgressBarObject()->set($this->getAMFMessageID(), $key);
                 }
             }
             unset($plf, $p_obj);
         }
         Debug::Text('Drawing timesheets...', __FILE__, __LINE__, __METHOD__, 10);
         $this->getProgressBarObject()->start($this->getAMFMessageID(), count($this->form_data['user_date_total']), NULL, TTi18n::getText('Generating TimeSheets...'));
         $key = 0;
         foreach ($this->form_data['user_date_total'] as $user_data) {
             if ($this->_pdf_checkMaximumPageLimit() == FALSE) {
                 Debug::Text('Exceeded maximum page count...', __FILE__, __LINE__, __METHOD__, 10);
                 //Exceeded maximum pages, stop processing.
                 $this->_pdf_displayMaximumPageLimitError();
                 break;
             }
             if (isset($user_data['first_name']) and isset($user_data['last_name']) and isset($user_data['employee_number'])) {
                 $this->pdf->AddPage($this->config['other']['page_orientation'], 'Letter');
                 $this->timesheetHeader($user_data);
                 //Start displaying dates/times here. Start with header.
                 $column_widths = array('line' => 5, 'date_stamp' => 20, 'dow' => 10, 'in_punch_time_stamp' => 20, 'out_punch_time_stamp' => 20, 'worked_time' => 20, 'regular_time' => 20, 'over_time' => 40.6, 'absence_time' => 45);
                 if (isset($user_data['data']) and is_array($user_data['data'])) {
                     $user_data['data'] = Sort::arrayMultiSort($user_data['data'], array('time_stamp' => SORT_ASC));
                     $this->timesheet_week_totals = Misc::preSetArrayValues(NULL, array('worked_time', 'absence_time', 'regular_time', 'over_time'), 0);
                     $this->timesheet_totals = array();
                     $this->timesheet_totals = Misc::preSetArrayValues($this->timesheet_totals, array('worked_time', 'absence_time', 'regular_time', 'over_time'), 0);
                     $this->counter_i = 1;
                     //Overall row counter.
                     $this->counter_x = 1;
                     //Row counter, starts over each week.
                     $this->counter_y = 1;
                     //Week counter.
                     $this->max_i = count($user_data['data']);
                     $prev_data = FALSE;
                     foreach ($user_data['data'] as $data) {
                         if ($this->_pdf_checkMaximumPageLimit() == FALSE) {
                             Debug::Text('Exceeded maximum page count...', __FILE__, __LINE__, __METHOD__, 10);
                             //Exceeded maximum pages, stop processing.
                             $this->_pdf_displayMaximumPageLimitError();
                             break 2;
                         }
                         if (isset($this->form_data['pay_period'][$data['pay_period_id']])) {
                             //Debug::Arr( $data, 'Data: i: '. $this->counter_i .' x: '. $this->counter_x .' Max I: '. $this->max_i, __FILE__, __LINE__, __METHOD__,10);
                             $data = Misc::preSetArrayValues($data, array('time_stamp', 'in_punch_time_stamp', 'out_punch_time_stamp', 'worked_time', 'absence_time', 'regular_time', 'over_time'), '--');
                             $data['start_week_day'] = $this->form_data['pay_period'][$data['pay_period_id']]['start_week_day'];
                             $row_date_gap = $prev_data !== FALSE ? TTDate::getMiddleDayEpoch($data['time_stamp']) - TTDate::getMiddleDayEpoch($prev_data['time_stamp']) : 0;
                             //Take into account DST by using mid-day epochs.
                             //Debug::Text('Row Gap: '. $row_date_gap, __FILE__, __LINE__, __METHOD__,10);
                             if ($prev_data !== FALSE and $row_date_gap > 86400) {
                                 //Handle gaps between individual days with hours.
                                 $prev_data = $this->timesheetHandleDayGaps($prev_data['time_stamp'] + 86400, $data['time_stamp'], $format, $columns, $column_widths, $user_data, $data, $prev_data);
                             } elseif ($this->counter_i == 1 and TTDate::getMiddleDayEpoch($data['time_stamp']) - TTDate::getMiddleDayEpoch($data['pay_period_start_date']) >= 86400) {
                                 //Always fill gaps between the pay period start date and the date with time, even if not filtering by pay period.
                                 //Handle gaps before the first date with hours is displayed, only when filtering by pay period though.
                                 $prev_data = $this->timesheetHandleDayGaps($data['pay_period_start_date'], $data['time_stamp'], $format, $columns, $column_widths, $user_data, $data, $prev_data);
                             }
                             //Check for gaps at the end of the date range and before the end of the pay period.
                             //If we find one we have to increase $max_i by one so the last timesheetDayRow doesn't display the week totals.
                             if ($this->counter_i == $this->max_i and TTDate::getMiddleDayEpoch($data['pay_period_end_date']) - TTDate::getMiddleDayEpoch($data['time_stamp']) >= 86400) {
                                 $this->max_i++;
                             }
                             $this->timesheetDayRow($format, $columns, $column_widths, $user_data, $data, $prev_data);
                             $prev_data = $data;
                         } else {
                             Debug::Text('Pay Period does not exist, skipping... ID: ' . $data['pay_period_id'], __FILE__, __LINE__, __METHOD__, 10);
                         }
                     }
                     //Check for gaps at the end of the date range and before the end of the pay period so we can fill them in. Only when filtering by pay period though.
                     //as filtering by start/end date can result in a lot of data if they want show time for the last year but an employee was just hired.
                     if (isset($data['pay_period_end_date']) and TTDate::getMiddleDayEpoch($data['pay_period_end_date']) - TTDate::getMiddleDayEpoch($data['time_stamp']) >= 86400) {
                         //Handle gaps between the last day with hours and the end of the pay period.
                         //Always fill gaps between the pay period end date and the current date with time, even if not filtering by pay period.
                         $this->timesheetHandleDayGaps($data['time_stamp'] + 86400, $data['pay_period_end_date'], $format, $columns, $column_widths, $user_data, $data, $prev_data);
                     }
                     if (isset($this->timesheet_totals) and is_array($this->timesheet_totals)) {
                         //Display overall totals.
                         $this->timesheetTotal($column_widths, $this->timesheet_totals);
                         unset($totals);
                     }
                     $this->timesheetSignature($user_data, $data);
                     unset($data, $prev_data);
                 } else {
                     $this->timesheetNoData();
                 }
                 $this->timesheetFooter($pdf_created_date, $adjust_x, $adjust_y);
             }
             $this->getProgressBarObject()->set($this->getAMFMessageID(), $key);
             if ($key % 25 == 0 and $this->isSystemLoadValid() == FALSE) {
                 return FALSE;
             }
             $key++;
         }
         $output = $this->pdf->Output('', 'S');
         return $output;
     }
     Debug::Text('No data to return...', __FILE__, __LINE__, __METHOD__, 10);
     return FALSE;
 }
Пример #14
0
 function setHireDate($epoch)
 {
     if (empty($epoch)) {
         $epoch = NULL;
     }
     if ($epoch == '' or $this->Validator->isDate('hire_date', $epoch, TTi18n::gettext('Hire date is invalid'))) {
         $this->data['hire_date'] = TTDate::getMiddleDayEpoch($epoch);
         return TRUE;
     }
     return FALSE;
 }
 function _getData($format = NULL)
 {
     $this->tmp_data = array('user' => array(), 'pay_stub_entry' => array(), 'pay_period' => array());
     $columns = $this->getColumnDataConfig();
     $filter_data = $this->getFilterConfig();
     $form_data = $this->formatFormConfig();
     $pseallf = TTnew('PayStubEntryAccountLinkListFactory');
     $pseallf->getByCompanyId($this->getUserObject()->getCompany());
     if ($pseallf->getRecordCount() > 0) {
         $pseal_obj = $pseallf->getCurrent();
     }
     $pself = TTnew('PayStubEntryListFactory');
     $pself->getAPIReportByCompanyIdAndArrayCriteria($this->getUserObject()->getCompany(), $filter_data);
     if ($pself->getRecordCount() > 0) {
         foreach ($pself as $pse_obj) {
             $user_id = $this->user_ids[] = $pse_obj->getColumn('user_id');
             $date_stamp = TTDate::strtotime($pse_obj->getColumn('pay_stub_transaction_date'));
             $branch = $pse_obj->getColumn('default_branch');
             $department = $pse_obj->getColumn('default_department');
             $pay_stub_entry_name_id = $pse_obj->getPayStubEntryNameId();
             if (!isset($this->tmp_data['pay_stub_entry'][$user_id][$date_stamp])) {
                 $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp] = array('pay_period_start_date' => strtotime($pse_obj->getColumn('pay_stub_start_date')), 'pay_period_end_date' => strtotime($pse_obj->getColumn('pay_stub_end_date')), 'pay_period_transaction_date' => TTDate::getMiddleDayEpoch(strtotime($pse_obj->getColumn('pay_stub_transaction_date'))), 'pay_period' => strtotime($pse_obj->getColumn('pay_stub_transaction_date')));
                 $this->form_data['pay_period'][] = strtotime($pse_obj->getColumn('pay_stub_transaction_date'));
             }
             if (isset($this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['psen_ids'][$pay_stub_entry_name_id])) {
                 $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['psen_ids'][$pay_stub_entry_name_id] = bcadd($this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['psen_ids'][$pay_stub_entry_name_id], $pse_obj->getColumn('amount'));
             } else {
                 $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['psen_ids'][$pay_stub_entry_name_id] = $pse_obj->getColumn('amount');
             }
         }
         if (isset($this->tmp_data['pay_stub_entry']) and is_array($this->tmp_data['pay_stub_entry'])) {
             foreach ($this->tmp_data['pay_stub_entry'] as $user_id => $data_a) {
                 foreach ($data_a as $date_stamp => $data_b) {
                     $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['ei_total'] = Misc::calculateMultipleColumns($data_b['psen_ids'], $form_data['ei']['include_pay_stub_entry_account'], $form_data['ei']['exclude_pay_stub_entry_account']);
                     $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['cpp_total'] = Misc::calculateMultipleColumns($data_b['psen_ids'], $form_data['cpp']['include_pay_stub_entry_account'], $form_data['cpp']['exclude_pay_stub_entry_account']);
                     $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['tax_total'] = Misc::calculateMultipleColumns($data_b['psen_ids'], $form_data['tax']['include_pay_stub_entry_account'], $form_data['tax']['exclude_pay_stub_entry_account']);
                     $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['total'] = $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['ei_total'] + $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['cpp_total'] + $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['tax_total'];
                     $this->tmp_data['pay_stub_entry'][$user_id][$date_stamp]['gross_payroll'] = Misc::calculateMultipleColumns($data_b['psen_ids'], (array) $pseal_obj->getTotalGross(), array());
                 }
             }
         }
     }
     $this->user_ids = array_unique($this->user_ids);
     //Used to get the total number of employees.
     //Get user data for joining.
     $ulf = TTnew('UserListFactory');
     $ulf->getAPISearchByCompanyIdAndArrayCriteria($this->getUserObject()->getCompany(), $filter_data);
     Debug::Text(' User Total Rows: ' . $ulf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
     $this->getProgressBarObject()->start($this->getAMFMessageID(), $ulf->getRecordCount(), NULL, TTi18n::getText('Retrieving Data...'));
     foreach ($ulf as $key => $u_obj) {
         $this->tmp_data['user'][$u_obj->getId()] = (array) $u_obj->getObjectAsArray($this->getColumnDataConfig());
         $this->getProgressBarObject()->set($this->getAMFMessageID(), $key);
     }
     //Debug::Arr($this->tmp_data['user'], 'User Raw Data: ', __FILE__, __LINE__, __METHOD__,10);
     return TRUE;
 }
Пример #16
0
 static function inApplyFrequencyWindow($frequency_id, $start_date, $end_date, $frequency_criteria = array())
 {
     /*
     		 Frequency IDs:
     												20 => 'Annually',
     												25 => 'Quarterly',
     												30 => 'Monthly',
     												40 => 'Weekly',
     												100 => 'Specific Date', //Pay Period Dates, Hire Dates, Termination Dates, etc...
     */
     if (!isset($frequency_criteria['month'])) {
         $frequency_criteria['month'] = 0;
     }
     if (!isset($frequency_criteria['day_of_month'])) {
         $frequency_criteria['day_of_month'] = 0;
     }
     if (!isset($frequency_criteria['day_of_week'])) {
         $frequency_criteria['day_of_week'] = 0;
     }
     if (!isset($frequency_criteria['quarter_month'])) {
         $frequency_criteria['quarter_month'] = 0;
     }
     if (!isset($frequency_criteria['date'])) {
         $frequency_criteria['date'] = 0;
     }
     //Debug::Arr($frequency_criteria, 'Freq ID: '. $frequency_id .' Date: Start: '. TTDate::getDate('DATE+TIME', $start_date) .'('.$start_date.') End: '. TTDate::getDate('DATE+TIME', $end_date) .'('.$end_date.')', __FILE__, __LINE__, __METHOD__,10);
     $retval = FALSE;
     switch ($frequency_id) {
         case 20:
             //Annually
             $year_epoch1 = mktime(TTDate::getHour($start_date), TTDate::getMinute($start_date), TTDate::getSecond($start_date), $frequency_criteria['month'], $frequency_criteria['day_of_month'], TTDate::getYear($start_date));
             $year_epoch2 = mktime(TTDate::getHour($end_date), TTDate::getMinute($end_date), TTDate::getSecond($end_date), $frequency_criteria['month'], $frequency_criteria['day_of_month'], TTDate::getYear($end_date));
             //Debug::Text('Year1 EPOCH: '. TTDate::getDate('DATE+TIME', $year_epoch1) .'('. $year_epoch1 .')', __FILE__, __LINE__, __METHOD__,10);
             //Debug::Text('Year2 EPOCH: '. TTDate::getDate('DATE+TIME', $year_epoch2) .'('. $year_epoch2 .')', __FILE__, __LINE__, __METHOD__,10);
             if ($year_epoch1 >= $start_date and $year_epoch1 <= $end_date or $year_epoch2 >= $start_date and $year_epoch2 <= $end_date) {
                 $retval = TRUE;
             }
             break;
         case 25:
             //Quarterly
             //Handle quarterly like month, we just need to set the specific month from quarter_month.
             if (abs($end_date - $start_date) > 86400 * 93) {
                 //3 months
                 $retval = TRUE;
             } else {
                 for ($i = TTDate::getMiddleDayEpoch($start_date); $i <= TTDate::getMiddleDayEpoch($end_date); $i += 86400 * 1) {
                     if (self::getYearQuarterMonthNumber($i) == $frequency_criteria['quarter_month'] and $frequency_criteria['day_of_month'] == self::getDayOfMonth($i)) {
                         $retval = TRUE;
                         break;
                     }
                 }
             }
             break;
         case 30:
             //Monthly
             //Make sure if they specify the day of month to be 31, that is still works for months with 30, or 28-29 days, assuming 31 basically means the last day of the month
             if ($frequency_criteria['day_of_month'] > TTDate::getDaysInMonth($start_date) or $frequency_criteria['day_of_month'] > TTDate::getDaysInMonth($end_date)) {
                 $frequency_criteria['day_of_month'] = TTDate::getDaysInMonth($start_date);
                 if (TTDate::getDaysInMonth($end_date) < $frequency_criteria['day_of_month']) {
                     $frequency_criteria['day_of_month'] = TTDate::getDaysInMonth($end_date);
                 }
                 //Debug::Text('Apply frequency day of month exceeds days in this month, using last day of the month instead: '. $frequency_criteria['day_of_month'], __FILE__, __LINE__, __METHOD__,10);
             }
             $month_epoch1 = mktime(TTDate::getHour($start_date), TTDate::getMinute($start_date), TTDate::getSecond($start_date), TTDate::getMonth($start_date), $frequency_criteria['day_of_month'], TTDate::getYear($start_date));
             $month_epoch2 = mktime(TTDate::getHour($end_date), TTDate::getMinute($end_date), TTDate::getSecond($end_date), TTDate::getMonth($end_date), $frequency_criteria['day_of_month'], TTDate::getYear($end_date));
             //Debug::Text('Day of Month: '. $frequency_criteria['day_of_month'] .' Month EPOCH: '. TTDate::getDate('DATE+TIME', $month_epoch1) .' Current Month: '. TTDate::getMonth( $start_date ), __FILE__, __LINE__, __METHOD__,10);
             //Debug::Text('Month1 EPOCH: '. TTDate::getDate('DATE+TIME', $month_epoch1) .'('. $month_epoch1 .') Greater Than: '. TTDate::getDate('DATE+TIME', ($start_date)) .' Less Than: '.  TTDate::getDate('DATE+TIME', $end_date) .'('. $end_date .')', __FILE__, __LINE__, __METHOD__,10);
             //Debug::Text('Month2 EPOCH: '. TTDate::getDate('DATE+TIME', $month_epoch2) .'('. $month_epoch2 .') Greater Than: '. TTDate::getDate('DATE+TIME', ($start_date)) .' Less Than: '.  TTDate::getDate('DATE+TIME', $end_date) .'('. $end_date .')', __FILE__, __LINE__, __METHOD__,10);
             if ($month_epoch1 >= $start_date and $month_epoch1 <= $end_date or $month_epoch2 >= $start_date and $month_epoch2 <= $end_date) {
                 $retval = TRUE;
             }
             break;
         case 40:
             //Weekly
             $start_dow = self::getDayOfWeek($start_date);
             $end_dow = self::getDayOfWeek($end_date);
             if ($start_dow == $frequency_criteria['day_of_week'] or $end_dow == $frequency_criteria['day_of_week']) {
                 $retval = TRUE;
             } else {
                 if ($end_date - $start_date > 86400 * 7) {
                     $retval = TRUE;
                 } else {
                     for ($i = TTDate::getMiddleDayEpoch($start_date); $i <= TTDate::getMiddleDayEpoch($end_date); $i += 86400) {
                         if (self::getDayOfWeek($i) == $frequency_criteria['day_of_week']) {
                             $retval = TRUE;
                             break;
                         }
                     }
                 }
             }
             break;
         case 100:
             //Specific date
             Debug::Text('Specific Date: ' . TTDate::getDate('DATE+TIME', $frequency_criteria['date']), __FILE__, __LINE__, __METHOD__, 10);
             if ($frequency_criteria['date'] >= $start_date and $frequency_criteria['date'] <= $end_date) {
                 $retval = TRUE;
             }
             break;
     }
     Debug::Text('Retval ' . (int) $retval, __FILE__, __LINE__, __METHOD__, 10);
     return $retval;
 }
Пример #17
0
 function calcAccrualTime($company_id, $accrual_policy_id, $start_date, $end_date)
 {
     $start_date = TTDate::getMiddleDayEpoch($start_date);
     $end_date = TTDate::getMiddleDayEpoch($end_date);
     $total_days = TTDate::getDays($end_date - $start_date);
     $offset = 79200;
     $apf = TTnew('AccrualPolicyFactory');
     $aplf = TTnew('AccrualPolicyListFactory');
     $aplf->getByIdAndCompanyId((int) $accrual_policy_id, $company_id);
     if ($aplf->getRecordCount() > 0) {
         foreach ($aplf as $ap_obj) {
             $aplf->StartTransaction();
             $x = 0;
             for ($i = $start_date; $i < $end_date; $i += 86400) {
                 Debug::Text('Recalculating Accruals for Date: ' . TTDate::getDate('DATE+TIME', TTDate::getBeginDayEpoch($i)), __FILE__, __LINE__, __METHOD__, 10);
                 $ap_obj->addAccrualPolicyTime(TTDate::getBeginDayEpoch($i) + 7201, $offset);
                 Debug::Text('----------------------------------', __FILE__, __LINE__, __METHOD__, 10);
                 $x++;
             }
             $aplf->CommitTransaction();
         }
     }
     return TRUE;
 }
 function calcPremiumPolicyTotalTime($udt_meal_policy_adjustment_arr, $udt_break_policy_adjustment_arr, $daily_total_time = FALSE, $schedule_policy_ids = FALSE)
 {
     global $profiler;
     $profiler->startTimer('UserDateTotal::calcPremiumPolicyTotalTime() - Part 1');
     if ($daily_total_time === FALSE) {
         $daily_total_time = $this->getDailyTotalTime();
     }
     $pplf = TTnew('PremiumPolicyListFactory');
     //$pplf->getByPolicyGroupUserId( $this->getUserDateObject()->getUser() );
     $pplf->getByPolicyGroupUserIdOrSchedulePolicyId($this->getUserDateObject()->getUser(), $schedule_policy_ids);
     if ($pplf->getRecordCount() > 0) {
         Debug::text('Found Premium Policies to apply.', __FILE__, __LINE__, __METHOD__, 10);
         foreach ($pplf as $pp_obj) {
             Debug::text('Found Premium Policy: Name: ' . $pp_obj->getName() . '(' . $pp_obj->getId() . ') Type: ' . $pp_obj->getType(), __FILE__, __LINE__, __METHOD__, 10);
             //FIXME: Support manually setting a premium policy through the Edit Hours page?
             //In those cases, just skip auto-calculating it and accept it?
             switch ($pp_obj->getType()) {
                 case 10:
                     //Date/Time
                 //Date/Time
                 case 100:
                     //Advanced
                 //Advanced
                 case 90:
                     //Holiday (coverts to Date/Time policy automatically)
                     if (is_object($this->getUserDateObject()->getPayPeriodObject()) and is_object($this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject())) {
                         $maximum_shift_time = $this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject()->getMaximumShiftTime();
                     }
                     if (!isset($maximum_shift_time) or $maximum_shift_time < 86400) {
                         $maximum_shift_time = 86400;
                     }
                     if ($pp_obj->getType() == 90) {
                         Debug::text(' Holiday Premium Policy...', __FILE__, __LINE__, __METHOD__, 10);
                         //Determine if the employee is eligible for holiday premium.
                         $hlf = TTnew('HolidayListFactory');
                         $hlf->getByPolicyGroupUserIdAndStartDateAndEndDate($this->getUserDateObject()->getUser(), $this->getUserDateObject()->getDateStamp() - $maximum_shift_time, $this->getUserDateObject()->getDateStamp() + $maximum_shift_time);
                         if ($hlf->getRecordCount() > 0) {
                             $holiday_obj = $hlf->getCurrent();
                             Debug::text(' Found Holiday: ' . $holiday_obj->getName() . ' Date: ' . TTDate::getDate('DATE', $holiday_obj->getDateStamp()) . ' Current Date: ' . TTDate::getDate('DATE', $this->getUserDateObject()->getDateStamp()), __FILE__, __LINE__, __METHOD__, 10);
                             if ($holiday_obj->getHolidayPolicyObject()->getForceOverTimePolicy() == TRUE or $holiday_obj->isEligible($this->getUserDateObject()->getUser())) {
                                 Debug::text(' User is Eligible for Holiday: ' . $holiday_obj->getName(), __FILE__, __LINE__, __METHOD__, 10);
                                 //Modify the premium policy in memory to make it like a date/time policy
                                 $pp_obj->setStartDate($holiday_obj->getDateStamp());
                                 $pp_obj->setEndDate($holiday_obj->getDateStamp());
                                 $pp_obj->setStartTime(TTDate::getBeginDayEpoch($holiday_obj->getDateStamp()));
                                 $pp_obj->setEndTime(TTDate::getEndDayEpoch($holiday_obj->getDateStamp()));
                                 $pp_obj->setSun(TRUE);
                                 $pp_obj->setMon(TRUE);
                                 $pp_obj->setTue(TRUE);
                                 $pp_obj->setWed(TRUE);
                                 $pp_obj->setThu(TRUE);
                                 $pp_obj->setFri(TRUE);
                                 $pp_obj->setSat(TRUE);
                                 $pp_obj->setDailyTriggerTime(0);
                                 $pp_obj->setWeeklyTriggerTime(0);
                             }
                         } else {
                             //If a Date/Time premium was created first, with all days activated, then switched to a holiday type,
                             //its still calculated on all days, even when its not a holiday.
                             $pp_obj->setSun(FALSE);
                             $pp_obj->setMon(FALSE);
                             $pp_obj->setTue(FALSE);
                             $pp_obj->setWed(FALSE);
                             $pp_obj->setThu(FALSE);
                             $pp_obj->setFri(FALSE);
                             $pp_obj->setSat(FALSE);
                         }
                         unset($hlf, $holiday_obj);
                     } else {
                         Debug::text(' Date/Time Premium Policy...', __FILE__, __LINE__, __METHOD__, 10);
                     }
                     //Make sure this is a valid day
                     //Take into account shifts that span midnight though, where one half of the shift is eligilble for premium time.
                     //ie: Premium Policy starts 7AM to 7PM on Sat/Sun. Punches in at 9PM Friday and out at 9AM Sat, we need to check if both days are valid.
                     if ($pp_obj->isActive($this->getUserDateObject()->getDateStamp() - $maximum_shift_time, $this->getUserDateObject()->getDateStamp() + $maximum_shift_time, $this->getUserDateObject()->getUser())) {
                         Debug::text(' Premium Policy Is Active On OR Around This Day.', __FILE__, __LINE__, __METHOD__, 10);
                         $total_daily_time_used = 0;
                         $daily_trigger_time = 0;
                         $maximum_daily_trigger_time = FALSE;
                         $udtlf = TTnew('UserDateTotalListFactory');
                         if ($pp_obj->isHourRestricted() == TRUE) {
                             if ($pp_obj->getWeeklyTriggerTime() > 0 or $pp_obj->getMaximumWeeklyTriggerTime() > 0) {
                                 //Get Pay Period Schedule info
                                 if (is_object($this->getUserDateObject()->getPayPeriodObject()) and is_object($this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject())) {
                                     $start_week_day_id = $this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject()->getStartWeekDay();
                                 } else {
                                     $start_week_day_id = 0;
                                 }
                                 Debug::text('Start Week Day ID: ' . $start_week_day_id, __FILE__, __LINE__, __METHOD__, 10);
                                 //$weekly_total_time = $udtlf->getWeekRegularTimeSumByUserIDAndEpochAndStartWeekEpoch( $this->getUserDateObject()->getUser(), $this->getUserDateObject()->getDateStamp(), TTDate::getBeginWeekEpoch($this->getUserDateObject()->getDateStamp(), $start_week_day_id) );
                                 $weekly_total_time = $udtlf->getWeekWorkedTimeSumByUserIDAndEpochAndStartWeekEpoch($this->getUserDateObject()->getUser(), $this->getUserDateObject()->getDateStamp(), TTDate::getBeginWeekEpoch($this->getUserDateObject()->getDateStamp(), $start_week_day_id));
                                 if ($weekly_total_time > $pp_obj->getWeeklyTriggerTime()) {
                                     $daily_trigger_time = 0;
                                 } else {
                                     $daily_trigger_time = $pp_obj->getWeeklyTriggerTime() - $weekly_total_time;
                                 }
                                 Debug::text(' Weekly Trigger Time: ' . $daily_trigger_time . ' Raw Weekly Time: ' . $weekly_total_time, __FILE__, __LINE__, __METHOD__, 10);
                             }
                             if ($pp_obj->getDailyTriggerTime() > 0 and $pp_obj->getDailyTriggerTime() > $daily_trigger_time) {
                                 $daily_trigger_time = $pp_obj->getDailyTriggerTime();
                             }
                             if ($pp_obj->getMaximumDailyTriggerTime() > 0 or $pp_obj->getMaximumWeeklyTriggerTime() > 0) {
                                 //$maximum_daily_trigger_time = ( $pp_obj->getMaximumDailyTriggerTime() > 0 ) ? ($pp_obj->getMaximumDailyTriggerTime()-$pp_obj->getDailyTriggerTime()) : FALSE;
                                 $maximum_daily_trigger_time = $pp_obj->getMaximumDailyTriggerTime() > 0 ? $pp_obj->getMaximumDailyTriggerTime() : FALSE;
                                 $maximum_weekly_trigger_time = (isset($weekly_total_time) and $pp_obj->getMaximumWeeklyTriggerTime() > 0) ? $pp_obj->getMaximumWeeklyTriggerTime() - $weekly_total_time : FALSE;
                                 Debug::text(' Maximum Daily: ' . $maximum_daily_trigger_time . ' Weekly: ' . $maximum_weekly_trigger_time . ' Daily Total Time Used: ' . $total_daily_time_used . ' Daily Trigger Time: ' . $daily_trigger_time, __FILE__, __LINE__, __METHOD__, 10);
                                 if ($maximum_daily_trigger_time > 0 and ($maximum_weekly_trigger_time === FALSE or $maximum_daily_trigger_time < $maximum_weekly_trigger_time)) {
                                     $pp_obj->setMaximumTime($maximum_daily_trigger_time);
                                     //Temporarily set the maximum time in memory so it doesn't exceed the maximum daily trigger time.
                                     Debug::text(' Set Daily Maximum Time to: ' . $pp_obj->getMaximumTime(), __FILE__, __LINE__, __METHOD__, 10);
                                 } else {
                                     if ($maximum_weekly_trigger_time !== FALSE and ($maximum_weekly_trigger_time <= 0 or $maximum_weekly_trigger_time < $daily_trigger_time)) {
                                         Debug::text(' Exceeded Weekly Maximum Time to: ' . $pp_obj->getMaximumTime() . ' Skipping...', __FILE__, __LINE__, __METHOD__, 10);
                                         continue;
                                     }
                                     $pp_obj->setMaximumTime($maximum_weekly_trigger_time);
                                     //Temporarily set the maximum time in memory so it doesn't exceed the maximum daily trigger time.
                                     Debug::text(' Set Weekly Maximum Time to: ' . $pp_obj->getMaximumTime(), __FILE__, __LINE__, __METHOD__, 10);
                                     $maximum_daily_trigger_time = $maximum_weekly_trigger_time;
                                 }
                                 unset($maximum_weekly_trigger_time);
                             }
                         }
                         Debug::text(' Daily Trigger Time: ' . $daily_trigger_time . ' Max: ' . $maximum_daily_trigger_time, __FILE__, __LINE__, __METHOD__, 10);
                         //Loop through all worked (status: 20) UserDateTotalRows
                         $udtlf->getByUserDateIdAndStatus($this->getUserDateID(), 20);
                         $i = 1;
                         if ($udtlf->getRecordCount() > 0) {
                             Debug::text('Found Total Hours to attempt to apply premium policy... Record Count: ' . $udtlf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
                             $valid_user_date_total_ids = array();
                             foreach ($udtlf as $udt_obj) {
                                 Debug::text('UserDateTotal ID: ' . $udt_obj->getID() . ' Total Time: ' . $udt_obj->getTotalTime(), __FILE__, __LINE__, __METHOD__, 10);
                                 //Ignore incomplete punches
                                 if ($udt_obj->getTotalTime() == 0) {
                                     continue;
                                 }
                                 //How do we handle actual shifts for premium time?
                                 //So if premium policy starts at 1PM for shifts, to not
                                 //include employees who return from lunch at 1:30PM.
                                 //Create a function that takes all punches for a day, and returns
                                 //the first in and last out time for a given shift when taking
                                 //into account minimum time between shifts, as well as the total time for that shift.
                                 //We can then use that time for ActiveTime on premium policies, and determine if a
                                 //punch falls within the active time, then we add it to the total.
                                 if (($pp_obj->getIncludePartialPunch() == TRUE or $pp_obj->isTimeRestricted() == TRUE) and $udt_obj->getPunchControlID() != FALSE) {
                                     Debug::text('Time Restricted Premium Policy, lookup punches to get times.', __FILE__, __LINE__, __METHOD__, 10);
                                     if ($pp_obj->getIncludePartialPunch() == FALSE) {
                                         $shift_data = $this->getShiftDataByUserDateID($this->getUserDateID());
                                     }
                                     $plf = TTnew('PunchListFactory');
                                     $plf->getByPunchControlId($udt_obj->getPunchControlID());
                                     if ($plf->getRecordCount() > 0) {
                                         Debug::text('Found Punches: ' . $plf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
                                         foreach ($plf as $punch_obj) {
                                             if ($pp_obj->getIncludePartialPunch() == TRUE) {
                                                 //Debug::text('Including Partial Punches...', __FILE__, __LINE__, __METHOD__, 10);
                                                 if ($punch_obj->getStatus() == 10) {
                                                     $punch_times['in'] = $punch_obj->getTimeStamp();
                                                 } elseif ($punch_obj->getStatus() == 20) {
                                                     $punch_times['out'] = $punch_obj->getTimeStamp();
                                                 }
                                             } else {
                                                 if (isset($shift_data) and is_array($shift_data)) {
                                                     foreach ($shift_data as $shift) {
                                                         if ($punch_obj->getTimeStamp() >= $shift['first_in'] and $punch_obj->getTimeStamp() <= $shift['last_out']) {
                                                             //Debug::Arr($shift,'Shift Data...', __FILE__, __LINE__, __METHOD__, 10);
                                                             Debug::text('Punch (' . TTDate::getDate('DATE+TIME', $punch_obj->getTimeStamp()) . ') inside shift time...', __FILE__, __LINE__, __METHOD__, 10);
                                                             $punch_times['in'] = $shift['first_in'];
                                                             $punch_times['out'] = $shift['last_out'];
                                                             break;
                                                         } else {
                                                             Debug::text('Punch (' . TTDate::getDate('DATE+TIME', $punch_obj->getTimeStamp()) . ') outside shift time...', __FILE__, __LINE__, __METHOD__, 10);
                                                         }
                                                     }
                                                 }
                                             }
                                         }
                                         if (isset($punch_times) and count($punch_times) == 2 and ($pp_obj->isActiveDate($punch_times['in']) == TRUE or $pp_obj->isActiveDate($punch_times['out'])) and $pp_obj->isActive($punch_times['in'], $punch_times['out'], $this->getUserDateObject()->getUser()) and $pp_obj->isActiveTime($punch_times['in'], $punch_times['out'], $this->getUserDateObject()->getUser()) == TRUE) {
                                             //Debug::Arr($punch_times, 'Punch Times: ', __FILE__, __LINE__, __METHOD__, 10);
                                             $punch_total_time = $pp_obj->getPartialPunchTotalTime($punch_times['in'], $punch_times['out'], $udt_obj->getTotalTime(), $this->getUserDateObject()->getUser());
                                             $valid_user_date_total_ids[] = $udt_obj->getID();
                                             //Need to record punches that fall within the active time so we can properly handle break/meal adjustments.
                                             Debug::text('Valid Punch pair in active time, Partial Punch Total Time: ' . $punch_total_time, __FILE__, __LINE__, __METHOD__, 10);
                                         } else {
                                             Debug::text('InValid Punch Pair or outside Active Time...', __FILE__, __LINE__, __METHOD__, 10);
                                             $punch_total_time = 0;
                                         }
                                     }
                                 } elseif ($pp_obj->isActive($udt_obj->getUserDateObject()->getDateStamp(), NULL, $this->getUserDateObject()->getUser()) == TRUE) {
                                     $punch_total_time = $udt_obj->getTotalTime();
                                     $valid_user_date_total_ids[] = $udt_obj->getID();
                                 } else {
                                     $punch_total_time = 0;
                                 }
                                 //Why is $tmp_punch_total_time not just $punch_total_time? Are the partial punches somehow separate from the meal/break calculation?
                                 //Yes, because tmp_punch_total_time is the DAILY total time used, whereas punch_total_time can be a partial shift. Without this the daily trigger time won't work.
                                 $tmp_punch_total_time = $udt_obj->getTotalTime();
                                 Debug::text('aPunch Total Time: ' . $punch_total_time . ' TMP Punch Total Time: ' . $tmp_punch_total_time, __FILE__, __LINE__, __METHOD__, 10);
                                 //When calculating meal/break policy adjustments, make sure they can be added to one another, in case there is a meal AND break
                                 //within the same shift, they both need to be included. Also make sure we double check the active date again.
                                 //Apply meal policy adjustment as early as possible.
                                 if ($pp_obj->getIncludeMealPolicy() == TRUE and $pp_obj->isActiveDate($this->getUserDateObject()->getDateStamp()) == TRUE and $pp_obj->isActiveDayofWeek($this->getUserDateObject()->getDateStamp()) == TRUE and isset($udt_meal_policy_adjustment_arr[$udt_obj->getId()]) and in_array($udt_obj->getID(), $valid_user_date_total_ids)) {
                                     Debug::text(' Meal Policy Adjustment Found: ' . $udt_meal_policy_adjustment_arr[$udt_obj->getId()], __FILE__, __LINE__, __METHOD__, 10);
                                     $punch_total_time = bcadd($punch_total_time, $udt_meal_policy_adjustment_arr[$udt_obj->getId()]);
                                     $tmp_punch_total_time = bcadd($tmp_punch_total_time, $udt_meal_policy_adjustment_arr[$udt_obj->getId()]);
                                 }
                                 Debug::text('bPunch Total Time: ' . $punch_total_time . ' TMP Punch Total Time: ' . $tmp_punch_total_time, __FILE__, __LINE__, __METHOD__, 10);
                                 //Apply break policy adjustment as early as possible.
                                 if ($pp_obj->getIncludeBreakPolicy() == TRUE and $pp_obj->isActiveDate($this->getUserDateObject()->getDateStamp()) == TRUE and $pp_obj->isActiveDayofWeek($this->getUserDateObject()->getDateStamp()) == TRUE and isset($udt_break_policy_adjustment_arr[$udt_obj->getId()]) and in_array($udt_obj->getID(), $valid_user_date_total_ids)) {
                                     Debug::text(' Break Policy Adjustment Found: ' . $udt_break_policy_adjustment_arr[$udt_obj->getId()], __FILE__, __LINE__, __METHOD__, 10);
                                     $punch_total_time = bcadd($punch_total_time, $udt_break_policy_adjustment_arr[$udt_obj->getId()]);
                                     $tmp_punch_total_time = bcadd($tmp_punch_total_time, $udt_break_policy_adjustment_arr[$udt_obj->getId()]);
                                 }
                                 Debug::text('cPunch Total Time: ' . $punch_total_time . ' TMP Punch Total Time: ' . $tmp_punch_total_time, __FILE__, __LINE__, __METHOD__, 10);
                                 $total_daily_time_used += $tmp_punch_total_time;
                                 Debug::text('Daily Total Time Used: ' . $total_daily_time_used . ' Maximum Trigger Time: ' . $maximum_daily_trigger_time . ' This Record: ' . ($total_daily_time_used - $tmp_punch_total_time), __FILE__, __LINE__, __METHOD__, 10);
                                 //FIXME: Should the daily/weekly trigger time be >= instead of >.
                                 //That way if the policy is active after 7.5hrs, punch time of exactly 7.5hrs will still
                                 //activate the policy, rather then requiring 7.501hrs+
                                 if ($punch_total_time > 0 and $total_daily_time_used > $daily_trigger_time and ($maximum_daily_trigger_time === FALSE or $maximum_daily_trigger_time !== FALSE and $total_daily_time_used - $tmp_punch_total_time < $maximum_daily_trigger_time)) {
                                     Debug::text('Past Trigger Time!! ' . ($total_daily_time_used - $tmp_punch_total_time), __FILE__, __LINE__, __METHOD__, 10);
                                     //Calculate how far past trigger time we are.
                                     $past_trigger_time = $total_daily_time_used - $daily_trigger_time;
                                     if ($punch_total_time > $past_trigger_time) {
                                         $punch_total_time = $past_trigger_time;
                                         Debug::text('Using Past Trigger Time as punch total time: ' . $past_trigger_time, __FILE__, __LINE__, __METHOD__, 10);
                                     } else {
                                         Debug::text('NOT Using Past Trigger Time as punch total time: ' . $past_trigger_time, __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                     //If we are close to exceeding the maximum daily/weekly time, just use the remaining time.
                                     if ($maximum_daily_trigger_time > 0 and $total_daily_time_used > $maximum_daily_trigger_time) {
                                         Debug::text('Using New Maximum Trigger Time as punch total time: ' . $maximum_daily_trigger_time . '(' . $total_daily_time_used . ')', __FILE__, __LINE__, __METHOD__, 10);
                                         $punch_total_time = $punch_total_time - ($total_daily_time_used - $maximum_daily_trigger_time);
                                     } else {
                                         Debug::text('NOT Using New Maximum Trigger Time as punch total time: ' . $maximum_daily_trigger_time . '(' . $total_daily_time_used . ')', __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                     $total_time = $punch_total_time;
                                     if ($pp_obj->getMinimumTime() > 0 or $pp_obj->getMaximumTime() > 0) {
                                         $premium_policy_daily_total_time = (int) $udtlf->getPremiumPolicySumByUserDateIDAndPremiumPolicyID($this->getUserDateID(), $pp_obj->getId());
                                         Debug::text(' Premium Policy Daily Total Time: ' . $premium_policy_daily_total_time . ' Minimum Time: ' . $pp_obj->getMinimumTime() . ' Maximum Time: ' . $pp_obj->getMaximumTime() . ' Total Time: ' . $total_time, __FILE__, __LINE__, __METHOD__, 10);
                                         if ($pp_obj->getMinimumTime() > 0) {
                                             //FIXME: Split the minimum time up between all the punches somehow.
                                             //Apply the minimum time on the last punch, otherwise if there are two punch pairs of 15min each
                                             //and a 1hr minimum time, if the minimum time is applied to the first, it will be 1hr and 15min
                                             //for the day. If its applied to the last it will be just 1hr.
                                             //Min & Max time is based on the shift time, rather then per punch pair time.
                                             //FIXME: If there is a minimum time set to say 9hrs, and the punches go like this:
                                             // In: 7:00AM Out: 3:00:PM, Out: 3:30PM (missing 2nd In Punch), the minimum time won't be calculated due to the invalid punch pair.
                                             if ($i == $udtlf->getRecordCount() and bcadd($premium_policy_daily_total_time, $total_time) < $pp_obj->getMinimumTime()) {
                                                 $total_time = bcsub($pp_obj->getMinimumTime(), $premium_policy_daily_total_time);
                                             }
                                         }
                                         Debug::text(' Total Time After Minimum is applied: ' . $total_time, __FILE__, __LINE__, __METHOD__, 10);
                                         if ($pp_obj->getMaximumTime() > 0) {
                                             //Min & Max time is based on the shift time, rather then per punch pair time.
                                             if (bcadd($premium_policy_daily_total_time, $total_time) > $pp_obj->getMaximumTime()) {
                                                 Debug::text(' bMore than Maximum Time...', __FILE__, __LINE__, __METHOD__, 10);
                                                 $total_time = bcsub($total_time, bcsub(bcadd($premium_policy_daily_total_time, $total_time), $pp_obj->getMaximumTime()));
                                             }
                                         }
                                     }
                                     Debug::text(' Premium Punch Total Time: ' . $total_time, __FILE__, __LINE__, __METHOD__, 10);
                                     if ($total_time > 0) {
                                         Debug::text(' Applying  Premium Time!: ' . $total_time, __FILE__, __LINE__, __METHOD__, 10);
                                         if ($pp_obj->getType() == 100) {
                                             //Check Shift Differential criteria *AFTER* calculatating daily/weekly time, as the shift differential
                                             //applies to the resulting time calculation, not the daily/weekly time calculation. Daily/Weekly should always include all time.
                                             //This is fundamentally different than the Shift Differential premium policy type.
                                             if ($pp_obj->getBranchSelectionType() == 10 and ($pp_obj->getExcludeDefaultBranch() == FALSE or $pp_obj->getExcludeDefaultBranch() == TRUE and $udt_obj->getBranch() != $this->getUserDateObject()->getUserObject()->getDefaultBranch()) or $pp_obj->getBranchSelectionType() == 20 and in_array($udt_obj->getBranch(), (array) $pp_obj->getBranch()) and ($pp_obj->getExcludeDefaultBranch() == FALSE or $pp_obj->getExcludeDefaultBranch() == TRUE and $udt_obj->getBranch() != $this->getUserDateObject()->getUserObject()->getDefaultBranch()) or $pp_obj->getBranchSelectionType() == 30 and !in_array($udt_obj->getBranch(), (array) $pp_obj->getBranch()) and ($pp_obj->getExcludeDefaultBranch() == FALSE or $pp_obj->getExcludeDefaultBranch() == TRUE and $udt_obj->getBranch() != $this->getUserDateObject()->getUserObject()->getDefaultBranch())) {
                                                 Debug::text(' Shift Differential... Meets Branch Criteria! Select Type: ' . $pp_obj->getBranchSelectionType() . ' Exclude Default Branch: ' . (int) $pp_obj->getExcludeDefaultBranch() . ' Default Branch: ' . $this->getUserDateObject()->getUserObject()->getDefaultBranch(), __FILE__, __LINE__, __METHOD__, 10);
                                                 if ($pp_obj->getDepartmentSelectionType() == 10 and ($pp_obj->getExcludeDefaultDepartment() == FALSE or $pp_obj->getExcludeDefaultDepartment() == TRUE and $udt_obj->getDepartment() != $this->getUserDateObject()->getUserObject()->getDefaultDepartment()) or $pp_obj->getDepartmentSelectionType() == 20 and in_array($udt_obj->getDepartment(), (array) $pp_obj->getDepartment()) and ($pp_obj->getExcludeDefaultDepartment() == FALSE or $pp_obj->getExcludeDefaultDepartment() == TRUE and $udt_obj->getDepartment() != $this->getUserDateObject()->getUserObject()->getDefaultDepartment()) or $pp_obj->getDepartmentSelectionType() == 30 and !in_array($udt_obj->getDepartment(), (array) $pp_obj->getDepartment()) and ($pp_obj->getExcludeDefaultDepartment() == FALSE or $pp_obj->getExcludeDefaultDepartment() == TRUE and $udt_obj->getDepartment() != $this->getUserDateObject()->getUserObject()->getDefaultDepartment())) {
                                                     Debug::text(' Shift Differential... Meets Department Criteria! Select Type: ' . $pp_obj->getDepartmentSelectionType() . ' Exclude Default Department: ' . (int) $pp_obj->getExcludeDefaultDepartment() . ' Default Department: ' . $this->getUserDateObject()->getUserObject()->getDefaultDepartment(), __FILE__, __LINE__, __METHOD__, 10);
                                                     if ($pp_obj->getJobGroupSelectionType() == 10 or $pp_obj->getJobGroupSelectionType() == 20 and is_object($udt_obj->getJobObject()) and in_array($udt_obj->getJobObject()->getGroup(), (array) $pp_obj->getJobGroup()) or $pp_obj->getJobGroupSelectionType() == 30 and is_object($udt_obj->getJobObject()) and !in_array($udt_obj->getJobObject()->getGroup(), (array) $pp_obj->getJobGroup())) {
                                                         Debug::text(' Shift Differential... Meets Job Group Criteria! Select Type: ' . $pp_obj->getJobGroupSelectionType(), __FILE__, __LINE__, __METHOD__, 10);
                                                         if ($pp_obj->getJobSelectionType() == 10 or $pp_obj->getJobSelectionType() == 20 and in_array($udt_obj->getJob(), (array) $pp_obj->getJob()) or $pp_obj->getJobSelectionType() == 30 and !in_array($udt_obj->getJob(), (array) $pp_obj->getJob())) {
                                                             Debug::text(' Shift Differential... Meets Job Criteria! Select Type: ' . $pp_obj->getJobSelectionType(), __FILE__, __LINE__, __METHOD__, 10);
                                                             if ($pp_obj->getJobItemGroupSelectionType() == 10 or $pp_obj->getJobItemGroupSelectionType() == 20 and is_object($udt_obj->getJobItemObject()) and in_array($udt_obj->getJobItemObject()->getGroup(), (array) $pp_obj->getJobItemGroup()) or $pp_obj->getJobItemGroupSelectionType() == 30 and is_object($udt_obj->getJobItemObject()) and !in_array($udt_obj->getJobItemObject()->getGroup(), (array) $pp_obj->getJobItemGroup())) {
                                                                 Debug::text(' Shift Differential... Meets Task Group Criteria! Select Type: ' . $pp_obj->getJobItemGroupSelectionType(), __FILE__, __LINE__, __METHOD__, 10);
                                                                 if ($pp_obj->getJobItemSelectionType() == 10 or $pp_obj->getJobItemSelectionType() == 20 and in_array($udt_obj->getJobItem(), (array) $pp_obj->getJobItem()) or $pp_obj->getJobItemSelectionType() == 30 and !in_array($udt_obj->getJobItem(), (array) $pp_obj->getJobItem())) {
                                                                     Debug::text(' Shift Differential... Meets Task Criteria! Select Type: ' . $pp_obj->getJobSelectionType(), __FILE__, __LINE__, __METHOD__, 10);
                                                                     $udtf = TTnew('UserDateTotalFactory');
                                                                     $udtf->setUserDateID($this->getUserDateID());
                                                                     $udtf->setStatus(10);
                                                                     //System
                                                                     $udtf->setType(40);
                                                                     //Premium
                                                                     $udtf->setPremiumPolicyId($pp_obj->getId());
                                                                     $udtf->setBranch($udt_obj->getBranch());
                                                                     $udtf->setDepartment($udt_obj->getDepartment());
                                                                     $udtf->setJob($udt_obj->getJob());
                                                                     $udtf->setJobItem($udt_obj->getJobItem());
                                                                     $udtf->setQuantity($udt_obj->getQuantity());
                                                                     $udtf->setBadQuantity($udt_obj->getBadQuantity());
                                                                     $udtf->setTotalTime($total_time);
                                                                     $udtf->setEnableCalcSystemTotalTime(FALSE);
                                                                     if ($udtf->isValid() == TRUE) {
                                                                         $udtf->Save();
                                                                     }
                                                                     unset($udtf);
                                                                 } else {
                                                                     Debug::text(' Shift Differential... DOES NOT Meet Task Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                                                                 }
                                                             } else {
                                                                 Debug::text(' Shift Differential... DOES NOT Meet Task Group Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                                                             }
                                                         } else {
                                                             Debug::text(' Shift Differential... DOES NOT Meet Job Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                                                         }
                                                     } else {
                                                         Debug::text(' Shift Differential... DOES NOT Meet Job Group Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                                                     }
                                                 } else {
                                                     Debug::text(' Shift Differential... DOES NOT Meet Department Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                                                 }
                                             } else {
                                                 Debug::text(' Shift Differential... DOES NOT Meet Branch Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                                             }
                                         } else {
                                             $udtf = TTnew('UserDateTotalFactory');
                                             $udtf->setUserDateID($this->getUserDateID());
                                             $udtf->setStatus(10);
                                             //System
                                             $udtf->setType(40);
                                             //Premium
                                             $udtf->setPremiumPolicyId($pp_obj->getId());
                                             $udtf->setBranch($udt_obj->getBranch());
                                             $udtf->setDepartment($udt_obj->getDepartment());
                                             $udtf->setJob($udt_obj->getJob());
                                             $udtf->setJobItem($udt_obj->getJobItem());
                                             $udtf->setQuantity($udt_obj->getQuantity());
                                             $udtf->setBadQuantity($udt_obj->getBadQuantity());
                                             $udtf->setTotalTime($total_time);
                                             $udtf->setEnableCalcSystemTotalTime(FALSE);
                                             if ($udtf->isValid() == TRUE) {
                                                 $udtf->Save();
                                             }
                                             unset($udtf);
                                         }
                                     } else {
                                         Debug::text(' Premium Punch Total Time is 0...', __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                 } else {
                                     Debug::text('Not Past Trigger Time Yet or Punch Time is 0...', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                                 $i++;
                             }
                             unset($valid_user_date_total_ids);
                         }
                     }
                     unset($udtlf, $udt_obj);
                     break;
                 case 20:
                     //Differential
                     Debug::text(' Differential Premium Policy...', __FILE__, __LINE__, __METHOD__, 10);
                     //Loop through all worked (status: 20) UserDateTotalRows
                     $udtlf = TTnew('UserDateTotalListFactory');
                     $udtlf->getByUserDateIdAndStatus($this->getUserDateID(), 20);
                     $i = 1;
                     if ($udtlf->getRecordCount() > 0) {
                         Debug::text('Found Total Hours to attempt to apply premium policy... Record Count: ' . $udtlf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
                         foreach ($udtlf as $udt_obj) {
                             //Ignore incomplete punches
                             if ($udt_obj->getTotalTime() == 0) {
                                 continue;
                             }
                             if ($pp_obj->getBranchSelectionType() == 10 and ($pp_obj->getExcludeDefaultBranch() == FALSE or $pp_obj->getExcludeDefaultBranch() == TRUE and $udt_obj->getBranch() != $this->getUserDateObject()->getUserObject()->getDefaultBranch()) or $pp_obj->getBranchSelectionType() == 20 and in_array($udt_obj->getBranch(), (array) $pp_obj->getBranch()) and ($pp_obj->getExcludeDefaultBranch() == FALSE or $pp_obj->getExcludeDefaultBranch() == TRUE and $udt_obj->getBranch() != $this->getUserDateObject()->getUserObject()->getDefaultBranch()) or $pp_obj->getBranchSelectionType() == 30 and !in_array($udt_obj->getBranch(), (array) $pp_obj->getBranch()) and ($pp_obj->getExcludeDefaultBranch() == FALSE or $pp_obj->getExcludeDefaultBranch() == TRUE and $udt_obj->getBranch() != $this->getUserDateObject()->getUserObject()->getDefaultBranch())) {
                                 Debug::text(' Shift Differential... Meets Branch Criteria! Select Type: ' . $pp_obj->getBranchSelectionType() . ' Exclude Default Branch: ' . (int) $pp_obj->getExcludeDefaultBranch() . ' Default Branch: ' . $this->getUserDateObject()->getUserObject()->getDefaultBranch(), __FILE__, __LINE__, __METHOD__, 10);
                                 if ($pp_obj->getDepartmentSelectionType() == 10 and ($pp_obj->getExcludeDefaultDepartment() == FALSE or $pp_obj->getExcludeDefaultDepartment() == TRUE and $udt_obj->getDepartment() != $this->getUserDateObject()->getUserObject()->getDefaultDepartment()) or $pp_obj->getDepartmentSelectionType() == 20 and in_array($udt_obj->getDepartment(), (array) $pp_obj->getDepartment()) and ($pp_obj->getExcludeDefaultDepartment() == FALSE or $pp_obj->getExcludeDefaultDepartment() == TRUE and $udt_obj->getDepartment() != $this->getUserDateObject()->getUserObject()->getDefaultDepartment()) or $pp_obj->getDepartmentSelectionType() == 30 and !in_array($udt_obj->getDepartment(), (array) $pp_obj->getDepartment()) and ($pp_obj->getExcludeDefaultDepartment() == FALSE or $pp_obj->getExcludeDefaultDepartment() == TRUE and $udt_obj->getDepartment() != $this->getUserDateObject()->getUserObject()->getDefaultDepartment())) {
                                     Debug::text(' Shift Differential... Meets Department Criteria! Select Type: ' . $pp_obj->getDepartmentSelectionType() . ' Exclude Default Department: ' . (int) $pp_obj->getExcludeDefaultDepartment() . ' Default Department: ' . $this->getUserDateObject()->getUserObject()->getDefaultDepartment(), __FILE__, __LINE__, __METHOD__, 10);
                                     if ($pp_obj->getJobGroupSelectionType() == 0 or $pp_obj->getJobGroupSelectionType() == 10 or $pp_obj->getJobGroupSelectionType() == 20 and (is_object($udt_obj->getJobObject()) and in_array($udt_obj->getJobObject()->getGroup(), (array) $pp_obj->getJobGroup())) or $pp_obj->getJobGroupSelectionType() == 30 and (is_object($udt_obj->getJobObject()) and !in_array($udt_obj->getJobObject()->getGroup(), (array) $pp_obj->getJobGroup()))) {
                                         Debug::text(' Shift Differential... Meets Job Group Criteria! Select Type: ' . $pp_obj->getJobGroupSelectionType(), __FILE__, __LINE__, __METHOD__, 10);
                                         if ($pp_obj->getJobSelectionType() == 0 or $pp_obj->getJobSelectionType() == 10 or $pp_obj->getJobSelectionType() == 20 and in_array($udt_obj->getJob(), (array) $pp_obj->getJob()) or $pp_obj->getJobSelectionType() == 30 and !in_array($udt_obj->getJob(), (array) $pp_obj->getJob())) {
                                             Debug::text(' Shift Differential... Meets Job Criteria! Select Type: ' . $pp_obj->getJobSelectionType(), __FILE__, __LINE__, __METHOD__, 10);
                                             if ($pp_obj->getJobItemGroupSelectionType() == 0 or $pp_obj->getJobItemGroupSelectionType() == 10 or $pp_obj->getJobItemGroupSelectionType() == 20 and (is_object($udt_obj->getJobItemObject()) and in_array($udt_obj->getJobItemObject()->getGroup(), (array) $pp_obj->getJobItemGroup())) or $pp_obj->getJobItemGroupSelectionType() == 30 and (is_object($udt_obj->getJobItemObject()) and !in_array($udt_obj->getJobItemObject()->getGroup(), (array) $pp_obj->getJobItemGroup()))) {
                                                 Debug::text(' Shift Differential... Meets Task Group Criteria! Select Type: ' . $pp_obj->getJobItemGroupSelectionType(), __FILE__, __LINE__, __METHOD__, 10);
                                                 if ($pp_obj->getJobItemSelectionType() == 0 or $pp_obj->getJobItemSelectionType() == 10 or $pp_obj->getJobItemSelectionType() == 20 and in_array($udt_obj->getJobItem(), (array) $pp_obj->getJobItem()) or $pp_obj->getJobItemSelectionType() == 30 and !in_array($udt_obj->getJobItem(), (array) $pp_obj->getJobItem())) {
                                                     Debug::text(' Shift Differential... Meets Task Criteria! Select Type: ' . $pp_obj->getJobSelectionType(), __FILE__, __LINE__, __METHOD__, 10);
                                                     $premium_policy_daily_total_time = 0;
                                                     $punch_total_time = $udt_obj->getTotalTime();
                                                     $total_time = 0;
                                                     //Apply meal policy adjustment BEFORE min/max times
                                                     if ($pp_obj->getIncludeMealPolicy() == TRUE and isset($udt_meal_policy_adjustment_arr[$udt_obj->getId()])) {
                                                         Debug::text(' Meal Policy Adjustment Found: ' . $udt_meal_policy_adjustment_arr[$udt_obj->getId()], __FILE__, __LINE__, __METHOD__, 10);
                                                         $punch_total_time = bcadd($punch_total_time, $udt_meal_policy_adjustment_arr[$udt_obj->getId()]);
                                                     }
                                                     if ($pp_obj->getIncludeBreakPolicy() == TRUE and isset($udt_break_policy_adjustment_arr[$udt_obj->getId()])) {
                                                         Debug::text(' Break Policy Adjustment Found: ' . $udt_break_policy_adjustment_arr[$udt_obj->getId()], __FILE__, __LINE__, __METHOD__, 10);
                                                         $punch_total_time = bcadd($punch_total_time, $udt_break_policy_adjustment_arr[$udt_obj->getId()]);
                                                     }
                                                     $total_time = $punch_total_time;
                                                     if ($pp_obj->getMinimumTime() > 0 or $pp_obj->getMaximumTime() > 0) {
                                                         $premium_policy_daily_total_time = $udtlf->getPremiumPolicySumByUserDateIDAndPremiumPolicyID($this->getUserDateID(), $pp_obj->getId());
                                                         Debug::text(' Premium Policy Daily Total Time: ' . $premium_policy_daily_total_time . ' Minimum Time: ' . $pp_obj->getMinimumTime() . ' Maximum Time: ' . $pp_obj->getMaximumTime(), __FILE__, __LINE__, __METHOD__, 10);
                                                         if ($pp_obj->getMinimumTime() > 0) {
                                                             //FIXME: Split the minimum time up between all the punches somehow.
                                                             if ($i == $udtlf->getRecordCount() and bcadd($premium_policy_daily_total_time, $total_time) < $pp_obj->getMinimumTime()) {
                                                                 $total_time = bcsub($pp_obj->getMinimumTime(), $premium_policy_daily_total_time);
                                                             }
                                                         } else {
                                                             $total_time = $punch_total_time;
                                                         }
                                                         Debug::text(' Total Time After Minimum is applied: ' . $total_time, __FILE__, __LINE__, __METHOD__, 10);
                                                         if ($pp_obj->getMaximumTime() > 0) {
                                                             //Min & Max time is based on the shift time, rather then per punch pair time.
                                                             if (bcadd($premium_policy_daily_total_time, $total_time) > $pp_obj->getMaximumTime()) {
                                                                 $total_time = bcsub($total_time, bcsub(bcadd($premium_policy_daily_total_time, $total_time), $pp_obj->getMaximumTime()));
                                                                 Debug::text(' bMore than Maximum Time... new Total Time: ' . $total_time, __FILE__, __LINE__, __METHOD__, 10);
                                                             }
                                                         }
                                                     } else {
                                                         $total_time = $punch_total_time;
                                                     }
                                                     Debug::text(' Premium Punch Total Time: ' . $total_time, __FILE__, __LINE__, __METHOD__, 10);
                                                     if ($total_time > 0) {
                                                         Debug::text(' Applying  Premium Time!: ' . $total_time, __FILE__, __LINE__, __METHOD__, 10);
                                                         $udtf = TTnew('UserDateTotalFactory');
                                                         $udtf->setUserDateID($this->getUserDateID());
                                                         $udtf->setStatus(10);
                                                         //System
                                                         $udtf->setType(40);
                                                         //Premium
                                                         $udtf->setPremiumPolicyId($pp_obj->getId());
                                                         $udtf->setBranch($udt_obj->getBranch());
                                                         $udtf->setDepartment($udt_obj->getDepartment());
                                                         $udtf->setJob($udt_obj->getJob());
                                                         $udtf->setJobItem($udt_obj->getJobItem());
                                                         $udtf->setQuantity($udt_obj->getQuantity());
                                                         $udtf->setBadQuantity($udt_obj->getBadQuantity());
                                                         $udtf->setTotalTime($total_time);
                                                         $udtf->setEnableCalcSystemTotalTime(FALSE);
                                                         if ($udtf->isValid() == TRUE) {
                                                             $udtf->Save();
                                                         }
                                                         unset($udtf);
                                                     } else {
                                                         Debug::text(' Premium Punch Total Time is 0...', __FILE__, __LINE__, __METHOD__, 10);
                                                     }
                                                 } else {
                                                     Debug::text(' Shift Differential... DOES NOT Meet Task Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                                                 }
                                             } else {
                                                 Debug::text(' Shift Differential... DOES NOT Meet Task Group Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                                             }
                                         } else {
                                             Debug::text(' Shift Differential... DOES NOT Meet Job Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                                         }
                                     } else {
                                         Debug::text(' Shift Differential... DOES NOT Meet Job Group Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                 } else {
                                     Debug::text(' Shift Differential... DOES NOT Meet Department Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                                 }
                             } else {
                                 Debug::text(' Shift Differential... DOES NOT Meet Branch Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                             }
                             $i++;
                         }
                     }
                     unset($udtlf, $udt_obj);
                     break;
                 case 30:
                     //Meal/Break
                     Debug::text(' Meal/Break Premium Policy...', __FILE__, __LINE__, __METHOD__, 10);
                     if ($pp_obj->getDailyTriggerTime() == 0 or $pp_obj->getDailyTriggerTime() > 0 and $daily_total_time >= $pp_obj->getDailyTriggerTime()) {
                         //Find maximum worked without a break.
                         $plf = TTnew('PunchListFactory');
                         $plf->getByUserDateId($this->getUserDateID());
                         //Get all punches for the day.
                         if ($plf->getRecordCount() > 0) {
                             Debug::text('Found Punches: ' . $plf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
                             foreach ($plf as $p_obj) {
                                 Debug::text('TimeStamp: ' . $p_obj->getTimeStamp() . ' Status: ' . $p_obj->getStatus(), __FILE__, __LINE__, __METHOD__, 10);
                                 $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)) {
                                 $prev_punch_timestamp = NULL;
                                 $maximum_time_worked_without_break = 0;
                                 foreach ($punch_pairs as $punch_pair) {
                                     if (count($punch_pair) > 1) {
                                         //Total Punch Time
                                         $total_punch_pair_time = $punch_pair[1]['time_stamp'] - $punch_pair[0]['time_stamp'];
                                         $maximum_time_worked_without_break += $total_punch_pair_time;
                                         Debug::text('Total Punch Pair Time: ' . $total_punch_pair_time . ' Maximum No Break Time: ' . $maximum_time_worked_without_break, __FILE__, __LINE__, __METHOD__, 10);
                                         if ($prev_punch_timestamp !== NULL) {
                                             $break_time = $punch_pair[0]['time_stamp'] - $prev_punch_timestamp;
                                             if ($break_time > $pp_obj->getMinimumBreakTime()) {
                                                 Debug::text('Exceeded Minimum Break Time: ' . $break_time . ' Minimum: ' . $pp_obj->getMinimumBreakTime(), __FILE__, __LINE__, __METHOD__, 10);
                                                 $maximum_time_worked_without_break = 0;
                                             }
                                         }
                                         if ($maximum_time_worked_without_break > $pp_obj->getMaximumNoBreakTime()) {
                                             Debug::text('Exceeded maximum no break time!', __FILE__, __LINE__, __METHOD__, 10);
                                             if ($pp_obj->getMaximumTime() > $pp_obj->getMinimumTime()) {
                                                 $total_time = $pp_obj->getMaximumTime();
                                             } else {
                                                 $total_time = $pp_obj->getMinimumTime();
                                             }
                                             if ($total_time > 0) {
                                                 Debug::text(' Applying Meal/Break Premium Time!: ' . $total_time, __FILE__, __LINE__, __METHOD__, 10);
                                                 //Get Punch Control obj.
                                                 $pclf = TTnew('PunchControlListFactory');
                                                 $pclf->getById($punch_pair[0]['punch_control_id']);
                                                 if ($pclf->getRecordCount() > 0) {
                                                     $pc_obj = $pclf->getCurrent();
                                                 }
                                                 $udtf = TTnew('UserDateTotalFactory');
                                                 $udtf->setUserDateID($this->getUserDateID());
                                                 $udtf->setStatus(10);
                                                 //System
                                                 $udtf->setType(40);
                                                 //Premium
                                                 $udtf->setPremiumPolicyId($pp_obj->getId());
                                                 if (isset($pc_obj) and is_object($pc_obj)) {
                                                     $udtf->setBranch($pc_obj->getBranch());
                                                     $udtf->setDepartment($pc_obj->getDepartment());
                                                     $udtf->setJob($pc_obj->getJob());
                                                     $udtf->setJobItem($pc_obj->getJobItem());
                                                 }
                                                 $udtf->setTotalTime($total_time);
                                                 $udtf->setEnableCalcSystemTotalTime(FALSE);
                                                 if ($udtf->isValid() == TRUE) {
                                                     $udtf->Save();
                                                 }
                                                 unset($udtf);
                                                 break;
                                                 //Stop looping through punches.
                                             }
                                         } else {
                                             Debug::text('Did not exceed maximum no break time yet...', __FILE__, __LINE__, __METHOD__, 10);
                                         }
                                         $prev_punch_timestamp = $punch_pair[1]['time_stamp'];
                                     } else {
                                         Debug::text('Found UnPaired Punch, Ignorning...', __FILE__, __LINE__, __METHOD__, 10);
                                     }
                                 }
                                 unset($plf, $punch_pairs, $punch_pair, $prev_punch_timestamp, $maximum_time_worked_without_break, $total_time);
                             }
                         }
                     } else {
                         Debug::text(' Not within Daily Total Time: ' . $daily_total_time . ' Trigger Time: ' . $pp_obj->getDailyTriggerTime(), __FILE__, __LINE__, __METHOD__, 10);
                     }
                     break;
                 case 40:
                     //Callback
                     Debug::text(' Callback Premium Policy...', __FILE__, __LINE__, __METHOD__, 10);
                     Debug::text(' Minimum Time Between Shifts: ' . $pp_obj->getMinimumTimeBetweenShift() . ' Minimum First Shift Time: ' . $pp_obj->getMinimumFirstShiftTime(), __FILE__, __LINE__, __METHOD__, 10);
                     $first_punch_epoch = FALSE;
                     $plf = TTnew('PunchListFactory');
                     $plf->getByUserDateId($this->getUserDateID());
                     //Get all punches for the day.
                     if ($plf->getRecordCount() > 0) {
                         Debug::text('Found Punches: ' . $plf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
                         $i = 0;
                         foreach ($plf as $p_obj) {
                             Debug::text('TimeStamp: ' . $p_obj->getTimeStamp() . ' Status: ' . $p_obj->getStatus(), __FILE__, __LINE__, __METHOD__, 10);
                             if ($i == 0) {
                                 $first_punch_epoch = $p_obj->getTimeStamp();
                             }
                             $punch_pairs[$p_obj->getPunchControlID()][] = array('status_id' => $p_obj->getStatus(), 'punch_control_id' => $p_obj->getPunchControlID(), 'time_stamp' => $p_obj->getTimeStamp());
                             $i++;
                         }
                     }
                     //Debug::Arr($punch_pairs, ' Punch Pairs...', __FILE__, __LINE__, __METHOD__, 10);
                     $shift_data = FALSE;
                     if (is_object($this->getUserDateObject()->getPayPeriodObject()) and is_object($this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject())) {
                         //This should return all shifts within the minimum time between shifts setting.
                         //We need to get all shifts within
                         $shift_data = $this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject()->getShiftData(NULL, $this->getUserDateObject()->getUser(), $first_punch_epoch, NULL, NULL, $pp_obj->getMinimumTimeBetweenShift() + $pp_obj->getMinimumFirstShiftTime());
                     } else {
                         Debug::text(' No Pay Period...', __FILE__, __LINE__, __METHOD__, 10);
                     }
                     //Debug::Arr($shift_data, ' Shift Data...', __FILE__, __LINE__, __METHOD__, 10);
                     //Only calculate if their are at least two shifts
                     if (count($shift_data) >= 2) {
                         Debug::text(' Found at least two shifts...', __FILE__, __LINE__, __METHOD__, 10);
                         //Loop through shifts backwards.
                         krsort($shift_data);
                         $prev_key = FALSE;
                         foreach ($shift_data as $key => $data) {
                             //Debug::Arr($data, ' Shift Data for Shift: '. $key, __FILE__, __LINE__, __METHOD__, 10);
                             //Check if previous shift is greater than minimum first shift time.
                             $prev_key = $key - 1;
                             if (isset($shift_data[$prev_key]) and isset($shift_data[$prev_key]['total_time']) and $shift_data[$prev_key]['total_time'] >= $pp_obj->getMinimumFirstShiftTime()) {
                                 Debug::text(' Previous shift exceeds minimum first shift time... Shift Total Time: ' . $shift_data[$prev_key]['total_time'], __FILE__, __LINE__, __METHOD__, 10);
                                 //Get last out time of the previous shift.
                                 if (isset($shift_data[$prev_key]['last_out'])) {
                                     $previous_shift_last_out_epoch = $shift_data[$prev_key]['last_out']['time_stamp'];
                                     $current_shift_cutoff = $previous_shift_last_out_epoch + $pp_obj->getMinimumTimeBetweenShift();
                                     Debug::text(' Previous Shift Last Out: ' . TTDate::getDate('DATE+TIME', $previous_shift_last_out_epoch) . '(' . $previous_shift_last_out_epoch . ') Current Shift Cutoff: ' . TTDate::getDate('DATE+TIME', $current_shift_cutoff) . '(' . $previous_shift_last_out_epoch . ')', __FILE__, __LINE__, __METHOD__, 10);
                                     //Loop through all worked (status: 20) UserDateTotalRows
                                     $udtlf = TTnew('UserDateTotalListFactory');
                                     $udtlf->getByUserDateIdAndStatus($this->getUserDateID(), 20);
                                     if ($udtlf->getRecordCount() > 0) {
                                         Debug::text('Found Total Hours to attempt to apply premium policy... Record Count: ' . $udtlf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
                                         $x = 1;
                                         foreach ($udtlf as $udt_obj) {
                                             Debug::text('X: ' . $x . '/' . $udtlf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
                                             //Ignore incomplete punches
                                             if ($udt_obj->getTotalTime() == 0) {
                                                 continue;
                                             }
                                             if ($udt_obj->getPunchControlID() > 0 and isset($punch_pairs[$udt_obj->getPunchControlID()])) {
                                                 Debug::text(' Found valid Punch Control ID: ' . $udt_obj->getPunchControlID(), __FILE__, __LINE__, __METHOD__, 10);
                                                 Debug::text(' First Punch: ' . TTDate::getDate('DATE+TIME', $punch_pairs[$udt_obj->getPunchControlID()][0]['time_stamp']) . ' Last Punch: ' . TTDate::getDate('DATE+TIME', $punch_pairs[$udt_obj->getPunchControlID()][1]['time_stamp']), __FILE__, __LINE__, __METHOD__, 10);
                                                 $punch_total_time = 0;
                                                 $force_minimum_time_calculation = FALSE;
                                                 //Make sure OUT punch is before current_shift_cutoff
                                                 if (isset($punch_pairs[$udt_obj->getPunchControlID()][1]) and $punch_pairs[$udt_obj->getPunchControlID()][1]['time_stamp'] <= $current_shift_cutoff) {
                                                     Debug::text(' Both punches are BEFORE the cutoff time...', __FILE__, __LINE__, __METHOD__, 10);
                                                     $punch_total_time = bcsub($punch_pairs[$udt_obj->getPunchControlID()][1]['time_stamp'], $punch_pairs[$udt_obj->getPunchControlID()][0]['time_stamp']);
                                                 } elseif (isset($punch_pairs[$udt_obj->getPunchControlID()][0]) and $punch_pairs[$udt_obj->getPunchControlID()][0]['time_stamp'] <= $current_shift_cutoff) {
                                                     Debug::text(' Only IN punch is BEFORE the cutoff time...', __FILE__, __LINE__, __METHOD__, 10);
                                                     $punch_total_time = bcsub($current_shift_cutoff, $punch_pairs[$udt_obj->getPunchControlID()][0]['time_stamp']);
                                                     $force_minimum_time_calculation = TRUE;
                                                 } else {
                                                     Debug::text(' Both punches are AFTER the cutoff time... Skipping...', __FILE__, __LINE__, __METHOD__, 10);
                                                     //continue;
                                                     $punch_total_time = 0;
                                                 }
                                                 Debug::text(' Punch Total Time: ' . $punch_total_time, __FILE__, __LINE__, __METHOD__, 10);
                                                 //Apply meal policy adjustment BEFORE min/max times
                                                 if ($pp_obj->getIncludeMealPolicy() == TRUE and isset($udt_meal_policy_adjustment_arr[$udt_obj->getId()])) {
                                                     Debug::text(' Meal Policy Adjustment Found: ' . $udt_meal_policy_adjustment_arr[$udt_obj->getId()], __FILE__, __LINE__, __METHOD__, 10);
                                                     $punch_total_time = bcadd($punch_total_time, $udt_meal_policy_adjustment_arr[$udt_obj->getId()]);
                                                 }
                                                 if ($pp_obj->getIncludeBreakPolicy() == TRUE and isset($udt_break_policy_adjustment_arr[$udt_obj->getId()])) {
                                                     Debug::text(' Break Policy Adjustment Found: ' . $udt_break_policy_adjustment_arr[$udt_obj->getId()], __FILE__, __LINE__, __METHOD__, 10);
                                                     $punch_total_time = bcadd($punch_total_time, $udt_break_policy_adjustment_arr[$udt_obj->getId()]);
                                                 }
                                                 $premium_policy_daily_total_time = 0;
                                                 if ($pp_obj->getMinimumTime() > 0 or $pp_obj->getMaximumTime() > 0) {
                                                     $premium_policy_daily_total_time = $udtlf->getPremiumPolicySumByUserDateIDAndPremiumPolicyID($this->getUserDateID(), $pp_obj->getId());
                                                     Debug::text('X: ' . $x . '/' . $udtlf->getRecordCount() . ' Premium Policy Daily Total Time: ' . $premium_policy_daily_total_time . ' Minimum Time: ' . $pp_obj->getMinimumTime() . ' Maximum Time: ' . $pp_obj->getMaximumTime(), __FILE__, __LINE__, __METHOD__, 10);
                                                     if ($pp_obj->getMinimumTime() > 0) {
                                                         //FIXME: Split the minimum time up between all the punches somehow.
                                                         //Apply the minimum time on the last punch, otherwise if there are two punch pairs of 15min each
                                                         //and a 1hr minimum time, if the minimum time is applied to the first, it will be 1hr and 15min
                                                         //for the day. If its applied to the last it will be just 1hr.
                                                         //Min & Max time is based on the shift time, rather then per punch pair time.
                                                         if (($force_minimum_time_calculation == TRUE or $x == $udtlf->getRecordCount()) and bcadd($premium_policy_daily_total_time, $punch_total_time) < $pp_obj->getMinimumTime()) {
                                                             $total_time = bcsub($pp_obj->getMinimumTime(), $premium_policy_daily_total_time);
                                                         } else {
                                                             $total_time = $punch_total_time;
                                                         }
                                                     } else {
                                                         $total_time = $punch_total_time;
                                                     }
                                                     Debug::text(' Total Time After Minimum is applied: ' . $total_time, __FILE__, __LINE__, __METHOD__, 10);
                                                     if ($pp_obj->getMaximumTime() > 0) {
                                                         //Min & Max time is based on the shift time, rather then per punch pair time.
                                                         if (bcadd($premium_policy_daily_total_time, $total_time) > $pp_obj->getMaximumTime()) {
                                                             Debug::text(' bMore than Maximum Time...', __FILE__, __LINE__, __METHOD__, 10);
                                                             $total_time = bcsub($total_time, bcsub(bcadd($premium_policy_daily_total_time, $total_time), $pp_obj->getMaximumTime()));
                                                         }
                                                     }
                                                 } else {
                                                     $total_time = $punch_total_time;
                                                 }
                                                 Debug::text(' Total Punch Control Time: ' . $total_time, __FILE__, __LINE__, __METHOD__, 10);
                                                 if ($total_time > 0) {
                                                     Debug::text(' Applying  Premium Time!: ' . $total_time, __FILE__, __LINE__, __METHOD__, 10);
                                                     $udtf = TTnew('UserDateTotalFactory');
                                                     $udtf->setUserDateID($this->getUserDateID());
                                                     $udtf->setStatus(10);
                                                     //System
                                                     $udtf->setType(40);
                                                     //Premium
                                                     $udtf->setPremiumPolicyId($pp_obj->getId());
                                                     $udtf->setBranch($udt_obj->getBranch());
                                                     $udtf->setDepartment($udt_obj->getDepartment());
                                                     $udtf->setJob($udt_obj->getJob());
                                                     $udtf->setJobItem($udt_obj->getJobItem());
                                                     $udtf->setQuantity($udt_obj->getQuantity());
                                                     $udtf->setBadQuantity($udt_obj->getBadQuantity());
                                                     $udtf->setTotalTime($total_time);
                                                     $udtf->setEnableCalcSystemTotalTime(FALSE);
                                                     if ($udtf->isValid() == TRUE) {
                                                         $udtf->Save();
                                                     }
                                                     unset($udtf);
                                                 }
                                             } else {
                                                 Debug::text(' Skipping invalid Punch Control ID: ' . $udt_obj->getPunchControlID(), __FILE__, __LINE__, __METHOD__, 10);
                                             }
                                             $x++;
                                         }
                                     }
                                 }
                                 unset($previous_shift_last_out_epoch, $current_shift_cutoff, $udtlf);
                             } else {
                                 Debug::text(' Previous shift does not exist or does NOT exceed minimum first shift time... Key: ' . $prev_key, __FILE__, __LINE__, __METHOD__, 10);
                             }
                         }
                     } else {
                         Debug::text(' Didnt find two shifts, or the first shift wasnt long enough... Total Shifts: ' . count($shift_data), __FILE__, __LINE__, __METHOD__, 10);
                     }
                     unset($udtlf, $udt_obj, $plf, $punch_pairs, $first_punch_epoch, $shift_data, $data);
                     break;
                 case 50:
                     //Minimum shift time
                     Debug::text(' Minimum Shift Time Premium Policy... Minimum Shift Time: ' . $pp_obj->getMinimumShiftTime() . ' UserDateID: ' . $this->getUserDateID() . '  Daily Total Time: ' . $daily_total_time, __FILE__, __LINE__, __METHOD__, 10);
                     //Get all shifts on this day.
                     //Minimum Shift time should be on a per shift level, not a per day level.
                     //However the Min/Max time for the policy is per day. Only Minimum Shift Time is per shift.
                     if ($daily_total_time > 0 and is_object($this->getUserDateObject()) and is_object($this->getUserDateObject()->getPayPeriodObject()) and is_object($this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject())) {
                         $plf = TTnew('PunchListFactory');
                         $plf->getShiftPunchesByUserIDAndEpochAndArrayCriteria($this->getUserDateObject()->getUser(), TTDate::getMiddleDayEpoch($this->getUserDateObject()->getDateStamp()), array('premium_policy_id' => $pp_obj->getId(), 'branch_selection_type_id' => $pp_obj->getBranchSelectionType(), 'exclude_default_branch' => $pp_obj->getExcludeDefaultBranch(), 'default_branch_id' => $this->getUserDateObject()->getUserObject()->getDefaultBranch(), 'department_selection_type_id' => $pp_obj->getDepartmentSelectionType(), 'exclude_default_department' => $pp_obj->getExcludeDefaultDepartment(), 'default_department_id' => $this->getUserDateObject()->getUserObject()->getDefaultDepartment(), 'job_group_selection_type_id' => $pp_obj->getJobGroupSelectionType(), 'job_selection_type_id' => $pp_obj->getJobSelectionType(), 'job_item_group_selection_type_id' => $pp_obj->getJobItemGroupSelectionType(), 'job_item_selection_type_id' => $pp_obj->getJobItemSelectionType()));
                         $shift_data = $this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject()->getShiftData(NULL, $this->getUserDateObject()->getUser(), TTDate::getMiddleDayEpoch($this->getUserDateObject()->getDateStamp()), 'nearest', NULL, NULL, $pp_obj->getMinimumTimeBetweenShift(), $plf);
                         //$shift_data = $this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject()->getShiftData( $this->getUserDateID() );
                         //Debug::Arr($shift_data, ' Shift Data:', __FILE__, __LINE__, __METHOD__, 10);
                         if (is_array($shift_data)) {
                             $udtlf = TTnew('UserDateTotalListFactory');
                             $total_shifts = count($shift_data);
                             $x = 1;
                             foreach ($shift_data as $shift_data_arr) {
                                 $total_time = 0;
                                 $punch_total_time = $shift_data_arr['total_time'];
                                 if ($punch_total_time == 0) {
                                     //Skip shift if its not complete.
                                     continue;
                                 }
                                 foreach ($shift_data_arr['user_date_ids'] as $user_date_id) {
                                     //Apply meal policy adjustment BEFORE min/max times
                                     if ($pp_obj->getIncludeMealPolicy() == TRUE and isset($udt_meal_policy_adjustment_arr[$user_date_id])) {
                                         Debug::text(' Meal Policy Adjustment Found: ' . $udt_meal_policy_adjustment_arr[$user_date_id], __FILE__, __LINE__, __METHOD__, 10);
                                         $punch_total_time = bcadd($punch_total_time, $udt_meal_policy_adjustment_arr[$user_date_id]);
                                     }
                                     if ($pp_obj->getIncludeBreakPolicy() == TRUE and isset($udt_break_policy_adjustment_arr[$user_date_id])) {
                                         Debug::text(' Break Policy Adjustment Found: ' . $udt_break_policy_adjustment_arr[$user_date_id], __FILE__, __LINE__, __METHOD__, 10);
                                         $punch_total_time = bcadd($punch_total_time, $udt_break_policy_adjustment_arr[$user_date_id]);
                                     }
                                     Debug::text(' Found at least one shift, total time: ' . $punch_total_time, __FILE__, __LINE__, __METHOD__, 10);
                                 }
                                 if ($punch_total_time > $pp_obj->getMinimumShiftTime()) {
                                     Debug::text(' Shift exceeds minimum shift time...', __FILE__, __LINE__, __METHOD__, 10);
                                     continue;
                                 } else {
                                     $punch_total_time = bcsub($pp_obj->getMinimumShiftTime(), $punch_total_time);
                                 }
                                 $premium_policy_daily_total_time = 0;
                                 if ($pp_obj->getMinimumTime() > 0 or $pp_obj->getMaximumTime() > 0) {
                                     $premium_policy_daily_total_time = $udtlf->getPremiumPolicySumByUserDateIDAndPremiumPolicyID($this->getUserDateID(), $pp_obj->getId());
                                     Debug::text('X: ' . $x . '/' . $total_shifts . ' Premium Policy Daily Total Time: ' . $premium_policy_daily_total_time . ' Minimum Time: ' . $pp_obj->getMinimumTime() . ' Maximum Time: ' . $pp_obj->getMaximumTime(), __FILE__, __LINE__, __METHOD__, 10);
                                     if ($pp_obj->getMinimumTime() > 0) {
                                         //FIXME: Split the minimum time up between all the punches somehow.
                                         //Apply the minimum time on the last punch, otherwise if there are two punch pairs of 15min each
                                         //and a 1hr minimum time, if the minimum time is applied to the first, it will be 1hr and 15min
                                         //for the day. If its applied to the last it will be just 1hr.
                                         //Min & Max time is based on the shift time, rather then per punch pair time.
                                         if ($x == $total_shifts and bcadd($premium_policy_daily_total_time, $punch_total_time) < $pp_obj->getMinimumTime()) {
                                             $total_time = bcsub($pp_obj->getMinimumTime(), $premium_policy_daily_total_time);
                                         } else {
                                             $total_time = $punch_total_time;
                                         }
                                     } else {
                                         $total_time = $punch_total_time;
                                     }
                                     Debug::text(' Total Time After Minimum is applied: ' . $total_time, __FILE__, __LINE__, __METHOD__, 10);
                                     if ($pp_obj->getMaximumTime() > 0) {
                                         //Min & Max time is based on the shift time, rather then per punch pair time.
                                         if (bcadd($premium_policy_daily_total_time, $total_time) > $pp_obj->getMaximumTime()) {
                                             Debug::text(' bMore than Maximum Time...', __FILE__, __LINE__, __METHOD__, 10);
                                             $total_time = bcsub($total_time, bcsub(bcadd($premium_policy_daily_total_time, $total_time), $pp_obj->getMaximumTime()));
                                         }
                                     }
                                 } else {
                                     $total_time = $punch_total_time;
                                 }
                                 Debug::text(' Total Punch Control Time: ' . $total_time, __FILE__, __LINE__, __METHOD__, 10);
                                 if ($total_time > 0) {
                                     Debug::text(' Applying  Premium Time!: ' . $total_time, __FILE__, __LINE__, __METHOD__, 10);
                                     //Find branch,department,job,task of last punch_control_id in shift.
                                     if (isset($shift_data_arr['punch_control_ids'])) {
                                         $punch_control_id = $shift_data_arr['punch_control_ids'][0];
                                         $udtlf->getByUserDateIdAndPunchControlId($this->getUserDateID(), $punch_control_id);
                                         if ($udtlf->getRecordCount() > 0) {
                                             $udt_obj = $udtlf->getCurrent();
                                             $udtf = TTnew('UserDateTotalFactory');
                                             $udtf->setUserDateID($this->getUserDateID());
                                             $udtf->setStatus(10);
                                             //System
                                             $udtf->setType(40);
                                             //Premium
                                             $udtf->setPremiumPolicyId($pp_obj->getId());
                                             $udtf->setBranch($udt_obj->getBranch());
                                             $udtf->setDepartment($udt_obj->getDepartment());
                                             $udtf->setJob($udt_obj->getJob());
                                             $udtf->setJobItem($udt_obj->getJobItem());
                                             $udtf->setQuantity($udt_obj->getQuantity());
                                             $udtf->setBadQuantity($udt_obj->getBadQuantity());
                                             $udtf->setTotalTime($total_time);
                                             $udtf->setEnableCalcSystemTotalTime(FALSE);
                                             if ($udtf->isValid() == TRUE) {
                                                 $udtf->Save();
                                             }
                                             unset($udtf);
                                         }
                                     }
                                 }
                                 $x++;
                             }
                             unset($shift_data_arr, $total_shifts, $punch_total_time, $total_time);
                         }
                         unset($shift_data);
                     } else {
                         Debug::Text('No shift data to process...', __FILE__, __LINE__, __METHOD__, 10);
                     }
                     unset($udtlf, $udt_obj);
                     break;
                     /*
                      *					//Merged with Date/Time criteria above to reduce code duplication.
                     					case 100: //Advanced
                     						Debug::text(' Advanced Premium Policy...', __FILE__, __LINE__, __METHOD__, 10);
                     
                     						if ( is_object( $this->getUserDateObject()->getPayPeriodObject() )
                     										AND is_object( $this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject() ) ) {
                     							$maximum_shift_time = $this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject()->getMaximumShiftTime();
                     						}
                     						if ( !isset($maximum_shift_time) OR $maximum_shift_time < 86400 ) {
                     							$maximum_shift_time = 86400;
                     						}
                     
                     						//Make sure this is a valid day
                     						if ( $pp_obj->isActive( $this->getUserDateObject()->getDateStamp()-$maximum_shift_time, $this->getUserDateObject()->getDateStamp()+$maximum_shift_time, $this->getUserDateObject()->getUser() ) ) {
                     							Debug::text(' Premium Policy Is Active On This Day.', __FILE__, __LINE__, __METHOD__, 10);
                     
                     							$total_daily_time_used = 0;
                     							$daily_trigger_time = 0;
                     							$maximum_daily_trigger_time = FALSE;
                     
                     							$udtlf = TTnew( 'UserDateTotalListFactory' );
                     
                     							if ( $pp_obj->isHourRestricted() == TRUE ) {
                     								if ( $pp_obj->getWeeklyTriggerTime() > 0 OR $pp_obj->getMaximumWeeklyTriggerTime() > 0 ) {
                     									//Get Pay Period Schedule info
                     									if ( is_object( $this->getUserDateObject()->getPayPeriodObject() )
                     											AND is_object( $this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject() ) ) {
                     										$start_week_day_id = $this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject()->getStartWeekDay();
                     									} else {
                     										$start_week_day_id = 0;
                     									}
                     									Debug::text('Start Week Day ID: '. $start_week_day_id, __FILE__, __LINE__, __METHOD__, 10);
                     
                     									//$weekly_total_time = $udtlf->getWeekRegularTimeSumByUserIDAndEpochAndStartWeekEpoch( $this->getUserDateObject()->getUser(), $this->getUserDateObject()->getDateStamp(), TTDate::getBeginWeekEpoch($this->getUserDateObject()->getDateStamp(), $start_week_day_id) );
                     									$weekly_total_time = $udtlf->getWeekWorkedTimeSumByUserIDAndEpochAndStartWeekEpoch( $this->getUserDateObject()->getUser(), $this->getUserDateObject()->getDateStamp(), TTDate::getBeginWeekEpoch($this->getUserDateObject()->getDateStamp(), $start_week_day_id) );
                     									if ( $weekly_total_time > $pp_obj->getWeeklyTriggerTime() ) {
                     										$daily_trigger_time = 0;
                     									} else {
                     										$daily_trigger_time = $pp_obj->getWeeklyTriggerTime() - $weekly_total_time;
                     									}
                     									Debug::text(' Weekly Trigger Time: '. $daily_trigger_time .' Weekly Total Time: '. $weekly_total_time, __FILE__, __LINE__, __METHOD__, 10);
                     								}
                     
                     								if ( $pp_obj->getDailyTriggerTime() > 0 AND $pp_obj->getDailyTriggerTime() > $daily_trigger_time ) {
                     									$daily_trigger_time = $pp_obj->getDailyTriggerTime();
                     								}
                     
                     								if ( $pp_obj->getMaximumDailyTriggerTime() > 0 OR $pp_obj->getMaximumWeeklyTriggerTime() > 0  ) {
                     									$maximum_daily_trigger_time = ( $pp_obj->getMaximumDailyTriggerTime() > 0 ) ? ($pp_obj->getMaximumDailyTriggerTime()-$pp_obj->getDailyTriggerTime()) : FALSE;
                     									$maximum_weekly_trigger_time = ( isset($weekly_total_time) AND $pp_obj->getMaximumWeeklyTriggerTime() > 0 ) ? ($pp_obj->getMaximumWeeklyTriggerTime()-$weekly_total_time) : FALSE;
                     
                     									Debug::text(' Maximum Daily: '. $maximum_daily_trigger_time .' Weekly: '. $maximum_weekly_trigger_time, __FILE__, __LINE__, __METHOD__, 10);
                     									if ( $maximum_daily_trigger_time > 0 AND ( $maximum_weekly_trigger_time === FALSE OR $maximum_daily_trigger_time < $maximum_weekly_trigger_time ) ) {
                     										$pp_obj->setMaximumTime( $maximum_daily_trigger_time ); //Temporarily set the maximum time in memory so it doesn't exceed the maximum daily trigger time.
                     										Debug::text(' Set Daily Maximum Time to: '. $pp_obj->getMaximumTime(), __FILE__, __LINE__, __METHOD__, 10);
                     									} else {
                     										if ( $maximum_weekly_trigger_time !== FALSE AND ( $maximum_weekly_trigger_time <= 0 OR ( $maximum_weekly_trigger_time < $daily_trigger_time ) ) ) {
                     											Debug::text(' Exceeded Weekly Maximum Time to: '. $pp_obj->getMaximumTime() .' Skipping...', __FILE__, __LINE__, __METHOD__, 10);
                     											continue;
                     										}
                     										$pp_obj->setMaximumTime( $maximum_weekly_trigger_time ); //Temporarily set the maximum time in memory so it doesn't exceed the maximum daily trigger time.
                     										Debug::text(' Set Weekly Maximum Time to: '. $pp_obj->getMaximumTime(), __FILE__, __LINE__, __METHOD__, 10);
                     										$maximum_daily_trigger_time = $maximum_weekly_trigger_time;
                     									}
                     									unset($maximum_weekly_trigger_time);
                     								}
                     							}
                     							Debug::text(' Daily Trigger Time: '. $daily_trigger_time, __FILE__, __LINE__, __METHOD__, 10);
                     
                     							//Loop through all worked (status: 20) UserDateTotalRows
                     							$udtlf->getByUserDateIdAndStatus( $this->getUserDateID(), 20 );
                     							$i = 1;
                     							if ( $udtlf->getRecordCount() > 0 ) {
                     								Debug::text('Found Total Hours to attempt to apply premium policy... Record Count: '. $udtlf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
                     
                     								foreach( $udtlf as $udt_obj ) {
                     									//Ignore incomplete punches
                     									if ( $udt_obj->getTotalTime() == 0 ) {
                     										continue;
                     									}
                     
                     									//How do we handle actual shifts for premium time?
                     									//So if premium policy starts at 1PM for shifts, to not
                     									//include employees who return from lunch at 1:30PM.
                     									//Create a function that takes all punches for a day, and returns
                     									//the first in and last out time for a given shift when taking
                     									//into account minimum time between shifts, as well as the total time for that shift.
                     									//We can then use that time for ActiveTime on premium policies, and determine if a
                     									//punch falls within the active time, then we add it to the total.
                     									if ( ($pp_obj->getIncludePartialPunch() == TRUE OR $pp_obj->isTimeRestricted() == TRUE ) AND $udt_obj->getPunchControlID() != FALSE ) {
                     										Debug::text('Time Restricted Premium Policy, lookup punches to get times.', __FILE__, __LINE__, __METHOD__, 10);
                     
                     										if ( $pp_obj->getIncludePartialPunch() == FALSE ) {
                     											$shift_data = $this->getShiftDataByUserDateID( $this->getUserDateID() );
                     										}
                     
                     										$plf = TTnew( 'PunchListFactory' );
                     										$plf->getByPunchControlId( $udt_obj->getPunchControlID() );
                     										if ( $plf->getRecordCount() > 0 ) {
                     											Debug::text('Found Punches: '. $plf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
                     											foreach( $plf as $punch_obj ) {
                     												if ( $pp_obj->getIncludePartialPunch() == TRUE ) {
                     													//Debug::text('Including Partial Punches...', __FILE__, __LINE__, __METHOD__, 10);
                     
                     													if ( $punch_obj->getStatus() == 10 ) {
                     														$punch_times['in'] = $punch_obj->getTimeStamp();
                     													} elseif ( $punch_obj->getStatus() == 20 ) {
                     														$punch_times['out'] = $punch_obj->getTimeStamp();
                     													}
                     												} else {
                     													if ( isset($shift_data) AND is_array($shift_data) ) {
                     														foreach( $shift_data as $shift ) {
                     															if ( $punch_obj->getTimeStamp() >= $shift['first_in']
                     																	AND $punch_obj->getTimeStamp() <= $shift['last_out'] ) {
                     																//Debug::Arr($shift,'Shift Data...', __FILE__, __LINE__, __METHOD__, 10);
                     																Debug::text('Punch ('. TTDate::getDate('DATE+TIME', $punch_obj->getTimeStamp() ).') inside shift time...', __FILE__, __LINE__, __METHOD__, 10);
                     																$punch_times['in'] = $shift['first_in'];
                     																$punch_times['out'] = $shift['last_out'];
                     																break;
                     															} else {
                     																Debug::text('Punch ('. TTDate::getDate('DATE+TIME', $punch_obj->getTimeStamp() ).') outside shift time...', __FILE__, __LINE__, __METHOD__, 10);
                     															}
                     														}
                     													}
                     												}
                     											}
                     
                     											if ( isset($punch_times) AND count($punch_times) == 2
                     													AND ( $pp_obj->isActiveDate( $punch_times['in'] ) == TRUE OR $pp_obj->isActiveDate( $punch_times['out'] ) )
                     													AND ( $pp_obj->isActive( $punch_times['in'], $punch_times['out'], $this->getUserDateObject()->getUser() ) )
                     													AND $pp_obj->isActiveTime( $punch_times['in'], $punch_times['out'], $this->getUserDateObject()->getUser() ) == TRUE ) {
                     												//Debug::Arr($punch_times, 'Punch Times: ', __FILE__, __LINE__, __METHOD__, 10);
                     												$punch_total_time = $pp_obj->getPartialPunchTotalTime( $punch_times['in'], $punch_times['out'], $udt_obj->getTotalTime(), $this->getUserDateObject()->getUser() );
                     												$valid_user_date_total_ids[] = $udt_obj->getID(); //Need to record punches that fall within the active time so we can properly handle break/meal adjustments.
                     												Debug::text('Valid Punch pair in active time, Partial Punch Total Time: '. $punch_total_time, __FILE__, __LINE__, __METHOD__, 10);
                     											} else {
                     												Debug::text('InValid Punch Pair or outside Active Time...', __FILE__, __LINE__, __METHOD__, 10);
                     												$punch_total_time = 0;
                     											}
                     										}
                     									} elseif ( $pp_obj->isActive( $udt_obj->getUserDateObject()->getDateStamp(), NULL, $this->getUserDateObject()->getUser() ) == TRUE )  {
                     										$punch_total_time = $udt_obj->getTotalTime();
                     										$valid_user_date_total_ids[] = $udt_obj->getID();
                     									} else {
                     										$punch_total_time = 0;
                     									}
                     
                     									$tmp_punch_total_time = $udt_obj->getTotalTime();
                     									Debug::text('aPunch Total Time: '. $punch_total_time .' TMP Punch Total Time: '. $tmp_punch_total_time, __FILE__, __LINE__, __METHOD__, 10);
                     
                     									//Apply meal policy adjustment as early as possible.
                     									if ( $pp_obj->getIncludeMealPolicy() == TRUE
                     											AND $pp_obj->isActiveDate( $this->getUserDateObject()->getDateStamp() ) == TRUE
                     											AND $pp_obj->isActiveDayofWeek( $this->getUserDateObject()->getDateStamp() ) == TRUE
                     											AND isset( $udt_meal_policy_adjustment_arr[$udt_obj->getId()] )
                     											AND in_array( $udt_obj->getID(), $valid_user_date_total_ids) ) {
                     										Debug::text(' Meal Policy Adjustment Found: '. $udt_meal_policy_adjustment_arr[$udt_obj->getId()], __FILE__, __LINE__, __METHOD__, 10);
                     										$punch_total_time = bcadd( $punch_total_time, $udt_meal_policy_adjustment_arr[$udt_obj->getId()] );
                     										$tmp_punch_total_time = bcadd( $tmp_punch_total_time, $udt_meal_policy_adjustment_arr[$udt_obj->getId()] );
                     									}
                     									Debug::text('bPunch Total Time: '. $punch_total_time .' TMP Punch Total Time: '. $tmp_punch_total_time, __FILE__, __LINE__, __METHOD__, 10);
                     
                     									//Apply break policy adjustment as early as possible.
                     									if ( $pp_obj->getIncludeBreakPolicy() == TRUE
                     										AND $pp_obj->isActiveDate( $this->getUserDateObject()->getDateStamp() ) == TRUE
                     										AND $pp_obj->isActiveDayofWeek( $this->getUserDateObject()->getDateStamp() ) == TRUE
                     										AND isset( $udt_break_policy_adjustment_arr[$udt_obj->getId()] )
                     										AND in_array( $udt_obj->getID(), $valid_user_date_total_ids) ) {
                     										Debug::text(' Break Policy Adjustment Found: '. $udt_break_policy_adjustment_arr[$udt_obj->getId()], __FILE__, __LINE__, __METHOD__, 10);
                     										$punch_total_time = bcadd( $punch_total_time, $udt_break_policy_adjustment_arr[$udt_obj->getId()] );
                     										$tmp_punch_total_time = bcadd( $tmp_punch_total_time, $udt_break_policy_adjustment_arr[$udt_obj->getId()] );
                     									}
                     									Debug::text('cPunch Total Time: '. $punch_total_time .' TMP Punch Total Time: '. $tmp_punch_total_time, __FILE__, __LINE__, __METHOD__, 10);
                     
                     									$total_daily_time_used += $tmp_punch_total_time;
                     									Debug::text('Daily Total Time Used: '. $total_daily_time_used, __FILE__, __LINE__, __METHOD__, 10);
                     
                     									if ( $punch_total_time > 0 AND $total_daily_time_used > $daily_trigger_time
                     											AND ( $maximum_daily_trigger_time === FALSE OR ( $maximum_daily_trigger_time !== FALSE AND ($total_daily_time_used-$tmp_punch_total_time) <= $maximum_daily_trigger_time ) )
                     											) {
                     										Debug::text('Past Trigger Time!!', __FILE__, __LINE__, __METHOD__, 10);
                     
                     										//Calculate how far past trigger time we are.
                     										$past_trigger_time = $total_daily_time_used - $daily_trigger_time;
                     										if ( $punch_total_time > $past_trigger_time ) {
                     											$punch_total_time = $past_trigger_time;
                     											Debug::text('Using Past Trigger Time as punch total time: '. $past_trigger_time, __FILE__, __LINE__, __METHOD__, 10);
                     										} else {
                     											Debug::text('NOT Using Past Trigger Time as punch total time: '. $past_trigger_time, __FILE__, __LINE__, __METHOD__, 10);
                     										}
                     
                     										//If we are close to exceeding the maximum daily/weekly time, just use the remaining time.
                     										$maximum_trigger_time = $maximum_daily_trigger_time - ($total_daily_time_used-$tmp_punch_total_time);
                     										if ( $punch_total_time > $maximum_trigger_time AND $maximum_trigger_time > 0 ) {
                     											Debug::text('Using New Maximum Trigger Time as punch total time: '. $maximum_trigger_time .'('. $total_daily_time_used.')', __FILE__, __LINE__, __METHOD__, 10);
                     											$punch_total_time = $maximum_trigger_time;
                     										} else {
                     											Debug::text('NOT Using New Maximum Trigger Time as punch total time: '. $maximum_trigger_time .'('. $total_daily_time_used.')', __FILE__, __LINE__, __METHOD__, 10);
                     										}
                     
                     										$total_time = $punch_total_time;
                     										if ( $pp_obj->getMinimumTime() > 0 OR $pp_obj->getMaximumTime() > 0 ) {
                     											$premium_policy_daily_total_time = (int)$udtlf->getPremiumPolicySumByUserDateIDAndPremiumPolicyID( $this->getUserDateID(), $pp_obj->getId() );
                     											Debug::text(' Premium Policy Daily Total Time: '. $premium_policy_daily_total_time .' Minimum Time: '. $pp_obj->getMinimumTime() .' Maximum Time: '. $pp_obj->getMaximumTime(), __FILE__, __LINE__, __METHOD__, 10);
                     
                     											if ( $pp_obj->getMinimumTime() > 0 ) {
                     												//FIXME: Split the minimum time up between all the punches somehow.
                     												if ( $i == $udtlf->getRecordCount() AND bcadd( $premium_policy_daily_total_time, $total_time ) < $pp_obj->getMinimumTime() ) {
                     													$total_time = bcsub( $pp_obj->getMinimumTime(), $premium_policy_daily_total_time );
                     												}
                     											}
                     
                     											Debug::text(' Total Time After Minimum is applied: '. $total_time, __FILE__, __LINE__, __METHOD__, 10);
                     											if ( $pp_obj->getMaximumTime() > 0 ) {
                     												//Make Min/Maximum time a per day setting rather than per user_date_total row setting.
                     												//This is ideal for fringe benefits or anything that applies on a "daily" basis.
                     												//if ( $total_time > $pp_obj->getMaximumTime() ) {
                     												//	Debug::text(' aMore than Maximum Time...', __FILE__, __LINE__, __METHOD__, 10);
                     												//	$total_time = $pp_obj->getMaximumTime();
                     												//} else
                     												if ( bcadd( $premium_policy_daily_total_time, $total_time ) > $pp_obj->getMaximumTime() ) {
                     													Debug::text(' bMore than Maximum Time...', __FILE__, __LINE__, __METHOD__, 10);
                     													$total_time = bcsub( $total_time, bcsub( bcadd( $premium_policy_daily_total_time, $total_time ), $pp_obj->getMaximumTime() ) );
                     												}
                     											}
                     										}
                     
                     										Debug::text(' Premium Punch Total Time: '. $total_time, __FILE__, __LINE__, __METHOD__, 10);
                     										if ( $total_time > 0 ) {
                     											Debug::text(' Applying Premium Time!: '. $total_time , __FILE__, __LINE__, __METHOD__, 10);
                     
                     											//Check Shift Differential criteria *AFTER* calculatating daily/weekly time, as the shift differential
                     											//applies to the resulting time calculation, not the daily/weekly time calculation. Daily/Weekly should always include all time.
                     											//This is fundamentally different than the Shift Differential premium policy type.
                     											if ( ( $pp_obj->getBranchSelectionType() == 10
                     														AND ( $pp_obj->getExcludeDefaultBranch() == FALSE
                     																OR ( $pp_obj->getExcludeDefaultBranch() == TRUE
                     																		AND $udt_obj->getBranch() != $this->getUserDateObject()->getUserObject()->getDefaultBranch() ) ) )
                     
                     													OR ( $pp_obj->getBranchSelectionType() == 20
                     															AND in_array( $udt_obj->getBranch(), (array)$pp_obj->getBranch() ) )
                     															AND ( $pp_obj->getExcludeDefaultBranch() == FALSE
                     																	OR ( $pp_obj->getExcludeDefaultBranch() == TRUE
                     																			AND $udt_obj->getBranch() != $this->getUserDateObject()->getUserObject()->getDefaultBranch() ) )
                     
                     													OR ( $pp_obj->getBranchSelectionType() == 30
                     															AND !in_array( $udt_obj->getBranch(), (array)$pp_obj->getBranch() ) )
                     															AND ( $pp_obj->getExcludeDefaultBranch() == FALSE
                     																	OR ( $pp_obj->getExcludeDefaultBranch() == TRUE
                     																			AND $udt_obj->getBranch() != $this->getUserDateObject()->getUserObject()->getDefaultBranch() ) )
                     
                     													) {
                     												Debug::text(' Shift Differential... Meets Branch Criteria! Select Type: '. $pp_obj->getBranchSelectionType() .' Exclude Default Branch: '. (int)$pp_obj->getExcludeDefaultBranch() .' Default Branch: '.  $this->getUserDateObject()->getUserObject()->getDefaultBranch(), __FILE__, __LINE__, __METHOD__, 10);
                     
                     												if ( ( $pp_obj->getDepartmentSelectionType() == 10
                     															AND ( $pp_obj->getExcludeDefaultDepartment() == FALSE
                     																	OR ( $pp_obj->getExcludeDefaultDepartment() == TRUE
                     																			AND $udt_obj->getDepartment() != $this->getUserDateObject()->getUserObject()->getDefaultDepartment() ) ) )
                     
                     														OR ( $pp_obj->getDepartmentSelectionType() == 20
                     																AND in_array( $udt_obj->getDepartment(), (array)$pp_obj->getDepartment() ) )
                     																AND ( $pp_obj->getExcludeDefaultDepartment() == FALSE
                     																		OR ( $pp_obj->getExcludeDefaultDepartment() == TRUE
                     																				AND $udt_obj->getDepartment() != $this->getUserDateObject()->getUserObject()->getDefaultDepartment() ) )
                     
                     														OR ( $pp_obj->getDepartmentSelectionType() == 30
                     																AND !in_array( $udt_obj->getDepartment(), (array)$pp_obj->getDepartment() ) )
                     																AND ( $pp_obj->getExcludeDefaultDepartment() == FALSE
                     																		OR ( $pp_obj->getExcludeDefaultDepartment() == TRUE
                     																				AND $udt_obj->getDepartment() != $this->getUserDateObject()->getUserObject()->getDefaultDepartment() ) )
                     
                     														) {
                     													Debug::text(' Shift Differential... Meets Department Criteria! Select Type: '. $pp_obj->getDepartmentSelectionType() .' Exclude Default Department: '. (int)$pp_obj->getExcludeDefaultDepartment() .' Default Department: '.  $this->getUserDateObject()->getUserObject()->getDefaultDepartment(), __FILE__, __LINE__, __METHOD__, 10);
                     
                     													if ( $pp_obj->getJobGroupSelectionType() == 10
                     															OR ( $pp_obj->getJobGroupSelectionType() == 20
                     																	AND is_object( $udt_obj->getJobObject() )
                     																	AND in_array( $udt_obj->getJobObject()->getGroup(), (array)$pp_obj->getJobGroup() ) )
                     															OR ( $pp_obj->getJobGroupSelectionType() == 30
                     																	AND is_object( $udt_obj->getJobObject() )
                     																	AND !in_array( $udt_obj->getJobObject()->getGroup(), (array)$pp_obj->getJobGroup() ) )
                     															) {
                     														Debug::text(' Shift Differential... Meets Job Group Criteria! Select Type: '. $pp_obj->getJobGroupSelectionType(), __FILE__, __LINE__, __METHOD__, 10);
                     
                     														if ( $pp_obj->getJobSelectionType() == 10
                     																OR ( $pp_obj->getJobSelectionType() == 20
                     																		AND in_array( $udt_obj->getJob(), (array)$pp_obj->getJob() ) )
                     																OR ( $pp_obj->getJobSelectionType() == 30
                     																		AND !in_array( $udt_obj->getJob(), (array)$pp_obj->getJob() ) )
                     																) {
                     															Debug::text(' Shift Differential... Meets Job Criteria! Select Type: '. $pp_obj->getJobSelectionType(), __FILE__, __LINE__, __METHOD__, 10);
                     
                     															if ( $pp_obj->getJobItemGroupSelectionType() == 10
                     																	OR ( $pp_obj->getJobItemGroupSelectionType() == 20
                     																			AND is_object( $udt_obj->getJobItemObject() )
                     																			AND in_array( $udt_obj->getJobItemObject()->getGroup(), (array)$pp_obj->getJobItemGroup() ) )
                     																	OR ( $pp_obj->getJobItemGroupSelectionType() == 30
                     																			AND is_object( $udt_obj->getJobItemObject() )
                     																			AND !in_array( $udt_obj->getJobItemObject()->getGroup(), (array)$pp_obj->getJobItemGroup() ) )
                     																	) {
                     																Debug::text(' Shift Differential... Meets Task Group Criteria! Select Type: '. $pp_obj->getJobItemGroupSelectionType(), __FILE__, __LINE__, __METHOD__, 10);
                     
                     																if ( $pp_obj->getJobItemSelectionType() == 10
                     																		OR ( $pp_obj->getJobItemSelectionType() == 20
                     																				AND in_array( $udt_obj->getJobItem(), (array)$pp_obj->getJobItem() ) )
                     																		OR ( $pp_obj->getJobItemSelectionType() == 30
                     																				AND !in_array( $udt_obj->getJobItem(), (array)$pp_obj->getJobItem() ) )
                     																		) {
                     																	Debug::text(' Shift Differential... Meets Task Criteria! Select Type: '. $pp_obj->getJobSelectionType(), __FILE__, __LINE__, __METHOD__, 10);
                     
                     
                     																	$udtf = TTnew( 'UserDateTotalFactory' );
                     																	$udtf->setUserDateID( $this->getUserDateID() );
                     																	$udtf->setStatus( 10 ); //System
                     																	$udtf->setType( 40 ); //Premium
                     																	$udtf->setPremiumPolicyId( $pp_obj->getId() );
                     																	$udtf->setBranch( $udt_obj->getBranch() );
                     																	$udtf->setDepartment( $udt_obj->getDepartment() );
                     																	$udtf->setJob( $udt_obj->getJob() );
                     																	$udtf->setJobItem( $udt_obj->getJobItem() );
                     
                     																	$udtf->setQuantity( $udt_obj->getQuantity() );
                     																	$udtf->setBadQuantity( $udt_obj->getBadQuantity() );
                     
                     																	$udtf->setTotalTime( $total_time );
                     																	$udtf->setEnableCalcSystemTotalTime(FALSE);
                     																	if ( $udtf->isValid() == TRUE ) {
                     																		$udtf->Save();
                     																	}
                     																	unset($udtf);
                     
                     																} else {
                     																	Debug::text(' Shift Differential... DOES NOT Meet Task Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                     																}
                     															} else {
                     																Debug::text(' Shift Differential... DOES NOT Meet Task Group Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                     															}
                     														} else {
                     															Debug::text(' Shift Differential... DOES NOT Meet Job Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                     														}
                     													} else {
                     														Debug::text(' Shift Differential... DOES NOT Meet Job Group Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                     													}
                     												} else {
                     													Debug::text(' Shift Differential... DOES NOT Meet Department Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                     												}
                     											} else {
                     												Debug::text(' Shift Differential... DOES NOT Meet Branch Criteria!', __FILE__, __LINE__, __METHOD__, 10);
                     											}
                     
                     										} else {
                     											Debug::text(' Premium Punch Total Time is 0...', __FILE__, __LINE__, __METHOD__, 10);
                     										}
                     									} else {
                     										Debug::text('Not Past Trigger Time Yet or Punch Time is 0...', __FILE__, __LINE__, __METHOD__, 10);
                     									}
                     
                     									$i++;
                     								}
                     							}
                     						}
                     						unset($udtlf, $udt_obj);
                     						break;
                     */
             }
         }
     }
     $profiler->stopTimer('UserDateTotal::calcPremiumPolicyTotalTime() - Part 1');
     return TRUE;
 }
Пример #19
0
    function getPreviousPunchByUserIdAndStatusAndTypeAndEpoch($user_id, $status_id, $type_id, $epoch, $order = NULL)
    {
        if ($user_id == '') {
            return FALSE;
        }
        if ($status_id == '') {
            return FALSE;
        }
        if ($type_id == '') {
            return FALSE;
        }
        if ($epoch == '') {
            return FALSE;
        }
        $udf = new UserDateFactory();
        $pcf = new PunchControlFactory();
        $ph = array('user_id' => $user_id, 'date_stamp1' => $this->db->BindDate(TTDate::getMiddleDayEpoch($epoch) - 86400), 'date_stamp2' => $this->db->BindDate(TTDate::getMiddleDayEpoch($epoch) + 86400), 'time_stamp' => $this->db->BindTimeStamp($epoch), 'status_id' => $status_id);
        //Narrow down the c.date_stamp column to speed this query up, as sometimes it can be so slow that connections timeout.
        //Status order matters, because if its a.status_id desc, OUT comes first, but if the last
        //punch doesn't have OUT yet, it defaults to IN
        // with a.status_id asc...
        $query = '
					select 	a.*
					from 	' . $this->getTable() . ' as a,
							' . $pcf->getTable() . ' as b,
							' . $udf->getTable() . ' as c
					where	a.punch_control_id = b.id
						AND b.user_date_id = c.id
						AND c.user_id = ?
						AND ( c.date_stamp >= ? AND c.date_stamp <= ? )
						AND a.time_stamp <= ?
						AND a.status_id = ?
						AND a.type_id in ( ' . $this->getListSQL($type_id, $ph) . ' )
						AND ( a.deleted = 0 AND b.deleted=0 )
					ORDER BY a.time_stamp desc
					LIMIT 1
					';
        $query .= $this->getSortSQL($order);
        //Debug::Arr($ph,'Query: '. $query, __FILE__, __LINE__, __METHOD__,10);
        $this->ExecuteSQL($query, $ph);
        return $this;
    }
Пример #20
0
 public static function getDateOfNextDayOfMonth($anchor_epoch, $day_of_month_epoch, $day_of_month = NULL)
 {
     //Anchor Epoch is the anchor date to start searching from.
     //Day of month epoch is the epoch we use to extract the day of the month from.
     Debug::text('-------- ', __FILE__, __LINE__, __METHOD__, 10);
     Debug::text('Anchor Epoch: ' . TTDate::getDate('DATE+TIME', $anchor_epoch) . ' Day Of Month Epoch: ' . TTDate::getDate('DATE+TIME', $day_of_month_epoch) . ' Day Of Month: ' . $day_of_month, __FILE__, __LINE__, __METHOD__, 10);
     if ($anchor_epoch == '') {
         return FALSE;
     }
     if ($day_of_month_epoch == '' and $day_of_month == '') {
         return FALSE;
     }
     if ($day_of_month_epoch == '' and $day_of_month != '' and $day_of_month <= 31) {
         $tmp_days_in_month = TTDate::getDaysInMonth($anchor_epoch);
         if ($day_of_month > $tmp_days_in_month) {
             $day_of_month = $tmp_days_in_month;
         }
         unset($tmp_days_in_month);
         $day_of_month_epoch = mktime(date('H', $anchor_epoch), date('i', $anchor_epoch), date('s', $anchor_epoch), date('m', $anchor_epoch), $day_of_month, date('Y', $anchor_epoch));
     }
     //If the anchor date is AFTER the day of the month, we want to get the same day
     //in the NEXT month.
     $src_dom = date('j', $anchor_epoch);
     $dst_dom = date('j', $day_of_month_epoch);
     //Debug::text('Anchor DOM: '. $src_dom .' DST DOM: '. $dst_dom, __FILE__, __LINE__, __METHOD__,10);
     if ($src_dom > $dst_dom) {
         //Debug::text('Anchor DOM is greater then Dest DOM', __FILE__, __LINE__, __METHOD__,10);
         //Get the epoch of the first day of the next month
         //Use getMiddleDayEpoch so daylight savings doesn't throw us off.
         $anchor_epoch = TTDate::getMiddleDayEpoch(TTDate::getEndMonthEpoch($anchor_epoch) + 1);
         //Find out how many days are in this month
         $days_in_month = TTDate::getDaysInMonth($anchor_epoch);
         if ($dst_dom > $days_in_month) {
             $dst_dom = $days_in_month;
         }
         $retval = $anchor_epoch + ($dst_dom - 1) * 86400;
     } else {
         //Debug::text('Anchor DOM is equal or LESS then Dest DOM', __FILE__, __LINE__, __METHOD__,10);
         $retval = mktime(date('H', $anchor_epoch), date('i', $anchor_epoch), date('s', $anchor_epoch), date('m', $anchor_epoch), date('j', $day_of_month_epoch), date('Y', $anchor_epoch));
     }
     return TTDate::getBeginDayEpoch($retval);
 }
 function setEffectiveDate($epoch)
 {
     $epoch = trim($epoch);
     //Adjust effective date, because we won't want it to be a
     //day boundary and have issues with pay period start/end dates.
     //Although with employees in timezones that differ from the pay period timezones, there can still be issues.
     $epoch = TTDate::getMiddleDayEpoch($epoch);
     if ($this->Validator->isDate('effective_date', $epoch, TTi18n::gettext('Incorrect effective date'))) {
         $this->data['effective_date'] = $epoch;
         return TRUE;
     }
     return FALSE;
 }
Пример #22
0
    function getOrphansByUserIdAndDate($user_id, $date_stamp, $where = NULL, $order = NULL)
    {
        if ($user_id == '') {
            return FALSE;
        }
        if ($date_stamp == '') {
            return FALSE;
        }
        $apf = new AccrualPolicyFactory();
        $udtf = new UserDateTotalFactory();
        $udf = new UserDateFactory();
        $ph = array('user_id' => $user_id, 'date_stamp1' => $this->db->BindDate(TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($date_stamp) - 86400)), 'date_stamp2' => $this->db->BindDate(TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($date_stamp) + 86400)));
        //Make sure we check if user_date rows are deleted where user_date_total rows are not.
        $query = '
					select 	a.*
					from	' . $this->getTable() . ' as a
					LEFT JOIN ' . $udtf->getTable() . ' as b ON a.user_date_total_id = b.id
					LEFT JOIN ' . $udf->getTable() . ' as c ON b.user_date_id = c.id
					LEFT JOIN ' . $apf->getTable() . ' as d ON a.accrual_policy_id = d.id
					where	a.user_id = ?
						AND ( a.time_stamp >= ? AND a.time_stamp <= ? )
						AND (
								( b.id is NULL OR b.deleted = 1 )
								OR
								( b.deleted = 0 AND ( c.id is NULL OR c.deleted = 1) )
							)
						AND ( a.type_id = 10 OR a.type_id = 20 OR ( a.type_id = 75 AND d.type_id = 30 ) )
						AND a.deleted = 0';
        $query .= $this->getWhereSQL($where);
        $query .= $this->getSortSQL($order);
        $this->ExecuteSQL($query, $ph);
        return $this;
    }
Пример #23
0
 /**
  * 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 calcAccrualPolicyTime($u_obj, $epoch, $offset, $pps_obj, $pay_period_arr, $accrual_balance, $update_records = TRUE)
 {
     $retval = 0;
     Debug::Text('User: '******' Status: ' . $u_obj->getStatus() . ' Epoch: ' . TTDate::getDate('DATE+TIME', $epoch), __FILE__, __LINE__, __METHOD__, 10);
     //Make sure only active employees accrue time *after* their hire date.
     //Will this negative affect Employees who may be on leave?
     if ($u_obj->getStatus() == 10 and $epoch >= $u_obj->getHireDate() and ($this->getMinimumEmployedDays() == 0 or TTDate::getDays($epoch - $u_obj->getHireDate()) >= $this->getMinimumEmployedDays())) {
         Debug::Text('&nbsp;&nbsp;User is active and has been employed long enough.', __FILE__, __LINE__, __METHOD__, 10);
         $annual_pay_periods = $pps_obj->getAnnualPayPeriods();
         $in_apply_frequency_window = FALSE;
         $in_apply_rollover_window = FALSE;
         $pay_period_start_date = NULL;
         $accrual_amount = 0;
         if ($this->getType() == 30) {
             Debug::Text('&nbsp;&nbsp;Accrual policy is hour based, real-time window.', __FILE__, __LINE__, __METHOD__, 10);
             //Hour based, apply frequency is real-time.
             $in_apply_frequency_window = TRUE;
         } else {
             if ($this->getApplyFrequency() == 10) {
                 $pay_period_dates = $this->getPayPeriodDatesFromArray($pay_period_arr, $epoch - $offset);
                 if (is_array($pay_period_dates)) {
                     Debug::Text('&nbsp;&nbsp; Pay Period Start Date: ' . TTDate::getDate('DATE+TIME', $pay_period_dates['start_date']) . ' End Date: ' . TTDate::getDate('DATE+TIME', $pay_period_dates['end_date']), __FILE__, __LINE__, __METHOD__, 10);
                     if ($this->inApplyFrequencyWindow($epoch, $offset, $pay_period_dates['end_date']) == TRUE) {
                         $in_apply_frequency_window = TRUE;
                         $pay_period_start_date = $pay_period_dates['start_date'];
                         //Used for inRolloverFrequencyWindow
                     } else {
                         Debug::Text('&nbsp;&nbsp;User not in Apply Frequency Window: ', __FILE__, __LINE__, __METHOD__, 10);
                     }
                 } else {
                     Debug::Arr($pay_period_dates, '&nbsp;&nbsp; No Pay Period Dates Found.', __FILE__, __LINE__, __METHOD__, 10);
                 }
             } elseif ($this->inApplyFrequencyWindow($epoch, $offset, NULL, $u_obj->getHireDate()) == TRUE) {
                 Debug::Text('&nbsp;&nbsp;User IS in NON-PayPeriod Apply Frequency Window.', __FILE__, __LINE__, __METHOD__, 10);
                 $in_apply_frequency_window = TRUE;
             } else {
                 Debug::Text('&nbsp;&nbsp;User is not in Apply Frequency Window.', __FILE__, __LINE__, __METHOD__, 10);
                 $in_apply_frequency_window = FALSE;
             }
         }
         if ($this->inRolloverFrequencyWindow($epoch, $offset, $u_obj->getHireDate(), $pay_period_start_date)) {
             Debug::Text('&nbsp;&nbsp; In rollover window...', __FILE__, __LINE__, __METHOD__, 10);
             $in_apply_rollover_window = TRUE;
         }
         if ($in_apply_frequency_window == TRUE or $in_apply_rollover_window == TRUE) {
             $milestone_obj = $this->getActiveMilestoneObject($u_obj, $epoch);
         }
         if ($in_apply_rollover_window == TRUE and (isset($milestone_obj) and is_object($milestone_obj))) {
             //Have accrual balance passed in for optimization
             //$accrual_balance = $this->getCurrentAccrualBalance( $u_obj->getID(), $this->getId() );
             //Handle maximum rollover adjustments before continuing.
             if ($accrual_balance > $milestone_obj->getRolloverTime()) {
                 $rollover_accrual_adjustment = bcsub($milestone_obj->getRolloverTime(), $accrual_balance, 0);
                 Debug::Text('&nbsp;&nbsp; Adding rollover adjustment of: ' . $rollover_accrual_adjustment, __FILE__, __LINE__, __METHOD__, 10);
                 //Check to make sure there isn't an identical entry already made.
                 //Ignore rollover adjustment is another adjustment of any amount has been made on the same day.
                 $alf = TTnew('AccrualListFactory');
                 if ($update_records == TRUE) {
                     $alf->getByCompanyIdAndUserIdAndAccrualPolicyIDAndTypeIDAndTimeStamp($u_obj->getCompany(), $u_obj->getID(), $this->getId(), 60, TTDate::getMiddleDayEpoch($epoch));
                 }
                 if ($alf->getRecordCount() == 0) {
                     //Get effective date, try to use the current milestone rollover date to make things more clear.
                     $current_milestone_rollover_date = $this->getCurrentMilestoneRolloverDate($epoch, $u_obj->getHireDate());
                     //If milestone rollover date comes after the current epoch, back date it by one year.
                     if ($current_milestone_rollover_date > $epoch) {
                         $current_milestone_rollover_date = mktime(0, 0, 0, TTDate::getMonth($current_milestone_rollover_date), TTDate::getDayOfMonth($current_milestone_rollover_date), TTDate::getYear($epoch) - 1);
                     }
                     if ($update_records == TRUE) {
                         //Don't round to the nearest minute, as that can cause too much error on weekly frequencies.
                         $af = TTnew('AccrualFactory');
                         $af->setUser($u_obj->getID());
                         $af->setType(60);
                         //Rollover Adjustment
                         $af->setAccrualPolicyID($this->getId());
                         $af->setAmount($rollover_accrual_adjustment);
                         $af->setTimeStamp(TTDate::getMiddleDayEpoch($current_milestone_rollover_date));
                         $af->setEnableCalcBalance(TRUE);
                         if ($af->isValid()) {
                             $af->Save();
                         }
                     } else {
                         Debug::Text('&nbsp;&nbsp; NOT UPDATING RECORDS...', __FILE__, __LINE__, __METHOD__, 10);
                         $retval = $rollover_accrual_adjustment;
                     }
                     //Make sure we get updated balance after rollover adjustment was made.
                     $accrual_balance += $rollover_accrual_adjustment;
                     unset($current_milestone_rollover_date);
                 } else {
                     Debug::Text('&nbsp;&nbsp; Found duplicate rollover accrual entry, skipping...', __FILE__, __LINE__, __METHOD__, 10);
                 }
             } else {
                 Debug::Text('&nbsp;&nbsp; Balance hasnt exceeded rollover adjustment...', __FILE__, __LINE__, __METHOD__, 10);
             }
             unset($rollover_accrual_adjustment, $alf, $af);
         }
         if ($in_apply_frequency_window === TRUE) {
             if (isset($milestone_obj) and is_object($milestone_obj)) {
                 Debug::Text('&nbsp;&nbsp;Found Matching Milestone, Accrual Rate: (ID: ' . $milestone_obj->getId() . ') ' . $milestone_obj->getAccrualRate() . '/year', __FILE__, __LINE__, __METHOD__, 10);
                 //Make sure we get updated balance after rollover adjustment was made.
                 //Have accrual balance passed in for optimization
                 //$accrual_balance = $this->getCurrentAccrualBalance( $u_obj->getID(), $this->getId() );
                 if ($accrual_balance < $milestone_obj->getMaximumTime()) {
                     $accrual_amount = $this->calcAccrualAmount($milestone_obj, 0, $annual_pay_periods);
                     if ($accrual_amount > 0) {
                         $new_accrual_balance = bcadd($accrual_balance, $accrual_amount);
                         //If Maximum time is set to 0, make that unlimited.
                         if ($milestone_obj->getMaximumTime() > 0 and $new_accrual_balance > $milestone_obj->getMaximumTime()) {
                             $accrual_amount = bcsub($milestone_obj->getMaximumTime(), $accrual_balance, 0);
                         }
                         Debug::Text('&nbsp;&nbsp; Min/Max Adjusted Accrual Amount: ' . $accrual_amount . ' Limits: Min: ' . $milestone_obj->getMinimumTime() . ' Max: ' . $milestone_obj->getMaximumTime(), __FILE__, __LINE__, __METHOD__, 10);
                         //Check to make sure there isn't an identical entry already made.
                         $alf = TTnew('AccrualListFactory');
                         if ($update_records == TRUE) {
                             $alf->getByCompanyIdAndUserIdAndAccrualPolicyIDAndTimeStampAndAmount($u_obj->getCompany(), $u_obj->getID(), $this->getId(), TTDate::getMiddleDayEpoch($epoch), $accrual_amount);
                         }
                         if ($alf->getRecordCount() == 0) {
                             if ($update_records == TRUE) {
                                 Debug::Text('&nbsp;&nbsp; UPDATING RECORDS...', __FILE__, __LINE__, __METHOD__, 10);
                                 //Round to nearest 1min
                                 $af = TTnew('AccrualFactory');
                                 $af->setUser($u_obj->getID());
                                 $af->setType(75);
                                 //Accrual Policy
                                 $af->setAccrualPolicyID($this->getId());
                                 $af->setAmount($accrual_amount);
                                 $af->setTimeStamp(TTDate::getMiddleDayEpoch($epoch));
                                 $af->setEnableCalcBalance(TRUE);
                                 if ($af->isValid()) {
                                     $af->Save();
                                 }
                             } else {
                                 Debug::Text('&nbsp;&nbsp; NOT UPDATING RECORDS...', __FILE__, __LINE__, __METHOD__, 10);
                                 $retval += $accrual_amount;
                             }
                         } else {
                             Debug::Text('&nbsp;&nbsp; Found duplicate accrual entry, skipping...', __FILE__, __LINE__, __METHOD__, 10);
                         }
                         unset($accrual_amount, $accrual_balance, $new_accrual_balance);
                     } else {
                         Debug::Text('&nbsp;&nbsp; Accrual Amount is 0...', __FILE__, __LINE__, __METHOD__, 10);
                     }
                 } else {
                     Debug::Text('&nbsp;&nbsp; Accrual Balance is outside Milestone Range. Skipping...', __FILE__, __LINE__, __METHOD__, 10);
                 }
             } else {
                 Debug::Text('&nbsp;&nbsp;DID NOT Find Matching Milestone.', __FILE__, __LINE__, __METHOD__, 10);
             }
             unset($milestone_obj);
         }
     } else {
         Debug::Text('&nbsp;&nbsp;User is not active (Status: ' . $u_obj->getStatus() . ') or has only been employed: ' . TTDate::getDays($epoch - $u_obj->getHireDate()) . ' Days, not enough. Hire Date: ' . TTDate::getDATE('DATE+TIME', $u_obj->getHireDate()), __FILE__, __LINE__, __METHOD__, 10);
     }
     if ($update_records == TRUE) {
         return TRUE;
     } else {
         Debug::Text('Retval: ' . $retval, __FILE__, __LINE__, __METHOD__, 10);
         return $retval;
     }
 }
Пример #25
0
         $ugsf = TTnew('UserGenericStatusFactory');
         $ugsf->setUser($current_user->getId());
         $ugsf->setBatchID($ugsf->getNextBatchId());
         $ugsf->setQueue(UserGenericStatusFactory::getStaticQueue());
         $ugsf->saveQueue();
         $progress_bar->setValue(100);
         $progress_bar->display();
         $next_page = URLBuilder::getURL(array('batch_id' => $ugsf->getBatchID(), 'batch_title' => 'Mass Schedule', 'batch_next_page' => urlencode(URLBuilder::getURL(array('data' => $data, 'filter_user_id' => $filter_user_id), '../schedule/AddMassSchedule.php'))), '../users/UserGenericStatusList.php');
     }
     break;
 case 'recalculate_accrual_policy':
     //Debug::setVerbosity(11);
     if (isset($data['accrual_policy_id']) and isset($data['start_date']) and isset($data['end_date'])) {
         if ($data['start_date'] <= $data['end_date']) {
             $start_date = TTDate::getMiddleDayEpoch($data['start_date']);
             $end_date = TTDate::getMiddleDayEpoch($data['end_date']);
             $total_days = TTDate::getDays($end_date - $start_date);
             $offset = 86400 / 2;
             $init_progress_bar = TRUE;
             if ($init_progress_bar == TRUE) {
                 InitProgressBar();
                 $init_progress_bar = FALSE;
             }
             $progress_bar->setValue(0);
             $progress_bar->display();
             $apf = TTnew('AccrualPolicyFactory');
             $aplf = TTnew('AccrualPolicyListFactory');
             $aplf->getByIdAndCompanyId((int) $data['accrual_policy_id'], $current_company->getId());
             if ($aplf->getRecordCount() > 0) {
                 foreach ($aplf as $ap_obj) {
                     $aplf->StartTransaction();
 function getScheduleObjectByUserIdAndEpoch($user_id, $epoch)
 {
     if ($user_id == '') {
         return FALSE;
     }
     if ($epoch == '') {
         return FALSE;
     }
     //Need to handle schedules on next/previous dates from when the punch is.
     //ie: if the schedule started on 11:30PM on Jul 5th and the punch is 01:00AM on Jul 6th.
     $slf = new ScheduleListFactory();
     $slf->getByUserIdAndStartDateAndEndDate($user_id, TTDate::getMiddleDayEpoch($epoch) - 86400, TTDate::getMiddleDayEpoch($epoch) + 86400);
     if ($slf->getRecordCount() > 0) {
         Debug::Text(' Found User Date ID! User: '******' Epoch: ' . TTDate::getDATE('DATE+TIME', $epoch) . '(' . $epoch . ')', __FILE__, __LINE__, __METHOD__, 10);
         $retval = FALSE;
         $best_diff = FALSE;
         //Check for schedule policy
         foreach ($slf as $s_obj) {
             Debug::Text(' Found Schedule!: ID: ' . $s_obj->getID(), __FILE__, __LINE__, __METHOD__, 10);
             //If the Start/Stop window is large (ie: 6-8hrs) we need to find the closest schedule.
             $schedule_diff = $s_obj->inScheduleDifference($epoch);
             if ($schedule_diff === 0) {
                 Debug::text(' Within schedule times. ', __FILE__, __LINE__, __METHOD__, 10);
                 return $s_obj;
             } else {
                 if ($schedule_diff > 0 and ($best_diff === FALSE or $schedule_diff < $best_diff)) {
                     Debug::text(' Within schedule start/stop time by: ' . $schedule_diff . ' Prev Best Diff: ' . $best_diff, __FILE__, __LINE__, __METHOD__, 10);
                     $best_diff = $schedule_diff;
                     $retval = $s_obj;
                 }
             }
         }
         if (isset($retval) and is_object($retval)) {
             return $retval;
         }
     }
     /*
     $udlf = new UserDateListFactory();
     //$udlf->getByUserIdAndDate( $user_id, $epoch );
     $udlf->getByUserIdAndStartDateAndEndDate($user_id, TTDate::getMiddleDayEpoch($epoch)-(86400), TTDate::getMiddleDayEpoch($epoch)+86400 );
     if ( $udlf->getRecordCount() > 0 ) {
     	Debug::Text(' Found User Date ID! User: '******' Epoch: '. TTDate::getDATE('DATE+TIME', $epoch ) .'('.$epoch.')' , __FILE__, __LINE__, __METHOD__,10);
     
     	//Loop through all user_Date
     	$user_date_ids = array();
     	foreach( $udlf as $ud_obj ) {
     		$user_date_ids[] = $ud_obj->getID();
     	}
     	
     	$slf = new ScheduleListFactory();
     	$slf->getByUserDateId( $user_date_ids );
     	if ( $slf->getRecordCount() > 0 ) {
     		$retval = FALSE;
     		$best_diff = FALSE;
     		//Check for schedule policy
     		foreach( $slf as $s_obj ) {
     			Debug::Text(' Found Schedule!: ID: '. $s_obj->getID(), __FILE__, __LINE__, __METHOD__,10);
     			//If the Start/Stop window is large (ie: 6-8hrs) we need to find the closest schedule.
     			$schedule_diff = $s_obj->inScheduleDifference( $epoch );
     			if ( $schedule_diff === 0 ) {
     				Debug::text(' Within schedule times. ', __FILE__, __LINE__, __METHOD__,10);
     				return $s_obj;
     			} else {
     				if ( $schedule_diff > 0 AND ( $best_diff === FALSE OR $schedule_diff < $best_diff ) ) {
     					Debug::text(' Within schedule start/stop time by: '. $schedule_diff .' Prev Best Diff: '. $best_diff, __FILE__, __LINE__, __METHOD__,10);
     					$best_diff = $schedule_diff;
     					$retval = $s_obj;
     				}
     			}
     		}
     
     		if ( isset($retval) AND is_object($retval) ) {
     			return $retval;
     		}
     	}
     }
     */
     return FALSE;
 }