/**
 * Smarty plugin
 * @package Smarty
 * @subpackage plugins
 */
function smarty_function_gettimeunit($params, &$smarty)
{
    $value = $params['value'];
    $default = $params['default'];
    $abs = $params['abs'];
    //var_dump($default);
    if ($default == 'TRUE') {
        $default = 'N/A';
    } elseif ($default == '0') {
        if ($value === FALSE or $value === NULL) {
            $value = 0;
        }
    } else {
        $default = NULL;
    }
    if ($abs == 'TRUE') {
        $value = abs($value);
    }
    //var_dump($value);
    //Make sure the default is set to TRUE to get "N/A"
    if ($value === FALSE or $value === NULL) {
        return $default;
    }
    $retval = TTDate::getTimeUnit($value);
    return $retval;
}
示例#2
0
         $rows = Sort::Multisort($tmp_rows, Misc::trimSortPrefix($filter_data['primary_sort']), Misc::trimSortPrefix($filter_data['secondary_sort']), $filter_data['primary_sort_dir'], $filter_data['secondary_sort_dir']);
         $total_row = Misc::ArrayAssocSum($rows, NULL, 2);
         $last_row = count($rows);
         $rows[$last_row] = $total_row;
         foreach ($static_columns as $static_column_key => $static_column_val) {
             $rows[$last_row][Misc::trimSortPrefix($static_column_key)] = NULL;
         }
         unset($static_column_key, $static_column_val);
         //Convert units
         $tmp_rows = $rows;
         unset($rows);
         $trimmed_static_columns = array_keys(Misc::trimSortPrefix($static_columns));
         foreach ($tmp_rows as $row) {
             foreach ($row as $column => $column_data) {
                 if (!strstr($column, 'wage') and !strstr($column, 'worked_days') and !in_array($column, $trimmed_static_columns)) {
                     $column_data = TTDate::getTimeUnit($column_data);
                 }
                 $row_columns[$column] = $column_data;
                 unset($column, $column_data);
             }
             $rows[] = $row_columns;
             unset($row_columns);
         }
     }
 }
 //var_dump($rows);
 foreach ($filter_data['column_ids'] as $column_key) {
     $filter_columns[Misc::trimSortPrefix($column_key)] = $columns[$column_key];
 }
 if ($action == 'export') {
     if (isset($rows) and isset($filter_columns)) {
 function Validate()
 {
     Debug::text('Validating...', __FILE__, __LINE__, __METHOD__, 10);
     //Call this here so getShiftData can get the correct total time, before we call findUserDate.
     if ($this->getEnableCalcTotalTime() == TRUE) {
         $this->calcTotalTime();
     }
     if (is_object($this->getPunchObject())) {
         $this->findUserDate();
     }
     Debug::text('User Date Id: ' . $this->getUserDateID(), __FILE__, __LINE__, __METHOD__, 10);
     if ($this->getUserDateObject() == FALSE or $this->getUserDateObject()->getPayPeriodObject() == FALSE) {
         $this->Validator->isTRUE('pay_period', FALSE, TTi18n::gettext('Date/Time is incorrect, or pay period does not exist for this date. Please create a pay period schedule if you have not done so already'));
     } elseif ($this->getUserDateObject() == FALSE or $this->getUserDateObject()->getPayPeriodObject()->getIsLocked() == TRUE) {
         $this->Validator->isTRUE('pay_period', FALSE, TTi18n::gettext('Pay Period is Currently Locked'));
     }
     $plf = $this->getPLFByPunchControlID();
     if ($plf !== NULL and ($this->isNew() and $plf->getRecordCount() == 2 or $plf->getRecordCount() > 2)) {
         //TTi18n::gettext('Punch Control can not have more than two punches. Please use the Add Punch button instead')
         //They might be trying to insert a punch inbetween two others?
         $this->Validator->isTRUE('punch_control', FALSE, TTi18n::gettext('Time conflicts with another punch on this day (c)'));
     }
     //Skip these checks if they are deleting a punch.
     if (is_object($this->getPunchObject()) and $this->getPunchObject()->getDeleted() == FALSE) {
         $shift_data = $this->getShiftData();
         if (is_array($shift_data)) {
             foreach ($shift_data['punches'] as $punch_data) {
                 //Make sure there aren't two In punches, or two Out punches in the same pair.
                 //This fixes the bug where if you have an In punch, then click the blank cell below it
                 //to add a new punch, but change the status from Out to In instead.
                 if (isset($punches[$punch_data['punch_control_id']][$punch_data['status_id']])) {
                     if ($punch_data['status_id'] == 10) {
                         $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('In punches cannot occur twice in the same punch pair, you may want to make this an out punch instead'));
                     } else {
                         $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('Out punches cannot occur twice in the same punch pair, you may want to make this an in punch instead'));
                     }
                 }
                 Debug::text(' Current Punch Object: ID: ' . $this->getPunchObject()->getId() . ' TimeStamp: ' . $this->getPunchObject()->getTimeStamp() . ' Status: ' . $this->getPunchObject()->getStatus(), __FILE__, __LINE__, __METHOD__, 10);
                 Debug::text(' Looping Punch Object: ID: ' . $punch_data['id'] . ' TimeStamp: ' . $punch_data['time_stamp'] . ' Status: ' . $punch_data['status_id'], __FILE__, __LINE__, __METHOD__, 10);
                 //Check for another punch that matches the timestamp and status.
                 if ($this->getPunchObject()->getID() != $punch_data['id']) {
                     if ($this->getPunchObject()->getTimeStamp() == $punch_data['time_stamp'] and $this->getPunchObject()->getStatus() == $punch_data['status_id']) {
                         $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('Time and status match that of another punch, this could be due to rounding (a)'));
                     }
                 }
                 //Check for another punch that matches the timestamp and NOT status in the SAME punch pair.
                 if ($this->getPunchObject()->getID() != $punch_data['id'] and $this->getID() == $punch_data['punch_control_id']) {
                     if ($this->getPunchObject()->getTimeStamp() == $punch_data['time_stamp'] and $this->getPunchObject()->getStatus() != $punch_data['status_id']) {
                         $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('Time matches another punch in the same punch pair, this could be due to rounding (b)'));
                     }
                 }
                 $punches[$punch_data['punch_control_id']][$punch_data['status_id']] = $punch_data;
             }
             unset($punch_data);
             if (isset($punches[$this->getID()])) {
                 Debug::text('Current Punch ID Id: ' . $this->getPunchObject()->getId() . ' Punch Control ID: ' . $this->getID() . ' Status: ' . $this->getPunchObject()->getStatus(), __FILE__, __LINE__, __METHOD__, 10);
                 //Debug::Arr($punches, 'Punches Arr: ', __FILE__, __LINE__, __METHOD__,10);
                 if ($this->getPunchObject()->getStatus() == 10 and isset($punches[$this->getID()][20]) and $this->getPunchObject()->getTimeStamp() > $punches[$this->getID()][20]['time_stamp']) {
                     $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('In punches cannot occur after an out punch, in the same punch pair'));
                 } elseif ($this->getPunchObject()->getStatus() == 20 and isset($punches[$this->getID()][10]) and $this->getPunchObject()->getTimeStamp() < $punches[$this->getID()][10]['time_stamp']) {
                     $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('Out punches cannot occur before an in punch, in the same punch pair'));
                 } else {
                     Debug::text('bPunch does not match any other punch pair.', __FILE__, __LINE__, __METHOD__, 10);
                     $punch_neighbors = Misc::getArrayNeighbors($punches, $this->getID(), 'both');
                     //Debug::Arr($punch_neighbors, ' Punch Neighbors: ', __FILE__, __LINE__, __METHOD__,10);
                     if (isset($punch_neighbors['next']) and isset($punches[$punch_neighbors['next']])) {
                         Debug::text('Found Next Punch...', __FILE__, __LINE__, __METHOD__, 10);
                         if (isset($punches[$punch_neighbors['next']][10]) and $this->getPunchObject()->getTimeStamp() > $punches[$punch_neighbors['next']][10]['time_stamp'] or isset($punches[$punch_neighbors['next']][20]) and $this->getPunchObject()->getTimeStamp() > $punches[$punch_neighbors['next']][20]['time_stamp']) {
                             $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('Time conflicts with another punch on this day') . ' (a)');
                         }
                     }
                     if (isset($punch_neighbors['prev']) and isset($punches[$punch_neighbors['prev']])) {
                         Debug::text('Found prev Punch...', __FILE__, __LINE__, __METHOD__, 10);
                         if (isset($punches[$punch_neighbors['prev']][10]) and $this->getPunchObject()->getTimeStamp() < $punches[$punch_neighbors['prev']][10]['time_stamp'] or isset($punches[$punch_neighbors['prev']][20]) and $this->getPunchObject()->getTimeStamp() < $punches[$punch_neighbors['prev']][20]['time_stamp']) {
                             $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('Time conflicts with another punch on this day') . ' (b)');
                         }
                     }
                 }
                 //Check to make sure punches don't exceed maximum shift time.
                 $maximum_shift_time = $plf->getPayPeriodMaximumShiftTime($this->getPunchObject()->getUser());
                 Debug::text('aaaMaximum shift time: ' . $maximum_shift_time, __FILE__, __LINE__, __METHOD__, 10);
                 if ($shift_data['total_time'] > $maximum_shift_time) {
                     $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('Punch exceeds maximum shift time of') . ' ' . TTDate::getTimeUnit($maximum_shift_time) . ' ' . TTi18n::getText('hrs set for this pay period schedule'));
                 }
             }
             unset($punches);
         }
     }
     if (getTTProductEdition() == TT_PRODUCT_PROFESSIONAL and $this->getEnableStrictJobValidation() == TRUE) {
         if ($this->getJob() > 0) {
             $jlf = new JobListFactory();
             $jlf->getById($this->getJob());
             if ($jlf->getRecordCount() > 0) {
                 $j_obj = $jlf->getCurrent();
                 if (is_object($this->getUserDateObject()) and $j_obj->isAllowedUser($this->getUserDateObject()->getUser()) == FALSE) {
                     $this->Validator->isTRUE('job', FALSE, TTi18n::gettext('Employee is not assigned to this job'));
                 }
                 if ($j_obj->isAllowedItem($this->getJobItem()) == FALSE) {
                     $this->Validator->isTRUE('job_item', FALSE, TTi18n::gettext('Task is not assigned to this job'));
                 }
             }
         }
     }
     return TRUE;
 }
         $x++;
     }
     unset($data);
 }
 if (isset($totals) and is_array($totals)) {
     //Display overall totals.
     $pdf->Ln(4);
     $total_cell_width = $column_widths['line'] + $column_widths['date_stamp'] + $column_widths['dow'] + $column_widths['in_punch_time_stamp'];
     $pdf->SetFont('', 'B', 9);
     $pdf->Cell($total_cell_width, 6, '', 0, 0, 'R', 0);
     $pdf->Cell($column_widths['out_punch_time_stamp'], 6, TTi18n::gettext('Overall Total:') . ' ', 'T', 0, 'R', 0);
     $pdf->Cell($column_widths['worked_time'], 6, TTDate::getTimeUnit($totals['worked_time']), 'T', 0, 'C', 0);
     $pdf->Cell($column_widths['paid_time'], 6, TTDate::getTimeUnit($totals['paid_time']), 'T', 0, 'C', 0);
     $pdf->Cell($column_widths['regular_time'], 6, TTDate::getTimeUnit($totals['regular_time']), 'T', 0, 'C', 0);
     $pdf->Cell($column_widths['over_time'], 6, TTDate::getTimeUnit($totals['over_time']), 'T', 0, 'C', 0);
     $pdf->Cell($column_widths['absence_time'], 6, TTDate::getTimeUnit($totals['absence_time']), 'T', 0, 'C', 0);
     $pdf->Ln();
     unset($totals);
 }
 $pdf->SetFont('', '', 10);
 $pdf->setFillColor(255, 255, 255);
 $pdf->Ln();
 //Signature lines
 $pdf->MultiCell(200, 5, TTi18n::gettext('By signing this timesheet I hereby certify that the above time accurately and fully reflects the time that') . ' ' . $user_data['first_name'] . ' ' . $user_data['last_name'] . ' ' . TTi18n::gettext('worked during the designated period.'), $border, 'L');
 $pdf->Ln(5);
 $border = 0;
 $pdf->Cell(40, 5, TTi18n::gettext('Employee Signature:'), $border, 0, 'L');
 $pdf->Cell(60, 5, '_____________________________', $border, 0, 'C');
 $pdf->Cell(40, 5, TTi18n::gettext('Supervisor Signature:'), $border, 0, 'R');
 $pdf->Cell(60, 5, '_____________________________', $border, 0, 'C');
 $pdf->Ln();
 function addLog($log_action)
 {
     $u_obj = $this->getUserObject();
     if (is_object($u_obj)) {
         return TTLog::addEntry($this->getId(), $log_action, TTi18n::getText('Accrual') . ' - ' . TTi18n::getText('Employee') . ': ' . $u_obj->getFullName(FALSE, TRUE) . ' ' . TTi18n::getText('Type') . ': ' . Option::getByKey($this->getType(), $this->getOptions('type')) . ' ' . TTi18n::getText('Date') . ': ' . TTDate::getDate('DATE', $this->getTimeStamp()) . ' ' . TTi18n::getText('Total Time') . ': ' . TTDate::getTimeUnit($this->getAmount()), NULL, $this->getTable(), $this);
     }
     return FALSE;
 }
 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);
 }
示例#7
0
 $utlf->getByCompanyId($current_company->getId());
 $title_options = $utlf->getArrayByListFactory($utlf, FALSE, TRUE);
 $blf = TTnew('BranchListFactory');
 $blf->getByCompanyId($current_company->getId());
 $branch_options = $blf->getArrayByListFactory($blf, FALSE, TRUE);
 $dlf = TTnew('DepartmentListFactory');
 $dlf->getByCompanyId($current_company->getId());
 $department_options = $dlf->getArrayByListFactory($dlf, FALSE, TRUE);
 $uglf = TTnew('UserGroupListFactory');
 $group_options = $uglf->getArrayByNodes(FastTree::FormatArray($uglf->getByCompanyIdArray($current_company->getId()), 'TEXT', TRUE));
 $ulf = TTnew('UserListFactory');
 $user_options = $ulf->getByCompanyIdArray($current_company->getID(), FALSE);
 foreach ($slf as $s_obj) {
     //Debug::Text('Status ID: '. $r_obj->getStatus() .' Status: '. $status_options[$r_obj->getStatus()], __FILE__, __LINE__, __METHOD__,10);
     $user_obj = $ulf->getById($s_obj->getColumn('user_id'))->getCurrent();
     $rows[] = array('id' => $s_obj->getColumn('schedule_id'), 'user_id' => $s_obj->getColumn('user_id'), 'first_name' => $user_obj->getFirstName(), 'last_name' => $user_obj->getLastName(), 'title' => Option::getByKey($user_obj->getTitle(), $title_options), 'group' => Option::getByKey($user_obj->getGroup(), $group_options), 'default_branch' => Option::getByKey($user_obj->getDefaultBranch(), $branch_options), 'default_department' => Option::getByKey($user_obj->getDefaultDepartment(), $department_options), 'branch_id' => Option::getByKey($s_obj->getBranch(), $branch_options), 'department_id' => Option::getByKey($s_obj->getDepartment(), $department_options), 'status_id' => Option::getByKey($s_obj->getStatus(), $schedule_status_options), 'start_time' => TTDate::getDate('DATE+TIME', $s_obj->getStartTime()), 'end_time' => TTDate::getDate('DATE+TIME', $s_obj->getEndTime()), 'total_time' => TTDate::getTimeUnit($s_obj->getTotalTime()), 'is_owner' => $permission->isOwner($s_obj->getCreatedBy(), $current_user->getId()), 'is_child' => $permission->isChild($s_obj->getColumn('user_id'), $permission_children_ids));
 }
 $smarty->assign_by_ref('rows', $rows);
 $all_array_option = array('-1' => TTi18n::gettext('-- Any --'));
 $ulf->getSearchByCompanyIdAndArrayCriteria($current_company->getId(), $filter_data);
 $filter_data['user_options'] = Misc::prependArray($all_array_option, UserListFactory::getArrayByListFactory($ulf, FALSE, TRUE));
 //Select box options;
 $filter_data['branch_options'] = Misc::prependArray($all_array_option, $branch_options);
 $filter_data['department_options'] = Misc::prependArray($all_array_option, $department_options);
 $filter_data['title_options'] = Misc::prependArray($all_array_option, $title_options);
 $filter_data['group_options'] = Misc::prependArray($all_array_option, $group_options);
 $filter_data['status_options'] = Misc::prependArray($all_array_option, $ulf->getOptions('status'));
 $filter_data['pay_period_options'] = Misc::prependArray($all_array_option, $pay_period_options);
 $filter_data['schedule_status_options'] = Misc::prependArray($all_array_option, $schedule_status_options);
 $filter_data['schedule_policy_options'] = Misc::prependArray($all_array_option, $schedule_policy_options);
 $filter_data['saved_search_options'] = $ugdlf->getArrayByListFactory($ugdlf->getByUserIdAndScript($current_user->getId(), $_SERVER['SCRIPT_NAME']), FALSE);
示例#8
0
 public static function parseTimeUnit($time_unit, $format = NULL)
 {
     /*
     	10 	=> 'hh:mm (2:15)',
     	12 	=> 'hh:mm:ss (2:15:59)',
     	20 	=> 'Hours (2.25)',
     	22 	=> 'Hours (2.241)',
     	30 	=> 'Minutes (135)'
     */
     if ($format == '') {
         $format = self::$time_unit_format;
     }
     $enable_rounding = TRUE;
     if (strpos($time_unit, '"') !== FALSE) {
         $enable_rounding = FALSE;
     }
     //Get rid of any spaces or commas.
     //ie: 1,100 :10 should still parse correctly
     $time_unit = trim(str_replace(array(',', ' ', '"'), '', $time_unit));
     //Debug::text('Time Unit: '. $time_unit .' Enable Rounding: '. (int)$enable_rounding, __FILE__, __LINE__, __METHOD__, 10);
     //Debug::text('Time Unit Format: '. self::$time_unit_format, __FILE__, __LINE__, __METHOD__, 10);
     //Convert string to seconds.
     switch ($format) {
         case 10:
             //hh:mm
         //hh:mm
         case 12:
             //hh:mm:ss
             if (strpos($time_unit, '.') !== FALSE and strpos($time_unit, ':') === FALSE) {
                 //Hybrid mode, they passed a decimal format HH:MM, try to handle properly.
                 $time_unit = TTDate::getTimeUnit(self::parseTimeUnit($time_unit, 20), $format);
             }
             $time_units = explode(':', $time_unit);
             if (!isset($time_units[0])) {
                 $time_units[0] = 0;
             }
             if (!isset($time_units[1])) {
                 $time_units[1] = 0;
             }
             if (!isset($time_units[2])) {
                 $time_units[2] = 0;
             }
             //Check if the first character is '-', or thre are any negative integers.
             if (strncmp($time_units[0], '-', 1) == 0 or $time_units[0] < 0 or $time_units[1] < 0 or $time_units[2] < 0) {
                 $negative_number = TRUE;
             }
             $seconds = abs((int) $time_units[0]) * 3600 + abs((int) $time_units[1]) * 60 + abs((int) $time_units[2]);
             if (isset($negative_number)) {
                 $seconds = $seconds * -1;
             }
             break;
         case 20:
             //hours
         //hours
         case 22:
             //hours [Precise]
             if (strpos($time_unit, ':') !== FALSE and strpos($time_unit, '.') === FALSE) {
                 //Hybrid mode, they passed a HH:MM format as a decimal, try to handle properly.
                 $time_unit = TTDate::getTimeUnit(self::parseTimeUnit($time_unit, 10), $format);
             }
             //Round to the nearest minute when entering decimal format to avoid issues with 0.33 (19.8 minutes) or 0.333 (19.98 minutes) or 0.33333...
             //This is only for input, for things like absence time, or meal/break policies, its rare they need sub-minute resolution, and if they
             //do they can use hh:mm:ss instead.
             //However accrual policies have to be second accurate (weekly accruals rounded to 1 minute can result in 52minute differences in a year),
             //so we need a way to disable this rounding as well so the user can properly zero out an accrual balance if needed.
             $seconds = $time_unit * 3600;
             if ($enable_rounding == TRUE) {
                 $seconds = self::roundTime($seconds, 60);
             }
             break;
         case 30:
             //minutes
             $seconds = $time_unit * 60;
             break;
     }
     if (isset($seconds)) {
         if ($seconds > 2147483646) {
             Debug::text('ERROR: Parsing time unit format exceeds maximum 4 byte integer!', __FILE__, __LINE__, __METHOD__, 10);
             $seconds = 2147483646;
         }
         return $seconds;
     }
     return FALSE;
 }
 function addLog($log_action)
 {
     if ($this->getOverride() == TRUE and $this->getStatus() == 30 and is_object($this->getUserDateObject())) {
         //Absence
         return TTLog::addEntry($this->getId(), $log_action, TTi18n::getText('Absence') . ' - ' . TTi18n::getText('Date') . ': ' . TTDate::getDate('DATE', $this->getUserDateObject()->getDateStamp()) . ' ' . TTi18n::getText('Total Time') . ': ' . TTDate::getTimeUnit($this->getTotalTime()), NULL, $this->getTable(), $this);
     }
 }
示例#10
0
 function getAccrualBalance($accrual_policy_id, $user_id)
 {
     if ($accrual_policy_id == '') {
         return FALSE;
     }
     if ($user_id == '') {
         return FALSE;
     }
     $ablf = TTnew('AccrualBalanceListFactory');
     $ablf->getByUserIdAndAccrualPolicyId($user_id, $accrual_policy_id);
     if ($ablf->getRecordCount() > 0) {
         $accrual_balance = $ablf->getCurrent()->getBalance();
     } else {
         $accrual_balance = 0;
     }
     return TTDate::getTimeUnit($accrual_balance);
 }
示例#11
0
                 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;
             default:
                 break;
         }
     }
 }
 if (Debug::getVerbosity() == 11) {
 function Validate()
 {
     Debug::text('Validating...', __FILE__, __LINE__, __METHOD__, 10);
     //Call this here so getShiftData can get the correct total time, before we call findUserDate.
     if ($this->getEnableCalcTotalTime() == TRUE) {
         $this->calcTotalTime();
     }
     if (is_object($this->getPunchObject())) {
         $this->findUserDate();
     }
     Debug::text('User Date Id: ' . $this->getUserDateID(), __FILE__, __LINE__, __METHOD__, 10);
     //Don't check for a valid pay period here, do that in PunchFactory->Validate(), as we need to allow users to delete punches that were created outside pay periods in legacy versions.
     if ($this->getDeleted() == FALSE and $this->getUserDateObject() == FALSE) {
         $this->Validator->isTRUE('date_stamp', FALSE, TTi18n::gettext('Date/Time is incorrect, or pay period does not exist for this date. Please create a pay period schedule and assign this employee to it if you have not done so already'));
     } elseif (is_object($this->getUserDateObject()) and is_object($this->getUserDateObject()->getPayPeriodObject()) and $this->getUserDateObject()->getPayPeriodObject()->getIsLocked() == TRUE) {
         $this->Validator->isTRUE('date_stamp', FALSE, TTi18n::gettext('Pay Period is Currently Locked'));
     }
     //Make sure the user isn't entering punches before the employees hire or after termination date, as its likely they wouldn't have a wage
     //set for that anyways and wouldn't get paid for it.
     if ($this->getDeleted() == FALSE and (is_object($this->getPunchObject()) and $this->getPunchObject()->getDeleted() == FALSE) and is_object($this->getUserDateObject()) and is_object($this->getUserDateObject()->getUserObject())) {
         if ($this->getUserDateObject()->getUserObject()->getHireDate() != '' and TTDate::getBeginDayEpoch($this->getUserDateObject()->getDateStamp()) < TTDate::getBeginDayEpoch($this->getUserDateObject()->getUserObject()->getHireDate())) {
             $this->Validator->isTRUE('date_stamp', FALSE, TTi18n::gettext('Punch is before employees hire date'));
         }
         if ($this->getUserDateObject()->getUserObject()->getTerminationDate() != '' and TTDate::getEndDayEpoch($this->getUserDateObject()->getDateStamp()) > TTDate::getEndDayEpoch($this->getUserDateObject()->getUserObject()->getTerminationDate())) {
             $this->Validator->isTRUE('date_stamp', FALSE, TTi18n::gettext('Punch is after employees termination date'));
         }
     }
     //Skip these checks if they are deleting a punch.
     if (is_object($this->getPunchObject()) and $this->getPunchObject()->getDeleted() == FALSE) {
         $plf = $this->getPLFByPunchControlID();
         if ($plf !== NULL and ($this->isNew() and $plf->getRecordCount() == 2 or $plf->getRecordCount() > 2)) {
             //TTi18n::gettext('Punch Control can not have more than two punches. Please use the Add Punch button instead')
             //They might be trying to insert a punch inbetween two others?
             $this->Validator->isTRUE('punch_control', FALSE, TTi18n::gettext('Time conflicts with another punch on this day (c)'));
         }
         //Sometimes shift data won't return all the punches to proper check for conflicting punches.
         //So we need to make sure other punches assigned to this punch_control record are proper.
         //This fixes the bug of having shifts: 2:00AM Lunch Out, 2:30AM Lunch In, 6:00AM Out, 10:00PM In (in that order), then trying to move the 10PM punch to the open IN slot before the 2AM punch.
         if ($plf->getRecordCount() > 0) {
             foreach ($plf as $p_obj) {
                 if ($p_obj->getID() != $this->getPunchObject()->getID()) {
                     if ($this->getPunchObject()->getStatus() == 10 and $p_obj->getStatus() == 10 and $this->getPunchObject()->getTimeStamp() > $p_obj->getTimeStamp()) {
                         //Make sure we match on status==10 for both sides, otherwise this fails to catch the problem case.
                         $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('In punches cannot occur after an out punch, in the same punch pair (a)'));
                     } elseif ($this->getPunchObject()->getStatus() == 20 and $p_obj->getStatus() == 10 and $this->getPunchObject()->getTimeStamp() < $p_obj->getTimeStamp()) {
                         $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('Out punches cannot occur before an in punch, in the same punch pair (a)'));
                     }
                 }
             }
         }
         unset($p_obj);
         if ($this->Validator->isValid() == TRUE) {
             //Don't bother checking these resource intensive issues if there are already validation errors.
             $shift_data = $this->getShiftData();
             if (is_array($shift_data) and $this->Validator->hasError('time_stamp') == FALSE) {
                 foreach ($shift_data['punches'] as $punch_data) {
                     //Make sure there aren't two In punches, or two Out punches in the same pair.
                     //This fixes the bug where if you have an In punch, then click the blank cell below it
                     //to add a new punch, but change the status from Out to In instead.
                     if (isset($punches[$punch_data['punch_control_id']][$punch_data['status_id']])) {
                         if ($punch_data['status_id'] == 10) {
                             $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('In punches cannot occur twice in the same punch pair, you may want to make this an out punch instead'));
                         } else {
                             $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('Out punches cannot occur twice in the same punch pair, you may want to make this an in punch instead'));
                         }
                     }
                     //Debug::text(' Current Punch Object: ID: '. $this->getPunchObject()->getId() .' TimeStamp: '. $this->getPunchObject()->getTimeStamp() .' Status: '. $this->getPunchObject()->getStatus(), __FILE__, __LINE__, __METHOD__,10);
                     //Debug::text(' Looping Punch Object: ID: '. $punch_data['id'] .' TimeStamp: '. $punch_data['time_stamp'] .' Status: '.$punch_data['status_id'], __FILE__, __LINE__, __METHOD__,10);
                     //Check for another punch that matches the timestamp and status.
                     if ($this->getPunchObject()->getID() != $punch_data['id']) {
                         if ($this->getPunchObject()->getTimeStamp() == $punch_data['time_stamp'] and $this->getPunchObject()->getStatus() == $punch_data['status_id']) {
                             $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('Time and status match that of another punch, this could be due to rounding') . ' (' . TTDate::getDate('DATE+TIME', $punch_data['time_stamp']) . ')');
                             break;
                             //Break the loop on validation error, so we don't get multiple errors that may be confusing.
                         }
                     }
                     //Check for another punch that matches the timestamp and NOT status in the SAME punch pair.
                     if ($this->getPunchObject()->getID() != $punch_data['id'] and $this->getID() == $punch_data['punch_control_id']) {
                         if ($this->getPunchObject()->getTimeStamp() == $punch_data['time_stamp'] and $this->getPunchObject()->getStatus() != $punch_data['status_id']) {
                             $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('Time matches another punch in the same punch pair, this could be due to rounding') . ' (' . TTDate::getDate('DATE+TIME', $punch_data['time_stamp']) . ')');
                             break;
                             //Break the loop on validation error, so we don't get multiple errors that may be confusing.
                         }
                     }
                     $punches[$punch_data['punch_control_id']][$punch_data['status_id']] = $punch_data;
                 }
                 unset($punch_data);
                 if (isset($punches[$this->getID()])) {
                     Debug::text('Current Punch ID: ' . $this->getPunchObject()->getId() . ' Punch Control ID: ' . $this->getID() . ' Status: ' . $this->getPunchObject()->getStatus(), __FILE__, __LINE__, __METHOD__, 10);
                     //Debug::Arr($punches, 'Punches Arr: ', __FILE__, __LINE__, __METHOD__,10);
                     if ($this->getPunchObject()->getStatus() == 10 and isset($punches[$this->getID()][20]) and $this->getPunchObject()->getTimeStamp() > $punches[$this->getID()][20]['time_stamp']) {
                         $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('In punches cannot occur after an out punch, in the same punch pair'));
                     } elseif ($this->getPunchObject()->getStatus() == 20 and isset($punches[$this->getID()][10]) and $this->getPunchObject()->getTimeStamp() < $punches[$this->getID()][10]['time_stamp']) {
                         $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('Out punches cannot occur before an in punch, in the same punch pair'));
                     } else {
                         Debug::text('bPunch does not match any other punch pair.', __FILE__, __LINE__, __METHOD__, 10);
                         $punch_neighbors = Misc::getArrayNeighbors($punches, $this->getID(), 'both');
                         //Debug::Arr($punch_neighbors, ' Punch Neighbors: ', __FILE__, __LINE__, __METHOD__,10);
                         if (isset($punch_neighbors['next']) and isset($punches[$punch_neighbors['next']])) {
                             Debug::text('Found Next Punch...', __FILE__, __LINE__, __METHOD__, 10);
                             if (isset($punches[$punch_neighbors['next']][10]) and $this->getPunchObject()->getTimeStamp() > $punches[$punch_neighbors['next']][10]['time_stamp'] or isset($punches[$punch_neighbors['next']][20]) and $this->getPunchObject()->getTimeStamp() > $punches[$punch_neighbors['next']][20]['time_stamp']) {
                                 $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('Time conflicts with another punch on this day') . ' (a)');
                             }
                         }
                         if (isset($punch_neighbors['prev']) and isset($punches[$punch_neighbors['prev']])) {
                             Debug::text('Found prev Punch...', __FILE__, __LINE__, __METHOD__, 10);
                             //This needs to take into account DST. Specifically if punches are like this:
                             //03-Nov-12: IN: 10:00PM
                             //04-Nov-12: OUT: 1:00AM L
                             //04-Nov-12: IN: 1:30AM L
                             //04-Nov-12: OUT: 6:30AM L
                             //Since the 1AM to 2AM occur twice due to the "fall back" DST change, we need to allow those punches to be entered.
                             if (isset($punches[$punch_neighbors['prev']][10]) and ($this->getPunchObject()->getTimeStamp() < $punches[$punch_neighbors['prev']][10]['time_stamp'] and TTDate::doesRangeSpanDST($this->getPunchObject()->getTimeStamp(), $punches[$punch_neighbors['prev']][10]['time_stamp']) == FALSE) or isset($punches[$punch_neighbors['prev']][20]) and ($this->getPunchObject()->getTimeStamp() < $punches[$punch_neighbors['prev']][20]['time_stamp'] and TTDate::doesRangeSpanDST($this->getPunchObject()->getTimeStamp(), $punches[$punch_neighbors['prev']][20]['time_stamp']) == FALSE)) {
                                 $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('Time conflicts with another punch on this day') . ' (b)');
                             }
                         }
                     }
                     //Check to make sure punches don't exceed maximum shift time.
                     $maximum_shift_time = $plf->getPayPeriodMaximumShiftTime($this->getPunchObject()->getUser());
                     Debug::text('Maximum shift time: ' . $maximum_shift_time, __FILE__, __LINE__, __METHOD__, 10);
                     if ($shift_data['total_time'] > $maximum_shift_time) {
                         $this->Validator->isTRUE('time_stamp', FALSE, TTi18n::gettext('Punch exceeds maximum shift time of') . ' ' . TTDate::getTimeUnit($maximum_shift_time) . ' ' . TTi18n::getText('hrs set for this pay period schedule'));
                     }
                 }
                 unset($punches);
             }
         }
     }
     if (getTTProductEdition() >= TT_PRODUCT_CORPORATE and $this->getEnableStrictJobValidation() == TRUE) {
         if ($this->getJob() > 0) {
             $jlf = TTnew('JobListFactory');
             $jlf->getById($this->getJob());
             if ($jlf->getRecordCount() > 0) {
                 $j_obj = $jlf->getCurrent();
                 if (is_object($this->getUserDateObject()) and $j_obj->isAllowedUser($this->getUserDateObject()->getUser()) == FALSE) {
                     $this->Validator->isTRUE('job', FALSE, TTi18n::gettext('Employee is not assigned to this job'));
                 }
                 if ($j_obj->isAllowedItem($this->getJobItem()) == FALSE) {
                     $this->Validator->isTRUE('job_item', FALSE, TTi18n::gettext('Task is not assigned to this job'));
                 }
             }
         }
     }
     return TRUE;
 }
示例#13
0
 function columnFormatter($type, $column, $value, $format = NULL)
 {
     if (is_array($value) and isset($value['display'])) {
         //Found sorting array, use display column.
         return $value['display'];
     } else {
         $retval = $value;
         if ($format == 'csv' or $format == 'raw') {
             //Force specific field formats for exporting to CSV format.
             switch ($type) {
                 case 'report_date':
                     $column = strpos($column, 'custom_column') === FALSE ? $column : $column . '-' . 'date_stamp';
                     $retval = TTDate::getReportDates($column, $value, TRUE, $this->getUserObject());
                     break;
                 case 'currency':
                 case 'percent':
                 case 'numeric':
                     //Don't format above types.
                     break;
                 case 'time_unit':
                     $retval = TTDate::getHours($value);
                     //Force to hours always.
                     break;
                 case 'date_stamp':
                     $retval = TTDate::getDate('DATE', $value);
                     break;
                 case 'time':
                     $retval = TTDate::getDate('TIME', $value);
                     break;
                 case 'time_stamp':
                     $retval = TTDate::getDate('DATE+TIME', $value);
                     break;
                 case 'boolean':
                     if ($value == TRUE) {
                         $retval = TTi18n::getText('Yes');
                     } else {
                         $retval = TTi18n::getText('No');
                     }
                 default:
                     break;
             }
         } elseif ($format == 'xml') {
             //Use standard XML formats whenever possible.
             switch ($type) {
                 case 'report_date':
                     $column = strpos($column, 'custom_column') === FALSE ? $column : $column . '-' . 'date_stamp';
                     $retval = TTDate::getReportDates($column, $value, TRUE, $this->getUserObject());
                     break;
                 case 'currency':
                 case 'percent':
                 case 'numeric':
                     //Don't format above types.
                     break;
                 case 'time_unit':
                     $retval = TTDate::getHours($value);
                     //Force to hours always.
                     break;
                 case 'date_stamp':
                     $retval = date('Y-m-d', $value);
                     ////type="xs:date"
                     break;
                 case 'time':
                     $retval = date('H:i:s', $value);
                     //type="xs:time"
                     break;
                 case 'time_stamp':
                     $retval = date('c', $value);
                     //type="xs:dateTime"
                     break;
                 case 'boolean':
                     if ($value == TRUE) {
                         $retval = TTi18n::getText('Yes');
                     } else {
                         $retval = TTi18n::getText('No');
                     }
                 default:
                     break;
             }
         } else {
             switch ($type) {
                 case 'report_date':
                     $column = strpos($column, 'custom_column') === FALSE ? $column : $column . '-' . 'date_stamp';
                     $retval = TTDate::getReportDates($column, $value, TRUE, $this->getUserObject());
                     break;
                 case 'currency':
                     if (is_object($this->getCurrencyObject())) {
                         //Set MIN decimals to 2 and max to the currency rounding.
                         $retval = $this->getCurrencyObject()->getSymbol() . TTi18n::formatNumber($value, TRUE, 2, $this->getCurrencyObject()->getRoundDecimalPlaces());
                     } else {
                         $retval = TTi18n::formatCurrency($value);
                     }
                     break;
                 case 'percent':
                     $retval = TTi18n::formatNumber($value, TRUE) . '%';
                     break;
                 case 'numeric':
                     $retval = TTi18n::formatNumber($value, TRUE);
                     break;
                 case 'time_unit':
                     $retval = TTDate::getTimeUnit($value);
                     break;
                 case 'date_stamp':
                     $retval = TTDate::getDate('DATE', $value);
                     break;
                 case 'time':
                     $retval = TTDate::getDate('TIME', $value);
                     break;
                 case 'time_stamp':
                     $retval = TTDate::getDate('DATE+TIME', $value);
                     break;
                 case 'boolean':
                     if ($value == TRUE) {
                         $retval = TTi18n::getText('Yes');
                     } else {
                         $retval = TTi18n::getText('No');
                     }
                     break;
                 case 'time_since':
                     $retval = TTDate::getHumanTimeSince($value);
                     break;
                 default:
                     break;
             }
         }
         //Debug::Text('Column: '. $column .' Value: '. $value .' Type: '. $type .' Retval: '. $retval, __FILE__, __LINE__, __METHOD__,10);
         return $retval;
     }
 }
 function timesheetTotal($column_widths, $totals)
 {
     $margins = $this->pdf->getMargins();
     $total_width = $this->pdf->getPageWidth() - $margins['left'] - $margins['right'];
     $buffer = ($total_width - 200) / 10;
     $line_h = $this->_pdf_scaleSize(6);
     $total_cell_width = $column_widths['line'] + $column_widths['date_stamp'] + $column_widths['dow'] + $column_widths['in_punch_time_stamp'] + $buffer * 4;
     $this->pdf->SetFont($this->config['other']['default_font'], 'B', $this->_pdf_fontSize(9));
     $this->pdf->Cell($total_cell_width, $line_h, '', 0, 0, 'R', 0);
     $this->pdf->Cell($column_widths['out_punch_time_stamp'] + $buffer, $line_h, TTi18n::gettext('Overall Total') . ': ', 'T', 0, 'R', 0);
     $this->pdf->Cell($column_widths['worked_time'] + $buffer, $line_h, TTDate::getTimeUnit($totals['worked_time']), 'T', 0, 'C', 0);
     $this->pdf->Cell($column_widths['regular_time'] + $buffer, $line_h, TTDate::getTimeUnit($totals['regular_time']), 'T', 0, 'C', 0);
     $this->pdf->Cell($column_widths['over_time'] + $buffer, $line_h, TTDate::getTimeUnit($totals['over_time']), 'T', 0, 'C', 0);
     $this->pdf->Cell($column_widths['absence_time'] + $buffer, $line_h, TTDate::getTimeUnit($totals['absence_time']), 'T', 0, 'C', 0);
     $this->pdf->Ln();
     return TRUE;
 }