function postInstall()
 {
     Debug::text('postInstall: ' . $this->getVersion(), __FILE__, __LINE__, __METHOD__, 9);
     //New Pay Period Schedule format, update any current schedules.
     $ppslf = new PayPeriodScheduleListFactory();
     $ppslf->getAll();
     Debug::text('Found Pay Period Schedules: ' . $ppslf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 9);
     if ($ppslf->getRecordCount() > 0) {
         foreach ($ppslf as $pps_obj) {
             if ($pps_obj->getType() == 10 or $pps_obj->getType() == 20) {
                 $pps_obj->setStartDayOfWeek(TTDate::getDayOfWeek(TTDate::strtotime($pps_obj->getColumn('anchor_date'))));
                 $pps_obj->setTransactionDate(floor((TTDate::strtotime($pps_obj->getColumn('primary_transaction_date')) - TTDate::strtotime($pps_obj->getColumn('primary_date'))) / 86400) + 1);
             } elseif ($pps_obj->getType() == 30) {
                 $pps_obj->setPrimaryDayOfMonth(TTDate::getDayOfMonth(TTDate::strtotime($pps_obj->getColumn('anchor_date'))) + 1);
                 if ($pps_obj->getColumn('primary_transaction_date_ldom') == 1) {
                     $pps_obj->setPrimaryTransactionDayOfMonth(-1);
                 } else {
                     $pps_obj->setPrimaryTransactionDayOfMonth(TTDate::getDayOfMonth(TTDate::strtotime($pps_obj->getColumn('primary_transaction_date'))));
                 }
                 $pps_obj->setSecondaryDayOfMonth(TTDate::getDayOfMonth(TTDate::strtotime($pps_obj->getColumn('primary_date'))));
                 if ($pps_obj->getColumn('secondary_transaction_date_ldom') == 1) {
                     $pps_obj->setSecondaryTransactionDayOfMonth(-1);
                 } else {
                     $pps_obj->setSecondaryTransactionDayOfMonth(TTDate::getDayOfMonth(TTDate::strtotime($pps_obj->getColumn('secondary_transaction_date'))));
                 }
             } elseif ($pps_obj->getType() == 50) {
                 $pps_obj->setPrimaryDayOfMonth(TTDate::getDayOfMonth(TTDate::strtotime($pps_obj->getColumn('anchor_date'))));
                 if ($pps_obj->getColumn('primary_transaction_date_ldom') == 1) {
                     $pps_obj->setPrimaryTransactionDayOfMonth(-1);
                 } else {
                     $pps_obj->setPrimaryTransactionDayOfMonth(TTDate::getDayOfMonth(TTDate::strtotime($pps_obj->getColumn('primary_transaction_date'))));
                 }
             }
             if ($pps_obj->getColumn('transaction_date_bd') == 1 or $pps_obj->getColumn('secondary_transaction_date_bd') == 1) {
                 $pps_obj->setTransactionDateBusinessDay(TRUE);
             }
             if ($pps_obj->isValid()) {
                 $pps_obj->Save();
             }
         }
     }
     return TRUE;
 }
     //Always try to keep one hour before the actual min time,
     //otherwise the schedule looks cluttered.
     if ($min_hour > 0) {
         $min_hour--;
     }
     //Debug::text(' aSetting Min Hour: '. $min_hour, __FILE__, __LINE__, __METHOD__,10);
 }
 if ($i == 0 or $tmp_end_hour > $max_hour) {
     $max_hour = $tmp_end_hour;
     Debug::text(' aSetting Max Hour: ' . $max_hour, __FILE__, __LINE__, __METHOD__, 10);
     if ($max_hour < 22) {
         $max_hour = $max_hour + 2;
     }
     Debug::text(' bSetting Max Hour: ' . $max_hour, __FILE__, __LINE__, __METHOD__, 10);
 }
 if (TTDate::getDayOfMonth($day_schedule_shift['start_time']) != TTDate::getDayOfMonth($day_schedule_shift['end_time'] - 1)) {
     //-1 from end time to handle a 12:00AM end time without going to next day.
     Debug::text(' aSchedule Spans the Day boundary!', __FILE__, __LINE__, __METHOD__, 10);
     $day_schedule_shift['span_day'] = TRUE;
     $min_hour = 0;
     $max_hour = 24;
 }
 if ($day_schedule_shift['span_day'] == TRUE) {
     //Cut shift into two days.
     $tmp_schedule_shift_day1 = $tmp_schedule_shift_day2 = $day_schedule_shift;
     $tmp_schedule_shift_day1['span_day_split'] = TRUE;
     $tmp_schedule_shift_day1['end_time'] = TTDate::getEndDayEpoch($day_schedule_shift['start_time']) + 1;
     $tmp_schedule_shift_day2['start_time'] = TTDate::getBeginDayEpoch($day_schedule_shift['end_time']);
     $tmp_schedule_shift_day2['span_day_split'] = FALSE;
     $tmp_schedule_shifts[$day_epoch][$day_schedule_shift['branch']][$day_schedule_shift['department']][$day_schedule_shift['user_id']][] = $tmp_schedule_shift_day1;
     $tmp_schedule_shifts[$tmp_schedule_shift_day2['start_time']][$day_schedule_shift['branch']][$day_schedule_shift['department']][$day_schedule_shift['user_id']][] = $tmp_schedule_shift_day2;
Beispiel #3
0
     }
     if (isset($lines_arr['3']['10'])) {
         $f941->l17_month3 = $lines_arr['3']['10'];
     }
 } elseif (isset($setup_data['deposit_schedule']) and $setup_data['deposit_schedule'] == 20) {
     $f941sb = $gf->getFormObject('941sb', 'US');
     $f941sb->setShowBackground($show_background);
     $f941sb->year = $filter_data['year'];
     $f941sb->ein = $current_company->getBusinessNumber();
     $f941sb->name = $setup_data['name'];
     $f941sb->quarter = $filter_data['quarter_id'];
     for ($i = 1; $i <= 3; $i++) {
         for ($d = 1; $d <= 31; $d++) {
             if (isset($pp_lines_arr[$i])) {
                 foreach ($pp_lines_arr[$i] as $pay_period_id => $data) {
                     $dom = TTDate::getDayOfMonth($pay_period_transaction_dates[$pay_period_id]);
                     if ($d == $dom) {
                         $f941sb_data[$i][$d] = Misc::MoneyFormat($data['10'], FALSE);
                     }
                 }
             }
         }
     }
     if (isset($f941sb_data[1])) {
         $f941sb->month1 = $f941sb_data[1];
     }
     if (isset($f941sb_data[2])) {
         $f941sb->month2 = $f941sb_data[2];
     }
     if (isset($f941sb_data[3])) {
         $f941sb->month3 = $f941sb_data[3];
 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;
 }
 function inApplyFrequencyWindow($pay_period_start_date, $pay_period_end_date, $hire_date = NULL, $termination_date = NULL, $birth_date = NULL)
 {
     if ($this->getApplyFrequency() == FALSE or $this->getApplyFrequency() == 10) {
         //Each pay period
         return TRUE;
     }
     $frequency_criteria = array('month' => $this->getApplyFrequencyMonth(), 'day_of_month' => $this->getApplyFrequencyDayOfMonth(), 'quarter_month' => $this->getApplyFrequencyQuarterMonth());
     $specific_date = FALSE;
     $frequency_id = $this->getApplyFrequency();
     switch ($this->getApplyFrequency()) {
         case 100:
             //Hire Date
             $frequency_criteria['date'] = $hire_date;
             $frequency_id = 100;
             //Specific date
             break;
         case 110:
             //Hire Date anniversary.
             $frequency_criteria['month'] = TTDate::getMonth($hire_date);
             $frequency_criteria['day_of_month'] = TTDate::getDayOfMonth($hire_date);
             $frequency_id = 20;
             //Annually
             break;
         case 120:
             $frequency_criteria['date'] = $termination_date;
             $frequency_id = 100;
             //Specific date
             break;
         case 130:
             //Birth Date anniversary.
             $frequency_criteria['month'] = TTDate::getMonth($birth_date);
             $frequency_criteria['day_of_month'] = TTDate::getDayOfMonth($birth_date);
             $frequency_id = 20;
             //Annually
             break;
     }
     $retval = TTDate::inApplyFrequencyWindow($frequency_id, $pay_period_start_date, $pay_period_end_date, $frequency_criteria);
     Debug::Arr($frequency_criteria, 'Frequency: ' . $this->getApplyFrequency() . ' Retval: ' . (int) $retval, __FILE__, __LINE__, __METHOD__, 10);
     return $retval;
 }
 function preSave()
 {
     if ($this->getFrequency() == 40) {
         if (TTDate::getDayOfMonth($this->getStartDate()) > 28) {
             Debug::text(' Start Date is After the 28th, making the 28th: ', __FILE__, __LINE__, __METHOD__, 10);
             $this->setStartDate(TTDate::getDateOfNextDayOfMonth($this->getStartDate(), strtotime('28-Feb-05')));
         }
     }
     if ($this->getType() == 10) {
         //If amount isn't set, but Rate and units are, calc amount for them.
         if (($this->getAmount() == NULL or $this->getAmount() == 0 or $this->getAmount() == '') and $this->getRate() !== NULL and $this->getUnits() !== NULL and $this->getRate() != 0 and $this->getUnits() != 0 and $this->getRate() != '' and $this->getUnits() != '') {
             $this->setAmount(bcmul($this->getRate(), $this->getUnits(), 4));
         }
     }
     if ($this->isNew() == TRUE) {
         $this->first_insert = TRUE;
     }
     return TRUE;
 }
 function detectPayPeriodScheduleSettings($type_id, $example_dates)
 {
     Debug::Arr($example_dates, 'Pay Period Type: ' . $type_id . ' Example Dates: ', __FILE__, __LINE__, __METHOD__, 10);
     if ($type_id == '') {
         $type_id = $this->getType();
     }
     if (!is_array($example_dates)) {
         $example_dates = array();
     }
     if (!isset($example_dates[0]['start_date']) or isset($example_dates[0]['start_date']) and $example_dates[0]['start_date'] == '') {
         Debug::Text('Example dates not specified properly, skipping...', __FILE__, __LINE__, __METHOD__, 10);
         return FALSE;
     }
     $this->setType($type_id);
     if (isset($example_dates[0]['start_date'])) {
         $this->setAnchorDate(TTDate::parseDateTime($example_dates[0]['start_date']) - 86400);
         //Anchor date one day before first start date.
     }
     $annual_pay_periods = $this->calcAnnualPayPeriods($type_id);
     switch ($type_id) {
         case 5:
             //Manual
             break;
         case 10:
             //Weekly
         //Weekly
         case 20:
             //BiWeekly
             //Need at least one example.
             foreach ($example_dates as $example_date) {
                 $start_dow[] = TTDate::getDayOfWeek(TTDate::parseDateTime($example_date['start_date']));
                 $transaction_days[] = (int) round(TTDate::getDays(TTDate::parseDateTime($example_date['transaction_date']) - TTDate::parseDateTime($example_date['end_date'])));
             }
             Debug::Arr($start_dow, 'Start DOW: ', __FILE__, __LINE__, __METHOD__, 10);
             Debug::Arr($transaction_days, 'Transaction Days: ', __FILE__, __LINE__, __METHOD__, 10);
             //Get the most common values from arrays.
             $start_day_of_week = Misc::arrayCommonValue($start_dow);
             Debug::Arr($start_dow, 'Start Day Of Week: ' . $start_day_of_week . ' Start DOW Count: ', __FILE__, __LINE__, __METHOD__, 10);
             $transaction_date = Misc::arrayCommonValue($transaction_days);
             Debug::Arr($transaction_days, 'Transaction Date: ' . $transaction_date . ' Transaction Days Count: ', __FILE__, __LINE__, __METHOD__, 10);
             $this->setStartDayOfWeek($start_day_of_week);
             $this->setTransactionDate($transaction_date);
             break;
         case 30:
             //Semi-monthly
             //Need at least three examples?
             $i = 0;
             foreach ($example_dates as $example_date) {
                 if ($i % 2 == 0) {
                     $primary_start_dom[] = TTDate::getDayOfMonth(TTDate::parseDateTime($example_date['start_date']));
                     $primary_transaction_dom[] = TTDate::getDayOfMonth(TTDate::parseDateTime($example_date['transaction_date']));
                 } else {
                     $secondary_start_dom[] = TTDate::getDayOfMonth(TTDate::parseDateTime($example_date['start_date']));
                     $secondary_transaction_dom[] = TTDate::getDayOfMonth(TTDate::parseDateTime($example_date['transaction_date']));
                 }
                 $i++;
             }
             Debug::Arr($primary_start_dom, 'Primary Start DOM: ', __FILE__, __LINE__, __METHOD__, 10);
             Debug::Arr($primary_transaction_dom, 'Primary Transaction DOM: ', __FILE__, __LINE__, __METHOD__, 10);
             Debug::Arr($secondary_start_dom, 'Secondary Start DOM: ', __FILE__, __LINE__, __METHOD__, 10);
             Debug::Arr($secondary_transaction_dom, 'Secondary Transaction DOM: ', __FILE__, __LINE__, __METHOD__, 10);
             $primary_dom = Misc::arrayCommonValue($primary_start_dom);
             $primary_transaction_dom = Misc::arrayCommonValue($primary_transaction_dom);
             $secondary_dom = Misc::arrayCommonValue($secondary_start_dom);
             $secondary_transaction_dom = Misc::arrayCommonValue($secondary_transaction_dom);
             Debug::Text('Primary: ' . $primary_dom . ' Trans: ' . $primary_transaction_dom . ' Secondary: ' . $secondary_dom . ' Trans: ' . $secondary_transaction_dom, __FILE__, __LINE__, __METHOD__, 10);
             $this->setPrimaryDayOfMonth($primary_dom);
             $this->setSecondaryDayOfMonth($secondary_dom);
             $this->setPrimaryTransactionDayOfMonth($primary_transaction_dom);
             $this->setSecondaryTransactionDayOfMonth($secondary_transaction_dom);
             break;
         case 50:
             //Monthly
             //Need at least one example.
             foreach ($example_dates as $example_date) {
                 $primary_start_dom[] = TTDate::getDayOfMonth(TTDate::parseDateTime($example_date['start_date']));
                 $primary_transaction_dom[] = TTDate::getDayOfMonth(TTDate::parseDateTime($example_date['transaction_date']));
             }
             Debug::Arr($primary_start_dom, 'Primary Start DOM: ', __FILE__, __LINE__, __METHOD__, 10);
             Debug::Arr($primary_transaction_dom, 'Primary Transaction DOM: ', __FILE__, __LINE__, __METHOD__, 10);
             $primary_dom = Misc::arrayCommonValue($primary_start_dom);
             $primary_transaction_dom = Misc::arrayCommonValue($primary_transaction_dom);
             $this->setPrimaryDayOfMonth($primary_dom);
             $this->setPrimaryTransactionDayOfMonth($primary_transaction_dom);
             break;
         default:
             return FALSE;
             break;
     }
     Debug::Arr($this->data, 'PP Schedule Data: ', __FILE__, __LINE__, __METHOD__, 10);
     return TRUE;
 }
 function _outputPayrollExport($format = NULL)
 {
     $setup_data = $this->getFormConfig();
     Debug::Text('Generating Payroll Export... Format: ' . $format, __FILE__, __LINE__, __METHOD__, 10);
     if (isset($setup_data['export_type'])) {
         Debug::Text('Export Type: ' . $setup_data['export_type'], __FILE__, __LINE__, __METHOD__, 10);
     } else {
         Debug::Text('No Export Type defined!', __FILE__, __LINE__, __METHOD__, 10);
         return FALSE;
     }
     Debug::Arr($setup_data, 'Setup Data: ', __FILE__, __LINE__, __METHOD__, 10);
     $rows = $this->data;
     //Debug::Arr($rows, 'PreData: ', __FILE__, __LINE__, __METHOD__,10);
     $file_name = strtolower(trim($setup_data['export_type'])) . '_' . date('Y_m_d') . '.txt';
     $mime_type = 'application/text';
     $data = NULL;
     switch (strtolower(trim($setup_data['export_type']))) {
         case 'adp':
             //ADP export format.
             //File format supports multiple rows per employee (file #) all using the same columns. No need to jump through nasty hoops to fit everything on row.
             $export_column_map = array('company_code' => 'Co Code', 'batch_id' => 'Batch ID', 'temp_dept' => 'Temp Dept', 'employee_number' => 'File #', 'regular_time' => 'Reg Hours', 'overtime' => 'O/T Hours', '3_code' => 'Hours 3 Code', '3_amount' => 'Hours 3 Amount', '4_code' => 'Hours 4 Code', '4_amount' => 'Hours 4 Amount');
             ksort($setup_data['adp']['columns']);
             $setup_data['adp']['columns'] = Misc::trimSortPrefix($setup_data['adp']['columns']);
             foreach ($setup_data['adp']['columns'] as $column_id => $column_data) {
                 $column_name = NULL;
                 if ($column_data['hour_column'] == 'regular_time') {
                     $export_data_map[$column_id] = 'regular_time';
                 } elseif ($column_data['hour_column'] == 'overtime') {
                     $export_data_map[$column_id] = 'overtime';
                 } elseif ($column_data['hour_column'] >= 3) {
                     $export_data_map[$column_id] = $column_data;
                 }
             }
             if (!isset($setup_data['adp']['company_code_value'])) {
                 $setup_data['adp']['company_code_value'] = NULL;
             }
             if (!isset($setup_data['adp']['batch_id_value'])) {
                 $setup_data['adp']['batch_id_value'] = NULL;
             }
             if (!isset($setup_data['adp']['temp_dept_value'])) {
                 $setup_data['adp']['temp_dept_value'] = NULL;
             }
             $company_code_column = Misc::trimSortPrefix($setup_data['adp']['company_code']);
             $batch_id_column = Misc::trimSortPrefix($setup_data['adp']['batch_id']);
             $temp_dept_column = Misc::trimSortPrefix($setup_data['adp']['temp_dept']);
             foreach ($rows as $row) {
                 $static_columns = array('company_code' => isset($row[$company_code_column]) ? $row[$company_code_column] : $setup_data['adp']['company_code_value'], 'batch_id' => isset($row[$batch_id_column]) ? $row[$batch_id_column] : $setup_data['adp']['batch_id_value'], 'temp_dept' => isset($row[$temp_dept_column]) ? $row[$temp_dept_column] : $setup_data['adp']['temp_dept_value'], 'employee_number' => str_pad($row['employee_number'], 6, 0, STR_PAD_LEFT));
                 foreach ($setup_data['adp']['columns'] as $column_id => $column_data) {
                     $column_data = Misc::trimSortPrefix($column_data, TRUE);
                     Debug::Text('ADP Column ID: ' . $column_id . ' Hour Column: ' . $column_data['hour_column'] . ' Code: ' . $column_data['hour_code'], __FILE__, __LINE__, __METHOD__, 10);
                     if (isset($row[$column_id]) and $column_data['hour_column'] != '0') {
                         foreach ($export_column_map as $export_column_id => $export_column_name) {
                             Debug::Arr($row, 'Row: Column ID: ' . $column_id . ' Export Column ID: ' . $export_column_id . ' Name: ' . $export_column_name, __FILE__, __LINE__, __METHOD__, 10);
                             if (($column_data['hour_column'] == $export_column_id or $column_data['hour_column'] . '_code' == $export_column_id) and !in_array($export_column_id, array('company_code', 'batch_id', 'temp_dept', 'employee_number'))) {
                                 if ((int) substr($export_column_id, 0, 1) > 0) {
                                     $tmp_row[$column_data['hour_column'] . '_code'] = $column_data['hour_code'];
                                     $tmp_row[$column_data['hour_column'] . '_amount'] = TTDate::getTimeUnit($row[$column_id], 20);
                                 } else {
                                     $tmp_row[$export_column_id] = TTDate::getTimeUnit($row[$column_id], 20);
                                 }
                                 //Break out every column onto its own row, that way its easier to handle multiple columns of the same type.
                                 $tmp_rows[] = array_merge($static_columns, $tmp_row);
                                 unset($tmp_row);
                             }
                         }
                     }
                 }
             }
             $file_name = 'EPI000000.csv';
             if (isset($tmp_rows)) {
                 //File format supports multiple entries per employee (file #) all using the same columns. No need to jump through nasty hoops to fit everyone one row.
                 $file_name = 'EPI' . $tmp_rows[0]['company_code'] . $tmp_rows[0]['batch_id'] . '.csv';
                 $data = Misc::Array2CSV($tmp_rows, $export_column_map, FALSE);
             }
             unset($tmp_rows, $export_column_map, $column_id, $column_data, $rows, $row);
             break;
         case 'adp_old':
             //ADP export format.
             $file_name = 'EPI' . $setup_data['adp']['company_code'] . $setup_data['adp']['batch_id'] . '.csv';
             $export_column_map = array();
             $static_export_column_map = array('company_code' => 'Co Code', 'batch_id' => 'Batch ID', 'employee_number' => 'File #');
             $static_export_data_map = array('company_code' => $setup_data['adp']['company_code'], 'batch_id' => $setup_data['adp']['batch_id']);
             //
             //Format allows for multiple duplicate columns.
             //ie: Hours 3 Code, Hours 3 Amount, Hours 3 Code, Hours 3 Amount, ...
             //However, we can only have a SINGLE O/T Hours column.
             //We also need to combine hours with the same code together.
             //
             ksort($setup_data['adp']['columns']);
             $setup_data['adp']['columns'] = Misc::trimSortPrefix($setup_data['adp']['columns']);
             foreach ($setup_data['adp']['columns'] as $column_id => $column_data) {
                 $column_name = NULL;
                 if ($column_data['hour_column'] == 'regular_time') {
                     $column_name = 'Reg Hours';
                     $export_data_map[$column_id] = trim($setup_data['adp']['columns'][$column_id]['hour_code']);
                 } elseif ($column_data['hour_column'] == 'overtime') {
                     $column_name = 'O/T Hours';
                     $export_data_map[$column_id] = trim($setup_data['adp']['columns'][$column_id]['hour_code']);
                 } elseif ($column_data['hour_column'] >= 3) {
                     $column_name = 'Hours ' . $column_data['hour_column'] . ' Amount';
                     $export_column_map[$setup_data['adp']['columns'][$column_id]['hour_code'] . '_code'] = 'Hours ' . $column_data['hour_column'] . ' Code';
                     $export_data_map[$column_id] = trim($setup_data['adp']['columns'][$column_id]['hour_code']);
                 }
                 if ($column_name != '') {
                     $export_column_map[trim($setup_data['adp']['columns'][$column_id]['hour_code'])] = $column_name;
                 }
             }
             $export_column_map = Misc::prependArray($static_export_column_map, $export_column_map);
             //
             //Combine time from all columns with the same hours code.
             //
             $i = 0;
             foreach ($rows as $row) {
                 foreach ($static_export_column_map as $column_id => $column_name) {
                     if (isset($static_export_data_map[$column_id])) {
                         //Copy over static config values like company code/batch_id.
                         $tmp_rows[$i][$column_id] = $static_export_data_map[$column_id];
                     } elseif (isset($row[$column_id])) {
                         if (isset($static_export_column_map[$column_id])) {
                             //Copy over employee_number. (File #)
                             $tmp_rows[$i][$column_id] = $row[$column_id];
                         }
                     }
                 }
                 foreach ($export_data_map as $column_id => $column_name) {
                     if (!isset($tmp_rows[$i][$column_name])) {
                         $tmp_rows[$i][$column_name] = 0;
                     }
                     if (isset($row[$column_id])) {
                         $tmp_rows[$i][$column_name] += $row[$column_id];
                     }
                     $tmp_rows[$i][$column_name . '_code'] = $column_name;
                 }
                 $i++;
             }
             //Convert time from seconds to hours.
             $convert_unit_columns = array_keys($static_export_column_map);
             foreach ($tmp_rows as $row => $data) {
                 foreach ($data as $column_id => $column_data) {
                     //var_dump($column_id,$column_data);
                     if (is_int($column_data) and !in_array($column_id, $convert_unit_columns)) {
                         $tmp_rows[$row][$column_id] = TTDate::getTimeUnit($column_data, 20);
                     }
                 }
             }
             unset($row, $data, $column_id, $column_data);
             $data = Misc::Array2CSV($tmp_rows, $export_column_map, FALSE);
             break;
         case 'paychex_preview_advanced_job':
             //PayChex Preview with job information
             unset($rows);
             //Ignore any existing timesheet summary data, we will be using our own job data below.
             //Debug::Arr($setup_data, 'PayChex Advanced Job Setup Data: ', __FILE__, __LINE__, __METHOD__,10);
             $config['columns'][] = 'employee_number';
             $config['columns'][] = 'date_stamp';
             $config['columns'] = array_merge($config['columns'], (array) $setup_data['paychex_preview_advanced_job']['job_columns']);
             $config['columns'][] = $setup_data['paychex_preview_advanced_job']['state_columns'];
             $config['columns'] += array_keys(Misc::trimSortPrefix($this->getOptions('dynamic_columns')));
             $config['group'][] = 'employee_number';
             $config['group'][] = 'date_stamp';
             $config['group'] = array_merge($config['columns'], (array) $setup_data['paychex_preview_advanced_job']['job_columns']);
             $config['group'][] = $setup_data['paychex_preview_advanced_job']['state_columns'];
             $config['sort'][] = array('employee_number' => 'asc');
             $config['sort'][] = array('date_stamp' => 'asc');
             //Debug::Arr($config, 'Job Detail Report Config: ', __FILE__, __LINE__, __METHOD__,10);
             //Get job data...
             $jar = TTNew('JobDetailReport');
             $jar->setAMFMessageID($this->getAMFMessageID());
             $jar->setUserObject($this->getUserObject());
             $jar->setPermissionObject($this->getPermissionObject());
             $jar->setConfig($config);
             $jar->setFilterConfig($this->getFilterConfig());
             $jar->setSortConfig($config['sort']);
             $jar->_getData();
             $jar->_preProcess();
             $jar->sort();
             $rows = $jar->data;
             //Debug::Arr($rows, 'Raw Rows: ', __FILE__, __LINE__, __METHOD__,10);
             //Need to get job data from job report instead of TimeSheet Summary report.
             if (!isset($setup_data['paychex_preview_advanced_job']['client_number'])) {
                 $setup_data['paychex_preview_advanced_job']['client_number'] = '0000';
             }
             $file_name = $setup_data['paychex_preview_advanced_job']['client_number'] . '_TA.txt';
             ksort($setup_data['paychex_preview_advanced_job']['columns']);
             $setup_data['paychex_preview_advanced_job']['columns'] = Misc::trimSortPrefix($setup_data['paychex_preview_advanced_job']['columns']);
             $data = NULL;
             foreach ($rows as $row) {
                 foreach ($setup_data['paychex_preview_advanced_job']['columns'] as $column_id => $column_data) {
                     if (isset($row[$column_id]) and trim($column_data['hour_code']) != '') {
                         $data .= str_pad($row['employee_number'], 6, ' ', STR_PAD_LEFT);
                         $data .= str_pad('', 31, ' ', STR_PAD_LEFT);
                         //Blank space.
                         if (isset($setup_data['paychex_preview_advanced_job']['job_columns']) and is_array($setup_data['paychex_preview_advanced_job']['job_columns'])) {
                             $job_column = array();
                             foreach ($setup_data['paychex_preview_advanced_job']['job_columns'] as $tmp_job_column) {
                                 $job_column[] = isset($row[$tmp_job_column]) ? $row[$tmp_job_column] : NULL;
                             }
                             $data .= str_pad(substr(implode('-', $job_column), 0, 12), 12, ' ', STR_PAD_LEFT);
                             unset($job_column);
                         } else {
                             $data .= str_pad('', 12, ' ', STR_PAD_LEFT);
                         }
                         $data .= str_pad('', 1, ' ', STR_PAD_LEFT);
                         //Shift identifier.
                         //Allow user to specify three digit hour codes to specify their own E/D codes. If codes are two digit, always use E.
                         if (strlen(trim($column_data['hour_code'])) < 3) {
                             $column_data['hour_code'] = 'E' . trim($column_data['hour_code']);
                         }
                         //Should start at col51
                         $data .= str_pad(substr(trim($column_data['hour_code']), 0, 3), 3, ' ', STR_PAD_RIGHT);
                         if (isset($setup_data['paychex_preview_advanced_job']['include_hourly_rate']) and $setup_data['paychex_preview_advanced_job']['include_hourly_rate'] == TRUE) {
                             $data .= str_pad(isset($row[$column_id . '_hourly_rate']) ? number_format($row[$column_id . '_hourly_rate'], 4, '.', '') : NULL, 9, 0, STR_PAD_LEFT);
                             //Override rate
                         } else {
                             $data .= str_pad('', 9, 0, STR_PAD_LEFT);
                             //Override rate
                         }
                         $data .= str_pad(TTDate::getTimeUnit($row[$column_id], 20), 8, 0, STR_PAD_LEFT);
                         //Break out time by day.
                         $data .= str_pad(TTDate::getYear($row['time_stamp']), 4, 0, STR_PAD_LEFT);
                         //Year, based on time_stamp epoch column
                         $data .= str_pad(TTDate::getMonth($row['time_stamp']), 2, 0, STR_PAD_LEFT);
                         //Month, based on time_stamp epoch column. Can be space padded.
                         $data .= str_pad(TTDate::getDayOfMonth($row['time_stamp']), 2, 0, STR_PAD_LEFT);
                         //Day, based on time_stamp epoch column. Can be space padded.
                         $data .= str_pad('', 4, ' ', STR_PAD_LEFT);
                         //Filler
                         $data .= str_pad('', 9, ' ', STR_PAD_LEFT);
                         //Amount. This can always be calculated from hours and hourly rate above though.
                         $data .= str_pad('', 13, ' ', STR_PAD_LEFT);
                         //Blank space
                         if (isset($setup_data['paychex_preview_advanced_job']['state_columns'])) {
                             $data .= str_pad(isset($row[$setup_data['paychex_preview_advanced_job']['state_columns']]) ? $row[$setup_data['paychex_preview_advanced_job']['state_columns']] : NULL, 2, ' ', STR_PAD_LEFT);
                             //State
                         }
                         $data .= "\n";
                     }
                 }
             }
             break;
         case 'paychex_preview':
             //Paychex Preview export format.
             //Add an advanced PayChex Preview format that supports rates perhaps?
             //http://kb.idb-sys.com/KnowledgebaseArticle10013.aspx
             if (!isset($setup_data['paychex_preview']['client_number'])) {
                 $setup_data['paychex_preview']['client_number'] = '0000';
             }
             $file_name = $setup_data['paychex_preview']['client_number'] . '_TA.txt';
             ksort($setup_data['paychex_preview']['columns']);
             $setup_data['paychex_preview']['columns'] = Misc::trimSortPrefix($setup_data['paychex_preview']['columns']);
             $data = NULL;
             foreach ($rows as $row) {
                 foreach ($setup_data['paychex_preview']['columns'] as $column_id => $column_data) {
                     if (isset($row[$column_id]) and trim($column_data['hour_code']) != '') {
                         $data .= str_pad($row['employee_number'], 6, ' ', STR_PAD_LEFT);
                         $data .= str_pad('E' . str_pad(trim($column_data['hour_code']), 2, ' ', STR_PAD_RIGHT), 47, ' ', STR_PAD_LEFT);
                         $data .= str_pad(str_pad(TTDate::getTimeUnit($row[$column_id], 20), 8, 0, STR_PAD_LEFT), 17, ' ', STR_PAD_LEFT) . "\n";
                     }
                 }
             }
             break;
         case 'paychex_online':
             //Paychex Online Payroll CSV
             ksort($setup_data['paychex_online']['columns']);
             $setup_data['paychex_online']['columns'] = Misc::trimSortPrefix($setup_data['paychex_online']['columns']);
             $earnings = array();
             //Find all the hours codes
             foreach ($setup_data['paychex_online']['columns'] as $column_id => $column_data) {
                 $hour_code = $column_data['hour_code'];
                 $earnings[] = $hour_code;
             }
             $export_column_map['employee_number'] = '';
             foreach ($earnings as $key => $value) {
                 $export_column_map[$value] = '';
             }
             $i = 0;
             foreach ($rows as $row) {
                 if ($i == 0) {
                     //Include header.
                     $tmp_row['employee_number'] = 'Employee Number';
                     foreach ($earnings as $key => $value) {
                         $tmp_row[$value] = $value . ' Hours';
                     }
                     $tmp_rows[] = $tmp_row;
                     unset($tmp_row);
                 }
                 //Combine all hours from the same code together.
                 foreach ($setup_data['paychex_online']['columns'] as $column_id => $column_data) {
                     $hour_code = trim($column_data['hour_code']);
                     if (isset($row[$column_id]) and $hour_code != '') {
                         if (!isset($tmp_hour_codes[$hour_code])) {
                             $tmp_hour_codes[$hour_code] = 0;
                         }
                         $tmp_hour_codes[$hour_code] = bcadd($tmp_hour_codes[$column_data['hour_code']], $row[$column_id]);
                         //Use seconds for math here.
                     }
                 }
                 if (isset($tmp_hour_codes)) {
                     $tmp_row['employee_number'] = $row['employee_number'];
                     foreach ($tmp_hour_codes as $hour_code => $hours) {
                         $tmp_row[$hour_code] = TTDate::getTimeUnit($hours, 20);
                     }
                     $tmp_rows[] = $tmp_row;
                     unset($tmp_hour_codes, $hour_code, $hours, $tmp_row);
                 }
                 $i++;
             }
             if (isset($tmp_rows)) {
                 $data = Misc::Array2CSV($tmp_rows, $export_column_map, FALSE, FALSE);
             }
             unset($tmp_rows, $export_column_map, $column_id, $column_data, $rows, $row);
             break;
         case 'millenium':
             //Millenium export format. Also used by Qqest.
             ksort($setup_data['millenium']['columns']);
             $setup_data['millenium']['columns'] = Misc::trimSortPrefix($setup_data['millenium']['columns']);
             $export_column_map = array('employee_number' => '', 'transaction_code' => '', 'hour_code' => '', 'hours' => '');
             foreach ($rows as $row) {
                 foreach ($setup_data['millenium']['columns'] as $column_id => $column_data) {
                     if (isset($row[$column_id]) and trim($column_data['hour_code']) != '') {
                         $tmp_rows[] = array('employee_number' => $row['employee_number'], 'transaction_code' => 'E', 'hour_code' => trim($column_data['hour_code']), 'hours' => TTDate::getTimeUnit($row[$column_id], 20));
                     }
                 }
             }
             if (isset($tmp_rows)) {
                 $data = Misc::Array2CSV($tmp_rows, $export_column_map, FALSE, FALSE);
             }
             unset($tmp_rows, $export_column_map, $column_id, $column_data, $rows, $row);
             break;
         case 'ceridian_insync':
             //Ceridian InSync export format. Needs to be .IMP to import? DOS line endings?
             if (!isset($setup_data['ceridian_insync']['employer_number']) or $setup_data['ceridian_insync']['employer_number'] == '') {
                 $setup_data['ceridian_insync']['employer_number'] = '0001';
             }
             $file_name = strtolower(trim($setup_data['export_type'])) . '_' . $setup_data['ceridian_insync']['employer_number'] . '_' . date('Y_m_d') . '.imp';
             ksort($setup_data['ceridian_insync']['columns']);
             $setup_data['ceridian_insync']['columns'] = Misc::trimSortPrefix($setup_data['ceridian_insync']['columns']);
             $export_column_map = array('employer_number' => '', 'import_type_id' => '', 'employee_number' => '', 'check_type' => '', 'hour_code' => '', 'value' => '', 'distribution' => '', 'rate' => '', 'premium' => '', 'day' => '', 'pay_period' => '');
             foreach ($rows as $row) {
                 foreach ($setup_data['ceridian_insync']['columns'] as $column_id => $column_data) {
                     if (isset($row[$column_id]) and trim($column_data['hour_code']) != '') {
                         $tmp_rows[] = array('employer_number' => $setup_data['ceridian_insync']['employer_number'], 'import_type_id' => 'COSTING', 'employee_number' => str_pad($row['employee_number'], 9, '0', STR_PAD_LEFT), 'check_type' => 'REG', 'hour_code' => trim($column_data['hour_code']), 'value' => TTDate::getTimeUnit($row[$column_id], 20), 'distribution' => NULL, 'rate' => NULL, 'premium' => NULL, 'day' => NULL, 'pay_period' => NULL);
                     }
                 }
             }
             if (isset($tmp_rows)) {
                 $data = Misc::Array2CSV($tmp_rows, $export_column_map, FALSE, FALSE, "\r\n");
                 //Use DOS line endings only.
             }
             unset($tmp_rows, $export_column_map, $column_id, $column_data, $rows, $row);
             break;
         case 'quickbooks':
             //Quickbooks Pro export format.
         //Quickbooks Pro export format.
         case 'quickbooks_advanced':
             //Quickbooks Pro export format.
             $file_name = 'payroll_export.iif';
             ksort($setup_data['quickbooks']['columns']);
             $setup_data['quickbooks']['columns'] = Misc::trimSortPrefix($setup_data['quickbooks']['columns']);
             //
             // Quickbooks header
             //
             /*
             	Company Create Time can be found by first running an Timer Activity export in QuickBooks and viewing the output.
             
             	PITEM field needs to be populated, as that is the PAYROLL ITEM in quickbooks. It can be the same as the ITEM field.
             	ITEM is the service item, can be mapped to department/task?
             	PROJ could be mapped to the default department/branch?
             */
             $data = "!TIMERHDR\tVER\tREL\tCOMPANYNAME\tIMPORTEDBEFORE\tFROMTIMER\tCOMPANYCREATETIME\n";
             $data .= "TIMERHDR\t8\t0\t" . trim($setup_data['quickbooks']['company_name']) . "\tN\tY\t" . trim($setup_data['quickbooks']['company_created_date']) . "\n";
             $data .= "!TIMEACT\tDATE\tJOB\tEMP\tITEM\tPITEM\tDURATION\tPROJ\tNOTE\tXFERTOPAYROLL\tBILLINGSTATUS\n";
             foreach ($rows as $row) {
                 foreach ($setup_data['quickbooks']['columns'] as $column_id => $column_data) {
                     if (isset($row[$column_id]) and trim($column_data['hour_code']) != '') {
                         //Make sure employee name is in format: LastName, FirstName MiddleInitial
                         $tmp_employee_name = $row['last_name'] . ', ' . $row['first_name'];
                         if (isset($row['middle_name']) and strlen($row['middle_name']) > 0) {
                             $tmp_employee_name .= ' ' . substr(trim($row['middle_name']), 0, 1);
                         }
                         $proj = NULL;
                         if (isset($row[$setup_data['quickbooks']['proj']])) {
                             $proj = $row[$setup_data['quickbooks']['proj']];
                         }
                         $item = NULL;
                         if (isset($row[$setup_data['quickbooks']['item']])) {
                             $item = $row[$setup_data['quickbooks']['item']];
                         }
                         $job = NULL;
                         if (isset($row[$setup_data['quickbooks']['job']])) {
                             $job = $row[$setup_data['quickbooks']['job']];
                         }
                         $data .= "TIMEACT\t" . date('n/j/y', $row['pay_period_end_date']) . "\t" . $job . "\t" . $tmp_employee_name . "\t" . $item . "\t" . trim($column_data['hour_code']) . "\t" . TTDate::getTimeUnit($row[$column_id], 10) . "\t" . $proj . "\t\tY\t0\n";
                         unset($tmp_employee_name);
                     }
                 }
             }
             break;
         case 'surepayroll':
             //SurePayroll Export format.
             ksort($setup_data['surepayroll']['columns']);
             $setup_data['surepayroll']['columns'] = Misc::trimSortPrefix($setup_data['surepayroll']['columns']);
             //
             //header
             //
             $data = 'TC' . "\n";
             $data .= '00001' . "\n";
             $export_column_map = array('pay_period_end_date' => 'Entry Date', 'employee_number' => 'Employee Number', 'last_name' => 'Last Name', 'first_name' => 'First Name', 'hour_code' => 'Payroll Code', 'value' => 'Hours');
             foreach ($rows as $row) {
                 foreach ($setup_data['surepayroll']['columns'] as $column_id => $column_data) {
                     if (isset($row[$column_id]) and trim($column_data['hour_code']) != '') {
                         //Debug::Arr($column_data,'Output2', __FILE__, __LINE__, __METHOD__,10);
                         $tmp_rows[] = array('pay_period_end_date' => date('m/d/Y', $row['pay_period_end_date']), 'employee_number' => $row['employee_number'], 'last_name' => $row['last_name'], 'first_name' => $row['first_name'], 'hour_code' => trim($column_data['hour_code']), 'value' => TTDate::getTimeUnit($row[$column_id], 20));
                     }
                 }
             }
             if (isset($tmp_rows)) {
                 $data .= Misc::Array2CSV($tmp_rows, $export_column_map, FALSE, FALSE);
                 $data = str_replace('"', '', $data);
             }
             unset($tmp_rows, $export_column_map, $column_id, $column_data, $rows, $row);
             break;
         case 'chris21':
             //Chris21 Export format.
             //Columns required: Employee_number (2), Date (10), ADJUSTMENT_CODE (12), HOURS (13), SIGNED_HOURS(15)[?]
             //Use SIGNED_HOURS only, as it provides more space?
             //When using absences a leave start/end date must be specified other it won't be imported.
             ksort($setup_data['chris21']['columns']);
             $setup_data['chris21']['columns'] = Misc::trimSortPrefix($setup_data['chris21']['columns']);
             $data = '';
             foreach ($rows as $row) {
                 foreach ($setup_data['chris21']['columns'] as $column_id => $column_data) {
                     if (isset($row[$column_id]) and trim($column_data['hour_code']) != '') {
                         //Debug::Arr($column_data,'Output2: ID: '. $column_id, __FILE__, __LINE__, __METHOD__,10);
                         $data .= str_repeat(' ', 8);
                         //8 digits Blank
                         $data .= str_pad(substr($row['employee_number'], 0, 7), 7, ' ', STR_PAD_RIGHT);
                         //7 digits
                         $data .= str_repeat(' ', 11);
                         //14 digits Blank
                         $data .= date('dmy', $row['pay_period_end_date']);
                         //4 digits Date
                         $data .= str_repeat(' ', 4);
                         //4 digits Blank
                         $data .= str_pad(substr(trim($column_data['hour_code']), 0, 4), 4, ' ', STR_PAD_RIGHT);
                         //4 digits
                         $data .= '0000';
                         //4 digits HOURS field, always be 0, use SIGNED_HOURS instead.
                         $data .= str_repeat(' ', 4);
                         //CC_CODE: 4 digits Blank
                         $data .= str_pad(str_replace('.', '', TTDate::getTimeUnit($row[$column_id], 20)), 6, 0, STR_PAD_LEFT) . '+';
                         //SIGNED_HOURS: Hours without decimal padded to 6 digits, with '+' on the end.
                         //$data .= '+000000000'; 																	//Filler: Redefintion of SIGNED_HOURS.
                         $data .= '000000000';
                         //RATE: 9 chars
                         $data .= str_repeat(' ', 20);
                         //ACCT_NO: 20 chars
                         $data .= str_repeat(' ', 16);
                         //JOB_NUMBER: 16 chars
                         if (strpos($column_id, 'absence') !== FALSE) {
                             //Absence column, include LEAVE dates.
                             $data .= date('dmy', $row['pay_period_end_date']);
                             //LEAVE Start Date: 6 digits
                             $data .= date('dmy', $row['pay_period_end_date']);
                             //LEAVE End Date: 6 digits
                         }
                         $data .= "\n";
                     }
                 }
             }
             unset($tmp_rows, $column_id, $column_data, $rows, $row);
             break;
         case 'csv':
             //Generic CSV.
             $file_name = strtolower(trim($setup_data['export_type'])) . '_' . date('Y_m_d') . '.csv';
             //If this needs to be customized, they can just export any regular report. This could probably be removed completely except for the Hour Code mapping...
             ksort($setup_data['csv']['columns']);
             $setup_data['csv']['columns'] = Misc::trimSortPrefix($setup_data['csv']['columns']);
             $export_column_map = array('employee' => '', 'employee_number' => '', 'default_branch' => '', 'default_department' => '', 'pay_period' => '', 'branch_name' => '', 'department_name' => '', 'hour_code' => '', 'hours' => '');
             $i = 0;
             foreach ($rows as $row) {
                 if ($i == 0) {
                     //Include header.
                     $tmp_rows[] = array('employee' => 'Employee', 'employee_number' => 'Employee Number', 'default_branch' => 'Default Branch', 'default_department' => 'Default Department', 'pay_period' => 'Pay Period', 'branch_name' => 'Branch', 'department_name' => 'Department', 'hour_code' => 'Hours Code', 'hours' => 'Hours');
                 }
                 //Combine all hours from the same code together.
                 foreach ($setup_data['csv']['columns'] as $column_id => $column_data) {
                     $hour_code = trim($column_data['hour_code']);
                     if (isset($row[$column_id]) and $hour_code != '') {
                         if (!isset($tmp_hour_codes[$hour_code])) {
                             $tmp_hour_codes[$hour_code] = 0;
                         }
                         $tmp_hour_codes[$hour_code] = bcadd($tmp_hour_codes[$column_data['hour_code']], $row[$column_id]);
                         //Use seconds for math here.
                     }
                 }
                 if (isset($tmp_hour_codes)) {
                     foreach ($tmp_hour_codes as $hour_code => $hours) {
                         $tmp_rows[] = array('employee' => isset($row['full_name']) ? $row['full_name'] : NULL, 'employee_number' => isset($row['employee_number']) ? $row['employee_number'] : NULL, 'default_branch' => isset($row['default_branch']) ? $row['default_branch'] : NULL, 'default_department' => isset($row['default_department']) ? $row['default_department'] : NULL, 'pay_period' => isset($row['pay_period']['display']) ? $row['pay_period']['display'] : NULL, 'branch_name' => isset($row['branch_name']) ? $row['branch_name'] : NULL, 'department_name' => isset($row['department_name']) ? $row['department_name'] : NULL, 'hour_code' => $hour_code, 'hours' => TTDate::getTimeUnit($hours, 20));
                     }
                     unset($tmp_hour_codes, $hour_code, $hours);
                 }
                 $i++;
             }
             if (isset($tmp_rows)) {
                 $data = Misc::Array2CSV($tmp_rows, $export_column_map, FALSE, FALSE);
             }
             unset($tmp_rows, $export_column_map, $column_id, $column_data, $rows, $row);
             break;
         case 'csv_advanced':
             //Generic CSV.
             unset($rows);
             //Ignore any existing timesheet summary data, we will be using our own job data below.
             //If this needs to be customized, they can just export any regular report. This could probably be removed completely except for the Hour Code mapping...
             if (!isset($setup_data['csv_advanced']['export_columns']) or isset($setup_data['csv_advanced']['export_columns']) and !is_array($setup_data['csv_advanced']['export_columns'])) {
                 $setup_data['csv_advanced']['export_columns'] = array('full_name', 'employee_number', 'default_branch', 'default_department', 'pay_period', 'date_stamp');
             }
             if (isset($setup_data['csv_advanced']['export_columns']) and is_array($setup_data['csv_advanced']['export_columns'])) {
                 //Debug::Arr($setup_data['csv_advanced']['export_columns'], 'Custom Columns defined: ', __FILE__, __LINE__, __METHOD__,10);
                 $config['columns'] = $config['group'] = $setup_data['csv_advanced']['export_columns'];
                 //Force sorting...
                 foreach ($setup_data['csv_advanced']['export_columns'] as $export_column) {
                     $config['sort'][] = array($export_column => 'asc');
                 }
                 $config['columns'] += array_keys(Misc::trimSortPrefix($this->getOptions('dynamic_columns')));
             }
             Debug::Arr($config, 'Job Detail Report Config: ', __FILE__, __LINE__, __METHOD__, 10);
             //Get job data...
             if (is_object($this->getUserObject()) and is_object($this->getUserObject()->getCompanyObject()) and $this->getUserObject()->getCompanyObject()->getProductEdition() >= TT_PRODUCT_CORPORATE) {
                 Debug::Text('Using Job Detail Report...', __FILE__, __LINE__, __METHOD__, 10);
                 $jar = TTNew('JobDetailReport');
             } else {
                 Debug::Text('Using TimeSheet Detail Report...', __FILE__, __LINE__, __METHOD__, 10);
                 $jar = TTNew('TimesheetDetailReport');
             }
             $jar->setAMFMessageID($this->getAMFMessageID());
             $jar->setUserObject($this->getUserObject());
             $jar->setPermissionObject($this->getPermissionObject());
             $jar->setConfig($config);
             $jar->setFilterConfig($this->getFilterConfig());
             $jar->setSortConfig($config['sort']);
             $jar->_getData();
             $jar->_preProcess();
             $jar->group();
             $jar->sort();
             $columns = Misc::trimSortPrefix($jar->getOptions('columns'));
             $rows = $jar->data;
             //Debug::Arr($rows, 'Raw Rows: ', __FILE__, __LINE__, __METHOD__,10);
             $file_name = strtolower(trim($setup_data['export_type'])) . '_' . date('Y_m_d') . '.csv';
             //If this needs to be customized, they can just export any regular report. This could probably be removed completely except for the Hour Code mapping...
             ksort($setup_data['csv_advanced']['columns']);
             $setup_data['csv_advanced']['columns'] = Misc::trimSortPrefix($setup_data['csv_advanced']['columns']);
             foreach ($setup_data['csv_advanced']['export_columns'] as $export_column) {
                 $export_column_map[$export_column] = '';
             }
             $export_column_map['hour_code'] = '';
             $export_column_map['hours'] = '';
             $i = 0;
             foreach ($rows as $row) {
                 if ($i == 0) {
                     //Include header.
                     foreach ($setup_data['csv_advanced']['export_columns'] as $export_column) {
                         Debug::Text('Header Row: ' . $export_column, __FILE__, __LINE__, __METHOD__, 10);
                         $tmp_rows[$i][$export_column] = isset($columns[$export_column]) ? $columns[$export_column] : NULL;
                     }
                     $tmp_rows[$i]['hour_code'] = 'Hours Code';
                     $tmp_rows[$i]['hours'] = 'Hours';
                     $i++;
                 }
                 //Combine all hours from the same code together.
                 foreach ($setup_data['csv_advanced']['columns'] as $column_id => $column_data) {
                     $hour_code = trim($column_data['hour_code']);
                     if (isset($row[$column_id]) and $hour_code != '') {
                         if (!isset($tmp_hour_codes[$hour_code])) {
                             $tmp_hour_codes[$hour_code] = 0;
                         }
                         $tmp_hour_codes[$hour_code] = bcadd($tmp_hour_codes[$column_data['hour_code']], $row[$column_id]);
                         //Use seconds for math here.
                     }
                 }
                 if (isset($tmp_hour_codes)) {
                     foreach ($tmp_hour_codes as $hour_code => $hours) {
                         foreach ($setup_data['csv_advanced']['export_columns'] as $export_column) {
                             $tmp_rows[$i][$export_column] = isset($row[$export_column]) ? isset($row[$export_column]['display']) ? $row[$export_column]['display'] : $row[$export_column] : NULL;
                             $tmp_rows[$i]['hour_code'] = $hour_code;
                             $tmp_rows[$i]['hours'] = TTDate::getTimeUnit($hours, 20);
                         }
                     }
                     unset($tmp_hour_codes, $hour_code, $hours);
                 }
                 $i++;
             }
             //Debug::Arr($tmp_rows, 'Tmp Rows: ', __FILE__, __LINE__, __METHOD__,10);
             if (isset($tmp_rows)) {
                 $data = Misc::Array2CSV($tmp_rows, $export_column_map, FALSE, FALSE);
             }
             unset($tmp_rows, $export_column_map, $column_id, $column_data, $rows, $row);
             break;
         default:
             //Send raw data so plugin can capture it and change it if needed.
             $data = $this->data;
             break;
     }
     //Debug::Arr($data, 'Export Data: ', __FILE__, __LINE__, __METHOD__,10);
     return array('file_name' => $file_name, 'mime_type' => $mime_type, 'data' => $data);
 }
 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;
     }
 }
Beispiel #10
0
 public static function getTimePeriodDates($time_period, $epoch = NULL, $user_obj = NULL, $params = NULL)
 {
     $time_period = Misc::trimSortPrefix($time_period);
     if ($epoch == NULL or $epoch == '' or !is_numeric($epoch)) {
         $epoch = self::getTime();
     }
     $start_week_day = 0;
     if (is_object($user_obj)) {
         $user_prefs = $user_obj->getUserPreferenceObject();
         if (is_object($user_prefs)) {
             $start_week_day = $user_prefs->getStartWeekDay();
         }
     }
     switch ($time_period) {
         case 'custom_date':
             //Params must pass start_date/end_date
             if (isset($params['start_date'])) {
                 $start_date = TTDate::getBeginDayEpoch($params['start_date']);
             }
             if (isset($params['end_date'])) {
                 $end_date = TTDate::getEndDayEpoch($params['end_date']);
             }
             break;
         case 'custom_time':
             //Params must pass start_date/end_date
             if (isset($params['start_date'])) {
                 $start_date = $params['start_date'];
             }
             if (isset($params['end_date'])) {
                 $end_date = $params['end_date'];
             }
             break;
         case 'custom_pay_period':
             //Params must pass pay_period_ids
             if (isset($params['pay_period_id'])) {
                 $pay_period_ids = (array) $params['pay_period_id'];
             }
             break;
         case 'today':
             $start_date = TTDate::getBeginDayEpoch($epoch);
             $end_date = TTDate::getEndDayEpoch($epoch);
             break;
         case 'yesterday':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             break;
         case 'last_24_hours':
             $start_date = $epoch - 86400;
             $end_date = $epoch;
             break;
         case 'last_48_hours':
             $start_date = $epoch - 86400 * 2;
             $end_date = $epoch;
             break;
         case 'last_72_hours':
             $start_date = $epoch - 86400 * 3;
             $end_date = $epoch;
             break;
         case 'this_week':
             $start_date = TTDate::getBeginWeekEpoch($epoch, $start_week_day);
             $end_date = TTDate::getEndWeekEpoch($epoch, $start_week_day);
             break;
         case 'last_week':
             $start_date = TTDate::getBeginWeekEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 7, $start_week_day);
             $end_date = TTDate::getEndWeekEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 7, $start_week_day);
             break;
         case 'last_2_weeks':
             $start_date = TTDate::getBeginWeekEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 14, $start_week_day);
             $end_date = TTDate::getEndWeekEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 7, $start_week_day);
             break;
         case 'last_7_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 7);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             break;
         case 'last_14_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 14);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             break;
             //Params must be passed if more than one pay period schedule exists.
         //Params must be passed if more than one pay period schedule exists.
         case 'no_pay_period':
         case 'this_pay_period':
         case 'last_pay_period':
             Debug::text('Time Period for Pay Period Schedule selected...', __FILE__, __LINE__, __METHOD__, 10);
             //Make sure user_obj is set.
             if (!is_object($user_obj)) {
                 Debug::text('User Object was not passsed...', __FILE__, __LINE__, __METHOD__, 10);
                 break;
             }
             if (!isset($params['pay_period_schedule_id'])) {
                 $params['pay_period_schedule_id'] = NULL;
             }
             $pay_period_ids = array();
             //Since we allow multiple pay_period schedules to be selected, we have to return pay_period_ids, not start/end dates.
             if ($time_period == 'this_pay_period') {
                 Debug::text('this_pay_period', __FILE__, __LINE__, __METHOD__, 10);
                 $pplf = TTnew('PayPeriodListFactory');
                 $pplf->getThisPayPeriodByCompanyIdAndPayPeriodScheduleIdAndDate($user_obj->getCompany(), $params['pay_period_schedule_id'], time());
                 if ($pplf->getRecordCount() > 0) {
                     foreach ($pplf as $pp_obj) {
                         $pay_period_ids[] = $pp_obj->getId();
                     }
                 }
             } elseif ($time_period == 'last_pay_period') {
                 Debug::text('last_pay_period', __FILE__, __LINE__, __METHOD__, 10);
                 $pplf = TTnew('PayPeriodListFactory');
                 $pplf->getLastPayPeriodByCompanyIdAndPayPeriodScheduleIdAndDate($user_obj->getCompany(), $params['pay_period_schedule_id'], time());
                 if ($pplf->getRecordCount() > 0) {
                     foreach ($pplf as $pp_obj) {
                         $pay_period_ids[] = $pp_obj->getId();
                     }
                 }
             } else {
                 Debug::text('no_pay_period', __FILE__, __LINE__, __METHOD__, 10);
             }
             Debug::Arr($pay_period_ids, 'Pay Period IDs: ', __FILE__, __LINE__, __METHOD__, 10);
             if (count($pay_period_ids) == 0) {
                 unset($pay_period_ids);
             }
             break;
         case 'this_month':
             $start_date = TTDate::getBeginMonthEpoch($epoch);
             $end_date = TTDate::getEndMonthEpoch($epoch);
             break;
         case 'last_month':
             $start_date = TTDate::getBeginMonthEpoch(TTDate::getBeginMonthEpoch($epoch) - 86400);
             $end_date = TTDate::getEndMonthEpoch(TTDate::getBeginMonthEpoch($epoch) - 86400);
             break;
         case 'last_2_months':
             $start_date = TTDate::getBeginMonthEpoch(TTDate::getBeginMonthEpoch($epoch) - 86400 * 32);
             $end_date = TTDate::getEndMonthEpoch(TTDate::getBeginMonthEpoch($epoch) - 86400);
             break;
         case 'last_30_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 30);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             break;
         case 'last_45_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 45);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             break;
         case 'last_60_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 60);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             break;
         case 'this_quarter':
             $quarter = TTDate::getYearQuarter($epoch);
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             //Debug::Arr($quarter_dates, 'Quarter Dates: Quarter: '. $quarter, __FILE__, __LINE__, __METHOD__,10);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'last_quarter':
             $quarter = TTDate::getYearQuarter($epoch) - 1;
             if ($quarter == 0) {
                 $quarter = 4;
                 $epoch = TTDate::getBeginYearEpoch() - 86400;
                 //Need to jump back into the previous year.
             }
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'last_90_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 90);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             break;
         case 'this_year_1st_quarter':
             $quarter = 1;
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'this_year_2nd_quarter':
             $quarter = 2;
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'this_year_3rd_quarter':
             $quarter = 3;
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'this_year_4th_quarter':
             $quarter = 4;
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'last_year_1st_quarter':
             $quarter = 1;
             $quarter_dates = TTDate::getYearQuarters(TTDate::getBeginYearEpoch($epoch) - 86400, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'last_year_2nd_quarter':
             $quarter = 2;
             $quarter_dates = TTDate::getYearQuarters(TTDate::getBeginYearEpoch($epoch) - 86400, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'last_year_3rd_quarter':
             $quarter = 3;
             $quarter_dates = TTDate::getYearQuarters(TTDate::getBeginYearEpoch($epoch) - 86400, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'last_year_4th_quarter':
             $quarter = 4;
             $quarter_dates = TTDate::getYearQuarters(TTDate::getBeginYearEpoch($epoch) - 86400, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'last_3_months':
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date) - 3, TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date));
             break;
         case 'last_6_months':
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date) - 6, TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date));
             break;
         case 'last_9_months':
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date) - 9, TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date));
             break;
         case 'last_12_months':
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date), TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date) - 1);
             break;
         case 'last_18_months':
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date) - 18, TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date));
             break;
         case 'last_24_months':
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date) - 24, TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date));
             break;
         case 'this_year':
             $start_date = TTDate::getBeginYearEpoch($epoch);
             $end_date = TTDate::getEndYearEpoch($epoch);
             break;
         case 'last_year':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch($epoch) - 86400);
             $end_date = TTDate::getEndYearEpoch(TTDate::getBeginYearEpoch($epoch) - 86400);
             break;
         case 'last_2_years':
             $end_date = TTDate::getEndYearEpoch(TTDate::getBeginYearEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date), TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date) - 2);
             break;
         case 'last_3_years':
             $end_date = TTDate::getEndYearEpoch(TTDate::getBeginYearEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date), TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date) - 3);
             break;
         case 'last_5_years':
             $end_date = TTDate::getEndYearEpoch(TTDate::getBeginYearEpoch($epoch) - 86400);
             $start_date = mktime(0, 0, 0, TTDate::getMonth($end_date), TTDate::getDayOfMonth($end_date), TTDate::getYear($end_date) - 5);
             break;
         case 'to_yesterday':
             //"Up To" means we need to use the end time of the day we go up to.
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400) - 1;
             break;
         case 'to_today':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch)) - 1;
             break;
         case 'to_this_week':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginWeekEpoch($epoch, $start_week_day) - 1;
             break;
         case 'to_last_week':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginWeekEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 7, $start_week_day) - 1;
             break;
         case 'to_7_days':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 7) - 1;
             break;
         case 'to_14_days':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 14) - 1;
             break;
         case 'to_last_pay_period':
         case 'to_this_pay_period':
             Debug::text('Time Period for Pay Period Schedule selected...', __FILE__, __LINE__, __METHOD__, 10);
             //Make sure user_obj is set.
             if (!is_object($user_obj)) {
                 Debug::text('User Object was not passsed...', __FILE__, __LINE__, __METHOD__, 10);
                 break;
             }
             if (!isset($params['pay_period_schedule_id'])) {
                 $params['pay_period_schedule_id'] = NULL;
             }
             $end_date = FALSE;
             //Since we allow multiple pay_period schedules to be selected, we have to return pay_period_ids, not start/end dates.
             if ($time_period == 'to_this_pay_period') {
                 Debug::text('to_this_pay_period', __FILE__, __LINE__, __METHOD__, 10);
                 $pplf = TTnew('PayPeriodListFactory');
                 $pplf->getThisPayPeriodByCompanyIdAndPayPeriodScheduleIdAndDate($user_obj->getCompany(), $params['pay_period_schedule_id'], time());
                 if ($pplf->getRecordCount() > 0) {
                     foreach ($pplf as $pp_obj) {
                         if ($end_date == FALSE or $pp_obj->getStartDate() < $end_date) {
                             $end_date = $pp_obj->getStartDate();
                         }
                     }
                 }
             } elseif ($time_period == 'to_last_pay_period') {
                 Debug::text('to_last_pay_period', __FILE__, __LINE__, __METHOD__, 10);
                 $pplf = TTnew('PayPeriodListFactory');
                 $pplf->getLastPayPeriodByCompanyIdAndPayPeriodScheduleIdAndDate($user_obj->getCompany(), $params['pay_period_schedule_id'], time());
                 if ($pplf->getRecordCount() > 0) {
                     foreach ($pplf as $pp_obj) {
                         if ($end_date == FALSE or $pp_obj->getStartDate() < $end_date) {
                             $end_date = $pp_obj->getStartDate();
                         }
                     }
                 }
             }
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = $end_date - 1;
             break;
         case 'to_last_month':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginMonthEpoch(TTDate::getBeginMonthEpoch($epoch) - 86400) - 1;
             break;
         case 'to_this_month':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginMonthEpoch($epoch) - 1;
             break;
         case 'to_30_days':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 30) - 1;
             break;
         case 'to_45_days':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 45) - 1;
             break;
         case 'to_60_days':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 60) - 1;
             break;
         case 'to_last_quarter':
             $quarter = TTDate::getYearQuarter($epoch) - 1;
             if ($quarter == 0) {
                 $quarter = 4;
                 $epoch = TTDate::getBeginYearEpoch() - 86400;
                 //Need to jump back into the previous year.
             }
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = $quarter_dates['start'] - 1;
             break;
         case 'to_this_quarter':
             $quarter = TTDate::getYearQuarter($epoch);
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = $quarter_dates['start'] - 1;
             break;
         case 'to_90_days':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) - 86400 * 90) - 1;
             break;
         case 'to_this_year':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginYearEpoch($epoch) - 1;
             break;
         case 'to_last_year':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch($epoch) - 86400) - 1;
             break;
         case 'tomorrow':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             break;
         case 'next_24_hours':
             $start_date = $epoch;
             $end_date = $epoch + 86400;
             break;
         case 'next_48_hours':
             $start_date = $epoch;
             $end_date = $epoch + 86400 * 2;
             break;
         case 'next_72_hours':
             $start_date = $epoch;
             $end_date = $epoch + 86400 * 3;
             break;
         case 'next_week':
             $start_date = TTDate::getBeginWeekEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 7, $start_week_day);
             $end_date = TTDate::getEndWeekEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 7, $start_week_day);
             break;
         case 'next_2_weeks':
             $start_date = TTDate::getBeginWeekEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 7, $start_week_day);
             $end_date = TTDate::getEndWeekEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 14, $start_week_day);
             break;
         case 'next_7_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 7);
             break;
         case 'next_14_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 14);
             break;
         case 'next_month':
             $start_date = TTDate::getBeginMonthEpoch(TTDate::getEndMonthEpoch($epoch) + 86400);
             $end_date = TTDate::getEndMonthEpoch(TTDate::getEndMonthEpoch($epoch) + 86400);
             break;
         case 'next_2_months':
             $start_date = TTDate::getBeginMonthEpoch(TTDate::getEndMonthEpoch($epoch) + 86400);
             $end_date = TTDate::getEndMonthEpoch(TTDate::getEndMonthEpoch($epoch) + 86400 * 32);
             break;
         case 'next_30_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 30);
             break;
         case 'next_45_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 45);
             break;
         case 'next_60_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 60);
             break;
         case 'next_quarter':
             $quarter = TTDate::getYearQuarter($epoch) + 1;
             if ($quarter == 5) {
                 $quarter = 1;
                 $epoch = TTDate::getEndYearEpoch() + 86400;
                 //Need to jump back into the previous year.
             }
             $quarter_dates = TTDate::getYearQuarters($epoch, $quarter);
             $start_date = $quarter_dates['start'];
             $end_date = $quarter_dates['end'];
             break;
         case 'next_90_days':
             $start_date = TTDate::getBeginDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400 * 90);
             break;
         case 'next_3_months':
             $start_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date) + 3, TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date));
             break;
         case 'next_6_months':
             $start_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date) + 6, TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date));
             break;
         case 'next_9_months':
             $start_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date) + 9, TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date));
             break;
         case 'next_12_months':
             $start_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date) + 12, TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date));
             break;
         case 'next_18_months':
             $start_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date) + 18, TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date));
             break;
         case 'next_24_months':
             $start_date = TTDate::getEndDayEpoch(TTDate::getMiddleDayEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date) + 24, TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date));
             break;
         case 'next_year':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getEndYearEpoch($epoch) + 86400);
             $end_date = TTDate::getEndYearEpoch(TTDate::getEndYearEpoch($epoch) + 86400);
             break;
         case 'next_2_years':
             $start_date = TTDate::getEndYearEpoch(TTDate::getEndYearEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date), TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date) + 2);
             break;
         case 'next_3_years':
             $start_date = TTDate::getEndYearEpoch(TTDate::getEndYearEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date), TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date) + 3);
             break;
         case 'next_5_years':
             $start_date = TTDate::getEndYearEpoch(TTDate::getEndYearEpoch($epoch) + 86400);
             $end_date = mktime(0, 0, 0, TTDate::getMonth($start_date), TTDate::getDayOfMonth($start_date), TTDate::getYear($start_date) + 5);
             break;
         case 'all_years':
             $start_date = TTDate::getBeginYearEpoch(TTDate::getBeginYearEpoch(31564800) - 86400);
             $end_date = TTDate::getEndYearEpoch(time() + 86400 * (365 * 2));
             break;
         default:
             break;
     }
     if (isset($start_date) and isset($end_date)) {
         //Debug::text('Period: '. $time_period .' Start: '. TTDate::getDate('DATE+TIME', $start_date ) .'('.$start_date.') End: '. TTDate::getDate('DATE+TIME', $end_date ) .'('.$end_date.')', __FILE__, __LINE__, __METHOD__,10);
         return array('start_date' => $start_date, 'end_date' => $end_date);
     } elseif (isset($pay_period_ids)) {
         //Debug::text('Period: '. $time_period .' returning just pay_period_ids...', __FILE__, __LINE__, __METHOD__,10);
         return array('pay_period_id' => $pay_period_ids);
     }
     return FALSE;
 }
 function _outputPDFForm($format = NULL)
 {
     $show_background = TRUE;
     if ($format == 'pdf_form_print') {
         $show_background = FALSE;
     }
     Debug::Text('Generating Form... Format: ' . $format, __FILE__, __LINE__, __METHOD__, 10);
     $setup_data = $this->getFormConfig();
     $filter_data = $this->getFilterConfig();
     //Debug::Arr($filter_data, 'Filter Data: ', __FILE__, __LINE__, __METHOD__,10);
     $current_company = $this->getUserObject()->getCompanyObject();
     if (!is_object($current_company)) {
         Debug::Text('Invalid company object...', __FILE__, __LINE__, __METHOD__, 10);
         return FALSE;
     }
     if ($format == 'efile_xml') {
         $return941 = $this->getRETURN941Object();
         $return941->TaxPeriodEndDate = TTDate::getDate('Y-m-d', TTDate::getEndDayEpoch($filter_data['end_date']));
         $return941->ReturnType = '';
         $return941->ein = (isset($setup_data['ein']) and $setup_data['ein'] != '') ? $setup_data['ein'] : $current_company->getBusinessNumber();
         $return941->BusinessName1 = '';
         $return941->BusinessNameControl = '';
         $return941->AddressLine = (isset($setup_data['address1']) and $setup_data['address1'] != '') ? $setup_data['address1'] : $current_company->getAddress1() . ' ' . $current_company->getAddress2();
         $return941->City = (isset($setup_data['city']) and $setup_data['city'] != '') ? $setup_data['city'] : $current_company->getCity();
         $return941->State = (isset($setup_data['province']) and ($setup_data['province'] != '' and $setup_data['province'] != 0)) ? $setup_data['province'] : $current_company->getProvince();
         $return941->ZIPCode = (isset($setup_data['postal_code']) and $setup_data['postal_code'] != '') ? $setup_data['postal_code'] : $current_company->getPostalCode();
         $this->getFormObject()->addForm($return941);
     }
     $f941 = $this->getF941Object();
     $f941->setDebug(FALSE);
     $f941->setShowBackground($show_background);
     $f941->year = TTDate::getYear($filter_data['end_date']);
     //Add support for the user to manually set this data in the setup_data. That way they can use multiple tax IDs for different employees, all beit manually.
     $f941->ein = (isset($setup_data['ein']) and $setup_data['ein'] != '') ? $setup_data['ein'] : $current_company->getBusinessNumber();
     $f941->name = (isset($setup_data['name']) and $setup_data['name'] != '') ? $setup_data['name'] : $this->getUserObject()->getFullName();
     $f941->trade_name = (isset($setup_data['company_name']) and $setup_data['company_name'] != '') ? $setup_data['company_name'] : $current_company->getName();
     $f941->address = (isset($setup_data['address1']) and $setup_data['address1'] != '') ? $setup_data['address1'] : $current_company->getAddress1() . ' ' . $current_company->getAddress2();
     $f941->city = (isset($setup_data['city']) and $setup_data['city'] != '') ? $setup_data['city'] : $current_company->getCity();
     $f941->state = (isset($setup_data['province']) and ($setup_data['province'] != '' and $setup_data['province'] != 0)) ? $setup_data['province'] : $current_company->getProvince();
     $f941->zip_code = (isset($setup_data['postal_code']) and $setup_data['postal_code'] != '') ? $setup_data['postal_code'] : $current_company->getPostalCode();
     $f941->quarter = TTDate::getYearQuarter($filter_data['end_date']);
     //Debug::Arr($this->form_data, 'Final Data for Form: ', __FILE__, __LINE__, __METHOD__,10);
     if (isset($this->form_data) and count($this->form_data) == 3) {
         $f941->l1 = count($this->user_ids);
         $f941->l2 = $this->form_data['total']['l2'];
         $f941->l3 = $this->form_data['total']['l3'];
         $f941->l5a = $this->form_data['total']['l5a'];
         $f941->l5b = $this->form_data['total']['l5b'];
         $f941->l5c = $this->form_data['total']['l5c'];
         $f941->l5d = $this->form_data['total']['l5d'];
         if (isset($setup_data['quarter_deposit']) and $setup_data['quarter_deposit'] != '') {
             $f941->l11 = Misc::MoneyFormat($setup_data['quarter_deposit'], FALSE);
         }
         //Debug::Text('L11: '. $f941->l11 .' L6: '. $f941->calcL6() .' - '. $this->form_data['total']['l10'] , __FILE__, __LINE__, __METHOD__,10);
         $f941->l15b = TRUE;
         if (isset($setup_data['deposit_schedule']) and $setup_data['deposit_schedule'] == 10) {
             if (isset($this->form_data['quarter'][1]['l10'])) {
                 $f941->l16_month1 = $this->form_data['quarter'][1]['l10'];
             }
             if (isset($this->form_data['quarter'][2]['l10'])) {
                 $f941->l16_month2 = $this->form_data['quarter'][2]['l10'];
             }
             if (isset($this->form_data['quarter'][3]['l10'])) {
                 $f941->l16_month3 = $this->form_data['quarter'][3]['l10'];
             }
         } elseif (isset($setup_data['deposit_schedule']) and $setup_data['deposit_schedule'] == 20) {
             $f941sb = $this->getFormObject()->getFormObject('941sb', 'US');
             $f941sb->setShowBackground($show_background);
             $f941sb->year = $f941->year;
             $f941sb->ein = $f941->ein;
             $f941sb->name = $f941->name;
             $f941sb->quarter = $f941->quarter;
             for ($i = 1; $i <= 3; $i++) {
                 if (isset($this->form_data['pay_period'][$i])) {
                     foreach ($this->form_data['pay_period'][$i] as $pay_period_epoch => $data) {
                         //Debug::Text('SB: Month: '. $i .' Pay Period Date: '. TTDate::getDate('DATE', $pay_period_epoch) .' DOM: '. TTDate::getDayOfMonth($pay_period_epoch) .' Amount: '. $data['l10'], __FILE__, __LINE__, __METHOD__,10);
                         $f941sb_data[$i][TTDate::getDayOfMonth($pay_period_epoch)] = $data['l10'];
                         //Don't round this as it can cause mismatches in the totals.
                     }
                 }
             }
             if (isset($f941sb_data[1])) {
                 $f941sb->month1 = $f941sb_data[1];
             }
             if (isset($f941sb_data[2])) {
                 $f941sb->month2 = $f941sb_data[2];
             }
             if (isset($f941sb_data[3])) {
                 $f941sb->month3 = $f941sb_data[3];
             }
             unset($i, $d, $f941sb_data);
         }
     } else {
         Debug::Arr($this->data, 'Invalid Form Data: ', __FILE__, __LINE__, __METHOD__, 10);
     }
     $this->getFormObject()->addForm($f941);
     if (isset($f941sb) and is_object($f941sb)) {
         $this->getFormObject()->addForm($f941sb);
     }
     if ($format == 'efile_xml') {
         $output_format = 'XML';
         $file_name = '941_efile_' . date('Y_m_d') . '.xml';
         $mime_type = 'applications/octet-stream';
         //Force file to download.
     } else {
         $output_format = 'PDF';
         $file_name = $this->file_name;
         $mime_type = $this->file_mime_type;
     }
     $output = $this->getFormObject()->output($output_format);
     return $output;
 }