function _outputPDFForm($format = NULL)
 {
     $show_background = TRUE;
     if ($format == 'pdf_form_print' or $format == 'pdf_form_print_government' or $format == 'efile') {
         $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;
     }
     $current_user = $this->getUserObject();
     if (!is_object($current_user)) {
         Debug::Text('Invalid user object...', __FILE__, __LINE__, __METHOD__, 10);
         return FALSE;
     }
     if ($format == 'efile_xml') {
         $return1040 = $this->getRETURN1040Object();
         // Ceate the all needed data for Return1040.xsd at here.
         $return1040->return_created_timestamp = TTDate::getDBTimeStamp(TTDate::getTime(), FALSE);
         $return1040->year = TTDate::getYear($filter_data['end_date']);
         $return1040->tax_period_begin_date = TTDate::getDate('Y-m-d', TTDate::getBeginDayEpoch($filter_data['start_date']));
         $return1040->tax_period_end__date = TTDate::getDate('Y-m-d', TTDate::getEndDayEpoch($filter_data['end_date']));
         $return1040->software_id = '';
         $return1040->originator_efin = '';
         $return1040->originator_type_code = '';
         $return1040->pin_type_code = '';
         $return1040->jurat_disclosure_code = '';
         $return1040->pin_entered_by = '';
         $return1040->signature_date = TTDate::getDate('Y-m-d', TTDate::getTime());
         $return1040->return_type = '';
         $return1040->ssn = '';
         $return1040->name = (isset($setup_data['company_name']) and $setup_data['company_name'] != '') ? $setup_data['company_name'] : $current_company->getName();
         $return1040->name_control = '';
         $return1040->address1 = (isset($setup_data['address1']) and $setup_data['address1'] != '') ? $setup_data['address1'] : $current_company->getAddress1() . ' ' . $current_company->getAddress2();
         $return1040->city = (isset($setup_data['city']) and $setup_data['city'] != '') ? $setup_data['city'] : $current_company->getCity();
         $return1040->state = (isset($setup_data['province']) and ($setup_data['province'] != '' and $setup_data['province'] != 0)) ? $setup_data['province'] : $current_company->getProvince();
         $return1040->zip_code = (isset($setup_data['postal_code']) and $setup_data['postal_code'] != '') ? $setup_data['postal_code'] : $current_company->getPostalCode();
         $return1040->ip_address = '';
         $return1040->ip_date = TTDate::getDate('Y-m-d', TTDate::getTime());
         $return1040->ip_time = TTDate::getDate('H:i:s', TTDate::getTime());
         $return1040->timezone = TTDate::getTimeZone();
         $this->getFormObject()->addForm($return1040);
     }
     $this->sortFormData();
     //Make sure forms are sorted.
     $fw2 = $this->getFW2Object();
     $fw2->setDebug(FALSE);
     //if ( $format == 'efile' ) {
     //	$fw2->setDebug(TRUE);
     //}
     $fw2->setShowBackground($show_background);
     if (stristr($format, 'government')) {
         $form_type = 'government';
     } else {
         $form_type = 'employee';
     }
     Debug::Text('Form Type: ' . $form_type, __FILE__, __LINE__, __METHOD__, 10);
     $fw2->setType($form_type);
     $fw2->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.
     $fw2->ein = (isset($setup_data['ein']) and $setup_data['ein'] != '') ? $setup_data['ein'] : $current_company->getBusinessNumber();
     $fw2->name = (isset($setup_data['name']) and $setup_data['name'] != '') ? $setup_data['name'] : $this->getUserObject()->getFullName();
     $fw2->trade_name = (isset($setup_data['company_name']) and $setup_data['company_name'] != '') ? $setup_data['company_name'] : $current_company->getName();
     $fw2->company_address1 = (isset($setup_data['address1']) and $setup_data['address1'] != '') ? $setup_data['address1'] : $current_company->getAddress1() . ' ' . $current_company->getAddress2();
     $fw2->company_city = (isset($setup_data['city']) and $setup_data['city'] != '') ? $setup_data['city'] : $current_company->getCity();
     $fw2->company_state = (isset($setup_data['province']) and ($setup_data['province'] != '' and $setup_data['province'] != 0)) ? $setup_data['province'] : $current_company->getProvince();
     $fw2->company_zip_code = (isset($setup_data['postal_code']) and $setup_data['postal_code'] != '') ? $setup_data['postal_code'] : $current_company->getPostalCode();
     $fw2->efile_user_id = (isset($setup_data['efile_user_id']) and $setup_data['efile_user_id'] != '') ? $setup_data['efile_user_id'] : NULL;
     $fw2->efile_state = (isset($setup_data['efile_state']) and $setup_data['efile_state'] != '') ? $setup_data['efile_state'] : 0;
     $fw2->contact_name = $current_user->getFullName();
     $fw2->contact_phone = $current_user->getWorkPhone();
     $fw2->contact_phone_ext = $current_user->getWorkPhoneExt();
     $fw2->contact_email = $current_user->getWorkEmail();
     if (isset($this->form_data) and count($this->form_data) > 0) {
         $i = 0;
         $n = 1;
         foreach ((array) $this->form_data as $row) {
             if (!isset($row['user_id'])) {
                 Debug::Text('User ID not set!', __FILE__, __LINE__, __METHOD__, 10);
                 continue;
             }
             $ulf = TTnew('UserListFactory');
             $ulf->getById((int) $row['user_id']);
             if ($ulf->getRecordCount() == 1) {
                 $user_obj = $ulf->getCurrent();
                 $ee_data = array('control_number' => $n, 'first_name' => $user_obj->getFirstName(), 'middle_name' => $user_obj->getMiddleName(), 'last_name' => $user_obj->getLastName(), 'address1' => $user_obj->getAddress1(), 'address2' => $user_obj->getAddress2(), 'city' => $user_obj->getCity(), 'state' => $user_obj->getProvince(), 'employment_province' => $user_obj->getProvince(), 'zip_code' => $user_obj->getPostalCode(), 'ssn' => $user_obj->getSIN(), 'employee_number' => $user_obj->getEmployeeNumber(), 'l1' => $row['l1'], 'l2' => $row['l2'], 'l3' => $row['l3'], 'l4' => $row['l4'], 'l5' => $row['l5'], 'l6' => $row['l6'], 'l7' => $row['l7'], 'l8' => $row['l8'], 'l10' => $row['l10'], 'l11' => $row['l11'], 'l12a_code' => NULL, 'l12a' => NULL, 'l12b_code' => NULL, 'l12b' => NULL, 'l12c_code' => NULL, 'l12c' => NULL, 'l12d_code' => NULL, 'l12d' => NULL, 'l14a_name' => NULL, 'l14a' => NULL, 'l14b_name' => NULL, 'l14b' => NULL, 'l14c_name' => NULL, 'l14c' => NULL, 'l14d_name' => NULL, 'l14d' => NULL);
                 if ($row['l12a'] > 0 and isset($setup_data['l12a_code']) and $setup_data['l12a_code'] != '') {
                     $ee_data['l12a_code'] = $setup_data['l12a_code'];
                     $ee_data['l12a'] = $row['l12a'];
                 }
                 if ($row['l12b'] > 0 and isset($setup_data['l12b_code']) and $setup_data['l12b_code'] != '') {
                     $ee_data['l12b_code'] = $setup_data['l12b_code'];
                     $ee_data['l12b'] = $row['l12b'];
                 }
                 if ($row['l12c'] > 0 and isset($setup_data['l12c_code']) and $setup_data['l12c_code'] != '') {
                     $ee_data['l12c_code'] = $setup_data['l12c_code'];
                     $ee_data['l12c'] = $row['l12c'];
                 }
                 if ($row['l12d'] > 0 and isset($setup_data['l12d_code']) and $setup_data['l12d_code'] != '') {
                     $ee_data['l12d_code'] = $setup_data['l12d_code'];
                     $ee_data['l12d'] = $row['l12d'];
                 }
                 if ($row['l14a'] > 0 and isset($setup_data['l14a_name']) and $setup_data['l14a_name'] != '') {
                     $ee_data['l14a_name'] = $setup_data['l14a_name'];
                     $ee_data['l14a'] = $row['l14a'];
                 }
                 if ($row['l14b'] > 0 and isset($setup_data['l14b_name']) and $setup_data['l14b_name'] != '') {
                     $ee_data['l14b_name'] = $setup_data['l14b_name'];
                     $ee_data['l14b'] = $row['l14b'];
                 }
                 if ($row['l14c'] > 0 and isset($setup_data['l14c_name']) and $setup_data['l14c_name'] != '') {
                     $ee_data['l14c_name'] = $setup_data['l14c_name'];
                     $ee_data['l14c'] = $row['l14c'];
                 }
                 if ($row['l14d'] > 0 and isset($setup_data['l14d_name']) and $setup_data['l14d_name'] != '') {
                     $ee_data['l14d_name'] = $setup_data['l14d_name'];
                     $ee_data['l14d'] = $row['l14d'];
                 }
                 foreach (range('a', 'z') as $z) {
                     //State income tax
                     if (isset($row['l16' . $z])) {
                         if (isset($setup_data['state'][$row['l15' . $z . '_state']])) {
                             $ee_data['l15' . $z . '_state_id'] = $setup_data['state'][$row['l15' . $z . '_state']]['state_id'];
                         }
                         $ee_data['l15' . $z . '_state'] = $row['l15' . $z . '_state'];
                         $ee_data['l16' . $z] = $row['l16' . $z];
                         $ee_data['l17' . $z] = $row['l17' . $z];
                     } else {
                         $ee_data['l15' . $z . '_state_id'] = NULL;
                         $ee_data['l15' . $z . '_state'] = NULL;
                         $ee_data['l16' . $z] = NULL;
                         $ee_data['l17' . $z] = NULL;
                     }
                     //District income tax
                     if (isset($row['l18' . $z])) {
                         $ee_data['l18' . $z] = $row['l18' . $z];
                         $ee_data['l19' . $z] = $row['l19' . $z];
                         $ee_data['l20' . $z] = $row['l20' . $z];
                     } else {
                         $ee_data['l18' . $z] = NULL;
                         $ee_data['l19' . $z] = NULL;
                         $ee_data['l20' . $z] = NULL;
                     }
                 }
                 $fw2->addRecord($ee_data);
                 unset($ee_data);
                 $i++;
                 $n++;
             }
         }
     }
     $this->getFormObject()->addForm($fw2);
     if ($form_type == 'government') {
         //Handle W3
         $fw3 = $this->getFW3Object();
         $fw3->setShowBackground($show_background);
         $fw3->year = $fw2->year;
         $fw3->ein = $fw2->ein;
         $fw3->name = $fw2->name;
         $fw3->trade_name = $fw2->trade_name;
         $fw3->company_address1 = $fw2->company_address1;
         $fw3->company_address2 = $fw2->company_address2;
         $fw3->company_city = $fw2->company_city;
         $fw3->company_state = $fw2->company_state;
         $fw3->company_zip_code = $fw2->company_zip_code;
         $fw3->contact_name = $current_user->getFullName();
         $fw3->contact_phone = $current_user->getWorkPhoneExt() != '' ? $current_user->getWorkPhone() . 'x' . $current_user->getWorkPhoneExt() : $current_user->getWorkPhone();
         $fw3->contact_email = $current_user->getWorkEmail();
         $fw3->kind_of_payer = '941';
         $fw3->kind_of_employer = 'none';
         //$fw3->third_party_sick_pay = TRUE;
         if (isset($setup_data['state'][$fw2->company_state]) and isset($setup_data['state'][$fw2->company_state]['state_id']) and $setup_data['state'][$fw2->company_state]['state_id'] != '') {
             $fw3->state_id1 = $setup_data['state'][$fw2->company_state]['state_id'];
         }
         $fw3->lc = count($this->form_data);
         $fw3->control_number = $fw3->lc + 1;
         //$fw3->ld = '1234568';
         $total_row = Misc::ArrayAssocSum($this->form_data);
         //Debug::Arr($total_row, 'Total Row Data: ', __FILE__, __LINE__, __METHOD__,10);
         if (is_array($total_row)) {
             $fw3->l1 = $total_row['l1'];
             $fw3->l2 = $total_row['l2'];
             $fw3->l3 = $total_row['l3'];
             $fw3->l4 = $total_row['l4'];
             $fw3->l5 = $total_row['l5'];
             $fw3->l6 = $total_row['l6'];
             $fw3->l7 = $total_row['l7'];
             $fw3->l8 = $total_row['l8'];
             $fw3->l10 = $total_row['l10'];
             $fw3->l11 = $total_row['l11'];
             foreach (range('a', 'z') as $z) {
                 //State income tax
                 if (isset($total_row['l16' . $z])) {
                     $fw3->l16 += $total_row['l16' . $z];
                     $fw3->l17 += $total_row['l17' . $z];
                 }
                 //District income tax
                 if (isset($total_row['l18' . $z])) {
                     $fw3->l18 += $total_row['l18' . $z];
                     $fw3->l19 += $total_row['l19' . $z];
                 }
             }
         }
         $this->getFormObject()->addForm($fw3);
     }
     if ($format == 'efile') {
         $output_format = 'EFILE';
         if ($fw2->getDebug() == TRUE) {
             $file_name = 'w2_efile_' . date('Y_m_d') . '.csv';
         } else {
             $file_name = 'w2_efile_' . date('Y_m_d') . '.txt';
         }
         $mime_type = 'applications/octet-stream';
         //Force file to download.
     } elseif ($format == 'efile_xml') {
         $output_format = 'XML';
         $file_name = 'w2_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 array('file_name' => $file_name, 'mime_type' => $mime_type, 'data' => $output);
 }
 function createNextPayPeriod($end_date = NULL, $offset = NULL)
 {
     if ($end_date == NULL or $end_date == '') {
         $end_date = NULL;
     }
     if ($offset == NULL or $offset == '') {
         $offset = 86400;
         //24hrs
     }
     if ($this->getType() == 5) {
         return FALSE;
     }
     Debug::text('Current TimeZone: ' . TTDate::getTimeZone(), __FILE__, __LINE__, __METHOD__, 10);
     //Handle timezones in this function rather then getNextPayPeriod()
     //Because if we set the timezone back to the original in that function, it
     //gets written to the database in the "original" timezone, not the proper timezone.
     $this->setPayPeriodTimeZone();
     Debug::text('Pay Period TimeZone: ' . TTDate::getTimeZone(), __FILE__, __LINE__, __METHOD__, 10);
     Debug::text('End Date (' . $end_date . '): ' . TTDate::getDate('DATE+TIME', $end_date), __FILE__, __LINE__, __METHOD__, 10);
     $this->getNextPayPeriod($end_date);
     Debug::text('Next pay period starts: ' . TTDate::getDate('DATE+TIME', $this->getNextStartDate()), __FILE__, __LINE__, __METHOD__, 10);
     //If the start date is within 24hrs of now, insert the next pay period.
     if ($this->getNextStartDate() <= TTDate::getTime() + $offset) {
         Debug::text('Insert new pay period. Start Date: ' . $this->getNextStartDate() . ' End Date: ' . $this->getNextEndDate(), __FILE__, __LINE__, __METHOD__, 10);
         $ppf = new PayPeriodFactory();
         $ppf->setCompany($this->getCompany());
         $ppf->setPayPeriodSchedule($this->getId());
         $ppf->setStatus(10);
         $ppf->setStartDate($this->getNextStartDate());
         $ppf->setEndDate($this->getNextEndDate());
         $ppf->setTransactionDate($this->getNextTransactionDate());
         $ppf->setPrimary($this->getNextPrimary());
         $ppf->setEnableImportData(TRUE);
         //Import punches when creating new pay periods.
         if ($ppf->isValid()) {
             $new_pay_period_id = $ppf->Save();
             Debug::text('New Pay Period ID: ' . $new_pay_period_id, __FILE__, __LINE__, __METHOD__, 10);
             if ($new_pay_period_id != '') {
                 $this->setOriginalTimeZone();
                 return TRUE;
             } else {
                 Debug::text('aSaving Pay Period Failed!', __FILE__, __LINE__, __METHOD__, 10);
             }
         } else {
             Debug::text('bSaving Pay Period Failed!', __FILE__, __LINE__, __METHOD__, 10);
         }
     } else {
         Debug::text('***NOT inserting or changing status of new pay period yet, not within offset.', __FILE__, __LINE__, __METHOD__, 10);
     }
     $this->setOriginalTimeZone();
     return FALSE;
 }
 function calcSystemTotalTime()
 {
     global $profiler;
     $profiler->startTimer('UserDateTotal::calcSystemTotalTime() - Part 1');
     if (!is_object($this->getUserDateObject())) {
         Debug::text(' UserDateObject not found!', __FILE__, __LINE__, __METHOD__, 10);
         return FALSE;
     }
     if (is_object($this->getUserDateObject()) and is_object($this->getUserDateObject()->getPayPeriodObject()) and $this->getUserDateObject()->getPayPeriodObject()->getStatus() == 20) {
         Debug::text(' Pay Period is closed!', __FILE__, __LINE__, __METHOD__, 10);
         return FALSE;
     }
     //IMPORTANT: Make sure the timezone is set to the users timezone, prior to calculating policies,
     //as that will affect when date/time premium policies apply
     //Its also important that the timezone gets set back after calculating multiple punches in a batch as this can prevent other employees
     //from using the wrong timezone.
     //FIXME: How do we handle the employee moving between stations that themselves are in different timezones from the users default timezone?
     //How do we apply time based premium policies in that case?
     if (is_object($this->getUserDateObject()) and is_object($this->getUserDateObject()->getUserObject()) and is_object($this->getUserDateObject()->getUserObject()->getUserPreferenceObject())) {
         $original_time_zone = TTDate::getTimeZone();
         TTDate::setTimeZone($this->getUserDateObject()->getUserObject()->getUserPreferenceObject()->getTimeZone());
     }
     //Take the worked hours, and calculate Total,Regular,Overtime,Premium hours from that.
     //This is where many of the policies will be applied
     //Such as any meal/overtime/premium policies.
     $return_value = FALSE;
     $udtlf = TTnew('UserDateTotalListFactory');
     $this->deleteSystemTotalTime();
     //We can't assign a dock absence to a given branch/dept automatically,
     //Because several punches with different branches could fall within a schedule punch pair.
     //Just total up entire day, and entire scheduled time to see if we're over/under
     //FIXME: Handle multiple schedules on a single day better.
     $schedule_total_time = 0;
     $meal_policy_ids = NULL;
     $break_policy_ids = NULL;
     $slf = TTnew('ScheduleListFactory');
     $profiler->startTimer('UserDateTotal::calcSystemTotalTime() - Holiday');
     //Check for Holidays
     $holiday_time = 0;
     $hlf = TTnew('HolidayListFactory');
     $hlf->getByPolicyGroupUserIdAndDate($this->getUserDateObject()->getUser(), $this->getUserDateObject()->getDateStamp());
     if ($hlf->getRecordCount() > 0) {
         $holiday_obj = $hlf->getCurrent();
         Debug::text(' Found Holiday: ' . $holiday_obj->getName(), __FILE__, __LINE__, __METHOD__, 10);
         if ($holiday_obj->isEligible($this->getUserDateObject()->getUser())) {
             Debug::text(' User is Eligible for Holiday: ' . $holiday_obj->getName(), __FILE__, __LINE__, __METHOD__, 10);
             $holiday_time = $holiday_obj->getHolidayTime($this->getUserDateObject()->getUser());
             Debug::text(' User average time for Holiday: ' . TTDate::getHours($holiday_time), __FILE__, __LINE__, __METHOD__, 10);
             if ($holiday_time > 0 and $holiday_obj->getHolidayPolicyObject()->getAbsencePolicyID() != FALSE) {
                 Debug::text(' Adding Holiday hours: ' . TTDate::getHours($holiday_time), __FILE__, __LINE__, __METHOD__, 10);
                 $udtf = TTnew('UserDateTotalFactory');
                 $udtf->setUserDateID($this->getUserDateID());
                 $udtf->setStatus(30);
                 //Absence
                 $udtf->setType(10);
                 //Total
                 $udtf->setBranch($this->getUserDateObject()->getUserObject()->getDefaultBranch());
                 $udtf->setDepartment($this->getUserDateObject()->getUserObject()->getDefaultDepartment());
                 $udtf->setAbsencePolicyID($holiday_obj->getHolidayPolicyObject()->getAbsencePolicyID());
                 $udtf->setTotalTime($holiday_time);
                 $udtf->setEnableCalcSystemTotalTime(FALSE);
                 if ($udtf->isValid()) {
                     $udtf->Save();
                 }
             }
         }
         $slf->getByUserDateIdAndStatusId($this->getUserDateID(), 20);
         $schedule_absence_total_time = 0;
         if ($slf->getRecordCount() > 0) {
             //Check for schedule policy
             foreach ($slf as $s_obj) {
                 Debug::text(' Schedule Absence Total Time: ' . $s_obj->getTotalTime(), __FILE__, __LINE__, __METHOD__, 10);
                 $schedule_absence_total_time += $s_obj->getTotalTime();
                 if (is_object($s_obj->getSchedulePolicyObject()) and $s_obj->getSchedulePolicyObject()->getAbsencePolicyID() > 0) {
                     $holiday_absence_policy_id = $s_obj->getSchedulePolicyObject()->getAbsencePolicyID();
                     Debug::text(' Found Absence Policy for docking: ' . $holiday_absence_policy_id, __FILE__, __LINE__, __METHOD__, 10);
                 } else {
                     Debug::text(' NO Absence Policy : ', __FILE__, __LINE__, __METHOD__, 10);
                 }
             }
         }
         $holiday_total_under_time = $schedule_absence_total_time - $holiday_time;
         if (isset($holiday_absence_policy_id) and $holiday_total_under_time > 0) {
             Debug::text(' Schedule Under Time Case: ' . $holiday_total_under_time, __FILE__, __LINE__, __METHOD__, 10);
             $udtf = TTnew('UserDateTotalFactory');
             $udtf->setUserDateID($this->getUserDateID());
             $udtf->setStatus(30);
             //Absence
             $udtf->setType(10);
             //Total
             $udtf->setBranch($this->getUserDateObject()->getUserObject()->getDefaultBranch());
             $udtf->setDepartment($this->getUserDateObject()->getUserObject()->getDefaultDepartment());
             $udtf->setAbsencePolicyID($holiday_absence_policy_id);
             $udtf->setTotalTime($holiday_total_under_time);
             $udtf->setEnableCalcSystemTotalTime(FALSE);
             if ($udtf->isValid()) {
                 $udtf->Save();
             }
         }
         unset($holiday_total_under_time, $holiday_absence_policy_id, $schedule_absence_total_time);
     }
     $profiler->stopTimer('UserDateTotal::calcSystemTotalTime() - Holiday');
     //Do this after holiday policies have been applied, so if someone
     //schedules a holiday manually, we don't double up on the time.
     $slf->getByUserDateId($this->getUserDateID());
     if ($slf->getRecordCount() > 0) {
         //Check for schedule policy
         foreach ($slf as $s_obj) {
             Debug::text(' Schedule Total Time: ' . $s_obj->getTotalTime(), __FILE__, __LINE__, __METHOD__, 10);
             if ($s_obj->getStatus() == 20 and $s_obj->getAbsencePolicyID() != '') {
                 Debug::text(' Scheduled Absence Found of Total Time: ' . $s_obj->getTotalTime(), __FILE__, __LINE__, __METHOD__, 10);
                 //If a holiday policy is applied on this day, ignore the schedule so we don't duplicate it.
                 //We could take the difference, and use the greatest of the two,
                 //But I think that will just open the door for errors.
                 if (!isset($holiday_obj) or $holiday_time == 0 and is_object($holiday_obj) and $holiday_obj->getHolidayPolicyObject()->getAbsencePolicyID() != $s_obj->getAbsencePolicyID()) {
                     $udtf = TTnew('UserDateTotalFactory');
                     $udtf->setUserDateID($this->getUserDateID());
                     $udtf->setStatus(30);
                     //Absence
                     $udtf->setType(10);
                     //Total
                     $udtf->setBranch($s_obj->getBranch());
                     $udtf->setDepartment($s_obj->getDepartment());
                     $udtf->setJob($s_obj->getJob());
                     $udtf->setJobItem($s_obj->getJobItem());
                     $udtf->setAbsencePolicyID($s_obj->getAbsencePolicyID());
                     $udtf->setTotalTime($s_obj->getTotalTime());
                     $udtf->setEnableCalcSystemTotalTime(FALSE);
                     if ($udtf->isValid()) {
                         $udtf->Save();
                     }
                 } else {
                     Debug::text(' Holiday Time Found, ignoring schedule!', __FILE__, __LINE__, __METHOD__, 10);
                 }
             }
             /*
             elseif ( $s_obj->getStatus() == 10 ) {
             
             	$schedule_policy_ids[] = $s_obj->getSchedulePolicyID(); //Save schedule policies ID so we can passs them onto Premium Policies.
             
             	$schedule_total_time += $s_obj->getTotalTime();
             	if ( is_object($s_obj->getSchedulePolicyObject() ) ) {
             		$schedule_absence_policy_id = $s_obj->getSchedulePolicyObject()->getAbsencePolicyID();
             		$meal_policy_obj = $s_obj->getSchedulePolicyObject()->getMealPolicyObject();
             		Debug::text(' Found Absence Policy for docking: '. $schedule_absence_policy_id, __FILE__, __LINE__, __METHOD__,10);
             	} else {
             		Debug::text(' NO Absence Policy : ', __FILE__, __LINE__, __METHOD__,10);
             	}
             }
             */
         }
     } else {
         Debug::text(' No Schedules found. ', __FILE__, __LINE__, __METHOD__, 10);
     }
     unset($s_obj);
     unset($holiday_time, $holiday_obj);
     //Loop through punches on this day finding matching schedules.
     //Since schedules and punches may or may not fall on the same day, (there are always cases where they may not, due to employees coming in late) this is the only real way to match them properly.
     //This can happen even with assign shifts to the day they start on, if an employees shift starts at 11PM and they are 1.5hrs late, or if the shift starts at 12:30AM and they are 30 mins early.
     $schedule_policy_ids = array();
     $plf = TTnew('PunchListFactory');
     $plf->getByUserDateId($this->getUserDateID());
     if ($plf->getRecordCount() > 0) {
         foreach ($plf as $p_obj) {
             $schedule_ids[] = $p_obj->findScheduleID(NULL, $this->getUserDateObject()->getUser());
         }
     } else {
         //Debug::text(' No Punches found, grabbing all schedules on this day...', __FILE__, __LINE__, __METHOD__,10);
         //FIXME: If no punches are on a specific day, then its schedules are not even considered.
         //This breaks undertime absences, since they should have a full day of absence time but instead they won't have any.
         //It also doesn't work properly with split shifts, where the employee works the first part but not the 2nd part and should get undertime absence for the 2nd.
         //However if we handle it this way, the same scheduled shift can accounted for twice when the schedule and punches fall on different days.
         /*
         $slf->getByUserDateId( $this->getUserDateID() );
         if ( $slf->getRecordCount() > 0 ) {
         	//Check for schedule policy
         	foreach ( $slf as $s_obj ) {
         		$schedule_ids[] = $s_obj->getId();
         	}
         }
         */
     }
     if (isset($schedule_ids)) {
         $slf->getByCompanyIDAndId($this->getUserDateObject()->getUserObject()->getCompany(), array_unique((array) $schedule_ids));
         if ($slf->getRecordCount() > 0) {
             foreach ($slf as $s_obj) {
                 //Save schedule policies ID so we can pass them onto Premium Policies.
                 //Do this for both working and absence schedules, for purposes of calculating premium when employees are not scheduled.
                 $schedule_policy_ids[] = $s_obj->getSchedulePolicyID();
                 if ($s_obj->getStatus() == 10) {
                     $schedule_total_time += $s_obj->getTotalTime();
                     if (is_object($s_obj->getSchedulePolicyObject())) {
                         $schedule_absence_policy_id = $s_obj->getSchedulePolicyObject()->getAbsencePolicyID();
                         $meal_policy_ids = $s_obj->getSchedulePolicyObject()->getMealPolicyID();
                         $break_policy_ids = $s_obj->getSchedulePolicyObject()->getBreakPolicy();
                         Debug::text(' Found Absence Policy for docking: ' . $schedule_absence_policy_id, __FILE__, __LINE__, __METHOD__, 10);
                     } else {
                         Debug::text(' NO Absence Policy : ', __FILE__, __LINE__, __METHOD__, 10);
                     }
                 }
             }
         }
     }
     unset($plf, $p_obj, $s_obj, $slf, $schedule_ids);
     //Handle Meal Policy time.
     //Do this after schedule meal policies have been looked up, as those override any policy group meal policies.
     $meal_policy_time = $this->calcMealPolicyTotalTime($meal_policy_ids);
     $udt_meal_policy_adjustment_arr = $this->calcUserTotalMealPolicyAdjustment($meal_policy_time);
     //Debug::Arr($udt_meal_policy_adjustment_arr, 'UserDateTotal Meal Policy Adjustment: ', __FILE__, __LINE__, __METHOD__,10);
     $break_policy_time = $this->calcBreakPolicyTotalTime($break_policy_ids);
     $udt_break_policy_adjustment_arr = $this->calcUserTotalBreakPolicyAdjustment($break_policy_time);
     //Debug::Arr($udt_break_policy_adjustment_arr, 'UserDateTotal Break Policy Adjustment: ', __FILE__, __LINE__, __METHOD__,10);
     $daily_total_time = $this->getDailyTotalTime();
     Debug::text(' Daily Total Time: ' . $daily_total_time . ' Schedule Total Time: ' . $schedule_total_time, __FILE__, __LINE__, __METHOD__, 10);
     //Check for overtime policies or undertime absence policies
     if ($daily_total_time > $schedule_total_time) {
         Debug::text(' Schedule Over Time Case: ', __FILE__, __LINE__, __METHOD__, 10);
     } elseif (isset($schedule_absence_policy_id) and $schedule_absence_policy_id != '' and $daily_total_time < $schedule_total_time) {
         $total_under_time = bcsub($schedule_total_time, $daily_total_time);
         if ($total_under_time > 0) {
             Debug::text(' Schedule Under Time Case: ' . $total_under_time . ' Absence Policy ID: ' . $schedule_absence_policy_id, __FILE__, __LINE__, __METHOD__, 10);
             $udtf = TTnew('UserDateTotalFactory');
             $udtf->setUserDateID($this->getUserDateID());
             $udtf->setStatus(30);
             //Absence
             $udtf->setType(10);
             //Total
             $udtf->setBranch($this->getUserDateObject()->getUserObject()->getDefaultBranch());
             $udtf->setDepartment($this->getUserDateObject()->getUserObject()->getDefaultDepartment());
             $udtf->setAbsencePolicyID($schedule_absence_policy_id);
             $udtf->setTotalTime($total_under_time);
             $udtf->setEnableCalcSystemTotalTime(FALSE);
             if ($udtf->isValid()) {
                 $udtf->Save();
             }
         } else {
             Debug::text(' Schedule Under Time is a negative value, skipping dock time: ' . $total_under_time . ' Absence Policy ID: ' . $schedule_absence_policy_id, __FILE__, __LINE__, __METHOD__, 10);
         }
     } else {
         Debug::text(' No Dock Absenses', __FILE__, __LINE__, __METHOD__, 10);
     }
     unset($schedule_absence_policy_id);
     /*
     //This is no longer needed as calcAbsencePolicyTotalTime() is a NO-OP now.
     //Do this AFTER the UnderTime absence policy is submitted.
     $recalc_daily_total_time = $this->calcAbsencePolicyTotalTime();
     if ( $recalc_daily_total_time == TRUE ) {
     	//Total up all "worked" hours for the day again, this time include
     	//Paid Absences.
     	$daily_total_time = $this->getDailyTotalTime();
     	Debug::text('ReCalc Daily Total Time for Day: '. $daily_total_time, __FILE__, __LINE__, __METHOD__, 10);
     }
     */
     $profiler->stopTimer('UserDateTotal::calcSystemTotalTime() - Part 1');
     $user_data_total_compact_arr = $this->calcOverTimePolicyTotalTime($udt_meal_policy_adjustment_arr, $udt_break_policy_adjustment_arr);
     //Debug::Arr($user_data_total_compact_arr, 'User Data Total Compact Array: ', __FILE__, __LINE__, __METHOD__, 10);
     //Insert User Date Total rows for each compacted array entry.
     //The reason for compacting is to reduce the amount of rows as much as possible.
     if (is_array($user_data_total_compact_arr)) {
         $profiler->startTimer('UserDateTotal::calcSystemTotalTime() - Part 2');
         Debug::text('Compact Array Exists: ', __FILE__, __LINE__, __METHOD__, 10);
         foreach ($user_data_total_compact_arr as $type_id => $udt_arr) {
             Debug::text('Compact Array Entry: Type ID: ' . $type_id, __FILE__, __LINE__, __METHOD__, 10);
             if ($type_id == 20) {
                 //Regular Time
                 //Debug::text('Compact Array Entry: Branch ID: '. $udt_arr[' , __FILE__, __LINE__, __METHOD__, 10);
                 foreach ($udt_arr as $branch_id => $branch_arr) {
                     //foreach($branch_arr as $department_id => $total_time ) {
                     foreach ($branch_arr as $department_id => $department_arr) {
                         foreach ($department_arr as $job_id => $job_arr) {
                             foreach ($job_arr as $job_item_id => $data_arr) {
                                 Debug::text('Compact Array Entry: Regular Time - Branch ID: ' . $branch_id . ' Department ID: ' . $department_id . ' Job ID: ' . $job_id . ' Job Item ID: ' . $job_item_id . ' Total Time: ' . $data_arr['total_time'], __FILE__, __LINE__, __METHOD__, 10);
                                 $user_data_total_expanded[] = array('type_id' => $type_id, 'over_time_policy_id' => NULL, 'branch_id' => $branch_id, 'department_id' => $department_id, 'job_id' => $job_id, 'job_item_id' => $job_item_id, 'total_time' => $data_arr['total_time'], 'quantity' => $data_arr['quantity'], 'bad_quantity' => $data_arr['bad_quantity']);
                             }
                         }
                     }
                 }
             } else {
                 //Overtime
                 //Overtime array is completely different then regular time array!
                 foreach ($udt_arr as $over_time_policy_id => $policy_arr) {
                     foreach ($policy_arr as $branch_id => $branch_arr) {
                         //foreach($branch_arr as $department_id => $total_time ) {
                         foreach ($branch_arr as $department_id => $department_arr) {
                             foreach ($department_arr as $job_id => $job_arr) {
                                 foreach ($job_arr as $job_item_id => $data_arr) {
                                     Debug::text('Compact Array Entry: Policy ID: ' . $over_time_policy_id . ' Branch ID: ' . $branch_id . ' Department ID: ' . $department_id . ' Job ID: ' . $job_id . ' Job Item ID: ' . $job_item_id . ' Total Time: ' . $data_arr['total_time'], __FILE__, __LINE__, __METHOD__, 10);
                                     $user_data_total_expanded[] = array('type_id' => $type_id, 'over_time_policy_id' => $over_time_policy_id, 'branch_id' => $branch_id, 'department_id' => $department_id, 'job_id' => $job_id, 'job_item_id' => $job_item_id, 'total_time' => $data_arr['total_time'], 'quantity' => $data_arr['quantity'], 'bad_quantity' => $data_arr['bad_quantity']);
                                 }
                             }
                         }
                     }
                 }
             }
             unset($policy_arr, $branch_arr, $department_arr, $job_arr, $over_time_policy_id, $branch_id, $department_id, $job_id, $job_item_id, $data_arr);
         }
         $profiler->stopTimer('UserDateTotal::calcSystemTotalTime() - Part 2');
         //var_dump($user_data_total_expanded);
         //Do the actual inserts now.
         if (isset($user_data_total_expanded)) {
             foreach ($user_data_total_expanded as $data_arr) {
                 $profiler->startTimer('UserDateTotal::calcSystemTotalTime() - Part 2b');
                 Debug::text('Inserting from expanded array, Type ID: ' . $data_arr['type_id'], __FILE__, __LINE__, __METHOD__, 10);
                 $udtf = TTnew('UserDateTotalFactory');
                 $udtf->setUserDateID($this->getUserDateID());
                 $udtf->setStatus(10);
                 //System
                 $udtf->setType($data_arr['type_id']);
                 if (isset($data_arr['over_time_policy_id'])) {
                     $udtf->setOverTimePolicyId($data_arr['over_time_policy_id']);
                 }
                 $udtf->setBranch($data_arr['branch_id']);
                 $udtf->setDepartment($data_arr['department_id']);
                 $udtf->setJob($data_arr['job_id']);
                 $udtf->setJobItem($data_arr['job_item_id']);
                 $udtf->setQuantity($data_arr['quantity']);
                 $udtf->setBadQuantity($data_arr['bad_quantity']);
                 $udtf->setTotalTime($data_arr['total_time']);
                 $udtf->setEnableCalcSystemTotalTime(FALSE);
                 if ($udtf->isValid()) {
                     $udtf->Save();
                 } else {
                     Debug::text('aINVALID UserDateTotal Entry!!: ', __FILE__, __LINE__, __METHOD__, 10);
                 }
                 $profiler->stopTimer('UserDateTotal::calcSystemTotalTime() - Part 2b');
             }
             unset($user_data_total_expanded);
         }
     } else {
         $profiler->startTimer('UserDateTotal::calcSystemTotalTime() - Part 3');
         //We need to break this out by branch, dept, job, task
         $udtlf = TTnew('UserDateTotalListFactory');
         //FIXME: Should Absence time be included as "regular time". We do this on
         //the timesheet view manually as of 12-Jan-06. If we included it in the
         //regular time system totals, we wouldn't have to do it manually.
         //$udtlf->getByUserDateIdAndStatus( $this->getUserDateID(), array(20,30) );
         $udtlf->getByUserDateIdAndStatus($this->getUserDateID(), array(20));
         if ($udtlf->getRecordCount() > 0) {
             Debug::text('Found Total Hours for just regular time: Record Count: ' . $udtlf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
             $user_date_regular_time_compact_arr = NULL;
             foreach ($udtlf as $udt_obj) {
                 //Create compact array, so we don't make as many system entries.
                 //Check if this is a paid absence or not.
                 if ($udt_obj->getStatus() == 20 and $udt_obj->getTotalTime() > 0) {
                     $udt_total_time = $udt_obj->getTotalTime();
                     if (isset($udt_meal_policy_adjustment_arr[$udt_obj->getId()])) {
                         $udt_total_time = bcadd($udt_total_time, $udt_meal_policy_adjustment_arr[$udt_obj->getId()]);
                     }
                     if (isset($udt_break_policy_adjustment_arr[$udt_obj->getId()])) {
                         $udt_total_time = bcadd($udt_total_time, $udt_break_policy_adjustment_arr[$udt_obj->getId()]);
                     }
                     if (isset($user_date_regular_time_compact_arr[(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()])) {
                         Debug::text('     Adding to Compact Array: Regular Time -  Branch: ' . (int) $udt_obj->getBranch() . ' Department: ' . (int) $udt_obj->getDepartment(), __FILE__, __LINE__, __METHOD__, 10);
                         $user_date_regular_time_compact_arr[(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()]['total_time'] += $udt_total_time;
                         $user_date_regular_time_compact_arr[(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()]['quantity'] += $udt_obj->getQuantity();
                         $user_date_regular_time_compact_arr[(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()]['bad_quantity'] += $udt_obj->getBadQuantity();
                     } else {
                         $user_date_regular_time_compact_arr[(int) $udt_obj->getBranch()][(int) $udt_obj->getDepartment()][(int) $udt_obj->getJob()][(int) $udt_obj->getJobItem()] = array('total_time' => $udt_total_time, 'quantity' => $udt_obj->getQuantity(), 'bad_quantity' => $udt_obj->getBadQuantity());
                     }
                     unset($udt_total_time);
                 } else {
                     Debug::text('Total Time is 0!!: ' . $udt_obj->getTotalTime() . ' Or its an UNPAID absence: ' . $udt_obj->getStatus(), __FILE__, __LINE__, __METHOD__, 10);
                 }
             }
             if (isset($user_date_regular_time_compact_arr)) {
                 foreach ($user_date_regular_time_compact_arr as $branch_id => $branch_arr) {
                     //foreach($branch_arr as $department_id => $total_time ) {
                     foreach ($branch_arr as $department_id => $department_arr) {
                         foreach ($department_arr as $job_id => $job_arr) {
                             foreach ($job_arr as $job_item_id => $data_arr) {
                                 Debug::text('Compact Array Entry: bRegular Time - Branch ID: ' . $branch_id . ' Department ID: ' . $department_id . ' Job ID: ' . $job_id . ' Job Item ID: ' . $job_item_id . ' Total Time: ' . $data_arr['total_time'], __FILE__, __LINE__, __METHOD__, 10);
                                 $udtf = TTnew('UserDateTotalFactory');
                                 $udtf->setUserDateID($this->getUserDateID());
                                 $udtf->setStatus(10);
                                 //System
                                 $udtf->setType(20);
                                 //Regular
                                 $udtf->setBranch($branch_id);
                                 $udtf->setDepartment($department_id);
                                 $udtf->setJob($job_id);
                                 $udtf->setJobItem($job_item_id);
                                 $udtf->setQuantity($data_arr['quantity']);
                                 $udtf->setBadQuantity($data_arr['bad_quantity']);
                                 $udtf->setTotalTime($data_arr['total_time']);
                                 $udtf->setEnableCalcSystemTotalTime(FALSE);
                                 $udtf->Save();
                             }
                         }
                     }
                 }
             }
             unset($user_date_regular_time_compact_arr);
         }
     }
     //Handle Premium time.
     $this->calcPremiumPolicyTotalTime($udt_meal_policy_adjustment_arr, $udt_break_policy_adjustment_arr, $daily_total_time, $schedule_policy_ids);
     //Total Hours
     $udtf = TTnew('UserDateTotalFactory');
     $udtf->setUserDateID($this->getUserDateID());
     $udtf->setStatus(10);
     //System
     $udtf->setType(10);
     //Total
     $udtf->setTotalTime($daily_total_time);
     $udtf->setEnableCalcSystemTotalTime(FALSE);
     if ($udtf->isValid()) {
         $return_value = $udtf->Save();
     } else {
         $return_value = FALSE;
     }
     $profiler->stopTimer('UserDateTotal::calcSystemTotalTime() - Part 3');
     if ($this->getEnableCalcException() == TRUE) {
         ExceptionPolicyFactory::calcExceptions($this->getUserDateID(), $this->getEnablePreMatureException());
     }
     if (isset($original_time_zone)) {
         TTDate::setTimeZone($original_time_zone);
     }
     return $return_value;
 }